diff --git a/sm/ChangeLog b/sm/ChangeLog index fa6f0b791..e6634689f 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2008-06-12 Marcus Brinkmann + + * gpgsm.h (struct keyserver_spec): New struct. + (opt): Add member keyserver. + * gpgsm.c (keyserver_list_free, parse_keyserver_line): New functions. + (main): Implement --keyserver option. + * call-dirmngr.c (prepare_dirmngr): Send LDAPSERVER commands. + 2008-05-20 Werner Koch * gpgsm.c (main) : Pass FP and not stdout to diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 63083cc92..35e937956 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -140,6 +140,8 @@ get_membuf (struct membuf *mb, size_t *len) static void prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err) { + struct keyserver_spec *server; + if (!ctrl->dirmngr_seen) { ctrl->dirmngr_seen = 1; @@ -152,6 +154,25 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err) } audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err); } + + server = opt.keyserver; + while (server) + { + char line[ASSUAN_LINELENGTH]; + char *user = server->user ? server->user : ""; + char *pass = server->pass ? server->pass : ""; + char *base = server->base ? server->base : ""; + + snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s", + server->host, server->port, user, pass, base); + line[DIM (line) - 1] = 0; + + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION) + err = 0; /* Allow the use of old dirmngr versions. */ + + server = server->next; + } } diff --git a/sm/gpgsm.c b/sm/gpgsm.c index a26775a58..50ffb84d2 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -361,7 +361,7 @@ static ARGPARSE_OPTS opts[] = { { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, - { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, + { oKeyServer, "keyserver",2, N_("|SPEC|use this keyserver to lookup keys")}, { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, { oOptions, "options" , 2, N_("read options from file")}, @@ -819,6 +819,99 @@ parse_validation_model (const char *model) } +/* Release the list of SERVERS. As usual it is okay to call this + function with SERVERS passed as NULL. */ +void +keyserver_list_free (struct keyserver_spec *servers) +{ + while (servers) + { + struct keyserver_spec *tmp = servers->next; + xfree (servers->host); + xfree (servers->user); + if (servers->pass) + memset (servers->pass, 0, strlen (servers->pass)); + xfree (servers->pass); + xfree (servers->base); + xfree (servers); + servers = tmp; + } +} + +/* See also dirmngr ldapserver_parse_one(). */ +struct keyserver_spec * +parse_keyserver_line (char *line, + const char *filename, unsigned int lineno) +{ + char *p; + char *endp; + struct keyserver_spec *server; + int fieldno; + int fail = 0; + + /* Parse the colon separated fields. */ + server = xcalloc (1, sizeof *server); + for (fieldno = 1, p = line; p; p = endp, fieldno++ ) + { + endp = strchr (p, ':'); + if (endp) + *endp++ = '\0'; + trim_spaces (p); + switch (fieldno) + { + case 1: + if (*p) + server->host = xstrdup (p); + else + { + log_error (_("%s:%u: no hostname given\n"), + filename, lineno); + fail = 1; + } + break; + + case 2: + if (*p) + server->port = atoi (p); + break; + + case 3: + if (*p) + server->user = xstrdup (p); + break; + + case 4: + if (*p && !server->user) + { + log_error (_("%s:%u: password given without user\n"), + filename, lineno); + fail = 1; + } + else if (*p) + server->pass = xstrdup (p); + break; + + case 5: + if (*p) + server->base = xstrdup (p); + break; + + default: + /* (We silently ignore extra fields.) */ + break; + } + } + + if (fail) + { + log_info (_("%s:%u: skipping this line\n"), filename, lineno); + keyserver_list_free (server); + } + + return server; +} + + int main ( int argc, char **argv) { @@ -1317,6 +1410,24 @@ main ( int argc, char **argv) case oValidationModel: parse_validation_model (pargs.r.ret_str); break; + case oKeyServer: + { + struct keyserver_spec *keyserver; + keyserver = parse_keyserver_line (pargs.r.ret_str, + configname, configlineno); + if (! keyserver) + log_error (_("could not parse keyserver\n")); + else + { + /* FIXME: Keep last next pointer. */ + struct keyserver_spec **next_p = &opt.keyserver; + while (*next_p) + next_p = &(*next_p)->next; + *next_p = keyserver; + } + } + break; + case aDummy: break; default: @@ -1578,40 +1689,25 @@ main ( int argc, char **argv) GC_OPT_FLAG_DEFAULT, config_filename_esc); xfree (config_filename_esc); - printf ("verbose:%lu:\n" - "quiet:%lu:\n" - "debug-level:%lu:\"none:\n" - "log-file:%lu:\n", - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_DEFAULT, - GC_OPT_FLAG_NONE ); - printf ("disable-crl-checks:%lu:\n", - GC_OPT_FLAG_NONE ); - printf ("disable-trusted-cert-crl-check:%lu:\n", - GC_OPT_FLAG_NONE ); - printf ("enable-ocsp:%lu:\n", - GC_OPT_FLAG_NONE ); - printf ("include-certs:%lu:1:\n", - GC_OPT_FLAG_DEFAULT ); - printf ("disable-policy-checks:%lu:\n", - GC_OPT_FLAG_NONE ); - printf ("auto-issuer-key-retrieve:%lu:\n", - GC_OPT_FLAG_NONE ); - printf ("disable-dirmngr:%lu:\n", - GC_OPT_FLAG_NONE ); + printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE); + printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE); + printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT); + printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE); + printf ("disable-crl-checks:%lu:\n", GC_OPT_FLAG_NONE); + printf ("disable-trusted-cert-crl-check:%lu:\n", GC_OPT_FLAG_NONE); + printf ("enable-ocsp:%lu:\n", GC_OPT_FLAG_NONE); + printf ("include-certs:%lu:1:\n", GC_OPT_FLAG_DEFAULT); + printf ("disable-policy-checks:%lu:\n", GC_OPT_FLAG_NONE); + printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE); + printf ("disable-dirmngr:%lu:\n", GC_OPT_FLAG_NONE); #ifndef HAVE_W32_SYSTEM - printf ("prefer-system-dirmngr:%lu:\n", - GC_OPT_FLAG_NONE ); + printf ("prefer-system-dirmngr:%lu:\n", GC_OPT_FLAG_NONE); #endif - printf ("cipher-algo:%lu:\"3DES:\n", - GC_OPT_FLAG_DEFAULT ); - printf ("p12-charset:%lu:\n", - GC_OPT_FLAG_DEFAULT ); - printf ("default-key:%lu:\n", - GC_OPT_FLAG_DEFAULT ); - printf ("encrypt-to:%lu:\n", - GC_OPT_FLAG_DEFAULT ); + printf ("cipher-algo:%lu:\"3DES:\n", GC_OPT_FLAG_DEFAULT); + printf ("p12-charset:%lu:\n", GC_OPT_FLAG_DEFAULT); + printf ("default-key:%lu:\n", GC_OPT_FLAG_DEFAULT); + printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_DEFAULT); + printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); } break; @@ -1883,6 +1979,8 @@ main ( int argc, char **argv) } /* cleanup */ + keyserver_list_free (opt.keyserver); + opt.keyserver = NULL; gpgsm_release_certlist (recplist); gpgsm_release_certlist (signerlist); FREE_STRLIST (remusr); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 73231671c..acc53b574 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -35,6 +35,18 @@ #define MAX_DIGEST_LEN 24 +struct keyserver_spec +{ + struct keyserver_spec *next; + + char *host; + int port; + char *user; + char *pass; + char *base; +}; + + /* A large struct named "opt" to keep global flags. */ struct { @@ -123,6 +135,8 @@ struct runtime option in case we want to check the integrity of the software at runtime. */ + + struct keyserver_spec *keyserver; } opt; diff --git a/tools/ChangeLog b/tools/ChangeLog index 6675e6157..9981212c7 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2008-06-12 Marcus Brinkmann + + * gpgconf-comp.c (gc_options_gpgsm): Add option keyserver. + 2008-05-26 Marcus Brinkmann * gpgconf-comp.c: Replace pathname by filename everywhere. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 5e7dd77f1..5cda2f118 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -732,6 +732,9 @@ static gc_option_t gc_options_gpgsm[] = { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", N_("|NAME|use encoding NAME for PKCS#12 passphrases"), GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, + { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + "gnupg", N_("|SPEC|use this keyserver to lookup keys"), + GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,