mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge pull request #527 from YunoHost/migrate-pwd
Synchronize root and admin password
This commit is contained in:
commit
4999cd8ba0
4 changed files with 102 additions and 5 deletions
|
@ -1446,7 +1446,7 @@ tools:
|
||||||
|
|
||||||
### tools_adminpw()
|
### tools_adminpw()
|
||||||
adminpw:
|
adminpw:
|
||||||
action_help: Change admin password
|
action_help: Change password of admin and root users
|
||||||
api: PUT /adminpw
|
api: PUT /adminpw
|
||||||
configuration:
|
configuration:
|
||||||
authenticate: all
|
authenticate: all
|
||||||
|
|
|
@ -273,6 +273,7 @@
|
||||||
"migration_description_0003_migrate_to_stretch": "Upgrade the system to Debian Stretch and YunoHost 3.0",
|
"migration_description_0003_migrate_to_stretch": "Upgrade the system to Debian Stretch and YunoHost 3.0",
|
||||||
"migration_description_0004_php5_to_php7_pools": "Reconfigure the PHP pools to use PHP 7 instead of 5",
|
"migration_description_0004_php5_to_php7_pools": "Reconfigure the PHP pools to use PHP 7 instead of 5",
|
||||||
"migration_description_0005_postgresql_9p4_to_9p6": "Migrate databases from postgresql 9.4 to 9.6",
|
"migration_description_0005_postgresql_9p4_to_9p6": "Migrate databases from postgresql 9.4 to 9.6",
|
||||||
|
"migration_description_0006_sync_admin_and_root_passwords": "Synchronize admin and root passwords",
|
||||||
"migration_0003_backward_impossible": "The stretch migration cannot be reverted.",
|
"migration_0003_backward_impossible": "The stretch migration cannot be reverted.",
|
||||||
"migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.",
|
"migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.",
|
||||||
"migration_0003_patching_sources_list": "Patching the sources.lists ...",
|
"migration_0003_patching_sources_list": "Patching the sources.lists ...",
|
||||||
|
@ -289,6 +290,8 @@
|
||||||
"migration_0005_postgresql_94_not_installed": "Postgresql was not installed on your system. Nothing to do!",
|
"migration_0005_postgresql_94_not_installed": "Postgresql was not installed on your system. Nothing to do!",
|
||||||
"migration_0005_postgresql_96_not_installed": "Postgresql 9.4 has been found to be installed, but not postgresql 9.6 !? Something weird might have happened on your system :( ...",
|
"migration_0005_postgresql_96_not_installed": "Postgresql 9.4 has been found to be installed, but not postgresql 9.6 !? Something weird might have happened on your system :( ...",
|
||||||
"migration_0005_not_enough_space": "Not enough space is available in {path} to run the migration right now :(.",
|
"migration_0005_not_enough_space": "Not enough space is available in {path} to run the migration right now :(.",
|
||||||
|
"migration_0006_disclaimer": "Yunohost now expects admin and root passwords to be synchronized. By running this migration, your root password is going to be replaced by the admin password.",
|
||||||
|
"migration_0006_done": "Your root password have been replaced by your admin password.",
|
||||||
"migrations_backward": "Migrating backward.",
|
"migrations_backward": "Migrating backward.",
|
||||||
"migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}",
|
"migrations_bad_value_for_target": "Invalid number for target argument, available migrations numbers are 0 or {}",
|
||||||
"migrations_cant_reach_migration_file": "Can't access migrations files at path %s",
|
"migrations_cant_reach_migration_file": "Can't access migrations files at path %s",
|
||||||
|
@ -371,6 +374,7 @@
|
||||||
"restore_running_app_script": "Running restore script of app '{app:s}'...",
|
"restore_running_app_script": "Running restore script of app '{app:s}'...",
|
||||||
"restore_running_hooks": "Running restoration hooks...",
|
"restore_running_hooks": "Running restoration hooks...",
|
||||||
"restore_system_part_failed": "Unable to restore the '{part:s}' system part",
|
"restore_system_part_failed": "Unable to restore the '{part:s}' system part",
|
||||||
|
"root_password_desynchronized": "The admin password has been changed, but YunoHost was unable to propagate this on the root password !",
|
||||||
"server_shutdown": "The server will shutdown",
|
"server_shutdown": "The server will shutdown",
|
||||||
"server_shutdown_confirm": "The server will shutdown immediatly, are you sure? [{answers:s}]",
|
"server_shutdown_confirm": "The server will shutdown immediatly, are you sure? [{answers:s}]",
|
||||||
"server_reboot": "The server will reboot",
|
"server_reboot": "The server will reboot",
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import spwd
|
||||||
|
import crypt
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
|
from moulinette.core import MoulinetteError
|
||||||
|
from moulinette.utils.log import getActionLogger
|
||||||
|
from moulinette.utils.process import run_commands, check_output
|
||||||
|
from moulinette.utils.filesystem import append_to_file
|
||||||
|
from moulinette.authenticators.ldap import Authenticator
|
||||||
|
from yunohost.tools import Migration
|
||||||
|
|
||||||
|
logger = getActionLogger('yunohost.migration')
|
||||||
|
SMALL_PWD_LIST = ["yunohost", "olinuxino", "olinux", "raspberry", "admin", "root", "test", "rpi"]
|
||||||
|
|
||||||
|
class MyMigration(Migration):
|
||||||
|
"Synchronize admin and root passwords"
|
||||||
|
|
||||||
|
def migrate(self):
|
||||||
|
|
||||||
|
new_hash = self._get_admin_hash()
|
||||||
|
self._replace_root_hash(new_hash)
|
||||||
|
|
||||||
|
logger.info(m18n.n("migration_0006_done"))
|
||||||
|
|
||||||
|
def backward(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self):
|
||||||
|
|
||||||
|
# If the root password is still a "default" value,
|
||||||
|
# then this is an emergency and migration shall
|
||||||
|
# be applied automatically
|
||||||
|
#
|
||||||
|
# Otherwise, as playing with root password is touchy,
|
||||||
|
# we set this as a manual migration.
|
||||||
|
return "auto" if self._is_root_pwd_listed(SMALL_PWD_LIST) else "manual"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def disclaimer(self):
|
||||||
|
if self._is_root_pwd_listed(SMALL_PWD_LIST):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return m18n.n("migration_0006_disclaimer")
|
||||||
|
|
||||||
|
def _get_admin_hash(self):
|
||||||
|
"""
|
||||||
|
Fetch the admin hash from the LDAP db using slapcat
|
||||||
|
"""
|
||||||
|
admin_hash = check_output("slapcat \
|
||||||
|
| grep 'dn: cn=admin,dc=yunohost,dc=org' -A20 \
|
||||||
|
| grep userPassword -A2 \
|
||||||
|
| tr -d '\n ' \
|
||||||
|
| tr ':' ' ' \
|
||||||
|
| awk '{print $2}' \
|
||||||
|
| base64 -d \
|
||||||
|
| sed 's/{CRYPT}//g'")
|
||||||
|
return admin_hash
|
||||||
|
|
||||||
|
def _replace_root_hash(self, new_hash):
|
||||||
|
hash_root = spwd.getspnam("root").sp_pwd
|
||||||
|
|
||||||
|
with open('/etc/shadow', 'r') as before_file:
|
||||||
|
before = before_file.read()
|
||||||
|
|
||||||
|
with open('/etc/shadow', 'w') as after_file:
|
||||||
|
after_file.write(before.replace("root:" + hash_root,
|
||||||
|
"root:" + new_hash))
|
||||||
|
|
||||||
|
def _is_root_pwd_listed(self, pwd_list):
|
||||||
|
hash_root = spwd.getspnam("root").sp_pwd
|
||||||
|
|
||||||
|
for password in pwd_list:
|
||||||
|
if hash_root == crypt.crypt(password, hash_root):
|
||||||
|
return True
|
||||||
|
return False
|
|
@ -129,18 +129,32 @@ def tools_adminpw(auth, new_password):
|
||||||
"""
|
"""
|
||||||
from yunohost.user import _hash_user_password
|
from yunohost.user import _hash_user_password
|
||||||
from yunohost.utils.password import assert_password_is_strong_enough
|
from yunohost.utils.password import assert_password_is_strong_enough
|
||||||
|
import spwd
|
||||||
|
|
||||||
assert_password_is_strong_enough("admin", new_password)
|
assert_password_is_strong_enough("admin", new_password)
|
||||||
|
|
||||||
|
new_hash = _hash_user_password(new_password)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
auth.update("cn=admin", {
|
auth.update("cn=admin", { "userPassword": new_hash, })
|
||||||
"userPassword": _hash_user_password(new_password),
|
|
||||||
})
|
|
||||||
except:
|
except:
|
||||||
logger.exception('unable to change admin password')
|
logger.exception('unable to change admin password')
|
||||||
raise MoulinetteError(errno.EPERM,
|
raise MoulinetteError(errno.EPERM,
|
||||||
m18n.n('admin_password_change_failed'))
|
m18n.n('admin_password_change_failed'))
|
||||||
else:
|
else:
|
||||||
|
# Write as root password
|
||||||
|
try:
|
||||||
|
hash_root = spwd.getspnam("root").sp_pwd
|
||||||
|
|
||||||
|
with open('/etc/shadow', 'r') as before_file:
|
||||||
|
before = before_file.read()
|
||||||
|
|
||||||
|
with open('/etc/shadow', 'w') as after_file:
|
||||||
|
after_file.write(before.replace("root:" + hash_root,
|
||||||
|
"root:" + new_hash.replace('{CRYPT}', '')))
|
||||||
|
except IOError as e:
|
||||||
|
logger.warning(m18n.n('root_password_desynchronized'))
|
||||||
|
return
|
||||||
logger.success(m18n.n('admin_password_changed'))
|
logger.success(m18n.n('admin_password_changed'))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue