]> git.decadent.org.uk Git - dak.git/blobdiff - scripts/debian/buildd-add-keys
And also catch double-sign-edit-failure-sign-whatever files
[dak.git] / scripts / debian / buildd-add-keys
index 2ba4bac176283804b6a8aae23d75d8434b200c0d..619a514f07458d432b418700574784f4774bdf8e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # No way I try to deal with a crippled sh just for POSIX foo.
 
-# Copyright (C) 2011 Joerg Jaspert <joerg@debian.org>
+# Copyright (C) 2011,2012 Joerg Jaspert <joerg@debian.org>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
@@ -43,20 +43,20 @@ function cleanup() {
     trap - ERR EXIT TERM HUP INT QUIT
 
     for TEMPFILE in GPGSTATUS GPGLOGS GPGOUTF TEMPKEYDATA; do
-        TFILE=${TEMPFILE:=$TEMPFILE}
-        DELF=${!TFILE:-""}
+        DELF=${!TEMPFILE:-""}
         if [ -n "${DELF}" ] && [ -f "${DELF}" ]; then
             rm -f "${DELF}"
         fi
     done
     exit $ERRVAL
 }
-trap cleanup ERR EXIT TERM HUP INT QUIT
 
 base="${base}/scripts/builddkeyrings"
 INCOMING="${base}/incoming"
 ERRORS="${base}/errors"
 ADMINS="${base}/adminkeys.gpg"
+ARCHADMINS="${base}/archadminkeys"
+STAMPFILE="${base}/updatedkeyring"
 
 # Default options for our gpg calls
 DEFGPGOPT="--no-default-keyring --batch --no-tty --no-options --exit-on-status-write-error --no-greeting"
@@ -66,11 +66,22 @@ if ! [ -d "${INCOMING}" ]; then
     exit 1
 fi
 
+cd "${INCOMING}"
+KEYS=$(find . -maxdepth 1 -mindepth 1 -type f -name \*.key | sed -e "s,./,," | xargs)
+if [ -z "${KEYS}" ]; then
+    exit 0
+fi
+
+trap cleanup ERR EXIT TERM HUP INT QUIT
+
+# Tell prepare-dir that there is an update and it can run
+touch "${STAMPFILE}"
+
 # Whenever something goes wrong, its put in there.
 mkdir -p "${ERRORS}"
 
 # We process all new files in our incoming directory
-for file in $(ls -1 ${INCOMING}/*.key); do
+for file in ${KEYS}; do
     file=${file##*/}
     # First we want to see if we recognize the filename. The buildd people have
     # to follow a certain schema:
@@ -120,8 +131,12 @@ for file in $(ls -1 ${INCOMING}/*.key); do
     exec 4> "${GPGSTATUS}"
     exec 5> "${GPGLOGS}"
 
+    KEYRINGS="--keyring ${ADMINS}"
+    if [ -f "${ARCHADMINS}/${ARCH}.gpg" ]; then
+        KEYRINGS="${KEYRINGS} --keyring ${ARCHADMINS}/${ARCH}.gpg"
+    fi
     # So lets run gpg, status/logger into the two files, to "decrypt" the keyfile
-    if ! gpg ${DEFGPGOPT} --keyring "${ADMINS}" --status-fd 4 --logger-fd 5 --decrypt "${INCOMING}/${file}" > "${GPGOUTF}"; then
+    if ! gpg ${DEFGPGOPT} ${KEYRINGS} --status-fd 4 --logger-fd 5 --decrypt "${INCOMING}/${file}" > "${GPGOUTF}"; then
         ret=$?
         log "gpg returned with ${ret}, not adding key from file ${file}"
         DATE=$(date -Is)
@@ -130,7 +145,7 @@ for file in $(ls -1 ${INCOMING}/*.key); do
         mv "${GPGLOGS}" "${ERRORS}/gpgerror.${file}.gpglogs.${DATE}"
         rm -f "${GPGOUTF}"
         continue
-    fi
+    fi # gpg broke
 
     # Read in the status output
     GPGSTAT=$(cat "${GPGSTATUS}")
@@ -156,65 +171,102 @@ for file in $(ls -1 ${INCOMING}/*.key); do
     # - keysize 4096 or larger
     # - RSA key, no encryption capability
     # - UID matching "buildd autosigning key BUILDDNAME <buildd_ARCH-BUILDDNAME@buildd.debian.org>
-    # - expire within a 120 days
+    # - expire within a 360 days
     # - maximum 2 keys per architecture and buildd
 
     TEMPKEYDATA=$(mktemp -p "${TMPDIR}" BDKEYS.XXXXXX)
 
-    gpg ${DEFGPGOPT} --with-colons "${GPGOUTF}" > "${TEMPKEYDATA}"
+    # We also need to ensure this works, otherwise manually mangled files can break us here
+    if ! gpg ${DEFGPGOPT} --with-colons "${GPGOUTF}" > "${TEMPKEYDATA}"; then
+        log "For some reason we could validate the sig but failed on getting key details"
+        DATE=$(date -Is)
+        mv "${INCOMING}/${file}" "${ERRORS}/badsig.${file}.${DATE}"
+        mv "${GPGSTATUS}" "${ERRORS}/badsig.${file}.gpgstatus.${DATE}"
+        mv "${GPGLOGS}" "${ERRORS}/badsig.${file}.gpglogs.${DATE}"
+        rm -f "${GPGOUTF}"
+        rm -f "${TMPKEYDATA}"
+        continue
+    fi
 
     # Read in the TEMPKEYDATAFILE, but avoid using a subshell like a
     # while read line otherwise would do
     exec 4<> "${TEMPKEYDATA}"
-    error=""
+    KEYUID=""
+    #pub:-:4096:1:FAB983612A6554FA:2011-03-24:2011-07-22::-:buildd autosigning key poulenc <buildd_powerpc-poulenc@buildd.debian.org>:
+
+    # Of course this sucky gpg crapshit of an "interface" does give you different things depending on how people
+    # created their keys. And of course the buildd people created the test keys differently to what they now do
+    # which just means extra work for nothing. So as they now do other steps, the thing we get back suddenly looks like
+
+    #pub:-:4096:1:99595DC7865BEAD2:2011-03-26:2011-07-24::-:
+    #uid:::::::::buildd autosigning key corelli <buildd_mips-corelli@buildd.debian.org>:
+
+    # Besides fiddling out the data we need to check later, this regex also check:
+    # - the keytype (:1:, 1 there means RSA)
+    # - the UID
+    # - that the key does have an expiration date (or it wont match, the second date
+    #   field would be empty
+    regex="^pub:-:([0-9]{4}):1:([0-9A-F]{16}):([0-9]{4}-[0-9]{2}-[0-9]{2}):([0-9]{4}-[0-9]{2}-[0-9]{2})::-:(buildd autosigning key ${BUILDD} <buildd_${ARCH}-${BUILDD}@buildd.debian.org>):$"
+    regex2="^pub:-:([0-9]{4}):1:([0-9A-F]{16}):([0-9]{4}-[0-9]{2}-[0-9]{2}):([0-9]{4}-[0-9]{2}-[0-9]{2})::-:$"
+    regex3="^uid:::::::::(buildd autosigning key ${BUILDD} <buildd_${ARCH}-${BUILDD}@buildd.debian.org>):$"
     while read line <&4; do
-        #pub:-:4096:1:FAB983612A6554FA:2011-03-24:2011-07-22::-:buildd autosigning key poulenc <buildd_powerpc-poulenc@buildd.debian.org>:
-
-        # Besides fiddling out the data we need to check later, this regex also check:
-        # - the keytype (:1:, 1 there means RSA)
-        # - the UID
-        # - that the key does have an expiration date (or it wont match, the second date
-        #   field would be empty
-        regex="^pub:-:([0-9]{4}):1:([0-9A-F]{16}):([0-9]{4}-[0-9]{2}-[0-9]{2}):([0-9]{4}-[0-9]{2}-[0-9]{2})::-:buildd autosigning key ${BUILDD} <buildd_${ARCH}-${BUILDD}@buildd.debian.org>:$"
         if [[ $line =~ $regex ]]; then
             KEYSIZE=${BASH_REMATCH[1]}
             KEYID=${BASH_REMATCH[2]}
             KEYCREATE=${BASH_REMATCH[3]}
             KEYEXPIRE=${BASH_REMATCH[4]}
-
-            # We do want 4096 or anything above
-            if [ ${KEYSIZE} -lt 4096 ]; then
-                log "Keysize ${KEYSIZE} too small"
-                error="${error} Keysize ${KEYSIZE} too small"
-                continue
-            fi
-
-            # We want a maximum lifetime of 120 days, so check that.
-            # Easiest to compare in epoch, so lets see, 120 days midnight from now,
-            # compared with their set expiration date at midnight
-            # maxdate should turn out higher. just in case we make it 121 for this check
-            maxdate=$(date -d '121 day 00:00:00' +%s)
-            theirexpire=$(date -d "${KEYEXPIRE} 00:00:00" +%s)
-            if [ ${theirexpire} -gt ${maxdate} ]; then
-                log "Key expiry ${KEYEXPIRE} wrong"
-                error="${error} Key expiry ${KEYEXPIRE} wrong"
-                continue
-            fi
-        else
-            log "Unknown line $line, sod off"
-            error="${error} Unknown line $line, sod off"
-            continue
-        fi
+        KEYUID=${BASH_REMATCH[5]}
+    elif [[ $line =~ $regex2 ]]; then
+        KEYSIZE=${BASH_REMATCH[1]}
+            KEYID=${BASH_REMATCH[2]}
+            KEYCREATE=${BASH_REMATCH[3]}
+            KEYEXPIRE=${BASH_REMATCH[4]}
+    elif [[ $line =~ $regex3 ]]; then
+        KEYUID=${BASH_REMATCH[1]}
+    else
+        log "Didn't recognize the key. Go kiss gpg"
+            DATE=$(date -Is)
+            mv "${INCOMING}/${file}" "${ERRORS}/badkey.${file}.${DATE}"
+            mv "${GPGSTATUS}" "${ERRORS}/badkey.${file}.gpgstatus.${DATE}"
+            mv "${GPGLOGS}" "${ERRORS}/badkey.${file}.gpglogs.${DATE}"
+            rm -f "${GPGOUTF}"
+        continue
+    fi
     done
-    if [ -n "${error}" ]; then
-        log ${error}
+    if [ -z "${KEYUID}" ]; then
+    log "Did not recognize the UID format"
         DATE=$(date -Is)
-        mv "${INCOMING}/${file}" "${ERRORS}/badkey.${file}.${DATE}"
-        mv "${GPGSTATUS}" "${ERRORS}/badkey.${file}.gpgstatus.${DATE}"
-        mv "${GPGLOGS}" "${ERRORS}/badkey.${file}.gpglogs.${DATE}"
-        echo "${error}" >> "${ERRORS}/badkey.${file}.error.${DATE}"
+        mv "${INCOMING}/${file}" "${ERRORS}/keyuid.${file}.${DATE}"
+        mv "${GPGSTATUS}" "${ERRORS}/keyuid.${file}.gpgstatus.${DATE}"
+        mv "${GPGLOGS}" "${ERRORS}/keyuid.${file}.gpglogs.${DATE}"
         rm -f "${GPGOUTF}"
-        continue
+    continue
+    fi
+    # We do want 4096 or anything above
+    if [ ${KEYSIZE} -lt 4096 ]; then
+        log "Keysize ${KEYSIZE} too small"
+        DATE=$(date -Is)
+        mv "${INCOMING}/${file}" "${ERRORS}/keysize.${file}.${DATE}"
+        mv "${GPGSTATUS}" "${ERRORS}/keysize.${file}.gpgstatus.${DATE}"
+        mv "${GPGLOGS}" "${ERRORS}/keysize.${file}.gpglogs.${DATE}"
+        rm -f "${GPGOUTF}"
+    continue
+    fi
+
+    # We want a maximum lifetime of 365 days, so check that.
+    # Easiest to compare in epoch, so lets see, 365 days midnight from now,
+    # compared with their set expiration date at midnight
+    # maxdate should turn out higher. just in case we make it 366 for this check
+    maxdate=$(date -d '366 day 00:00:00' +%s)
+    theirexpire=$(date -d "${KEYEXPIRE} 00:00:00" +%s)
+    if [ ${theirexpire} -gt ${maxdate} ]; then
+        log "Key expiry ${KEYEXPIRE} wrong"
+        DATE=$(date -Is)
+        mv "${INCOMING}/${file}" "${ERRORS}/keyexpire.${file}.${DATE}"
+        mv "${GPGSTATUS}" "${ERRORS}/keyexpire.${file}.gpgstatus.${DATE}"
+        mv "${GPGLOGS}" "${ERRORS}/keyexpire.${file}.gpglogs.${DATE}"
+        rm -f "${GPGOUTF}"
+    continue
     fi
 
     # And now lets check how many keys this buildd already has. 2 is the maximum, so key
@@ -234,7 +286,9 @@ for file in $(ls -1 ${INCOMING}/*.key); do
 
     # Right. At this point everything should be in order, which means we should put the key into
     # the keyring
-    log "Accepting key ${KEYID} for ${ARCH} buildd ${BUILDD}, expire ${KEYEXPIRE}"
+    KEYSUBMITTER=$(cat "${GPGSTATUS}"|grep GOODSIG)
+    KEYSUBMITTER=${KEYSUBMITTER##*GOODSIG}
+    log "${KEYSUBMITTER} added key ${KEYID} for ${ARCH} buildd ${BUILDD}, expire ${KEYEXPIRE}"
     gpg ${DEFGPGOPT} --status-fd 4 --logger-fd 5 --keyring "${ARCHKEYRING}" --import "${GPGOUTF}" 2>/dev/null
 
     mv "${INCOMING}/${file}" "${base}/${ARCH}"