Skip to content

Commit

Permalink
rename udbot1 to ubot1, add flags for it and for pks/add
Browse files Browse the repository at this point in the history
  • Loading branch information
jbar committed Oct 19, 2012
1 parent 596a84a commit a5e642d
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 66 deletions.
22 changes: 11 additions & 11 deletions docs/OpenUDC_Authentication_Mechanisms.draft.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Request for Comments: Open-UDC Team
4.4 Explicit living trust level .................................
4.5 Proof of life ...............................................
5. Bot Authentication .............................................
6. Node Authentication .............................................
6. Pool Authentication .............................................

1.== Introduction ==

Expand Down Expand Up @@ -73,10 +73,10 @@ Request for Comments: Open-UDC Team
Was used for Human Authentication, now deprecated.
- "udid2"
Used for Human Authentication.
- "udbot1"
Used for Bot Authentication.
- "udnode1"
Used for Node Authentication.
- "ubot1"
Used for Bot (ie. Node) Authentication.
- "upoo1"
Used for Pool Authentication.

The charaters after the last recognized field in the string SHOULD be
ignored and MAY use other charset (UTF-8...). They MAY be use to add
Expand Down Expand Up @@ -347,13 +347,13 @@ Request for Comments: Open-UDC Team
To prevent that, each bot are authenticated as a human's minion:

Each bots have their own OpenPGP certificate, and one of the uid
comment field MUST begin with the special string "udbot1;" ,
comment field MUST begin with the special string "ubot1;" ,
followed immediately by the full udid2 of its master.

e.g.: the OpenPGP certificate of François-Xavier-Robert's bot MUST
have this string in the comment field of one of its uid:

udbot1;udid2;h;85bbb64915ae7f2cdbe54618453b3ed107f1f242;0;
ubot1;udid2;h;85bbb64915ae7f2cdbe54618453b3ed107f1f242;0;

And this OpenPGP uid MUST be signed by the human master to proove
she/he recognized this minion.
Expand All @@ -364,10 +364,10 @@ Request for Comments: Open-UDC Team
Note: take care that private key(s) of bots are often not protected
by a passphrase.

6.== Node Authentication ==
6.== Pool Authentication ==

As long as a single network will be enough to trade efficiently in
a given web of trust, splitting the network into different node will
not be mandatory.
a given web of trust, splitting the network into different pools
will not be mandatory.

(Today, 31 may 2011) Node specification may wait.
(Today, 31 may 2011) Pool specification may wait.
2 changes: 1 addition & 1 deletion ludd/src/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ mmc.o: mmc.h libhttpd.h
timers.o: timers.h
match.o: match.h
tdate_parse.o: tdate_parse.h
hkp.o: hkp.h libhttpd.h
hkp.o: config.h hkp.h libhttpd.h
22 changes: 21 additions & 1 deletion ludd/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
/* CONFIGURE: How many seconds to allow for reading the initial request
** on a new connection.
*/
#define IDLE_READ_TIMELIMIT 60
#define IDLE_READ_TIMELIMIT 30

/* CONFIGURE: How many seconds before an idle connection gets closed.
*/
Expand All @@ -113,6 +113,26 @@
*/
//#define AUTH_FILE ".htpasswd"


/* CONFIGURE: This disable new keys to be added through pks/add. If defined
* the keyring only accept existing key through pks/add (for updates like revoking).
* The default procedure for importing new keys is to write their fingerprint in a
* creation sheet.
* If you don't want to have unused or unknow keys in your keyring, you should define it.
*/
#define RESTRICTED_PKS_ADD

/* CONFIGURE: This is required for OpenUDC compatibility : it checks that your bot
* certificate contain a valid udid2.
* (ie: "udid2;c;[A-Z]\{1,20\};[A-Z-]\{1,20\};[0-9-]\{10\};[0-9.e+-]\{14\};[0-9]\+" )
* Note: if RESTRICTED_PKS_ADD is undef, it also checks those added through pks/add.
*/
#define CHECK_UDID2

/* CONFIGURE: It implies to log keys sended to pks/add (still via syslog).
*/
//#define LOG_PKS_ADD

/* CONFIGURE: The default character set name to use with text MIME types.
** This gets substituted into the MIME types where they have a "%s".
**
Expand Down
106 changes: 77 additions & 29 deletions ludd/src/hkp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
#include <unistd.h>
#include <errno.h> /* errno */
#include <gpgme.h>
#include <regex.h>
#include <pthread.h>

#include "config.h"
#include "hkp.h"
#include "timers.h"
#include "libhttpd.h"
Expand All @@ -26,25 +28,30 @@ struct gpgdata4export_handle {
char ** searchs;
};


static int export_start=0; /* set to 1 once by gpgdata4export_cb(...) */

/* return this first comment starting with ud found in uids (or NULL if non found) */
static char * get_starting_comment(char * ud, gpgme_key_t gkey) {
#if defined CHECK_UDID2 && ! defined RESTRICTED_PKS_ADD
extern regex_t udid2c_regex;

/* get first uid in a key where comment match preg
* \return the uid (or NULL if non found) */
static char * get_matching_comment(const regex_t *preg,const gpgme_key_t gkey) {
gpgme_user_id_t gpguids;
size_t n;

if (! ud)
if (! preg)
return((char *) 0);

n=strlen(ud);
gpguids=gkey->uids;
while (gpguids) {
if (!strncmp(gpguids->comment,ud,n))
return gpguids->comment;
if ( !regexec(preg,gpguids->comment, 0, NULL, 0)
|| !regexec(preg,gpguids->comment+sizeof("ubot1"), 0, NULL, 0) )
return gpguids->uid;
gpguids=gpguids->next;
}
return((char *) 0);
}
#endif

int hkp_add( httpd_conn* hc ) {
#define INPUT_MAX (1<<17) /* 1<<17 = 128ko */
Expand All @@ -54,13 +61,17 @@ int hkp_add( httpd_conn* hc ) {
gpgme_ctx_t gpglctx;
gpgme_error_t gpgerr;
gpgme_data_t gpgdata;
gpgme_import_result_t gpgimport;
gpgme_import_status_t gpgikey;
gpgme_key_t gpgkey;
gpgme_import_result_t gpgimport=NULL;
#if defined RESTRICTED_PKS_ADD || defined CHECK_UDID2 || defined LOG_PKS_ADD
gpgme_import_status_t gpgikey=NULL;
gpgme_key_t gpgkey=NULL;
char * uid2=NULL;
#endif

char * buff;
int buffsize, rcode=200;


if ( hc->method == METHOD_HEAD ) {
send_mime(
hc, 200, ok200title, "", "", "text/html; charset=%s", (off_t) -1,
Expand Down Expand Up @@ -154,8 +165,8 @@ int hkp_add( httpd_conn* hc ) {
exit(EXIT_FAILURE);
}

if ((gpgimport= gpgme_op_import_result(gpglctx)) == NULL ) {
httpd_send_err(hc, 500, err500title, "", err500form, "" );
if ((gpgimport=gpgme_op_import_result(gpglctx)) == NULL ) {
httpd_send_err(hc, 500, err500title, "", err500form, "r" );
exit(EXIT_FAILURE);
}

Expand All @@ -164,46 +175,83 @@ int hkp_add( httpd_conn* hc ) {
exit(EXIT_FAILURE);
}

#if defined RESTRICTED_PKS_ADD || defined CHECK_UDID2 || defined LOG_PKS_ADD
/* Check (and eventually delete) imported keys */
gpgikey=gpgimport->imports;
while (gpgikey) {

if ( (gpgikey->result != GPG_ERR_NO_ERROR) || (! (gpgikey->status & GPGME_IMPORT_NEW)) ) {
/* erronous or known key */
if ( gpgikey->result != GPG_ERR_NO_ERROR ) {
/* erronous key */
gpgikey=gpgikey->next;
continue;
}

/* key is new, check that it match our policy. */
if ( (gpgerr=gpgme_get_key (gpglctx,gpgikey->fpr,&gpgkey,0)) != GPG_ERR_NO_ERROR ) {
/* should not happen */
httpd_send_err(hc, 500, err500title, "", err500form, "" );
exit(EXIT_FAILURE);
/* Is the key new ? */
if ( gpgikey->status & GPGME_IMPORT_NEW ) {
/* get the key. */
if ( (gpgerr=gpgme_get_key (gpglctx,gpgikey->fpr,&gpgkey,0)) != GPG_ERR_NO_ERROR ) {
/* should not happen */
httpd_send_err(hc, 500, err500title, "", err500form, "" );
exit(EXIT_FAILURE);
}
#ifdef RESTRICTED_PKS_ADD
if (1)
#else
#ifdef CHECK_UDID2
/* Check an uid with comment matching "udid2;c;..." or "ubot1;udid2;c..." */
uid2=get_matching_comment(&udid2c_regex,gpgkey);
if (!uid2)
#else
if (0)
#endif /* CHECK_UDID2 */
#endif /* RESTRICTED_PKS_ADD */
{
#ifdef LOG_PKS_ADD
syslog(LOG_INFO,"pks/add:reject:%d:%s:%s:",gpgikey->status,gpgikey->fpr,uid2?uid2:gpgkey->uids->uid);
#endif /* LOG_PKS_ADD */
rcode=202;
gpgerr=gpgme_op_delete(gpglctx,gpgkey,1); /* Note: this also unref the key */
}
#ifdef LOG_PKS_ADD
else
syslog(LOG_INFO,"pks/add:accept:%d:%s:%s:",gpgikey->status,gpgikey->fpr,uid2?uid2:gpgkey->uids->uid);
#endif /* LOG_PKS_ADD */
gpgme_key_unref(gpgkey);
}
#ifdef LOG_PKS_ADD
else
syslog(LOG_INFO,"pks/add:update:%d:%s:",gpgikey->status,gpgikey->fpr);
#endif /* LOG_PKS_ADD */

/* Check that it does expire and an uid comment start with "udid2;c;" or "udbot1;" */
if (!( gpgkey->subkeys->expires > 0
&& (get_starting_comment("udid2;c;",gpgkey)
|| get_starting_comment("udbot1;",gpgkey)) )) {
rcode=202;
gpgme_op_delete (gpglctx,gpgkey,1);
}
#ifdef REEXPORT_PKS_ADD /* I have try almost every thing, but it doesn't work ! :-( */
if (gpgkey)
{
gpgme_key_t keyarray[10];
keyarray[0]=gpgkey;
keyarray[1]=NULL;
//gpgerr=gpgme_set_keylist_mode(gpglctx,gpgme_get_keylist_mode(gpglctx)|GPGME_KEYLIST_MODE_EXTERN|GPGME_KEYLIST_MODE_EPHEMERAL|GPGME_KEYLIST_MODE_LOCAL);
gpgme_set_armor(gpglctx,1);
//gpgerr=gpgme_op_export(gpglctx,gpgikey->fpr,GPGME_EXPORT_MODE_EXTERN,NULL); /* Doesn't seems to work :-( */
gpgerr=gpgme_op_export_keys(gpglctx, keyarray,GPGME_KEYLIST_MODE_EXTERN,NULL); /* Doesn't work either :-( */
//syslog(LOG_INFO,"gpgme_op_export: %s ",gpgme_strerror(gpgerr));
}
#endif /* REEXPORT_PKS_ADD */
gpgikey=gpgikey->next;
}

if (rcode==202)
send_mime(hc, 202, ok200title, "", "X-HKP-Status: 418 some key(s) was rejected as per keyserver policy\015\012", "text/html; charset=%s",(off_t) -1, hc->sb.st_mtime );
else
#endif /* RESTRICTED_PKS_ADD || CHECK_UDID2 */
send_mime(hc, 200, ok200title, "", "", "text/html; charset=%s",(off_t) -1, hc->sb.st_mtime );
httpd_write_response(hc);
r=snprintf(buff,buffsize,"<html><head><title>%d keys sended </title></head><body><h2>Total: %d<br>imported: %d<br>unchanged: %d<br>no_user_id: %d<br>new_user_ids: %d<br>new_sub_keys: %d<br>new_signatures: %d<br>new_revocations: %d<br>secret_read: %d<br>not_imported: %d</h2></body></html>", gpgimport->considered, gpgimport->considered, gpgimport->imported, gpgimport->unchanged, gpgimport->no_user_id, gpgimport->new_user_ids, gpgimport->new_sub_keys, gpgimport->new_signatures, gpgimport->new_revocations, gpgimport->secret_read, gpgimport->not_imported);
r=snprintf(buff,buffsize,"<html><head><title>pks/add %d keys</title></head><body><h2>Total: %d<br>imported: %d<br>unchanged: %d<br>no_user_id: %d<br>new_user_ids: %d<br>new_sub_keys: %d<br>new_signatures: %d<br>new_revocations: %d<br>secret_read: %d<br>not_imported: %d</h2></body></html>", gpgimport->considered, gpgimport->considered, gpgimport->imported, gpgimport->unchanged, gpgimport->no_user_id, gpgimport->new_user_ids, gpgimport->new_sub_keys, gpgimport->new_signatures, gpgimport->new_revocations, gpgimport->secret_read, gpgimport->not_imported);
httpd_write_fully( hc->conn_fd, buff,MIN(r,buffsize));

gpgme_release (gpglctx);
exit(EXIT_SUCCESS);

/* TODO:
* Note in memory the fpr in gpgme_import_status_t of all keys imported to :
* - clean them (remove previous or useless signatures).
* - revoke the one with with an usable secret key.
* - propagate them to other ludd key server.
* DONE:
Expand Down
2 changes: 1 addition & 1 deletion ludd/src/libhttpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ httpd_send_err( httpd_conn* hc, int status, char* title, char* extraheads, const

/* log server error */
if (status>=500)
syslog( LOG_ERR, "HTTP %d (%.80s):%m \"%.80s\"",status,arg,hc->encodedurl );
syslog( LOG_ERR, "HTTP %d (%.80s) - %m \"%.80s\"",status,arg,hc->encodedurl );

send_mime(
hc, status, title, "", extraheads, "text/html; charset=%s", (off_t) -1,
Expand Down
23 changes: 13 additions & 10 deletions ludd/src/ludd_init.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function ludd_genbotkey {
for ((;;)) ; do
read -p "What is ur id (udid2;c;...) ? " myudid
if grep "^udid2;c;[A-Z]\{1,20\};[A-Z-]\{1,20\};[0-9-]\{10\};[0-9.e+-]\{14\};[0-9]\+;\?$" <(echo $myudid) > /dev/null ; then
myudid=${myudid%;} #remove last ';' if present.
break;
else
echo "Warning: this id ($myudid) is not a valid udid2 for OpenUDC" >&2
Expand Down Expand Up @@ -77,7 +78,7 @@ function ludd_genbotkey {
8y
$mname
$email
udbot1;$myudid;
ubot1;$myudid
EOF
Expand Down Expand Up @@ -121,7 +122,7 @@ if [[ "$dir" != "$refdir" ]] ; then
cp -avf "$refdir/pub/c" "$dir/pub"
fi

mybotkeys=($(gpg --list-secret-keys --with-colons --with-fingerprint "udbot1;" | grep "^fpr" | cut -d: -f 10))
mybotkeys=($(gpg --list-secret-keys --with-colons --with-fingerprint "ubot1;" | grep "^fpr" | cut -d: -f 10))

echo "NOTE: passphrase to cypher bot's private key is unsupported yet".
ludd_chooseinlist "bot key to use ?" 1 "create a new one" "${mybotkeys[@]}"
Expand All @@ -133,38 +134,40 @@ case $bki in
;;
1)
ludd_genbotkey || exit 4
mybotkeys=($(gpg --list-secret-keys --with-colons --with-fingerprint "udbot1;udid2;" | grep "^fpr" | cut -d: -f 10))
mybotkeys=($(gpg --list-secret-keys --with-colons --with-fingerprint "ubot1;udid2;" | grep "^fpr" | cut -d: -f 10))
bki=$((${#mybotkeys[@]}-1))
;;
*)
((bki-=2))
esac

myudid="$(gpg --list-secret-keys --with-colons ${mybotkeys[$bki]} | sed -n ' s/^sec:.*(udbot1;\(udid2;c;[A-Z]\{1,20\};[A-Z-]\{1,20\};[0-9-]\{10\};[0-9.e+-]\{14\};[0-9]\+\).*/\1/p ' )"
myudid="$(gpg --list-secret-keys --with-colons ${mybotkeys[$bki]} | sed -n ' s/^sec:.*(ubot1;\(udid2;c;[A-Z]\{1,20\};[A-Z-]\{1,20\};[0-9-]\{10\};[0-9.e+-]\{14\};[0-9]\+\);\?).*/\1/p ' )"
if [ -z "$myudid" ] ; then
echo "Warning: key ${mybotkeys[$bki]} is not a valid bot key for OpenUDC" >&2
read -p " Will your node join an OpenUDC network ? (y/n) " answer
case "$answer" in
Y* | y* | O* | o* )
exit 3 ;;
esac
myudid="$(gpg --list-secret-keys --with-colons ${mybotkeys[$bki]} | sed -n ' s/^sec:.*(udbot1;\([^)]\+\).*/\1/p ' )"
myudid="$(gpg --list-secret-keys --with-colons ${mybotkeys[$bki]} | sed -n ' s/^sec:.*(ubot1;\([^)]\+\).*/\1/p ' )"
[ -z "$myudid" ] && exit 3
fi

# Export udbot1 key and owner's key to the keyring.
gpg --homedir "$dir/gpgme" --keyserver "$KEYSERVER" --search-keys "$myudid"
gpg --export-secret-keys "${mybotkeys[$bki]}" | gpg --import --homedir "$dir/gpgme"
# Export ubot1 key and owner's key to the keyring.
gpg --keyserver "$KEYSERVER" --search-keys "$myudid"
gpg --export "($myudid" | gpg --import --homedir "$dir/gpgme" > /dev/null
gpg --export-secret-keys "${mybotkeys[$bki]}" | gpg --import --homedir "$dir/gpgme" > /dev/null

if ((isroot)) ; then
chown -R .ludd "$dir/gpgme"
fi

if ! grep "$LUDDVERSION ###" "$dir/gpgme/gpg.conf" > /dev/null ; then
if ! grep "$LUDDVERSION ###" "$dir/gpgme/gpg.conf" > /dev/null 2>&1 ; then
cat >> "$dir/gpgme/gpg.conf" <<EOF
### following import-option line has been added $(date -R) by ${0##*/} - $LUDDVERSION ###
#import-options import-clean
keyserver $KEYSERVER
EOF
fi
chmod go+r "$dir/gpgme/gpg.conf"
Expand Down Expand Up @@ -239,7 +242,7 @@ EOF
cat <<EOF
NOTE: your bot's certificate have to be signed with your own OpenPGP certificate.
It means that on the machine where your secret key is available, you should do:
$ gpg --sign "${mybotkeys[$bki]}"
$ gpg --sign-key "${mybotkeys[$bki]}"
$ gpg --keyserver "$myhost:$myport" --send-keys "0x${mybotkeys[$bki]}"
EOF

Expand Down
Loading

0 comments on commit a5e642d

Please sign in to comment.