[aur-dev] [PATCH] Add field for PGP key in profile information
This is handy for verifying the PGP key of new Trusted Users. Also, this could potentially used as a basis to allow signed package uploads in the future. Implements FS#29028. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 3 ++ support/schema/aur-schema.sql | 1 + web/html/account.php | 13 ++++---- web/lib/acctfuncs.inc.php | 67 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/UPGRADING b/UPGRADING index 6557b95..6f87944 100644 --- a/UPGRADING +++ b/UPGRADING @@ -6,7 +6,10 @@ From 1.9.1 to 2.0.0 1. Add new "Users" table login date column: +---- ALTER TABLE Users ADD COLUMN LastLogin BIGINT NOT NULL DEFAULT 0; +ALTER TABLE Users ADD COLUMN PGPKey CHAR(40) NULL DEFAULT NULL; +---- From 1.9.0 to 1.9.1 ------------------- diff --git a/support/schema/aur-schema.sql b/support/schema/aur-schema.sql index 6c8feca..ca7ddbe 100644 --- a/support/schema/aur-schema.sql +++ b/support/schema/aur-schema.sql @@ -31,6 +31,7 @@ CREATE TABLE Users ( RealName VARCHAR(64) NOT NULL DEFAULT '', LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', IRCNick VARCHAR(32) NOT NULL DEFAULT '', + PGPKey CHAR(40) NULL DEFAULT NULL, LastVoted BIGINT UNSIGNED NOT NULL DEFAULT 0, LastLogin BIGINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (ID), diff --git a/web/html/account.php b/web/html/account.php index d94d711..339316b 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -33,7 +33,8 @@ if (isset($_COOKIE["AURSID"])) { # search_results_page($atype, in_request("O"), in_request("SB"), in_request("U"), in_request("T"), in_request("S"), - in_request("E"), in_request("R"), in_request("I")); + in_request("E"), in_request("R"), in_request("I"), + in_request("K")); } else { # a non-privileged user is trying to access the search page @@ -64,7 +65,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } } @@ -82,7 +83,7 @@ if (isset($_COOKIE["AURSID"])) { $row = mysql_fetch_assoc($result); display_account_info($row["Username"], $row["AccountType"], $row["Email"], $row["RealName"], - $row["IRCNick"], $row["LastVoted"]); + $row["IRCNick"], $row["PGPKey"], $row["LastVoted"]); } } elseif ($action == "UpdateAccount") { @@ -92,7 +93,7 @@ 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("ID")); + in_request("K"), in_request("ID")); } else { @@ -127,7 +128,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } } } @@ -143,7 +144,7 @@ if (isset($_COOKIE["AURSID"])) { process_account_form("","new", "NewAccount", in_request("U"), 1, 0, in_request("E"), in_request("P"), in_request("C"), in_request("R"), - in_request("L"), in_request("I")); + in_request("L"), in_request("I"), in_request("K")); } else { # display the account request form diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php index 512e66c..8246cc9 100644 --- a/web/lib/acctfuncs.inc.php +++ b/web/lib/acctfuncs.inc.php @@ -8,10 +8,28 @@ function in_request($name) { return ""; } +# Format PGP key fingerprint +function html_format_pgp_fingerprint($fingerprint) { + if (strlen($fingerprint) != 40 || !ctype_xdigit($fingerprint)) { + return $fingerprint; + } + + return htmlspecialchars(substr($fingerprint, 0, 4) . " " . + substr($fingerprint, 4, 4) . " " . + substr($fingerprint, 8, 4) . " " . + substr($fingerprint, 12, 4) . " " . + substr($fingerprint, 16, 4) . " " . + substr($fingerprint, 20, 4) . " " . + substr($fingerprint, 24, 4) . " " . + substr($fingerprint, 28, 4) . " " . + substr($fingerprint, 32, 4) . " " . + substr($fingerprint, 36, 4) . " ", ENT_QUOTES); +} + # Display the standard Account form, pass in default values if any function display_account_form($UTYPE,$A,$U="",$T="",$S="", - $E="",$P="",$C="",$R="",$L="",$I="",$UID=0) { + $E="",$P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: what user type the form is being displayed for # A: what "form" name to use # U: value to display for username @@ -113,6 +131,12 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", print "</tr>\n"; print "<tr>"; + print "<td align='left'>".__("PGP Key Fingerprint").":</td>"; + print "<td align='left'><input type='text' size='30' maxlength='50'"; + print " name='K' value='".html_format_pgp_fingerprint($K)."' /></td>"; + print "</tr>\n"; + + print "<tr>"; print "<td align='left'>".__("Language").":</td>"; print "<td align='left'><select name=L>\n"; @@ -152,7 +176,7 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", # process form input from a new/edit account form # function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", - $P="",$C="",$R="",$L="",$I="",$UID=0) { + $P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: The user's account type # TYPE: either "edit" or "new" # A: what parent "form" name to use @@ -215,6 +239,11 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if (!$error && !valid_email($E)) { $error = __("The email address is invalid."); } + + if (!$error && $K != '' && !valid_pgp_fingerprint($K)) { + $error = __("The PGP key fingerprint is invalid."); + } + if ($UTYPE == "Trusted User" && $T == 3) { $error = __("A Trusted User cannot assign Developer status."); } @@ -260,17 +289,17 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if ($error) { print "<span class='error'>".$error."</span><br/>\n"; display_account_form($UTYPE, $A, $U, $T, $S, $E, "", "", - $R, $L, $I, $UID); + $R, $L, $I, $K, $UID); } else { if ($TYPE == "new") { # no errors, go ahead and create the unprivileged user $salt = generate_salt(); $P = salted_hash($P, $salt); $escaped = array_map('db_escape_string', - array($U, $E, $P, $salt, $R, $L, $I)); + array($U, $E, $P, $salt, $R, $L, $I, str_replace(" ", "", $K))); $q = "INSERT INTO Users (" . "AccountTypeID, Suspended, Username, Email, Passwd, Salt" . - ", RealName, LangPreference, IRCNick) " . + ", RealName, LangPreference, IRCNick, PGPKey) " . "VALUES (1, 0, '" . implode("', '", $escaped) . "')"; $result = db_query($q, $dbh); if (!$result) { @@ -308,6 +337,7 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", $q.= ", RealName = '".db_escape_string($R)."'"; $q.= ", LangPreference = '".db_escape_string($L)."'"; $q.= ", IRCNick = '".db_escape_string($I)."'"; + $q.= ", PGPKey = '".db_escape_string(str_replace(" ", "", $K))."'"; $q.= " WHERE ID = ".intval($UID); $result = db_query($q, $dbh); if (!$result) { @@ -333,7 +363,7 @@ function search_accounts_form() { # search results page # function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", - $S="",$E="",$R="",$I="") { + $S="",$E="",$R="",$I="",$K="") { # UTYPE: what account type the user belongs to # O: what row offset we're at # SB: how to sort the results @@ -388,6 +418,10 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $q.= "AND IRCNick LIKE '%".db_escape_like($I)."%' "; $search_vars[] = "I"; } + if ($K) { + $q.= "AND PGPKey LIKE '%".db_escape_like(str_replace(" ", "", $K))."%' "; + $search_vars[] = "K"; + } switch ($SB) { case 't': $q.= "ORDER BY AccountTypeID, Username "; @@ -429,6 +463,8 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", print "<th class='header'>"; print "<span class='f2'>".__("IRC Nick")."</span></th>"; print "<th class='header'>"; + print "<span class='f2'>".__("PGP Key Fingerprint")."</span></th>"; + print "<th class='header'>"; print "<span class='f2'>".__("Last Voted")."</span></th>"; print "<th class='header'>"; print "<span class='f2'>".__("Edit Account")."</span></th>"; @@ -460,6 +496,9 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $row["IRCNick"] ? print htmlspecialchars($row["IRCNick"],ENT_QUOTES) : print " "; print "</span></td>"; print "<td class='".$c."'><span class='f5'>"; + $row["PGPKey"] ? print html_format_pgp_fingerprint($row["PGPKey"]) : print " "; + print "</span></td>"; + print "<td class='".$c."'><span class='f5'>"; $row["LastVoted"] ? print date("Y-m-d", $row["LastVoted"]) : print __("Never"); @@ -526,7 +565,7 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", # Display non-editable account info # -function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { +function display_account_info($U="", $T="", $E="", $R="", $I="", $K="", $LV="") { # U: value to display for username # T: value to display for account type # E: value to display for email address @@ -575,6 +614,11 @@ function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { print " </tr>\n"; print " <tr>\n"; + print " <td align='left'>".__("PGP Key Fingerprint").":</td>\n"; + print " <td align='left'>".html_format_pgp_fingerprint($K)."</td>\n"; + print " </tr>\n"; + + print " <tr>\n"; print " <td align='left'>".__("Last Voted").":</td>\n"; print " <td align='left'>"; print $LV ? date("Y-m-d", $LV) : __("Never"); @@ -784,6 +828,15 @@ function valid_passwd( $userID, $passwd, $dbh ) } /* + * Checks if the PGP key fingerprint is valid (must be 40 hexadecimal digits). + */ +function valid_pgp_fingerprint ( $fingerprint ) +{ + $fingerprint = str_replace(" ", "", $fingerprint); + return (strlen($fingerprint) == 40 && ctype_xdigit($fingerprint)); +} + +/* * Is the user account suspended? */ function user_suspended( $id, $dbh ) -- 1.7.9.4
On Thu, Mar 22, 2012 at 3:45 AM, Lukas Fleischer <archlinux@cryptocrack.de> wrote:
This is handy for verifying the PGP key of new Trusted Users. Also, this could potentially used as a basis to allow signed package uploads in the future.
Implements FS#29028.
Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 3 ++ support/schema/aur-schema.sql | 1 + web/html/account.php | 13 ++++---- web/lib/acctfuncs.inc.php | 67 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/UPGRADING b/UPGRADING index 6557b95..6f87944 100644 --- a/UPGRADING +++ b/UPGRADING @@ -6,7 +6,10 @@ From 1.9.1 to 2.0.0
1. Add new "Users" table login date column:
+---- ALTER TABLE Users ADD COLUMN LastLogin BIGINT NOT NULL DEFAULT 0; +ALTER TABLE Users ADD COLUMN PGPKey CHAR(40) NULL DEFAULT NULL; CHAR is a type from like the 70's when that extra byte to hold the length mattered. VARCHAR is much smarter here, especially since you allow NULL, which all existing users will be- otherwise you are actually wasting 40 bytes per user. The difference between CHAR and VARCHAR here is only 1 byte anyway...
You'll notice the current schema uses very few CHAR over VARCHAR columns (only Passwd, Salt, ResetKey, SessionID). I think it would be best to keep it this way. MySQL semantics regarding trailing spaces, truncation, etc. are a total joke in this area, and VARCHAR is definitely the safer route when it comes to that. Finally, any so-called performance benefit is nullified by the fact that you already have VARCHAR columns on this table, so there is no fixed-width records happening anyway.
+----
From 1.9.0 to 1.9.1 ------------------- diff --git a/support/schema/aur-schema.sql b/support/schema/aur-schema.sql index 6c8feca..ca7ddbe 100644 --- a/support/schema/aur-schema.sql +++ b/support/schema/aur-schema.sql @@ -31,6 +31,7 @@ CREATE TABLE Users ( RealName VARCHAR(64) NOT NULL DEFAULT '', LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', IRCNick VARCHAR(32) NOT NULL DEFAULT '', + PGPKey CHAR(40) NULL DEFAULT NULL, LastVoted BIGINT UNSIGNED NOT NULL DEFAULT 0, LastLogin BIGINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (ID), diff --git a/web/html/account.php b/web/html/account.php index d94d711..339316b 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -33,7 +33,8 @@ if (isset($_COOKIE["AURSID"])) { # search_results_page($atype, in_request("O"), in_request("SB"), in_request("U"), in_request("T"), in_request("S"), - in_request("E"), in_request("R"), in_request("I")); + in_request("E"), in_request("R"), in_request("I"), + in_request("K"));
} else { # a non-privileged user is trying to access the search page @@ -64,7 +65,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } }
@@ -82,7 +83,7 @@ if (isset($_COOKIE["AURSID"])) { $row = mysql_fetch_assoc($result); display_account_info($row["Username"], $row["AccountType"], $row["Email"], $row["RealName"], - $row["IRCNick"], $row["LastVoted"]); + $row["IRCNick"], $row["PGPKey"], $row["LastVoted"]); }
} elseif ($action == "UpdateAccount") { @@ -92,7 +93,7 @@ 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("ID")); + in_request("K"), in_request("ID"));
} else { @@ -127,7 +128,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } } } @@ -143,7 +144,7 @@ if (isset($_COOKIE["AURSID"])) { process_account_form("","new", "NewAccount", in_request("U"), 1, 0, in_request("E"), in_request("P"), in_request("C"), in_request("R"), - in_request("L"), in_request("I")); + in_request("L"), in_request("I"), in_request("K"));
} else { # display the account request form diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php index 512e66c..8246cc9 100644 --- a/web/lib/acctfuncs.inc.php +++ b/web/lib/acctfuncs.inc.php @@ -8,10 +8,28 @@ function in_request($name) { return ""; }
+# Format PGP key fingerprint +function html_format_pgp_fingerprint($fingerprint) { + if (strlen($fingerprint) != 40 || !ctype_xdigit($fingerprint)) { + return $fingerprint; + } + + return htmlspecialchars(substr($fingerprint, 0, 4) . " " . + substr($fingerprint, 4, 4) . " " . + substr($fingerprint, 8, 4) . " " . + substr($fingerprint, 12, 4) . " " . + substr($fingerprint, 16, 4) . " " . + substr($fingerprint, 20, 4) . " " . + substr($fingerprint, 24, 4) . " " . + substr($fingerprint, 28, 4) . " " . + substr($fingerprint, 32, 4) . " " . + substr($fingerprint, 36, 4) . " ", ENT_QUOTES); +} + # Display the standard Account form, pass in default values if any
function display_account_form($UTYPE,$A,$U="",$T="",$S="", - $E="",$P="",$C="",$R="",$L="",$I="",$UID=0) { + $E="",$P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: what user type the form is being displayed for # A: what "form" name to use # U: value to display for username @@ -113,6 +131,12 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", print "</tr>\n";
print "<tr>"; + print "<td align='left'>".__("PGP Key Fingerprint").":</td>"; + print "<td align='left'><input type='text' size='30' maxlength='50'"; + print " name='K' value='".html_format_pgp_fingerprint($K)."' /></td>"; + print "</tr>\n"; + + print "<tr>"; print "<td align='left'>".__("Language").":</td>"; print "<td align='left'><select name=L>\n";
@@ -152,7 +176,7 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", # process form input from a new/edit account form # function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", - $P="",$C="",$R="",$L="",$I="",$UID=0) { + $P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: The user's account type # TYPE: either "edit" or "new" # A: what parent "form" name to use @@ -215,6 +239,11 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if (!$error && !valid_email($E)) { $error = __("The email address is invalid."); } + + if (!$error && $K != '' && !valid_pgp_fingerprint($K)) { + $error = __("The PGP key fingerprint is invalid."); + } + if ($UTYPE == "Trusted User" && $T == 3) { $error = __("A Trusted User cannot assign Developer status."); } @@ -260,17 +289,17 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if ($error) { print "<span class='error'>".$error."</span><br/>\n"; display_account_form($UTYPE, $A, $U, $T, $S, $E, "", "", - $R, $L, $I, $UID); + $R, $L, $I, $K, $UID); } else { if ($TYPE == "new") { # no errors, go ahead and create the unprivileged user $salt = generate_salt(); $P = salted_hash($P, $salt); $escaped = array_map('db_escape_string', - array($U, $E, $P, $salt, $R, $L, $I)); + array($U, $E, $P, $salt, $R, $L, $I, str_replace(" ", "", $K))); $q = "INSERT INTO Users (" . "AccountTypeID, Suspended, Username, Email, Passwd, Salt" . - ", RealName, LangPreference, IRCNick) " . + ", RealName, LangPreference, IRCNick, PGPKey) " . "VALUES (1, 0, '" . implode("', '", $escaped) . "')"; $result = db_query($q, $dbh); if (!$result) { @@ -308,6 +337,7 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", $q.= ", RealName = '".db_escape_string($R)."'"; $q.= ", LangPreference = '".db_escape_string($L)."'"; $q.= ", IRCNick = '".db_escape_string($I)."'"; + $q.= ", PGPKey = '".db_escape_string(str_replace(" ", "", $K))."'"; $q.= " WHERE ID = ".intval($UID); $result = db_query($q, $dbh); if (!$result) { @@ -333,7 +363,7 @@ function search_accounts_form() { # search results page # function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", - $S="",$E="",$R="",$I="") { + $S="",$E="",$R="",$I="",$K="") { # UTYPE: what account type the user belongs to # O: what row offset we're at # SB: how to sort the results @@ -388,6 +418,10 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $q.= "AND IRCNick LIKE '%".db_escape_like($I)."%' "; $search_vars[] = "I"; } + if ($K) { + $q.= "AND PGPKey LIKE '%".db_escape_like(str_replace(" ", "", $K))."%' "; + $search_vars[] = "K"; + } switch ($SB) { case 't': $q.= "ORDER BY AccountTypeID, Username "; @@ -429,6 +463,8 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", print "<th class='header'>"; print "<span class='f2'>".__("IRC Nick")."</span></th>"; print "<th class='header'>"; + print "<span class='f2'>".__("PGP Key Fingerprint")."</span></th>"; + print "<th class='header'>"; print "<span class='f2'>".__("Last Voted")."</span></th>"; print "<th class='header'>"; print "<span class='f2'>".__("Edit Account")."</span></th>"; @@ -460,6 +496,9 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $row["IRCNick"] ? print htmlspecialchars($row["IRCNick"],ENT_QUOTES) : print " "; print "</span></td>"; print "<td class='".$c."'><span class='f5'>"; + $row["PGPKey"] ? print html_format_pgp_fingerprint($row["PGPKey"]) : print " "; + print "</span></td>"; + print "<td class='".$c."'><span class='f5'>"; $row["LastVoted"] ? print date("Y-m-d", $row["LastVoted"]) : print __("Never"); @@ -526,7 +565,7 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="",
# Display non-editable account info # -function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { +function display_account_info($U="", $T="", $E="", $R="", $I="", $K="", $LV="") { # U: value to display for username # T: value to display for account type # E: value to display for email address @@ -575,6 +614,11 @@ function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { print " </tr>\n";
print " <tr>\n"; + print " <td align='left'>".__("PGP Key Fingerprint").":</td>\n"; + print " <td align='left'>".html_format_pgp_fingerprint($K)."</td>\n"; + print " </tr>\n"; + + print " <tr>\n"; print " <td align='left'>".__("Last Voted").":</td>\n"; print " <td align='left'>"; print $LV ? date("Y-m-d", $LV) : __("Never"); @@ -784,6 +828,15 @@ function valid_passwd( $userID, $passwd, $dbh ) }
/* + * Checks if the PGP key fingerprint is valid (must be 40 hexadecimal digits). + */ +function valid_pgp_fingerprint ( $fingerprint ) +{ + $fingerprint = str_replace(" ", "", $fingerprint); + return (strlen($fingerprint) == 40 && ctype_xdigit($fingerprint)); +} + +/* * Is the user account suspended? */ function user_suspended( $id, $dbh ) -- 1.7.9.4
This is handy for verifying the PGP key of new Trusted Users. Also, this could potentially used as a basis to allow signed package uploads in the future. Implements FS#29028. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- Use "VARCHAR" instead of "CHAR". Thanks, Dan! UPGRADING | 3 ++ support/schema/aur-schema.sql | 1 + web/html/account.php | 13 ++++---- web/lib/acctfuncs.inc.php | 67 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/UPGRADING b/UPGRADING index 6557b95..40d4485 100644 --- a/UPGRADING +++ b/UPGRADING @@ -6,7 +6,10 @@ From 1.9.1 to 2.0.0 1. Add new "Users" table login date column: +---- ALTER TABLE Users ADD COLUMN LastLogin BIGINT NOT NULL DEFAULT 0; +ALTER TABLE Users ADD COLUMN PGPKey VARCHAR(40) NULL DEFAULT NULL; +---- From 1.9.0 to 1.9.1 ------------------- diff --git a/support/schema/aur-schema.sql b/support/schema/aur-schema.sql index 6c8feca..726fd2f 100644 --- a/support/schema/aur-schema.sql +++ b/support/schema/aur-schema.sql @@ -31,6 +31,7 @@ CREATE TABLE Users ( RealName VARCHAR(64) NOT NULL DEFAULT '', LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', IRCNick VARCHAR(32) NOT NULL DEFAULT '', + PGPKey VARCHAR(40) NULL DEFAULT NULL, LastVoted BIGINT UNSIGNED NOT NULL DEFAULT 0, LastLogin BIGINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (ID), diff --git a/web/html/account.php b/web/html/account.php index d94d711..339316b 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -33,7 +33,8 @@ if (isset($_COOKIE["AURSID"])) { # search_results_page($atype, in_request("O"), in_request("SB"), in_request("U"), in_request("T"), in_request("S"), - in_request("E"), in_request("R"), in_request("I")); + in_request("E"), in_request("R"), in_request("I"), + in_request("K")); } else { # a non-privileged user is trying to access the search page @@ -64,7 +65,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } } @@ -82,7 +83,7 @@ if (isset($_COOKIE["AURSID"])) { $row = mysql_fetch_assoc($result); display_account_info($row["Username"], $row["AccountType"], $row["Email"], $row["RealName"], - $row["IRCNick"], $row["LastVoted"]); + $row["IRCNick"], $row["PGPKey"], $row["LastVoted"]); } } elseif ($action == "UpdateAccount") { @@ -92,7 +93,7 @@ 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("ID")); + in_request("K"), in_request("ID")); } else { @@ -127,7 +128,7 @@ if (isset($_COOKIE["AURSID"])) { display_account_form($atype, "UpdateAccount", $row["Username"], $row["AccountType"], $row["Suspended"], $row["Email"], "", "", $row["RealName"], $row["LangPreference"], - $row["IRCNick"], $row["ID"]); + $row["IRCNick"], $row["PGPKey"], $row["ID"]); } } } @@ -143,7 +144,7 @@ if (isset($_COOKIE["AURSID"])) { process_account_form("","new", "NewAccount", in_request("U"), 1, 0, in_request("E"), in_request("P"), in_request("C"), in_request("R"), - in_request("L"), in_request("I")); + in_request("L"), in_request("I"), in_request("K")); } else { # display the account request form diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php index 512e66c..8246cc9 100644 --- a/web/lib/acctfuncs.inc.php +++ b/web/lib/acctfuncs.inc.php @@ -8,10 +8,28 @@ function in_request($name) { return ""; } +# Format PGP key fingerprint +function html_format_pgp_fingerprint($fingerprint) { + if (strlen($fingerprint) != 40 || !ctype_xdigit($fingerprint)) { + return $fingerprint; + } + + return htmlspecialchars(substr($fingerprint, 0, 4) . " " . + substr($fingerprint, 4, 4) . " " . + substr($fingerprint, 8, 4) . " " . + substr($fingerprint, 12, 4) . " " . + substr($fingerprint, 16, 4) . " " . + substr($fingerprint, 20, 4) . " " . + substr($fingerprint, 24, 4) . " " . + substr($fingerprint, 28, 4) . " " . + substr($fingerprint, 32, 4) . " " . + substr($fingerprint, 36, 4) . " ", ENT_QUOTES); +} + # Display the standard Account form, pass in default values if any function display_account_form($UTYPE,$A,$U="",$T="",$S="", - $E="",$P="",$C="",$R="",$L="",$I="",$UID=0) { + $E="",$P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: what user type the form is being displayed for # A: what "form" name to use # U: value to display for username @@ -113,6 +131,12 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", print "</tr>\n"; print "<tr>"; + print "<td align='left'>".__("PGP Key Fingerprint").":</td>"; + print "<td align='left'><input type='text' size='30' maxlength='50'"; + print " name='K' value='".html_format_pgp_fingerprint($K)."' /></td>"; + print "</tr>\n"; + + print "<tr>"; print "<td align='left'>".__("Language").":</td>"; print "<td align='left'><select name=L>\n"; @@ -152,7 +176,7 @@ function display_account_form($UTYPE,$A,$U="",$T="",$S="", # process form input from a new/edit account form # function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", - $P="",$C="",$R="",$L="",$I="",$UID=0) { + $P="",$C="",$R="",$L="",$I="",$K="",$UID=0) { # UTYPE: The user's account type # TYPE: either "edit" or "new" # A: what parent "form" name to use @@ -215,6 +239,11 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if (!$error && !valid_email($E)) { $error = __("The email address is invalid."); } + + if (!$error && $K != '' && !valid_pgp_fingerprint($K)) { + $error = __("The PGP key fingerprint is invalid."); + } + if ($UTYPE == "Trusted User" && $T == 3) { $error = __("A Trusted User cannot assign Developer status."); } @@ -260,17 +289,17 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", if ($error) { print "<span class='error'>".$error."</span><br/>\n"; display_account_form($UTYPE, $A, $U, $T, $S, $E, "", "", - $R, $L, $I, $UID); + $R, $L, $I, $K, $UID); } else { if ($TYPE == "new") { # no errors, go ahead and create the unprivileged user $salt = generate_salt(); $P = salted_hash($P, $salt); $escaped = array_map('db_escape_string', - array($U, $E, $P, $salt, $R, $L, $I)); + array($U, $E, $P, $salt, $R, $L, $I, str_replace(" ", "", $K))); $q = "INSERT INTO Users (" . "AccountTypeID, Suspended, Username, Email, Passwd, Salt" . - ", RealName, LangPreference, IRCNick) " . + ", RealName, LangPreference, IRCNick, PGPKey) " . "VALUES (1, 0, '" . implode("', '", $escaped) . "')"; $result = db_query($q, $dbh); if (!$result) { @@ -308,6 +337,7 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="", $q.= ", RealName = '".db_escape_string($R)."'"; $q.= ", LangPreference = '".db_escape_string($L)."'"; $q.= ", IRCNick = '".db_escape_string($I)."'"; + $q.= ", PGPKey = '".db_escape_string(str_replace(" ", "", $K))."'"; $q.= " WHERE ID = ".intval($UID); $result = db_query($q, $dbh); if (!$result) { @@ -333,7 +363,7 @@ function search_accounts_form() { # search results page # function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", - $S="",$E="",$R="",$I="") { + $S="",$E="",$R="",$I="",$K="") { # UTYPE: what account type the user belongs to # O: what row offset we're at # SB: how to sort the results @@ -388,6 +418,10 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $q.= "AND IRCNick LIKE '%".db_escape_like($I)."%' "; $search_vars[] = "I"; } + if ($K) { + $q.= "AND PGPKey LIKE '%".db_escape_like(str_replace(" ", "", $K))."%' "; + $search_vars[] = "K"; + } switch ($SB) { case 't': $q.= "ORDER BY AccountTypeID, Username "; @@ -429,6 +463,8 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", print "<th class='header'>"; print "<span class='f2'>".__("IRC Nick")."</span></th>"; print "<th class='header'>"; + print "<span class='f2'>".__("PGP Key Fingerprint")."</span></th>"; + print "<th class='header'>"; print "<span class='f2'>".__("Last Voted")."</span></th>"; print "<th class='header'>"; print "<span class='f2'>".__("Edit Account")."</span></th>"; @@ -460,6 +496,9 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", $row["IRCNick"] ? print htmlspecialchars($row["IRCNick"],ENT_QUOTES) : print " "; print "</span></td>"; print "<td class='".$c."'><span class='f5'>"; + $row["PGPKey"] ? print html_format_pgp_fingerprint($row["PGPKey"]) : print " "; + print "</span></td>"; + print "<td class='".$c."'><span class='f5'>"; $row["LastVoted"] ? print date("Y-m-d", $row["LastVoted"]) : print __("Never"); @@ -526,7 +565,7 @@ function search_results_page($UTYPE,$O=0,$SB="",$U="",$T="", # Display non-editable account info # -function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { +function display_account_info($U="", $T="", $E="", $R="", $I="", $K="", $LV="") { # U: value to display for username # T: value to display for account type # E: value to display for email address @@ -575,6 +614,11 @@ function display_account_info($U="", $T="", $E="", $R="", $I="", $LV="") { print " </tr>\n"; print " <tr>\n"; + print " <td align='left'>".__("PGP Key Fingerprint").":</td>\n"; + print " <td align='left'>".html_format_pgp_fingerprint($K)."</td>\n"; + print " </tr>\n"; + + print " <tr>\n"; print " <td align='left'>".__("Last Voted").":</td>\n"; print " <td align='left'>"; print $LV ? date("Y-m-d", $LV) : __("Never"); @@ -784,6 +828,15 @@ function valid_passwd( $userID, $passwd, $dbh ) } /* + * Checks if the PGP key fingerprint is valid (must be 40 hexadecimal digits). + */ +function valid_pgp_fingerprint ( $fingerprint ) +{ + $fingerprint = str_replace(" ", "", $fingerprint); + return (strlen($fingerprint) == 40 && ctype_xdigit($fingerprint)); +} + +/* * Is the user account suspended? */ function user_suspended( $id, $dbh ) -- 1.7.9.4
participants (2)
-
Dan McGee
-
Lukas Fleischer