Database create: allow special chars in password, return real errors, safe SQL

- secMiddleware: allow dbPassword to bypass strict char check (stronger passwords)
- mysqlUtilities.createDatabase: return (0, error_message) on failure so UI shows real error instead of '0'
- mysqlUtilities.createDatabase: backtick-quote db name (fix 'near -admin' with hyphens), escape password and user for SQL
- submitDBCreation: pass through error message from createDatabase
- backupUtilities, Backupsv2, restoreMeta: treat createDatabase != 1 as failure (tuple return)
- patches/allow-dbpassword-special-chars.patch for secMiddleware deploy
This commit is contained in:
master3395
2026-03-13 23:36:19 +01:00
parent 17d1eb55e0
commit cc0a002fd6
6 changed files with 39 additions and 23 deletions

View File

@@ -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' \

View File

@@ -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' \

View File

@@ -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))

View File

@@ -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'])

View File

@@ -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()

View File

@@ -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))