From 2700e1d081d78a3c280cd3ef68b39032b305425c Mon Sep 17 00:00:00 2001 From: John Klug Date: Tue, 10 Dec 2019 18:24:23 -0600 Subject: Improved Security with passwords read from stdin, length limited user-id --- www/commission/index.php | 133 +++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/www/commission/index.php b/www/commission/index.php index 3e87e7a..ef8b68d 100644 --- a/www/commission/index.php +++ b/www/commission/index.php @@ -27,7 +27,7 @@ openlog("Commission:", LOG_PID | LOG_PERROR, LOG_LOCAL0); // uid number must be 1000 or larger. function chk_username($userid) { - $cmd = "/usr/bin/id -u " . $userid . " 2>/dev/null"; + $cmd = "/usr/bin/id -u \"" . $userid . "\" 2>/dev/null"; syslog(LOG_ALERT, "/usr/bin/id cmd: $cmd"); $handle = popen($cmd, 'r'); $result = trim(fread($handle, 4192)); @@ -59,16 +59,22 @@ if($_SERVER["REQUEST_METHOD"] == "POST"){ goto err_exit; } - $save_password = trim($_POST["save_password"]); + $save_password = $_POST["save_password"]; syslog(LOG_ALERT, "Enter post: save_password = $save_password"); + $username = trim($_POST["username"]); + $userlen = strlen($username); // Validate username - if(strlen(trim($_POST["username"])) == 0){ + // Be generous on the character length of the username + // in case it is some kind of character encoding scheme. + // useradd should catch it if the length is a little off. + if($userlen == 0) { $username_err = "Please enter a username."; + } elseif ($userlen > 80) { + $username_err = "mLinux username must not exceed 32 characters"; } else { - $username = trim($_POST["username"]); syslog(LOG_ALERT, "Enter username check: $username"); $id = chk_username($username); syslog(LOG_ALERT, "after username check: chk_username $id"); @@ -77,26 +83,45 @@ if($_SERVER["REQUEST_METHOD"] == "POST"){ } } - // Validate password - if(strlen(trim($_POST["password"])) == 0){ + // Validate password. Password length is not set in + // Linux. It depends on how much memory we have. + // To avoid unknown issues, reject if > 4096 + $tmpfile = tempnam("/var/volatile/tmp","commission"); + $password = $_POST["password"]; + $passlen = strlen($password); + $save_passwordlen = strlen($save_password); + syslog(LOG_ALERT, "passlen: $passlen, save_password len: $save_passwordlen"); + syslog(LOG_ALERT, "password: $password, save_password: $save_password"); + if ($passlen == 0) { $password_err = "Please enter a password."; $mismatch = 0; + } elseif ($passlen > 4096) { + $password_err = "Too long. Limit password length to 4096 characters"; + $password = ""; + } else { - $password = trim($_POST["password"]); - if (strlen($save_password) == 0) { + if ($save_passwordlen === 0) { $mismatch = 0; - $cmd = "echo '" . $password . "' | /usr/bin/pwscore 2>&1"; - $handle = popen($cmd, 'r'); - $result = trim(fread($handle,4192)); - if (pclose($handle) === 0) { - $pwdscore = "Password score: " . $result; + $cmd = "/usr/bin/pwscore >$tmpfile 2>&1"; + $handle = popen($cmd, 'w'); + fwrite($handle,$password); + $status = pclose($handle); + + $result2 = file_get_contents($tmpfile); + if (strlen($result2) > 0) + syslog(LOG_ALERT, "read pwscore log: status: $status result: $result2"); + else + syslog(LOG_ALERT, "pwscore has no results!"); + + if ($status === 0) { + $pwdscore = "Password score: " . $result2; $save_password = $password; $password = ""; $conftxt = "Re-Enter"; } else { $conftxt = "Re-Enter"; - $password_err = $result . - ". Confirm password if you really want this." . + $password_err = $result2 . + " Confirm password if you really want this." . " Click reset to start again"; $save_password = $password; $password = ""; @@ -106,19 +131,24 @@ if($_SERVER["REQUEST_METHOD"] == "POST"){ } } - if ((strlen($password) != 0) && ($password === $save_password) && (strlen($username) != 0)) { - syslog(LOG_ALERT, "Have password: $password username: $password"); + if (($passlen != 0) && ($password === $save_password)) + $mismatch = 0; + + if (($mismatch === 0) && ($passlen > 0) && ($save_passwordlen > 0)) { + syslog(LOG_ALERT, "Have password: $password username: $username"); if((strlen($username_err) == 0) && (strlen($password_err) == 0) && (strlen($confirm_password_err) == 0)){ // Create user in sudo group - $cmd = "/usr/sbin/useradd -U -m -G sudo,dialout,disk -s /bin/bash " . $username . " 2>&1"; + $cmd = "/usr/sbin/useradd -U -m -G sudo,dialout,disk -s /bin/bash -- \"" . $username . "\" 2>&1"; syslog(LOG_ALERT, "useradd cmd: $cmd"); $handle = popen($cmd, 'r'); $username_err = trim(fread($handle, 4192)); $status = pclose($handle); syslog(LOG_ALERT, "useradd: status: $status result: $result"); $uid = chk_username($username); - $cmd = "/usr/bin/id " . $username . " 2>/dev/null"; - if (! ($uid > 999)) { + if ($uid === -1) { + syslog(LOG_ALERT, "useradd: $status"); + goto err_exit; + } elseif (! ($uid > 999)) { syslog(LOG_ALERT, "useradd: system user-id cannot be chosen: $username uid: $uid"); $username_err = "useradd: system user-id cannot be chosen: $username uid: $uid"; $username = ""; @@ -126,29 +156,38 @@ if($_SERVER["REQUEST_METHOD"] == "POST"){ $password = ""; goto err_exit; } // Must have uid > 999 - $tmpfile = tempnam("/var/volatile/tmp","commission"); - $cmd = "/usr/bin/passwd " . $username . " 2>&1 >$tmpfile"; + $cmd = "/usr/bin/passwd \"" . $username . "\" 2>&1 >$tmpfile"; $handle = popen($cmd, 'w'); $pwdtxt = $password . "\n" . $password; fwrite($handle, $pwdtxt); $status = pclose($handle); syslog(LOG_ALERT, "set passwd: status: $status result: $result"); - $cmd = "/bin/cat $tmpfile"; - $handle = popen($cmd, 'r'); - $result2 = trim(fread($handle, 4192)); - $status2 = pclose($handle); - if (($result2 != 0) || (strlen($result2) > 0)) - syslog(LOG_ALERT, "read passwd log: status: $status2 result: $result2"); + $result2 = file_get_contents($tmpfile); + if (strlen($result2) > 0) { + syslog(LOG_ALERT, "passwd log: status: $status2 result: $result2"); + } + + $cmd = "/sbin/mts-ubpasswd -up >$tmpfile 2>&1"; + $handle = popen($cmd, 'w'); + fwrite($handle,$password); + $status = pclose($handle); + + $result3 = file_get_contents($tmpfile); - $cmd = "/sbin/mts-ubpasswd -u " . $password; - $handle = popen($cmd, 'r'); - $result3 = trim(fread($handle, 4192)); - $status3 = pclose($handle); - if ($status != 0) - syslog(LOG_ALERT, "mts-ubpasswd: status: $status result: $result"); - else + // Delete the password entry log + $handle = fopen($tmpfile, 'w'); + ftruncate($handle,0); + fclose($handle); + + if (strlen($result2) > 0) + syslog(LOG_ALERT, "read mts-ubpasswd log: result: $result2"); + + if ($status != 0) { + syslog(LOG_ALERT, "mts-ubpasswd failed: status: $status"); + syslog(LOG_ALERT, "mts-ubpasswd failed: result: $result3"); + } else // Dont print if successful or password is in the log. syslog(LOG_ALERT, "mts-ubpasswd: set u-boot password"); if ($status == 0) { @@ -156,25 +195,19 @@ if($_SERVER["REQUEST_METHOD"] == "POST"){ $password_err = $result2; $username_err = $result; // Disable commissioning - $cmd = "echo 'ENABLED=\"no\"' >/run/mt-commission 2>&1"; + $data = 'ENABLED=\"no\"'; + file_put_contents("/run/mt-commission",$data); + + // shut off web server + $cmd = "/usr/sbin/start-stop-daemon -S -p /var/run/commissionoff.pid -b -a /bin/bash -- -c " . + "/usr/libexec/commission/off.sh"; + syslog(LOG_ALERT, "turn off web server: command: $cmd"); $handle = popen($cmd, 'r'); $result = trim(fread($handle, 4192)); $status = pclose($handle); if ($status > 0) { - syslog(LOG_ALERT, "configure commissioning off failure: command: $cmd"); - syslog(LOG_ALERT, "passwd: status: $status result: $result"); - } else { - // shut off web server - $cmd = "/usr/sbin/start-stop-daemon -S -p /var/run/commissionoff.pid -b -a /bin/bash -- -c " . - "/usr/libexec/commission/off.sh"; - syslog(LOG_ALERT, "turn off web server: command: $cmd"); - $handle = popen($cmd, 'r'); - $result = trim(fread($handle, 4192)); - $status = pclose($handle); - if ($status > 0) { - syslog(LOG_ALERT, "turn off commissioning service: command: $cmd"); - syslog(LOG_ALERT, "stopping service: status: $status result: $result"); - } + syslog(LOG_ALERT, "turn off commissioning service: command: $cmd"); + syslog(LOG_ALERT, "stopping service: status: $status result: $result"); } } else { $finished = "Errors: " . $result; -- cgit v1.2.3