def check_update_user(self, name, passwd, newPasswd): """ This checks if a combination (user, password) is OK and tries to set a new password if provided user - the username to check passwd - the password for this user. if null will check only if the user name is valid newPasswd - id specified it will change the password for the user returns success status (boolean) """ if newPasswd: self.updatelock.acquire() try: (err, users) = self.get_checked_users(name = name, passwd = passwd) if err != USER_OK: return false # If we get here, the user was authenticated. All that remains to # be done is check if we need to set a new password. if newPasswd != None: # request to set it urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() hashedPasswd = password.sha1_base64_hash(newPasswd, salt) users[name].passwd = hashedPasswd users[name].salt = base64.encodestring(salt)[:-1] self.save_passwd_file(users) if not self.update_vmanage_password(name, users[name].passwd, users[name].salt): logging.error("Error updating vmanager password for user %s" % name) self.sync_password_file() finally: if newPasswd: self.updatelock.release() return true
def check_update_user(self, name, passwd, newPasswd): """ This checks if a combination (user, password) is OK and tries to set a new password if provided user - the username to check passwd - the password for this user. if null will check only if the user name is valid newPasswd - id specified it will change the password for the user returns success status (boolean) """ if newPasswd: self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name, passwd=passwd) if err != USER_OK: return false # If we get here, the user was authenticated. All that remains to # be done is check if we need to set a new password. if newPasswd != None: # request to set it urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() hashedPasswd = password.sha1_base64_hash(newPasswd, salt) users[name].passwd = hashedPasswd users[name].salt = base64.encodestring(salt)[:-1] self.save_passwd_file(users) if not self.update_vmanage_password(name, users[name].passwd, users[name].salt): logging.error( "Error updating vmanager password for user %s" % name) self.sync_password_file() finally: if newPasswd: self.updatelock.release() return true
def createUser(self, creatorName, ip, newUserName, newUserPassword, newUserEmail, newUserAccountType, newUserPermissions): """ Creates a new user given: creatorName - the username who creates the user ip - from which ip is created newUserXXXX - corresponding data for the new user isEncrypted - if the password given is encrypted Upon creation we send a confirmation email to the creator and a welcome message to to the new user (with password included) returns an error code (see at the top of the file) """ self.updatelock.acquire() try: # Pass the creator name when getting the user file (err, users) = self.get_checked_users(name = creatorName) if err != USER_OK: logging.error("Error %s while reading the users file. user create "\ " failed" % err) return CREATE_UNKNOWN if newUserName in users.keys(): logging.error("User %s already exists. Cannot re-create it" % ( newUserName)) return CREATE_USEREXISTS if len(newUserPassword) == 0: newUserPassword = password.createRandomPasswd(PASSWORD_LENGTH); # validate the user name if not entconfig.IsNameValid(newUserName): logging.error("Invalid user name %s -- cannot create" % (newUserName)) return CREATE_INVALIDUSERNAME # $TODO$ -- add email validation if " " in newUserEmail: logging.error("Invalid email %s while creating user %s" % ( newUserEmail, newUserName)) return CREATE_INVALIDEMAIL decryptedPasswd = newUserPassword urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() newUserPassword = password.sha1_base64_hash(newUserPassword, salt) newSalt = base64.encodestring(salt)[:-1] users[newUserName] = UserData(newUserName, newUserPassword, newSalt, newUserEmail, newUserAccountType, newUserPermissions) self.save_passwd_file(users) if not self.update_vmanage_password(newUserName, newUserPassword, newSalt): logging.error("Error updating vmanager password for user %s" % newUserName) finally: self.updatelock.release() self.sync_password_file() if creatorName: creatorEmail = users[creatorName].email else: creatorEmail = None accountType = users[newUserName].AccountTypePrintName() # and send email, first, to the creator if creatorEmail: SendMail.send(self.cfg, creatorEmail, false, M.MSG_NEWUSERPASSWORDSUBJECT % newUserName, M.MSG_NEWUSERPASSWORD % ( newUserName, accountType, newUserEmail, ip, creatorName, creatorEmail ), false) # next, to the created rootURI = "http://%s:8000" % self.cfg.getGlobalParam("EXTERNAL_WEB_IP") SendMail.send(self.cfg, newUserEmail, false, M.MSG_WELCOMENEWUSERSUBJECT, M.MSG_WELCOMENEWUSER % ( accountType, creatorEmail, newUserName, decryptedPasswd, rootURI, creatorEmail ), false) logging.info("User %s [email %s] created OK by %s" % ( newUserName, newUserEmail, creatorName)) return CREATE_OK
class UserManager: """ Give me a Configuartor and I know how to check if a user is Ok, if it has the right poassword, change its password, etc NOTE: the function that return booleans here, they return true on success (this is different than handlers which traditionally return error codes with 0 meaning the success) """ def __init__(self, cfg): self.cfg = cfg self.updatelock = threading.Lock() def getPasswd(self, name, ip): """ This sets a new password for a user and mails it to the user. (We touch or keep it) returns success status (boolean) """ # Refuse changing password for username google. this is a special username # that we use as a back-door for controling the box. Changing this password # may make it inaccessible (bug#36271) if name == 'google': logging.info("Refusing to set password for user %s" % name) return false newPassword = password.createRandomPasswd(PASSWORD_LENGTH) if self.check_update_user(name, None, newPassword): SendMail.send(self.cfg, self.getEmail(name), false, M.MSG_FORGOTPASSWORDSUBJECT, M.MSG_FORGOTPASSWORD % (newPassword, ip), false) self.cfg.writeAdminRunnerOpMsg( "A new password has been sent to your email address") return true logging.error("couldn't set password to user %s" % name) return false def doesUserExist(self, name): """ This check if the provided user name is valid returns success status (boolean) """ return self.check_update_user(name, None, None) def isUserPasswdValid(self, name, passwd): """ This checks if the provided user/password combination is valid. returns success status (boolean) """ return self.check_update_user(name, passwd, None) def changePasswd(self, name, passwd, newPasswd): """ This sets a new password if the provided user/password combination is valid returns success status (boolean) """ return self.check_update_user(name, passwd, newPasswd) def forcePasswd(self, name, newPasswd): """ This sets a new password with no checks - used by administrators returns success status (boolean) """ return self.check_update_user(name, None, newPasswd) def getEmail(self, name): """ Return the email address of the given user, None on error """ (err, users) = self.get_checked_users(name=name) if err != USER_OK: return None return users[name].email def setEmail(self, name, email): """ Set the email address of the given user. Returns an error code (CREATE_XXX) described at the top of the file """ self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name) if err != USER_OK: return err # $TODO$ -- add email validation if " " in email: return CREATE_INVALIDEMAIL users[name].email = email self.save_passwd_file(users) finally: self.updatelock.release() self.sync_password_file() return CREATE_OK def getAllUserData(self): """ Return the map with all users, None on error """ (err, users) = self.get_checked_users() if err != USER_OK: return None return users def getAllUserNames(self): """ Return all the user named. None on error """ (err, users) = self.get_checked_users() if err != USER_OK: return None return users.keys() def getUserData(self, name): """ Returns UserData about a user / None on error """ (err, users) = self.get_checked_users(name=name) if err != USER_OK: return None return users[name] def createUser(self, creatorName, ip, newUserName, newUserPassword, newUserEmail, newUserAccountType, newUserPermissions): """ Creates a new user given: creatorName - the username who creates the user ip - from which ip is created newUserXXXX - corresponding data for the new user isEncrypted - if the password given is encrypted Upon creation we send a confirmation email to the creator and a welcome message to to the new user (with password included) returns an error code (see at the top of the file) """ self.updatelock.acquire() try: # Pass the creator name when getting the user file (err, users) = self.get_checked_users(name=creatorName) if err != USER_OK: logging.error("Error %s while reading the users file. user create "\ " failed" % err) return CREATE_UNKNOWN if newUserName in users.keys(): logging.error("User %s already exists. Cannot re-create it" % (newUserName)) return CREATE_USEREXISTS if len(newUserPassword) == 0: newUserPassword = password.createRandomPasswd(PASSWORD_LENGTH) # validate the user name if not entconfig.IsNameValid(newUserName): logging.error("Invalid user name %s -- cannot create" % (newUserName)) return CREATE_INVALIDUSERNAME # $TODO$ -- add email validation if " " in newUserEmail: logging.error("Invalid email %s while creating user %s" % (newUserEmail, newUserName)) return CREATE_INVALIDEMAIL decryptedPasswd = newUserPassword urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() newUserPassword = password.sha1_base64_hash(newUserPassword, salt) newSalt = base64.encodestring(salt)[:-1] users[newUserName] = UserData(newUserName, newUserPassword, newSalt, newUserEmail, newUserAccountType, newUserPermissions) self.save_passwd_file(users) if not self.update_vmanage_password(newUserName, newUserPassword, newSalt): logging.error("Error updating vmanager password for user %s" % newUserName) finally: self.updatelock.release() self.sync_password_file() if creatorName: creatorEmail = users[creatorName].email else: creatorEmail = None accountType = users[newUserName].AccountTypePrintName() # and send email, first, to the creator if creatorEmail: SendMail.send( self.cfg, creatorEmail, false, M.MSG_NEWUSERPASSWORDSUBJECT % newUserName, M.MSG_NEWUSERPASSWORD % (newUserName, accountType, newUserEmail, ip, creatorName, creatorEmail), false) # next, to the created rootURI = "http://%s:8000" % self.cfg.getGlobalParam("EXTERNAL_WEB_IP") SendMail.send( self.cfg, newUserEmail, false, M.MSG_WELCOMENEWUSERSUBJECT, M.MSG_WELCOMENEWUSER % (accountType, creatorEmail, newUserName, decryptedPasswd, rootURI, creatorEmail), false) logging.info("User %s [email %s] created OK by %s" % (newUserName, newUserEmail, creatorName)) return CREATE_OK def deleteUser(self, name): """ Deletes the specified user returns success status (boolean) """ self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name) if err != USER_OK: return false del users[name] self.save_passwd_file(users) finally: self.updatelock.release() self.sync_password_file() return true def getAccountType(self, name): """ Return the account type of the given user, None on error """ (err, users) = self.get_checked_users(name=name) if err != USER_OK: return None return users[name].accountType def setAccountType(self, name, accountType): """ Sets the account type of a user Returns an error code (CREATE_XXX) described at the top of the file """ self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name) if err != USER_OK: return err users[name].accountType = accountType self.save_passwd_file(users) finally: self.updatelock.release() self.sync_password_file() return CREATE_OK def hasPermission(self, name, permission): """ Check if a user has a permission returns success status (boolean) """ (err, users) = self.get_checked_users(name=name) if err != USER_OK: return false return (users[name].accountType == SUPERUSER or permission in users[name].permissions) def setPermission(self, name, permission, on): """ Sets on or off a user permission returns success status (boolean) """ self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name) if err != USER_OK: return false if on: if not permission in users[name].permissions: users[name].permissions.append(permission) else: if permission in users[name].permissions: users[name].permissions.remove(permission) self.save_passwd_file(users) finally: self.updatelock.release() self.sync_password_file() return true def filterPermissions(self, name, permissions): """ Takes a username and a list of permissions and returns the permissions that the user has, out of that list returns a list of permissions (subset of permissions) """ (err, users) = self.get_checked_users(name=name) if err != USER_OK: return [] out = [] for p in permissions: if (users[name].accountType == SUPERUSER or p in users[name].permissions): out.append(p) return out ############################################################################# # # From now on *private* functions # def check_update_user(self, name, passwd, newPasswd): """ This checks if a combination (user, password) is OK and tries to set a new password if provided user - the username to check passwd - the password for this user. if null will check only if the user name is valid newPasswd - id specified it will change the password for the user returns success status (boolean) """ if newPasswd: self.updatelock.acquire() try: (err, users) = self.get_checked_users(name=name, passwd=passwd) if err != USER_OK: return false # If we get here, the user was authenticated. All that remains to # be done is check if we need to set a new password. if newPasswd != None: # request to set it urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() hashedPasswd = password.sha1_base64_hash(newPasswd, salt) users[name].passwd = hashedPasswd users[name].salt = base64.encodestring(salt)[:-1] self.save_passwd_file(users) if not self.update_vmanage_password(name, users[name].passwd, users[name].salt): logging.error( "Error updating vmanager password for user %s" % name) self.sync_password_file() finally: if newPasswd: self.updatelock.release() return true def get_checked_users(self, name=None, passwd=None): """ This returns the content of the password file: a map from user name to user data. If name is provided it also checks in user 'name' is in defined. If passwd is prodided it also check if passwd for user matches the one provided returns a pair (err, usersmap) where errcodes are listed at the top of the file """ # if passwd is specified - name also has to be there assert passwd == None or name != None try: users = self.load_passwd_file() except IOError, e: logging.error("IO error %s loading the user file" % e) return (USER_IOERROR, {}) if users == None: logging.error( "Problems (bad format?) while loading the users file") return (USER_INVALIDFORMAT, {}) if name and not users.has_key(name): logging.error("Unknown user %s tries to use the users file" % name) return (USER_UNKNOWN, users) if (passwd != None and password.sha1_base64_hash( passwd, base64.decodestring(users[name].salt)) != users[name].passwd): logging.error("Passwords don't match for user %s" % name) return (USER_INVALIDSPASSWD, users) return (USER_OK, users)
def createUser(self, creatorName, ip, newUserName, newUserPassword, newUserEmail, newUserAccountType, newUserPermissions): """ Creates a new user given: creatorName - the username who creates the user ip - from which ip is created newUserXXXX - corresponding data for the new user isEncrypted - if the password given is encrypted Upon creation we send a confirmation email to the creator and a welcome message to to the new user (with password included) returns an error code (see at the top of the file) """ self.updatelock.acquire() try: # Pass the creator name when getting the user file (err, users) = self.get_checked_users(name=creatorName) if err != USER_OK: logging.error("Error %s while reading the users file. user create "\ " failed" % err) return CREATE_UNKNOWN if newUserName in users.keys(): logging.error("User %s already exists. Cannot re-create it" % (newUserName)) return CREATE_USEREXISTS if len(newUserPassword) == 0: newUserPassword = password.createRandomPasswd(PASSWORD_LENGTH) # validate the user name if not entconfig.IsNameValid(newUserName): logging.error("Invalid user name %s -- cannot create" % (newUserName)) return CREATE_INVALIDUSERNAME # $TODO$ -- add email validation if " " in newUserEmail: logging.error("Invalid email %s while creating user %s" % (newUserEmail, newUserName)) return CREATE_INVALIDEMAIL decryptedPasswd = newUserPassword urandom = open('/dev/urandom') salt = urandom.read(2) urandom.close() newUserPassword = password.sha1_base64_hash(newUserPassword, salt) newSalt = base64.encodestring(salt)[:-1] users[newUserName] = UserData(newUserName, newUserPassword, newSalt, newUserEmail, newUserAccountType, newUserPermissions) self.save_passwd_file(users) if not self.update_vmanage_password(newUserName, newUserPassword, newSalt): logging.error("Error updating vmanager password for user %s" % newUserName) finally: self.updatelock.release() self.sync_password_file() if creatorName: creatorEmail = users[creatorName].email else: creatorEmail = None accountType = users[newUserName].AccountTypePrintName() # and send email, first, to the creator if creatorEmail: SendMail.send( self.cfg, creatorEmail, false, M.MSG_NEWUSERPASSWORDSUBJECT % newUserName, M.MSG_NEWUSERPASSWORD % (newUserName, accountType, newUserEmail, ip, creatorName, creatorEmail), false) # next, to the created rootURI = "http://%s:8000" % self.cfg.getGlobalParam("EXTERNAL_WEB_IP") SendMail.send( self.cfg, newUserEmail, false, M.MSG_WELCOMENEWUSERSUBJECT, M.MSG_WELCOMENEWUSER % (accountType, creatorEmail, newUserName, decryptedPasswd, rootURI, creatorEmail), false) logging.info("User %s [email %s] created OK by %s" % (newUserName, newUserEmail, creatorName)) return CREATE_OK