def DBUpdate(self): try: db = catocommon.new_conn() # if the password has not changed leave it as is. sPasswordUpdate = "" if self.Password and self.Password != "~!@@!~": sPasswordUpdate = ", password = '******'" # same for privileged_password sPriviledgedPasswordUpdate = "" if self.PrivilegedPassword != "~!@@!~": # updated password # priviledged password can be blank, so if it is, set it to null if self.PrivilegedPassword: sPriviledgedPasswordUpdate = ", privileged_password = null" else: sPriviledgedPasswordUpdate = ", privileged_password = '******'" sSQL = "update asset_credential " \ "set username = '******'," \ "domain = '" + self.Domain + "'," \ "shared_or_local = '" + self.SharedOrLocal + "'," \ "shared_cred_desc = '" + catocommon.tick_slash(self.Description) + "'" \ + sPasswordUpdate + sPriviledgedPasswordUpdate + \ "where credential_id = '" + self.ID + "'" if not db.exec_db_noexcep(sSQL): return False, db.error # # add security log # uiCommon.WriteObjectPropertyChangeLog(uiGlobals.CatoObjectTypes.Asset, sAssetID, sAssetName.strip().replace("'", "''") + "Changed credential", sOriginalUserName, sCredUsername) return True, None except Exception, ex: raise ex
def DBCreateNew(self): db = catocommon.new_conn() if not self.Username and not self.PrivateKey: raise Exception("A Credential requires a User Name OR a Private Key.") sPriviledgedPasswordUpdate = catocommon.cato_encrypt(self.PrivilegedPassword) if self.PrivilegedPassword else None # if it's a local credential, the credential_name is the asset_id. # if it's shared, there will be a name. if self.SharedOrLocal == "1": # whack and add - easiest way to avoid conflicts sSQL = "delete from asset_credential where credential_name = %s and shared_or_local = '1'" db.exec_db(sSQL, (self.Name)) sSQL = """insert into asset_credential (credential_id, credential_name, username, password, domain, shared_or_local, shared_cred_desc, privileged_password, private_key) values (%s, %s, %s, %s, %s, %s, %s, %s, %s)""" params = (self.ID, self.Name, self.Username, catocommon.cato_encrypt(self.Password), self.Domain, self.SharedOrLocal, self.Description, sPriviledgedPasswordUpdate, catocommon.cato_encrypt(self.PrivateKey)) if not db.exec_db_noexcep(sSQL, params): if db.error == "key_violation": raise Exception("A Credential with that name already exists. Please select another name.") else: raise Exception(db.error) return True
def DBUpdate(self): db = catocommon.new_conn() # if the password has not changed leave it as is. sPasswordUpdate = "" if self.Password and self.Password != "~!@@!~": sPasswordUpdate = ", password = '******'" # same for privileged_password sPriviledgedPasswordUpdate = "" if self.PrivilegedPassword != "~!@@!~": # updated password # priviledged password can be blank, so if it is, set it to null if self.PrivilegedPassword: sPriviledgedPasswordUpdate = ", privileged_password = null" else: sPriviledgedPasswordUpdate = ", privileged_password = '******'" # same for private key, but a different rule since it's a textarea sPKUpdate = "" if self.PrivateKey != "********": sPKUpdate = ", private_key = '" + catocommon.cato_encrypt(self.PrivateKey) + "'" sSQL = """update asset_credential set credential_name = %s, username = %s, domain = %s, shared_or_local = %s, shared_cred_desc = %s {0} {1} {2} where credential_id = %s""".format(sPasswordUpdate, sPriviledgedPasswordUpdate, sPKUpdate) db.exec_db(sSQL, (self.Name, self.Username, self.Domain, self.SharedOrLocal, self.Description, self.ID)) db.close() return True
def DBCreateNew(sUsername, sFullName, sAuthType, sPassword, sGeneratePW, sForcePasswordChange, sUserRole, sEmail, sStatus, sGroupArray): try: # TODO: All the password testing, etc. db = catocommon.new_conn() sNewID = catocommon.new_guid() if sAuthType == "local": if sPassword: if sPassword: result, msg = User.ValidatePassword(None, sPassword) if result: sEncPW = "'%s'" % catocommon.cato_encrypt(sPassword) else: return None, msg elif catocommon.is_true(sGeneratePW): sEncPW = "'%s'" % catocommon.cato_encrypt(catocommon.generate_password()) else: return None, "A password must be provided, or check the box to generate one." elif sAuthType == "ldap": sEncPW = " null" sSQL = "insert into users" \ " (user_id, username, full_name, authentication_type, force_change, email, status, user_role, user_password)" \ " values ('" + sNewID + "'," \ "'" + sUsername + "'," \ "'" + sFullName + "'," \ "'" + sAuthType + "'," \ "'" + sForcePasswordChange + "'," \ "'" + (sEmail if sEmail else "") + "'," \ "'" + sStatus + "'," \ "'" + sUserRole + "'," \ "" + sEncPW + "" \ ")" if not db.tran_exec_noexcep(sSQL): if db.error == "key_violation": return None, "A User with that Login ID already exists. Please select another." else: return None, db.error db.tran_commit() if sGroupArray: # if we can't create groups we don't actually fail... for tag in sGroupArray: sql = "insert object_tags (object_type, object_id, tag_name) values (1, '%s','%s')" % (sNewID, tag) if not db.exec_db_noexcep(sql): print "Error creating Groups for new user %s." % sNewID # now it's inserted... lets get it back from the db as a complete object for confirmation. u = User() u.FromID(sNewID) u.AddPWToHistory(sEncPW) return u, None except Exception, ex: raise ex
def AddKeyPair(self, name, private_key, passphrase): if not name: return "KeyPair Name is Required." pk_clause = "'%s'" % (catocommon.cato_encrypt(private_key)) if private_key else "" pp_clause = "'%s'" % (catocommon.cato_encrypt(passphrase)) if passphrase else " null" sql = """insert into clouds_keypair (keypair_id, cloud_id, keypair_name, private_key, passphrase) values (%s, %s, %s, {0}, {1})""".format(pk_clause, pp_clause) db = catocommon.new_conn() db.exec_db(sql, (catocommon.new_guid(), self.ID, name)) db.close()
def SaveKeyPair(self, kpid, name, private_key, passphrase): # multiple sqls, but clean and to the point. Happens once in a blue moon so I don't care about performance. db = catocommon.new_conn() if name: sql = """update clouds_keypair set keypair_name = %s where keypair_id = %s""" db.exec_db(sql, (name, kpid)) if private_key: sql = """update clouds_keypair set private_key = %s where keypair_id = %s""" db.exec_db(sql, (catocommon.cato_encrypt(private_key), kpid)) if passphrase != "!2E4S6789O": sql = """update clouds_keypair set passphrase = %s where keypair_id = %s""" db.exec_db(sql, (catocommon.cato_encrypt(passphrase), kpid)) db.close()
def SetNodeText(self, xpath, value, encrypt): try: if self.xml_tree is None: return False, "Registry object has no xml document." # if the xpath is "registry" or "" ... can't delete the root element if xpath == "registry" or xpath == "": return False, "Cannot set text on the root registry element." x_to_set = self.xml_tree.find(xpath) if x_to_set is not None: # setting the text on an element clears any children # we don't allow mixed content x_to_set.clear() # should we encrypt if catocommon.is_true(encrypt): value = catocommon.cato_encrypt(value) #encrypting also sets an attribute defining the data as such x_to_set.set("encrypt", encrypt) x_to_set.text = (value.replace("\\","\\\\") if value is not None else "") # update the xml_text in case we intend to keep using this object self.xml_text = ET.tostring(self.xml_tree) result, msg = self.DBSave() if not result: return False, msg else: return False, "Unable to update - path [%s] was not found in registry." % xpath return True, "" except Exception, ex: raise Exception(ex)
def DBCreateNew(self): try: db = catocommon.new_conn() sPriviledgedPasswordUpdate = "" if self.PrivilegedPassword: sPriviledgedPasswordUpdate = "NULL" else: sPriviledgedPasswordUpdate = "'" + catocommon.cato_encrypt(self.PrivilegedPassword) + "'" # if it's a local credential, the credential_name is the asset_id. # if it's shared, there will be a name. if self.SharedOrLocal == "1": # whack and add - easiest way to avoid conflicts sSQL = "delete from asset_credential where credential_name = '%s' and shared_or_local = '1'" % self.Name if not db.exec_db_noexcep(sSQL): return False, db.error sSQL = "insert into asset_credential " \ "(credential_id, credential_name, username, password, domain, shared_or_local, shared_cred_desc, privileged_password) " \ "values ('" + self.ID + "','" + self.Name + "','" + self.Username + "','" + catocommon.cato_encrypt(self.Password) + "','" \ + self.Domain + "','" + self.SharedOrLocal + "','" + self.Description + "'," + sPriviledgedPasswordUpdate + ")" if not db.exec_db_noexcep(sSQL): if db.error == "key_violation": return False, "A Credential with that name already exists. Please select another name." else: return False, db.error # add security log # need to move this function to catocommon # uiCommon.WriteObjectAddLog(uiGlobals.CatoObjectTypes.Credential, sCredentialID, sCredentialName, "") return True, None except Exception, ex: raise ex
def DBSave(self): try: """ The messenger has some special considerations when updating! ($#d@x!& ^^^ can't even use that, it was messing up the web.py templator - do something else """ sSQL = """update messenger_settings set mode_off_on='{0}', loop_delay_sec={1}, retry_delay_min={2}, retry_max_attempts={3}, smtp_server_addr='{4}', smtp_server_user='******', smtp_server_port={6}, from_email='{7}', from_name='{8}', admin_email='{9}'""" # only update password if it has been changed. sPasswordFiller = "~!@@!~" if self.SMTPUserPassword != sPasswordFiller: sSQL += ",smtp_server_password='******'"; sSQL = sSQL.format(("1" if catocommon.is_true(self.Enabled) else "0"), str(self.PollLoop), str(self.RetryDelay), str(self.RetryMaxAttempts), self.SMTPServerAddress, self.SMTPUserAccount, str(self.SMTPServerPort), self.FromEmail, self.FromName, self.AdminEmail, catocommon.cato_encrypt(self.SMTPUserPassword)) db = catocommon.new_conn() if not db.exec_db_noexcep(sSQL): return False, db.error return True, "" except Exception, ex: print ex.__str__() raise Exception(ex)
def ValidatePassword(uid, pwd): """ Checks a password against the system settings for length, complexity, etc. """ s_set = settings.settings.security() # is this password long enough? too long? if len(pwd) < s_set.PassMinLength or len(pwd) > s_set.PassMaxLength: return False, "Password must be between %d and %d characters in length." % (s_set.PassMinLength, s_set.PassMaxLength) # is it complex (if required to be)? if s_set.PassComplexity: if not re.search(r"[A-Z~!@#$%^&?+=]", pwd): return False, "Password must contain at least one capital letter and at least one special character. (~!@#$%^&?+=)" # has it been used lately (if that's required)? # in which case we need to save the old one to history, and delete # any rows over this counter. # this test isn't necessary if no user_id was provided if uid and s_set.PasswordHistory: db = catocommon.new_conn() sql = """select password from user_password_history where user_id = '%s' order by change_time desc limit %d""" % (uid, s_set.PasswordHistory) previous_pwds = db.select_csv(sql, False) if previous_pwds: if catocommon.cato_encrypt(pwd) in previous_pwds: return False, "That password cannot yet be reused." db.close() return True, None
def DBUpdate(self): db = catocommon.new_conn() # only update the passwword if it has changed sNewPassword = "" if self.LoginPassword != "($%#d@x!&": sNewPassword = (", login_password = '******'" if self.LoginPassword else "") sSQL = "update cloud_account set" \ " account_name = '" + self.Name + "'," \ " account_number = '" + self.AccountNumber + "'," \ " provider = '" + self.Provider.Name + "'," \ " default_cloud_id = '" + self.DefaultCloud.ID + "'," \ " is_default = '" + ("1" if self.IsDefault else "0") + "'," \ " auto_manage_security = 0," \ " login_id = '" + self.LoginID + "'" + \ sNewPassword + \ " where account_id = '" + self.ID + "'" if not db.exec_db_noexcep(sSQL): if db.error == "key_violation": raise InfoException("A Cloud Account with that name already exists. Please select another name.") else: raise Exception(db.error) # if "default" was selected, unset all the others if self.IsDefault: sSQL = "update cloud_account set is_default = 0 where account_id <> %s" # not worth failing... we'll just end up with two defaults. db.exec_db_noexcep(sSQL, (self.ID)) db.close() return True
def GET(self): args = web.input() db = catocommon.new_conn() out = [] out.append("Configuring Cato...\n\n") # should we create the Administrator account msg = "Administrator Account:" out.append(msg) logger.info(msg) sql = "select count(*) from users where username = '******'" cnt = db.select_col_noexcep(sql) if not cnt: msg = " Configuring Administrator account..." out.append(msg) logger.info(msg) pw = catocommon.cato_encrypt("password") sql = """INSERT INTO users (user_id, username, full_name, status, authentication_type, failed_login_attempts, force_change, email, user_role, user_password) VALUES ( '0002bdaf-bfd5-4b9d-82d1-fd39c2947d19','administrator','Administrator',1,'local',0,1,'','Administrator',%s )""" db.exec_db_noexcep(sql, (pw)) sql = """INSERT INTO user_password_history (user_id, change_time, password) VALUES ('0002bdaf-bfd5-4b9d-82d1-fd39c2947d19',now(),%s)""" db.exec_db_noexcep(sql, (pw)) msg = " ... done." out.append(msg) logger.info(msg) else: msg = " ... exists ... not changing." out.append(msg) logger.info(msg) # should we create AWS clouds? if catocommon.is_true(args.get("createclouds")): from catocloud import cloud msg = "Checking Static Clouds..." out.append(msg) logger.info(msg) success = cloud.create_static_clouds() if success: msg = " ... done." out.append(msg) logger.info(msg) else: msg = " Errors occurred while creating Clouds. Please check the REST API logfile for details." out.append(msg) logger.info(msg) db.close() out.append("\n") return "\n".join(out)
def DBCreateNew(sAccountName, sAccountNumber, sProvider, sLoginID, sLoginPassword, sIsDefault): try: db = catocommon.new_conn() # if there are no rows yet, make this one the default even if the box isn't checked. if sIsDefault == "0": iExists = -1 sSQL = "select count(*) as cnt from cloud_account" iExists = db.select_col_noexcep(sSQL) if iExists == None: if db.error: db.tran_rollback() return None, "Unable to count Cloud Accounts: " + db.error if iExists == 0: sIsDefault = "1" sNewID = catocommon.new_guid() sPW = (catocommon.cato_encrypt(sLoginPassword) if sLoginPassword else "") sSQL = "insert into cloud_account" \ " (account_id, account_name, account_number, provider, is_default, login_id, login_password, auto_manage_security)" \ " values ('" + sNewID + "'," \ "'" + sAccountName + "'," \ "'" + sAccountNumber + "'," \ "'" + sProvider + "'," \ "'" + sIsDefault + "'," \ "'" + sLoginID + "'," \ "'" + sPW + "'," \ "0)" if not db.tran_exec_noexcep(sSQL): if db.error == "key_violation": sErr = "A Cloud Account with that name already exists. Please select another name." return None, sErr else: return None, db.error # if "default" was selected, unset all the others if sIsDefault == "1": sSQL = "update cloud_account set is_default = 0 where account_id <> '" + sNewID + "'" if not db.tran_exec_noexcep(sSQL): raise Exception(db.error) db.tran_commit() # now it's inserted... lets get it back from the db as a complete object for confirmation. ca = CloudAccount() ca.FromID(sNewID) # yay! return ca, None except Exception, ex: raise ex
def DBCreateNew(sProvider, sAccountName, sLoginID, sLoginPassword, sAccountNumber, sDefaultCloud, sIsDefault="0"): db = catocommon.new_conn() # some sanity checks... # 1) is the provider valid? providers = CloudProviders(include_products=False, include_clouds=False) if sProvider not in providers.iterkeys(): raise InfoException("The specified Provider [%s] is not a valid Cloud Provider." % sProvider) # 2) if given, does the 'default cloud' exist c = Cloud() c.FromName(sDefaultCloud) if not c.ID: raise InfoException("The specified default Cloud [%s] is not defined." % sDefaultCloud) # if there are no rows yet, make this one the default even if the box isn't checked. if sIsDefault == "0": sSQL = "select count(*) as cnt from cloud_account" iExists = db.select_col(sSQL) if not iExists: sIsDefault = "1" sNewID = catocommon.new_guid() sPW = (catocommon.cato_encrypt(sLoginPassword) if sLoginPassword else "") sSQL = """insert into cloud_account (account_id, account_name, account_number, provider, is_default, default_cloud_id, login_id, login_password, auto_manage_security) values ('%s','%s','%s','%s','%s','%s','%s','%s',0)""" % (sNewID, sAccountName, sAccountNumber, sProvider, sIsDefault, c.ID, sLoginID, sPW) if not db.tran_exec_noexcep(sSQL): if db.error == "key_violation": raise InfoException("A Cloud Account with that name already exists. Please select another name.") else: raise Exception(db.error) # if "default" was selected, unset all the others if sIsDefault == "1": sSQL = "update cloud_account set is_default = 0 where account_id <> %s" db.tran_exec_noexcep(sSQL, (sNewID)) db.tran_commit() db.close() # now it's inserted... lets get it back from the db as a complete object for confirmation. ca = CloudAccount() ca.FromID(sNewID) # yay! return ca
def DBSave(self): """ The messenger has some special considerations when updating! """ self.Enabled = catocommon.is_true(self.Enabled) self.SMTPLegacySSL = catocommon.is_true(self.SMTPLegacySSL) self.PollLoop = int(self.PollLoop) if str(self.PollLoop).isdigit() else 30 self.RetryDelay = int(self.RetryDelay) if str(self.RetryDelay).isdigit() else 5 self.RetryMaxAttempts = int(self.RetryMaxAttempts) if str(self.RetryMaxAttempts).isdigit() else 3 self.SMTPServerPort = int(self.SMTPServerPort) if str(self.SMTPServerPort).isdigit() else 25 self.SMTPConnectionTimeout = int(self.SMTPConnectionTimeout) if str(self.SMTPConnectionTimeout).isdigit() else 30 # only update password if it has been changed. This "filler" is set in the gui to show stars so ignore it. if self.SMTPUserPassword and self.SMTPUserPassword != "~!@@!~": self.SMTPUserPassword = catocommon.cato_encrypt(self.SMTPUserPassword) # don't put these in the settings, they're utility del self.SMTPPasswordConfirm settings.set_application_section("messenger", json.dumps(self.__dict__)) return True
def ValidatePassword(uid, pwd): """ Checks a password against the system settings for length, complexity, etc. """ try: s_set = settings.settings.security() # is this password long enough? too long? if len(pwd) < s_set.PassMinLength or len(pwd) > s_set.PassMaxLength: return False, "Password must be between %d and %d characters in length." % (s_set.PassMinLength, s_set.PassMaxLength) # is it complex (if required to be)? if s_set.PassComplexity: if not re.search(r"[A-Z~!@#$%^&?+=]", pwd): return False, "Password must contain at least one capital letter and at least one special character. (~!@#$%^&?+=)" # has it been used lately (if that's required)? # in which case we need to save the old one to history, and delete # any rows over this counter. # this test isn't necessary if no user_id was provided if uid and s_set.PasswordHistory: db = catocommon.new_conn() sql = """select password from user_password_history where user_id = '%s' order by change_time desc limit %d""" % (uid, s_set.PasswordHistory) previous_pwds = db.select_csv(sql, False) if previous_pwds: if catocommon.cato_encrypt(pwd) in previous_pwds: return False, "That password cannot yet be reused." db.close() return True, None except Exception, ex: raise Exception(ex)
def DBUpdate(self): try: db = catocommon.new_conn() # only update the passwword if it has changed sNewPassword = "" if self.LoginPassword != "($%#d@x!&": sNewPassword = (", login_password = '******'" if self.LoginPassword else "") sSQL = "update cloud_account set" \ " account_name = '" + self.Name + "'," \ " account_number = '" + self.AccountNumber + "'," \ " provider = '" + self.Provider.Name + "'," \ " is_default = '" + ("1" if self.IsDefault else "0") + "'," \ " auto_manage_security = 0," \ " login_id = '" + self.LoginID + "'" + \ sNewPassword + \ " where account_id = '" + self.ID + "'" if not db.exec_db_noexcep(sSQL): if db.error == "key_violation": sErr = "A Cloud Account with that name already exists. Please select another name." return False, sErr else: return False, db.error # if "default" was selected, unset all the others if self.IsDefault: sSQL = "update cloud_account set is_default = 0 where account_id <> '" + self.ID + "'" # not worth failing... we'll just end up with two defaults. db.exec_db_noexcep(sSQL) return True, None except Exception, ex: raise ex
def CatoEncrypt(s): return catocommon.cato_encrypt(s)
def wmSaveKeyPair(self): try: sKeypairID = uiCommon.getAjaxArg("sKeypairID") sAccountID = uiCommon.getAjaxArg("sAccountID") sName = uiCommon.getAjaxArg("sName") sPK = uiCommon.getAjaxArg("sPK") sPP = uiCommon.getAjaxArg("sPP") if not sName: return "KeyPair Name is Required." sPK = uiCommon.unpackJSON(sPK) bUpdatePK = False if sPK: bUpdatePK = True bUpdatePP = False if sPP and sPP != "!2E4S6789O": bUpdatePP = True if not sKeypairID: # empty id, it's a new one. sPKClause = "" if bUpdatePK: sPKClause = "'" + catocommon.cato_encrypt(sPK) + "'" sPPClause = "null" if bUpdatePP: sPPClause = "'" + catocommon.cato_encrypt(sPP) + "'" sSQL = "insert into cloud_account_keypair (keypair_id, account_id, keypair_name, private_key, passphrase)" \ " values ('" + catocommon.new_guid() + "'," \ "'" + sAccountID + "'," \ "'" + sName.replace("'", "''") + "'," \ + sPKClause + "," \ + sPPClause + \ ")" else: sPKClause = "" if bUpdatePK: sPKClause = ", private_key = '" + catocommon.cato_encrypt(sPK) + "'" sPPClause = "" if bUpdatePP: sPPClause = ", passphrase = '" + catocommon.cato_encrypt(sPP) + "'" sSQL = "update cloud_account_keypair set" \ " keypair_name = '" + sName.replace("'", "''") + "'" \ + sPKClause + sPPClause + \ " where keypair_id = '" + sKeypairID + "'" if not self.db.exec_db_noexcep(sSQL): uiCommon.log(self.db.error) return self.db.error return "" except Exception: uiCommon.log_nouser(traceback.format_exc(), 0) return traceback.format_exc()
def DBCreateNew(username, fullname, role, password, generatepw, authtype="local", forcechange=1, email=None, status=1, expires=None, groups=None): # TODO: All the password testing, etc. db = catocommon.new_conn() # all sorts of validation if re.match("^[\a-zA-Z0-9_.-@]+$", username) is None: raise Exception("Usernames cannot contain spaces or any characters other than letters, numbers or these chars [_.@-].") newid = catocommon.new_guid() authtype = authtype if authtype else "local" forcechange = 0 if forcechange == 0 or forcechange == "0" else 1 email = email if email else "" encpw = None if authtype == "local": if password: result, msg = User.ValidatePassword(None, password) if result: encpw = catocommon.cato_encrypt(password) else: raise Exception(msg) elif catocommon.is_true(generatepw): encpw = catocommon.cato_encrypt(catocommon.generate_password()) else: raise Exception("A password must be provided, or check the box to generate one.") if role not in ("Administrator", "Developer", "User"): raise Exception("Role must be 'Administrator', 'Developer', or 'User'.") pw2insert = "'%s'" % encpw if encpw else " null" ex2insert = ("str_to_date('{0}', '%%m/%%d/%%Y')".format(expires) if expires else " null") sql = """insert into users (user_id, username, full_name, authentication_type, force_change, email, status, user_role, user_password, expiration_dt) values ('%s', '%s', '%s', '%s', %s, '%s', '%s', '%s', %s, %s)""" % (newid, username, fullname, authtype, forcechange, email, status, role, pw2insert, ex2insert) if not db.tran_exec_noexcep(sql): if db.error == "key_violation": raise Exception("A User with that Login ID already exists. Please select another.") else: raise Exception(db.error) db.tran_commit() if groups: # if we can't create groups we don't actually fail... sql = "select group_concat(tag_name order by tag_name separator ',') as tags from tags" alltags = db.select_col_noexcep(sql) if alltags: alltags = alltags.split(",") for tag in groups: if tag in alltags: sql = "insert object_tags (object_type, object_id, tag_name) values (1, '%s','%s')" % (newid, tag) if not db.exec_db_noexcep(sql): logger.error("Error creating Groups for new user %s." % newid) # now it's inserted... lets get it back from the db as a complete object for confirmation. u = User() u.FromID(newid) u.AddPWToHistory(encpw) db.close() return u
def Authenticate(self, login_id, password, client_ip, change_password=None, answer=None): # Some of the failure to authenticate return values pass back a token. # this is so we can know how to prompt the user. # but, to make hacking a little more difficult, we don't return too much detail about # usernames or passwords. if not login_id: return False, "id required" if not password and not answer: return False, "Password required." self.ClientIP = client_ip # alrighty, lets check the password # we do this by encrypting the form submission and comparing, # NOT by decrypting it here. db = catocommon.new_conn() sset = settings.settings.security() self.PopulateUser(login_id=login_id) # These checks happen BEFORE we verify the password # Check for "locked" or "disabled" status if self.Status < 1: return False, "disabled" # Check failed login attempts against the security policy if self.FailedLoginAttempts and sset.PassMaxAttempts: if self.FailedLoginAttempts >= sset.PassMaxAttempts: logger.warning("User.Authenticate : Invalid login attempt - excessive failures.") return False, "failures" # TODO - check if the account is expired # once you've gotten your account locked due to failed attempts, you can no longer # use the forgot password feature. # that's why this happens after that. # forgot password # if an 'answer' was provided, it can serve as an alternate authentication # but it will force a password change. if answer: sql = "select security_answer from users where username='******'" % login_id db_ans = db.select_col_noexcep(sql) encans = catocommon.cato_encrypt(answer) if db_ans == encans: self.ForceChange = True sql = "update users set force_change=1 where user_id='%s'" % self.ID db.exec_db(sql) else: sql = "update users set failed_login_attempts=failed_login_attempts+1 where user_id='%s'" % self.ID db.exec_db(sql) logger.warning("User.Authenticate : Invalid login attempt - [%s] wrong security question answer." % (login_id)) return False, "Incorrect security answer." # try the password if it was provided if password: sql = "select user_password from users where username='******'" % login_id db_pwd = db.select_col_noexcep(sql) encpwd = catocommon.cato_encrypt(password) if db_pwd != encpwd: sql = "update users set failed_login_attempts=failed_login_attempts+1 where user_id='%s'" % self.ID db.exec_db(sql) logger.warning("User.Authenticate : Invalid login attempt - [%s] bad password." % (login_id)) return False, "" # TODO: # Check Expiration coming up - for a warning # force change # the user authenticated, but they are required to change their password if self.ForceChange: if change_password: # a new password was provided result, msg = User.ValidatePassword(self.ID, change_password) if not result: return False, msg # put it in the history self.AddPWToHistory(change_password) # and update with the new one sql = "update users set force_change=0, user_password=%s where user_id=%s" db.exec_db(sql, (catocommon.cato_encrypt(change_password), self.ID)) else: return False, "change" self._create_user_session() db.close() return True, ""
def ChangePassword(self, new_password=None, generate=False, force_change=True): """ Updating a user password is a different function with extra rules, so it's kept separate from the DBUpdate function. You cannot explicitly change a password, AND do the Generate function, so if a password is set it'll use it and continue, otherwise it'll generate. """ if not new_password and not self.Email: raise InfoException("Unable to generate a random password - User [%s] does not have an email address defined." % (self.FullName)) if not new_password and not generate: raise InfoException("Unable to reset password - New password is required or random generation option must be specified.") return False # TODO: maybe have a setting for the application url in the email? # TODO: should have the ability to use a configurable "company" name in the email db = catocommon.new_conn() # only do the password if _NewPassword exists on the object. # NOTE: no function that inits a user will set a password property, so it must've been set explicitly if new_password: logger.info("Updating password for User [%s]" % (self.FullName)) result, msg = User.ValidatePassword(self.ID, new_password) if result: sql = "update users set user_password = %s where user_id = %s" db.exec_db(sql, (catocommon.cato_encrypt(new_password), self.ID)) # this flag can be reset from the calling function at it's discretion. # for example, if the user making the request IS the user being changed, # which we don't know at this point. if not force_change: sql = "update users set force_change = 0 where user_id = %s" db.exec_db(sql, (self.ID)) body = """%s - your password has been reset by an Administrator.""" % (self.FullName) if self.Email: catocommon.send_email_via_messenger(self.Email, "Cloud Sidekick - Account Information", body) else: logger.warning("Attempt to send a password message failed - User [%s] has no email defined." % (self.FullName)) else: raise InfoException(msg) # Here's something special... # If the arg "_NewRandomPassword" was provided and is true... # Generate a new password and send out an email. # IF for some reason this AND a password were provided, it means someone is hacking # (We don't do both of them at the same time.) # so the provided one takes precedence. if generate: logger.info("Generating a new password for User [%s]" % (self.FullName)) sNewPassword = catocommon.generate_password() sql = "update users set force_change = 1, user_password = %s where user_id = %s" db.exec_db(sql, (catocommon.cato_encrypt(sNewPassword), self.ID)) s_set = settings.settings.security() body = s_set.NewUserMessage if not body: body = """%s - your password has been reset by an Administrator.\n\n Your temporary password is: %s.""" % (self.FullName, sNewPassword) # replace our special tokens with the values body = body.replace("##FULLNAME##", self.FullName).replace("##USERNAME##", self.LoginID).replace("##PASSWORD##", sNewPassword) if self.Email: catocommon.send_email_via_messenger(self.Email, "Cloud Sidekick - Account Information", body) else: logger.warning("Attempt to send a password message failed - User [%s] has no email defined." % (self.FullName)) # f !uiCommon.SendEmailMessage(sEmail.strip(), ag.APP_COMPANYNAME + " Account Management", "Account Action in " + ag.APP_NAME, sBody, 0000BYREF_ARG0000sErr: db.close() return True
def wmSaveKeyPair(self): try: sKeypairID = uiCommon.getAjaxArg("sKeypairID") sAccountID = uiCommon.getAjaxArg("sAccountID") sName = uiCommon.getAjaxArg("sName") sPK = uiCommon.getAjaxArg("sPK") sPP = uiCommon.getAjaxArg("sPP") if not sName: return "KeyPair Name is Required." sPK = uiCommon.unpackJSON(sPK) bUpdatePK = False if sPK: bUpdatePK = True bUpdatePP = False if sPP and sPP != "!2E4S6789O": bUpdatePP = True if not sKeypairID: # empty id, it's a new one. sPKClause = "" if bUpdatePK: sPKClause = "'" + catocommon.cato_encrypt(sPK) + "'" sPPClause = "null" if bUpdatePP: sPPClause = "'" + catocommon.cato_encrypt(sPP) + "'" sSQL = "insert into cloud_account_keypair (keypair_id, account_id, keypair_name, private_key, passphrase)" \ " values ('" + catocommon.new_guid() + "'," \ "'" + sAccountID + "'," \ "'" + sName.replace("'", "''") + "'," \ + sPKClause + "," \ + sPPClause + \ ")" else: sPKClause = "" if bUpdatePK: sPKClause = ", private_key = '" + catocommon.cato_encrypt( sPK) + "'" sPPClause = "" if bUpdatePP: sPPClause = ", passphrase = '" + catocommon.cato_encrypt( sPP) + "'" sSQL = "update cloud_account_keypair set" \ " keypair_name = '" + sName.replace("'", "''") + "'" \ + sPKClause + sPPClause + \ " where keypair_id = '" + sKeypairID + "'" if not self.db.exec_db_noexcep(sSQL): uiCommon.log(self.db.error) return self.db.error return "" except Exception: uiCommon.log_nouser(traceback.format_exc(), 0) return traceback.format_exc()
def Authenticate(self, login_id, password, change_password=None, answer=None): try: # Some of the failure to authenticate return values pass back a token. # this is so we can know how to prompt the user. # but, to make hacking a little more difficult, we don't return too much detail about # usernames or passwords. # alrighty, lets check the password # we do this by encrypting the form submission and comparing, # NOT by decrypting it here. db = catocommon.new_conn() sset = settings.settings.security() self.PopulateUser(login_id=login_id) if not self.ID: print "User.Authenticate : Unable to find user record for [%s]." % login_id return False, "" # These checks happen BEFORE we verify the password # Check for "locked" or "disabled" status if self.Status < 1: return False, "disabled" # Check failed login attempts against the security policy if self.FailedLoginAttempts and sset.PassMaxAttempts: if self.FailedLoginAttempts >= sset.PassMaxAttempts: print "User.Authenticate : Invalid login attempt - excessive failures." return False, "failures" # TODO - check if the account is expired # once you've gotten your account locked due to failed attempts, you can no longer # use the forgot password feature. # that's why this happens after that. db = catocommon.new_conn() # forgot password # if an 'answer' was provided, it can serve as an alternate authentication # but it will force a password change. if answer: sql = "select security_answer from users where username='******'" % login_id db_ans = db.select_col_noexcep(sql) encans = catocommon.cato_encrypt(answer) if db_ans == encans: self.ForceChange = True sql = "update users set force_change=1 where user_id='%s'" % self.ID if not db.exec_db_noexcep(sql): print db.error else: sql = "update users set failed_login_attempts=failed_login_attempts+1 where user_id='%s'" % self.ID if not db.exec_db_noexcep(sql): print db.error print "User.Authenticate : Invalid login attempt - [%s] wrong security question answer." % (login_id) return False, "Incorrect security answer." # try the password if it was provided if password: sql = "select user_password from users where username='******'" % login_id db_pwd = db.select_col_noexcep(sql) encpwd = catocommon.cato_encrypt(password) if db_pwd != encpwd: sql = "update users set failed_login_attempts=failed_login_attempts+1 where user_id='%s'" % self.ID if not db.exec_db_noexcep(sql): print db.error print "User.Authenticate : Invalid login attempt - [%s] bad password." % (login_id) return False, "" # TODO: # Check Expiration coming up - for a warning # force change # the user authenticated, but they are required to change their password change_clause = "" if self.ForceChange: if change_password: # a new password was provided result, msg = User.ValidatePassword(self.ID, change_password) if not result: return False, msg # put it in the history self.AddPWToHistory(change_password) # and update with the new one change_clause = ",force_change=0, user_password='******'" % catocommon.cato_encrypt(change_password) else: return False, "change" # ALL GOOD! # reset the user counters and last_login sql = "update users set failed_login_attempts=0, last_login_dt=now() %s where user_id='%s'" % (change_clause, self.ID) if not db.exec_db_noexcep(sql): print db.error return True, "" except Exception, ex: print ex.__str__() return False, ex.__str__()