diff --git a/CyberCP/secMiddleware.py b/CyberCP/secMiddleware.py index dcf498c22..86b2f14fe 100644 --- a/CyberCP/secMiddleware.py +++ b/CyberCP/secMiddleware.py @@ -207,7 +207,8 @@ class secMiddleware: final_json = json.dumps(final_dic) return HttpResponse(final_json) continue - if key == 'MainDashboardCSS' or key == 'ownerPassword' or key == 'scriptUrl' or key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' \ + # Allow dbPassword to contain special characters for stronger database passwords (create DB / change password) + if key == 'MainDashboardCSS' or key == 'ownerPassword' or key == 'dbPassword' or key == 'scriptUrl' or key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' \ or key == 'non_smtpd_milters' or key == 'key' or key == 'cert' or key == 'recordContentAAAA' or key == 'backupDestinations'\ or key == 'ports' \ or key == 'imageByPass' or key == 'passwordByPass' or key == 'PasswordByPass' or key == 'cronCommand' \ diff --git a/patches/allow-dbpassword-special-chars.patch b/patches/allow-dbpassword-special-chars.patch new file mode 100644 index 000000000..d4646f652 --- /dev/null +++ b/patches/allow-dbpassword-special-chars.patch @@ -0,0 +1,11 @@ +--- a/CyberCP/secMiddleware.py ++++ b/CyberCP/secMiddleware.py +@@ -214,7 +214,8 @@ class secMiddleware: + return HttpResponse(final_json) + continue +- if key == 'MainDashboardCSS' or key == 'ownerPassword' or key == 'scriptUrl' or key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' \ ++ # Allow dbPassword to contain special characters for stronger database passwords (create DB / change password) ++ if key == 'MainDashboardCSS' or key == 'ownerPassword' or key == 'dbPassword' or key == 'scriptUrl' or key == 'CLAMAV_VIRUS' or key == "Rspamdserver" or key == 'smtpd_milters' \ + or key == 'non_smtpd_milters' or key == 'key' or key == 'cert' or key == 'recordContentAAAA' or key == 'backupDestinations'\ + or key == 'ports' \ + or key == 'imageByPass' or key == 'passwordByPass' or key == 'PasswordByPass' or key == 'cronCommand' \ diff --git a/plogical/Backupsv2.py b/plogical/Backupsv2.py index f07148fe1..25f29f7a3 100644 --- a/plogical/Backupsv2.py +++ b/plogical/Backupsv2.py @@ -923,7 +923,7 @@ team_drive = logging.CyberCPLogFileWriter.writeToFile('Database did not exist, creating new.. %s' % (dbName)) - if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") == 0: + if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") != 1: logging.CyberCPLogFileWriter.writeToFile('Failed the creation of database: %s' % (dbName)) else: logging.CyberCPLogFileWriter.writeToFile('Database: %s successfully created.' % (dbName)) diff --git a/plogical/backupUtilities.py b/plogical/backupUtilities.py index bfb0eb5a9..a1e8dd944 100644 --- a/plogical/backupUtilities.py +++ b/plogical/backupUtilities.py @@ -748,7 +748,7 @@ class backupUtilities: dbUser = databaseUser.find('dbUser').text res = mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, 'cyberpanel') - if res == 0: + if res != 1: logging.CyberCPLogFileWriter.writeToFile( 'Failed to restore database %s. But it can be false positive, moving on..' % (dbName)) @@ -759,7 +759,7 @@ class backupUtilities: else: dbUser = database.find('dbUser').text - if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") == 0: + if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") != 1: raise BaseException newDB = Databases(website=website, dbName=dbName, dbUser=dbUser) @@ -2135,7 +2135,7 @@ class backupUtilities: mysqlUtilities.mysqlUtilities.submitDBDeletion(db['databaseName']) - if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") == 0: + if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") != 1: raise BaseException("Failed to create Databases!") newDB = Databases(website=self.website, dbName=db['databaseName'], dbUser=db['databaseUser']) @@ -2340,7 +2340,7 @@ class backupUtilities: mysqlUtilities.mysqlUtilities.submitDBDeletion(db['databaseName']) - if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") == 0: + if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") != 1: raise BaseException("Failed to create Databases!") newDB = Databases(website=self.website, dbName=db['databaseName'], dbUser=db['databaseUser']) diff --git a/plogical/mysqlUtilities.py b/plogical/mysqlUtilities.py index 92eef09f8..14eeca6f3 100644 --- a/plogical/mysqlUtilities.py +++ b/plogical/mysqlUtilities.py @@ -119,31 +119,33 @@ class mysqlUtilities: connection, cursor = mysqlUtilities.setupConnection() if connection == 0: - return 0 + return 0, "Could not connect to MySQL." if dbcreate == 1: HostToUse = mysqlUtilities.LOCALHOST else: HostToUse = host - ## Create db + ## Escape password and user for use in SQL single-quoted strings + _pw = str(dbpassword).replace('\\', '\\\\').replace("'", "''") + _user_quoted = "'" + str(dbuser).replace("'", "''") + "'" + ## Backtick-quote database name so names with hyphens work (e.g. my-admin) + _db = '`' + str(dbname).replace('`', '``') + '`' if dbcreate: - query = "CREATE DATABASE %s" % (dbname) + query = "CREATE DATABASE " + _db if os.path.exists(ProcessUtilities.debugPath): logging.CyberCPLogFileWriter.writeToFile(query) cursor.execute(query) - ## create user - + ## create user (user and password in single-quoted strings, escaped) if mysqlUtilities.REMOTEHOST.find('ondigitalocean') > -1: - query = "CREATE USER '%s'@'%s' IDENTIFIED WITH mysql_native_password BY '%s'" % ( - dbuser, HostToUse, dbpassword) + query = "CREATE USER " + _user_quoted + "@'%s' IDENTIFIED WITH mysql_native_password BY '%s'" % ( + HostToUse, _pw) else: - query = "CREATE USER '" + dbuser + "'@'%s' IDENTIFIED BY '" % ( - HostToUse) + dbpassword + "'" + query = "CREATE USER " + _user_quoted + "@'%s' IDENTIFIED BY '%s'" % (HostToUse, _pw) if os.path.exists(ProcessUtilities.debugPath): logging.CyberCPLogFileWriter.writeToFile(query) @@ -151,14 +153,14 @@ class mysqlUtilities: cursor.execute(query) if mysqlUtilities.RDS == 0: - cursor.execute("GRANT ALL PRIVILEGES ON " + dbname + ".* TO '" + dbuser + "'@'%s'" % (HostToUse)) + cursor.execute("GRANT ALL PRIVILEGES ON " + _db + ".* TO " + _user_quoted + "@'%s'" % (HostToUse)) if os.path.exists(ProcessUtilities.debugPath): - logging.CyberCPLogFileWriter.writeToFile("GRANT ALL PRIVILEGES ON " + dbname + ".* TO '" + dbuser + "'@'%s'" % (HostToUse)) + logging.CyberCPLogFileWriter.writeToFile("GRANT ALL PRIVILEGES ON " + _db + ".* TO " + _user_quoted + "@'%s'" % (HostToUse)) else: cursor.execute( - "GRANT INDEX, DROP, UPDATE, ALTER, CREATE, SELECT, INSERT, DELETE ON " + dbname + ".* TO '" + dbuser + "'@'%s'" % (HostToUse)) + "GRANT INDEX, DROP, UPDATE, ALTER, CREATE, SELECT, INSERT, DELETE ON " + _db + ".* TO " + _user_quoted + "@'%s'" % (HostToUse)) if os.path.exists(ProcessUtilities.debugPath): - logging.CyberCPLogFileWriter.writeToFile("GRANT INDEX, DROP, UPDATE, ALTER, CREATE, SELECT, INSERT, DELETE ON " + dbname + ".* TO '" + dbuser + "'@'%s'" % (HostToUse)) + logging.CyberCPLogFileWriter.writeToFile("GRANT INDEX, DROP, UPDATE, ALTER, CREATE, SELECT, INSERT, DELETE ON " + _db + ".* TO " + _user_quoted + "@'%s'" % (HostToUse)) connection.close() @@ -169,8 +171,9 @@ class mysqlUtilities: if os.path.exists(ProcessUtilities.debugPath): logging.CyberCPLogFileWriter.writeToFile('Deleting database because failed to create %s' % (dbname)) #mysqlUtilities.deleteDatabase(dbname, dbuser) - logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[createDatabase]") - return 0 + err_msg = str(msg) + logging.CyberCPLogFileWriter.writeToFile(err_msg + "[createDatabase]") + return 0, err_msg @staticmethod def createDBUser(dbuser, dbpassword): @@ -477,7 +480,8 @@ password=%s if result == 1: pass else: - raise BaseException(result) + err_msg = result[1] if isinstance(result, (list, tuple)) and len(result) > 1 else str(result) + raise BaseException(err_msg) db = Databases(website=website, dbName=dbName, dbUser=dbUsername) db.save() diff --git a/plogical/restoreMeta.py b/plogical/restoreMeta.py index df8ce82ed..06c382086 100644 --- a/plogical/restoreMeta.py +++ b/plogical/restoreMeta.py @@ -144,7 +144,7 @@ class restoreMeta(): logging.statusWriter(statusPath, 'Database did not exist, creating new.. %s' % (dbName)) - if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") == 0: + if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") != 1: logging.statusWriter(statusPath, 'Failed the creation of database: %s' % (dbName)) else: logging.statusWriter(statusPath, 'Database: %s successfully created.' % (dbName))