diff options
author | Lukas Fleischer <archlinux@cryptocrack.de> | 2014-06-03 16:37:50 +0200 |
---|---|---|
committer | Lukas Fleischer <archlinux@cryptocrack.de> | 2014-12-27 12:42:12 +0100 |
commit | 253e76d8cc718acef6bab802c76c4a70623b59cc (patch) | |
tree | df58aad0e2846690f12a23b56e1a5472602d6721 | |
parent | 1af375828f7c4ef11e63e09e1070a9f77b679d71 (diff) | |
download | aur-253e76d8cc718acef6bab802c76c4a70623b59cc.tar.gz aur-253e76d8cc718acef6bab802c76c4a70623b59cc.tar.xz |
Add support for adding SSH public keys to profiles
Users can now add an SSH public key on the account edit page. This will
later be used to authenticate users via SSH.
Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de>
-rw-r--r-- | schema/aur-schema.sql | 1 | ||||
-rw-r--r-- | upgrading/4.0.0.txt | 5 | ||||
-rw-r--r-- | web/html/account.php | 5 | ||||
-rw-r--r-- | web/lib/acctfuncs.inc.php | 78 | ||||
-rw-r--r-- | web/template/account_edit_form.php | 5 |
5 files changed, 85 insertions, 9 deletions
diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 9c57683b..dfd158fd 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -33,6 +33,7 @@ CREATE TABLE Users ( LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', IRCNick VARCHAR(32) NOT NULL DEFAULT '', PGPKey VARCHAR(40) NULL DEFAULT NULL, + SSHPubKey VARCHAR(4096) NULL DEFAULT NULL, LastLogin BIGINT UNSIGNED NOT NULL DEFAULT 0, LastLoginIPAddress INTEGER UNSIGNED NOT NULL DEFAULT 0, InactivityTS BIGINT UNSIGNED NOT NULL DEFAULT 0, diff --git a/upgrading/4.0.0.txt b/upgrading/4.0.0.txt new file mode 100644 index 00000000..543fbac9 --- /dev/null +++ b/upgrading/4.0.0.txt @@ -0,0 +1,5 @@ +1. Add a field for the SSH public key to the Users table: + +---- +ALTER TABLE Users ADD COLUMN SSHPubKey VARCHAR(4096) NULL DEFAULT NULL; +---- diff --git a/web/html/account.php b/web/html/account.php index c1a1cd7c..3dc8ef01 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -59,7 +59,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form("UpdateAccount", $row["Username"], $row["AccountTypeID"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["PGPKey"], + $row["IRCNick"], $row["PGPKey"], $row["SSHPubKey"], $row["InactivityTS"] ? 1 : 0, $row["ID"]); } else { print __("You do not have permission to edit this account."); @@ -98,7 +98,8 @@ if (isset($_COOKIE["AURSID"])) { in_request("U"), in_request("T"), in_request("S"), in_request("E"), in_request("P"), in_request("C"), in_request("R"), in_request("L"), in_request("I"), - in_request("K"), in_request("J"), in_request("ID")); + in_request("K"), in_request("PK"), in_request("J"), + in_request("ID")); } } else { if (has_credential(CRED_ACCOUNT_SEARCH)) { diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php index 2d8dbafd..20ac081d 100644 --- a/web/lib/acctfuncs.inc.php +++ b/web/lib/acctfuncs.inc.php @@ -53,13 +53,14 @@ function html_format_pgp_fingerprint($fingerprint) { * @param string $L The language preference of the displayed user * @param string $I The IRC nickname of the displayed user * @param string $K The PGP key fingerprint of the displayed user + * @param string $PK The SSH public key of the displayed user * @param string $J The inactivity status of the displayed user * @param string $UID The user ID of the displayed user * * @return void */ -function display_account_form($A,$U="",$T="",$S="", - $E="",$P="",$C="",$R="",$L="",$I="",$K="",$J="", $UID=0) { +function display_account_form($A,$U="",$T="",$S="",$E="",$P="",$C="",$R="", + $L="",$I="",$K="",$PK="",$J="", $UID=0) { global $SUPPORTED_LANGS; include("account_edit_form.php"); @@ -82,13 +83,14 @@ function display_account_form($A,$U="",$T="",$S="", * @param string $L The language preference of the user * @param string $I The IRC nickname of the user * @param string $K The PGP fingerprint of the user + * @param string $PK The SSH public key of the user * @param string $J The inactivity status of the user * @param string $UID The user ID of the modified account * * @return string|void Return void if successful, otherwise return error */ -function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="", - $P="",$C="",$R="",$L="",$I="",$K="",$J="",$UID=0) { +function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$P="",$C="", + $R="",$L="",$I="",$K="",$PK="",$J="",$UID=0) { global $SUPPORTED_LANGS; $error = ''; @@ -146,6 +148,15 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="", $error = __("The PGP key fingerprint is invalid."); } + if (!$error && !empty($PK)) { + if (valid_ssh_pubkey($PK)) { + $tokens = explode(" ", $PK); + $PK = $tokens[0] . " " . $tokens[1]; + } else { + $error = __("The SSH public key is invalid."); + } + } + if (isset($_COOKIE['AURSID'])) { $atype = account_from_sid($_COOKIE['AURSID']); if (($atype == "User" && $T > 1) || ($atype == "Trusted User" && $T > 2)) { @@ -192,11 +203,29 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="", "<strong>", htmlspecialchars($E,ENT_QUOTES), "</strong>"); } } + if (!$error) { + /* + * Check whether the SSH public key is available. + * TODO: Fix race condition. + */ + $q = "SELECT COUNT(*) FROM Users "; + $q.= "WHERE SSHPubKey = " . $dbh->quote($PK); + if ($TYPE == "edit") { + $q.= " AND ID != " . intval($UID); + } + $result = $dbh->query($q); + $row = $result->fetch(PDO::FETCH_NUM); + + if ($row[0]) { + $error = __("The SSH public key, %s%s%s, is already in use.", + "<strong>", htmlspecialchars($PK, ENT_QUOTES), "</strong>"); + } + } if ($error) { print "<ul class='errorlist'><li>".$error."</li></ul>\n"; display_account_form($A, $U, $T, $S, $E, "", "", - $R, $L, $I, $K, $J, $UID); + $R, $L, $I, $K, $PK, $J, $UID); return; } @@ -218,11 +247,13 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="", $L = $dbh->quote($L); $I = $dbh->quote($I); $K = $dbh->quote(str_replace(" ", "", $K)); + $PK = $dbh->quote($PK); $q = "INSERT INTO Users (AccountTypeID, Suspended, "; $q.= "InactivityTS, Username, Email, Passwd, Salt, "; - $q.= "RealName, LangPreference, IRCNick, PGPKey) "; + $q.= "RealName, LangPreference, IRCNick, PGPKey, "; + $q.= "SSHPubKey) "; $q.= "VALUES (1, 0, 0, $U, $E, $P, $salt, $R, $L, "; - $q.= "$I, $K)"; + $q.= "$I, $K, $PK)"; $result = $dbh->exec($q); if (!$result) { print __("Error trying to create account, %s%s%s.", @@ -290,6 +321,7 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="", $q.= ", LangPreference = " . $dbh->quote($L); $q.= ", IRCNick = " . $dbh->quote($I); $q.= ", PGPKey = " . $dbh->quote(str_replace(" ", "", $K)); + $q.= ", SSHPubKey = " . $dbh->quote($PK); $q.= ", InactivityTS = " . $inactivity_ts; $q.= " WHERE ID = ".intval($UID); $result = $dbh->exec($q); @@ -800,6 +832,38 @@ function valid_pgp_fingerprint($fingerprint) { } /** + * Determine if the SSH public key is valid + * + * @param string $pubkey SSH public key to check + * + * @return bool True if the SSH public key is valid, otherwise false + */ +function valid_ssh_pubkey($pubkey) { + $valid_prefixes = array( + "ssh-rsa", "ssh-dss", "ecdsa-sha2-nistp256", + "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521", "ssh-ed25519" + ); + + $has_valid_prefix = false; + foreach ($valid_prefixes as $prefix) { + if (strpos($pubkey, $prefix . " ") === 0) { + $has_valid_prefix = true; + break; + } + } + if (!$has_valid_prefix) { + return false; + } + + $tokens = explode(" ", $pubkey); + if (empty($tokens[1])) { + return false; + } + + return (base64_encode(base64_decode($tokens[1], true)) == $tokens[1]); +} + +/** * Determine if the user account has been suspended * * @param string $id The ID of user to check if suspended diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php index 17dd9371..996c207b 100644 --- a/web/template/account_edit_form.php +++ b/web/template/account_edit_form.php @@ -98,6 +98,11 @@ </p> <p> + <label for="id_ssh"><?= __("SSH Public Key") ?>:</label> + <textarea name="PK" id="id_ssh" rows="5" cols="30"><?= htmlspecialchars($PK) ?></textarea> + </p> + + <p> <label for="id_language"><?= __("Language") ?>:</label> <select name="L" id="id_language"> <?php |