From 99829ef5fbff1c0a4aa9fb0b55b4720b44985c39 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 26 Nov 2001 13:08:36 +0000 Subject: [PATCH] * keydb.c (keydb_add_resource): Create keybox * keylist.c (gpgsm_list_keys): Fixed non-server keylisting. * server.c (rc_to_assuan_status): New. Use it for all commands. --- sm/ChangeLog | 20 ++++ sm/call-agent.c | 8 +- sm/keydb.c | 255 +++++++++++++++++++++++------------------------- sm/keylist.c | 14 +-- sm/server.c | 58 +++++++++-- sm/sign.c | 15 ++- sm/verify.c | 34 +++++++ 7 files changed, 251 insertions(+), 153 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index e69de29bb..878002c5d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -0,0 +1,20 @@ +2001-11-26 Werner Koch + + * keydb.c (keydb_add_resource): Create keybox + + * keylist.c (gpgsm_list_keys): Fixed non-server keylisting. + + * server.c (rc_to_assuan_status): New. Use it for all commands. + + + Copyright 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + diff --git a/sm/call-agent.c b/sm/call-agent.c index c440f2bf1..16cc46fb7 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -470,16 +470,16 @@ request_reply (const char *line, struct membuf *membuf) for (;len && *p != '%'; len--, p++) ; put_membuf (membuf, buf, p-buf); - buf = p; if (len>2) { /* handle escaping */ unsigned char tmp[1]; - buf++; - *tmp = xtoi_2 (buf); - buf += 2; + p++; + *tmp = xtoi_2 (p); + p += 2; len -= 3; put_membuf (membuf, tmp, 1); } + buf = p; } goto again; } diff --git a/sm/keydb.c b/sm/keydb.c index b6501fe5f..a5f3f41d8 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -78,134 +78,130 @@ static void unlock_all (KEYDB_HANDLE hd); int keydb_add_resource (const char *url, int force, int secret) { - static int any_secret, any_public; - const char *resname = url; - char *filename = NULL; - int rc = 0; - KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; -/* const char *created_fname = NULL; */ + static int any_secret, any_public; + const char *resname = url; + char *filename = NULL; + int rc = 0; + FILE *fp; + KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; + const char *created_fname = NULL; - /* Do we have an URL? - * gnupg-ring:filename := this is a plain keybox - * filename := See what is is, but create as plain keybox. - */ - if (strlen (resname) > 11) { - if (!strncmp( resname, "gnupg-kbx:", 10) ) { - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - resname += 11; - } - #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) - else if (strchr (resname, ':')) { - log_error ("invalid key resource URL `%s'\n", url ); - rc = GNUPG_General_Error; - goto leave; - } - #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ - } - - if (*resname != DIRSEP_C ) { /* do tilde expansion etc */ - if (strchr(resname, DIRSEP_C) ) - filename = make_filename (resname, NULL); - else - filename = make_filename (opt.homedir, resname, NULL); - } - else - filename = xstrdup (resname); - - if (!force) - force = secret? !any_secret : !any_public; - - /* see whether we can determine the filetype */ - if (rt == KEYDB_RESOURCE_TYPE_NONE) { - FILE *fp2 = fopen( filename, "rb" ); - - if (fp2) { - u32 magic; - - /* FIXME: check for the keybox magic */ - if (fread( &magic, 4, 1, fp2) == 1 ) - { - if (magic == 0x13579ace || magic == 0xce9a5713) - ; /* GDBM magic - no more support */ - else - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - } - else /* maybe empty: assume ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - fclose (fp2); - } - else /* no file yet: create ring */ + /* Do we have an URL? + gnupg-kbx:filename := this is a plain keybox + filename := See what is is, but create as plain keybox. + */ + if (strlen (resname) > 10) + { + if (!strncmp (resname, "gnupg-kbx:", 10) ) + { rt = KEYDB_RESOURCE_TYPE_KEYBOX; + resname += 10; + } +#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) + else if (strchr (resname, ':')) + { + log_error ("invalid key resource URL `%s'\n", url ); + rc = GNUPG_General_Error; + goto leave; + } +#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ } - switch (rt) { - case KEYDB_RESOURCE_TYPE_NONE: - log_error ("unknown type of key resource `%s'\n", url ); - rc = GNUPG_General_Error; - goto leave; - - case KEYDB_RESOURCE_TYPE_KEYBOX: -#if 0 - fp = fopen (filename); - if (!iobuf && !force) { - rc = G10ERR_OPEN_FILE; - goto leave; - } - - if (!fp) { - char *last_slash_in_filename; - - last_slash_in_filename = strrchr (filename, DIRSEP_C); - *last_slash_in_filename = 0; - - if (access(filename, F_OK)) { - /* on the first time we try to create the default + if (*resname != DIRSEP_C ) + { /* do tilde expansion etc */ + if (strchr(resname, DIRSEP_C) ) + filename = make_filename (resname, NULL); + else + filename = make_filename (opt.homedir, resname, NULL); + } + else + filename = xstrdup (resname); + + if (!force) + force = secret? !any_secret : !any_public; + + /* see whether we can determine the filetype */ + if (rt == KEYDB_RESOURCE_TYPE_NONE) + { + FILE *fp2 = fopen( filename, "rb" ); + + if (fp2) { + u32 magic; + + /* FIXME: check for the keybox magic */ + if (fread( &magic, 4, 1, fp2) == 1 ) + { + if (magic == 0x13579ace || magic == 0xce9a5713) + ; /* GDBM magic - no more support */ + else + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } + else /* maybe empty: assume ring */ + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + fclose (fp2); + } + else /* no file yet: create ring */ + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } + + switch (rt) + { + case KEYDB_RESOURCE_TYPE_NONE: + log_error ("unknown type of key resource `%s'\n", url ); + rc = GNUPG_General_Error; + goto leave; + + case KEYDB_RESOURCE_TYPE_KEYBOX: + fp = fopen (filename, "rb"); + if (!fp && !force) + { + rc = GNUPG_File_Open_Error; + goto leave; + } + + if (!fp) + { /* no file */ +#if 0 /* no autocreate of the homedirectory yet */ + { + char *last_slash_in_filename; + + last_slash_in_filename = strrchr (filename, DIRSEP_C); + *last_slash_in_filename = 0; + if (access (filename, F_OK)) + { /* on the first time we try to create the default homedir and in this case the process will be - terminated, so that on the next invocation it can + terminated, so that on the next invocation can read the options file in on startup */ - try_make_homedir (filename); - rc = G10ERR_OPEN_FILE; - *last_slash_in_filename = DIRSEP_C; - goto leave; + try_make_homedir (filename); + rc = GNUPG_File_Open_Error; + *last_slash_in_filename = DIRSEP_C; + goto leave; + } + *last_slash_in_filename = DIRSEP_C; + } +#endif + fp = fopen (filename, "w"); + if (!fp) + { + log_error (_("error creating keybox `%s': %s\n"), + filename, strerror(errno)); + rc = GNUPG_File_Create_Error; + goto leave; } - *last_slash_in_filename = DIRSEP_C; - - iobuf = iobuf_create (filename); - if (!iobuf) { - log_error ( _("error creating keybox `%s': %s\n"), - filename, strerror(errno)); - rc = G10ERR_OPEN_FILE; - goto leave; - } - else { - #ifndef HAVE_DOSISH_SYSTEM - if (secret && !opt.preserve_permissionws) { - if (chmod (filename, S_IRUSR | S_IWUSR) ) { - log_error (_("changing permission of " - " `%s' failed: %s\n"), - filename, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - goto leave; - } - } - #endif - if (!opt.quiet) - log_info (_("keybox `%s' created\n"), filename); - created_fname = filename; - } + if (!opt.quiet) + log_info (_("keybox `%s' created\n"), filename); + created_fname = filename; } - iobuf_close (iobuf); - iobuf = NULL; - if (created_fname) /* must invalidate that ugly cache */ - iobuf_ioctl (NULL, 2, 0, (char*)created_fname); -#endif + fclose (fp); + fp = NULL; + /* now regsiter the file */ { void *token = keybox_register_file (filename, secret); if (!token) ; /* already registered - ignore it */ else if (used_resources >= MAX_KEYDB_RESOURCES) - rc = GNUPG_Resource_Limit; + rc = GNUPG_Resource_Limit; else { all_resources[used_resources].type = rt; @@ -216,29 +212,26 @@ keydb_add_resource (const char *url, int force, int secret) } } break; - - default: - log_error ("resource type of `%s' not supported\n", url); - rc = GNUPG_General_Error; - goto leave; + default: + log_error ("resource type of `%s' not supported\n", url); + rc = GNUPG_Not_Supported; + goto leave; } - /* fixme: check directory permissions and print a warning */ + /* fixme: check directory permissions and print a warning */ - leave: - if (rc) - log_error ("keyblock resource `%s': %s\n", filename, gnupg_strerror(rc)); - else if (secret) - any_secret = 1; - else - any_public = 1; - xfree (filename); - return rc; + leave: + if (rc) + log_error ("keyblock resource `%s': %s\n", filename, gnupg_strerror(rc)); + else if (secret) + any_secret = 1; + else + any_public = 1; + xfree (filename); + return rc; } - - KEYDB_HANDLE keydb_new (int secret) { diff --git a/sm/keylist.c b/sm/keylist.c index 19bc9dd40..98ae8eb67 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -168,13 +168,13 @@ gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp) putc ('\n', fp); lastresname = resname; } - if (ctrl->with_colons) - list_cert_colon (cert, fp); - else - list_cert_colon (cert, fp); - ksba_cert_release (cert); - cert = NULL; - } + } + if (ctrl->with_colons) + list_cert_colon (cert, fp); + else + list_cert_colon (cert, fp); + ksba_cert_release (cert); + cert = NULL; } while (!(rc = keydb_search_next (hd))); if (rc && rc != -1) diff --git a/sm/server.c b/sm/server.c index e2f7ec086..e83506049 100644 --- a/sm/server.c +++ b/sm/server.c @@ -42,6 +42,45 @@ struct server_local_s { int message_fd; }; +/* Map GNUPG_xxx error codes to Assuan status codes */ +static int +rc_to_assuan_status (int rc) +{ + switch (rc) + { + case 0: break; + case GNUPG_Bad_Certificate: rc = ASSUAN_Bad_Certificate; break; + case GNUPG_Bad_Certificate_Path: rc = ASSUAN_Bad_Certificate_Path; break; + case GNUPG_Missing_Certificate: rc = ASSUAN_Missing_Certificate; break; + case GNUPG_No_Data: rc = ASSUAN_No_Data_Available; break; + case GNUPG_Bad_Signature: rc = ASSUAN_Bad_Signature; break; + case GNUPG_Not_Implemented: rc = ASSUAN_Not_Implemented; break; + case GNUPG_No_Agent: rc = ASSUAN_No_Agent; break; + case GNUPG_Agent_Error: rc = ASSUAN_Agent_Error; break; + case GNUPG_No_Public_Key: rc = ASSUAN_No_Public_Key; break; + case GNUPG_No_Secret_Key: rc = ASSUAN_No_Secret_Key; break; + + case GNUPG_Read_Error: + case GNUPG_Write_Error: + case GNUPG_IO_Error: + rc = ASSUAN_Server_IO_Error; + break; + case GNUPG_Out_Of_Core: + case GNUPG_Resource_Limit: + rc = ASSUAN_Server_Resource_Problem; + break; + case GNUPG_Bug: + case GNUPG_Internal_Error: + rc = ASSUAN_Server_Bug; + break; + default: + rc = ASSUAN_Server_Fault; + break; + } + return rc; +} + + /* RECIPIENT @@ -116,15 +155,17 @@ cmd_decrypt (ASSUAN_CONTEXT ctx, char *line) static int cmd_verify (ASSUAN_CONTEXT ctx, char *line) { + int rc; CTRL ctrl = assuan_get_pointer (ctx); int fd = assuan_get_input_fd (ctx); if (fd == -1) return set_error (No_Input, NULL); - gpgsm_verify (assuan_get_pointer (ctx), fd, ctrl->server_local->message_fd); + rc = gpgsm_verify (assuan_get_pointer (ctx), fd, + ctrl->server_local->message_fd); - return 0; + return rc_to_assuan_status (rc); } @@ -139,6 +180,7 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line) int inp_fd, out_fd; FILE *out_fp; int detached; + int rc; inp_fd = assuan_get_input_fd (ctx); if (inp_fd == -1) @@ -152,10 +194,10 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line) out_fp = fdopen ( dup(out_fd), "w"); if (!out_fp) return set_error (General_Error, "fdopen() failed"); - gpgsm_sign (assuan_get_pointer (ctx), inp_fd, detached, out_fp); + rc = gpgsm_sign (assuan_get_pointer (ctx), inp_fd, detached, out_fp); fclose (out_fp); - return 0; + return rc_to_assuan_status (rc); } @@ -168,14 +210,15 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line) static int cmd_import (ASSUAN_CONTEXT ctx, char *line) { + int rc; int fd = assuan_get_input_fd (ctx); if (fd == -1) return set_error (No_Input, NULL); - gpgsm_import (assuan_get_pointer (ctx), fd); + rc = gpgsm_import (assuan_get_pointer (ctx), fd); - return 0; + return rc_to_assuan_status (rc); } /* MESSAGE FD= @@ -211,7 +254,8 @@ cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) ctrl->with_colons = 1; /* fixme: check that the returned data_fp is not NULL */ - gpgsm_list_keys (assuan_get_pointer (ctx), NULL, assuan_get_data_fp (ctx)); + gpgsm_list_keys (assuan_get_pointer (ctx), NULL, + assuan_get_data_fp (ctx)); return 0; } diff --git a/sm/sign.c b/sm/sign.c index f87f1ce48..a246511e3 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -244,16 +244,16 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp) gcry_md_enable (data_md, algo); } + signer = 0; if (detached) - { /* we hash the data right now so tha we can store the message - digest. ksba_cms_build() takes this as an flag that deatched + { /* we hash the data right now so that we can store the message + digest. ksba_cms_build() takes this as an flag that detached data is expected. */ unsigned char *digest; size_t digest_len; /* Fixme do this for all signers and get the algo to use from the signer's certificate - does not make mich sense, bu we should do this consistent as we have already done it above */ - signer = 0; algo = GCRY_MD_SHA1; hash_data (data_fd, data_md); digest = gcry_md_read (data_md, algo); @@ -274,7 +274,14 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp) } } - + err = ksba_cms_set_signing_time (cms, signer, 0 /*now*/); + if (err) + { + log_error ("ksba_cms_set_signing_time failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } do { diff --git a/sm/verify.c b/sm/verify.c index 581cafeef..5b3a5a848 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -136,6 +136,28 @@ print_integer (unsigned char *p) } } +static void +print_time (time_t t) +{ + + if (!t) + log_printf ("none"); + else if ( t == (time_t)(-1) ) + log_printf ("error"); + else + { + struct tm *tp; + + tp = gmtime (&t); + log_printf ("%04d-%02d-%02d %02d:%02d:%02d", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + assert (!tp->tm_isdst); + } +} + + + static void hash_data (int fd, GCRY_MD_HD md) @@ -316,6 +338,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd) { char *issuer = NULL; char *sigval = NULL; + time_t sigtime; unsigned char *serial; char *msgdigest = NULL; size_t msgdigestlen; @@ -328,6 +351,17 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd) print_integer (serial); log_printf ("\n"); + err = ksba_cms_get_signing_time (cms, signer, &sigtime); + if (err) + { + log_debug ("error getting signing time: %s\n", ksba_strerror (err)); + sigtime = (time_t)-1; + } + log_debug ("signer %d - sigtime: ", signer); + print_time (sigtime); + log_printf ("\n"); + + err = ksba_cms_get_message_digest (cms, signer, &msgdigest, &msgdigestlen); if (err)