Message info
 
To:Arch User Repository (AUR) Development From:Dan McGee Subject:Re: [aur-dev] [PATCH] Add field for PGP key in profile information Date:Fri, 23 Mar 2012 09:48:42 -0500
 

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
>