From 97be197d31314ce89b91683e6440c4630075296d Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 19 Oct 2009 09:18:46 +0000 Subject: [PATCH] [g13] Add RECIPEINT and CREATE command. [sm] Chnage --include-certs default --- doc/gpgsm.texi | 2 +- g10/ChangeLog | 6 +++++ g10/mainproc.c | 2 ++ g10/options.h | 5 ++++ g10/server.c | 3 +++ g13/call-gpg.c | 21 ++++++++++------ g13/call-gpg.h | 1 + g13/create.c | 15 +++++++---- g13/create.h | 3 ++- g13/g13.c | 35 +++++--------------------- g13/server.c | 66 +++++++++++++++++++++++++++++++++++++------------ jnlib/ChangeLog | 4 +++ jnlib/strlist.c | 19 ++++++++++++++ jnlib/strlist.h | 1 + sm/ChangeLog | 6 +++++ sm/gpgsm.c | 25 +++++++++++++++---- 16 files changed, 150 insertions(+), 64 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index a2b3db0cf..5835c7213 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -560,7 +560,7 @@ Using @var{n} of -2 includes all certificate except for the root cert, -1 includes all certs, 0 does not include any certs, 1 includes only the signers cert (this is the default) and all other positive values include up to @var{n} certificates starting with the signer cert. - +The default is -2. @item --cipher-algo @var{oid} @opindex cipher-algo diff --git a/g10/ChangeLog b/g10/ChangeLog index 11e13fb0c..dfe54e770 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2009-10-19 Werner Koch + + * options.h (glo_ctrl): Add field LASTERR. + * mainproc.c (proc_encrypted): Set LASTERR. + * server.c (cmd_decrypt): Check LASTERR. + 2009-10-02 Werner Koch * server.c (cmd_encrypt, cmd_decrypt): Implement. diff --git a/g10/mainproc.c b/g10/mainproc.c index 4a8df6f57..c3d082c56 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -581,6 +581,7 @@ proc_encrypted( CTX c, PACKET *pkt ) } } else if( result == G10ERR_BAD_SIGN ) { + glo_ctrl.lasterr = result; log_error(_("WARNING: encrypted message has been manipulated!\n")); write_status( STATUS_BADMDC ); write_status( STATUS_DECRYPTION_FAILED ); @@ -593,6 +594,7 @@ proc_encrypted( CTX c, PACKET *pkt ) c->dek->s2k_cacheid); passphrase_clear_cache (NULL, c->dek->s2k_cacheid, 0); } + glo_ctrl.lasterr = result; write_status( STATUS_DECRYPTION_FAILED ); log_error(_("decryption failed: %s\n"), g10_errstr(result)); /* Hmmm: does this work when we have encrypted using multiple diff --git a/g10/options.h b/g10/options.h index 3a2a68e61..b6e7e55b8 100644 --- a/g10/options.h +++ b/g10/options.h @@ -257,6 +257,11 @@ EXTERN_UNLESS_MAIN_MODULE struct { int in_auto_key_retrieve; /* True if we are doing an auto_key_retrieve. */ + /* Hack to store the last error. We currently need it because the + proc_packet machinery is not able to reliabale return error + codes. Thus for the --server purposes we store some of the error + codes here. FIXME! */ + gpg_error_t lasterr; } glo_ctrl; #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ diff --git a/g10/server.c b/g10/server.c index 478c0ec28..657091b0e 100644 --- a/g10/server.c +++ b/g10/server.c @@ -362,7 +362,10 @@ cmd_decrypt (assuan_context_t ctx, char *line) if (out_fd == -1) return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); + glo_ctrl.lasterr = 0; err = decrypt_message_fd (inp_fd, out_fd); + if (!err) + err = glo_ctrl.lasterr; /* Close and reset the fds. */ close_message_fd (ctrl); diff --git a/g13/call-gpg.c b/g13/call-gpg.c index 6e5c55f40..c6b0abe30 100644 --- a/g13/call-gpg.c +++ b/g13/call-gpg.c @@ -43,7 +43,7 @@ start_gpg (ctrl_t ctrl, int input_fd, int output_fd, assuan_context_t *r_ctx) gpg_error_t err; assuan_context_t ctx = NULL; const char *pgmname; - const char *argv[7]; + const char *argv[10]; int no_close_list[5]; int i; char line[ASSUAN_LINELENGTH]; @@ -86,6 +86,8 @@ start_gpg (ctrl_t ctrl, int input_fd, int output_fd, assuan_context_t *r_ctx) argv[i++] = "--debug=1024"; argv[i++] = "-z"; argv[i++] = "0"; + argv[i++] = "--trust-model"; + argv[i++] = "always"; argv[i++] = NULL; i = 0; @@ -326,7 +328,7 @@ start_reader (int fd, membuf_t *mb, pth_t *r_tid, gpg_error_t *err_addr) */ gpg_error_t gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen, - void **r_ciph, size_t *r_ciphlen) + strlist_t keys, void **r_ciph, size_t *r_ciphlen) { gpg_error_t err; assuan_context_t ctx; @@ -336,6 +338,8 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen, pth_t reader_tid = NULL; gpg_error_t writer_err, reader_err; membuf_t reader_mb; + char line[ASSUAN_LINELENGTH]; + strlist_t sl; *r_ciph = NULL; *r_ciphlen = 0; @@ -376,13 +380,16 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen, outbound_fds[0] = -1; /* The thread owns the FD now. */ /* Run the encryption. */ - err = assuan_transact (ctx, "RECIPIENT alpha@example.net", - NULL, NULL, NULL, NULL, NULL, NULL); - if (err) + for (sl = keys; sl; sl = sl->next) { - log_error ("the engine's RECIPIENT command failed: %s <%s>\n", + snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + { + log_error ("the engine's RECIPIENT command failed: %s <%s>\n", gpg_strerror (err), gpg_strsource (err)); - goto leave; + goto leave; + } } err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/g13/call-gpg.h b/g13/call-gpg.h index ffc5f29b5..339544d50 100644 --- a/g13/call-gpg.h +++ b/g13/call-gpg.h @@ -22,6 +22,7 @@ gpg_error_t gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen, + strlist_t keys, void **r_ciph, size_t *r_ciphlen); gpg_error_t gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen, void **r_plain, size_t *r_plainlen); diff --git a/g13/create.c b/g13/create.c index 9de9edc0b..bde67579e 100644 --- a/g13/create.c +++ b/g13/create.c @@ -106,12 +106,13 @@ create_new_keyblob (ctrl_t ctrl, int is_detached, concatenation of both with the CMS packet being the last. */ static gpg_error_t encrypt_keyblob (ctrl_t ctrl, void *keyblob, size_t keybloblen, + strlist_t keys, void **r_encblob, size_t *r_encbloblen) { gpg_error_t err; /* FIXME: For now we only implement OpenPGP. */ - err = gpg_encrypt_blob (ctrl, keyblob, keybloblen, + err = gpg_encrypt_blob (ctrl, keyblob, keybloblen, keys, r_encblob, r_encbloblen); return err; @@ -217,10 +218,11 @@ write_keyblob (const char *filename, /* Create a new container under the name FILENAME and intialize it - using the current settings. If the file already exists an error is - returned. */ + using the current settings. KEYS is a list of public keys to which + the container will be encrypted. If the file already exists an + error is returned. */ gpg_error_t -g13_create_container (ctrl_t ctrl, const char *filename) +g13_create_container (ctrl_t ctrl, const char *filename, strlist_t keys) { gpg_error_t err; dotlock_t lock; @@ -233,6 +235,9 @@ g13_create_container (ctrl_t ctrl, const char *filename) tupledesc_t tuples = NULL; unsigned int dummy_rid; + if (!keys) + return gpg_error (GPG_ERR_NO_PUBKEY); + /* A quick check to see that no container with that name already exists. */ if (!access (filename, F_OK)) @@ -284,7 +289,7 @@ g13_create_container (ctrl_t ctrl, const char *filename) goto leave; /* Encrypt that keyblob. */ - err = encrypt_keyblob (ctrl, keyblob, keybloblen, + err = encrypt_keyblob (ctrl, keyblob, keybloblen, keys, &enckeyblob, &enckeybloblen); if (err) goto leave; diff --git a/g13/create.h b/g13/create.h index d533c0852..cc4ddfd08 100644 --- a/g13/create.h +++ b/g13/create.h @@ -20,7 +20,8 @@ #ifndef G13_CREATE_H #define G13_CREATE_H -gpg_error_t g13_create_container (ctrl_t ctrl, const char *filename); +gpg_error_t g13_create_container (ctrl_t ctrl, const char *filename, + strlist_t keys); #endif /*G13_CREATE_H*/ diff --git a/g13/g13.c b/g13/g13.c index 5838b13fa..754371df2 100644 --- a/g13/g13.c +++ b/g13/g13.c @@ -47,6 +47,7 @@ enum cmd_and_opt_values { aNull = 0, oQuiet = 'q', oVerbose = 'v', + oRecipient = 'r', aGPGConfList = 500, aGPGConfTest, @@ -91,8 +92,6 @@ enum cmd_and_opt_values { oDryRun, oNoDetach, - oRecipient, - oNoRandomSeedFile, oFakedSystemTime }; @@ -308,30 +307,6 @@ set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd) } -/* Helper to add recipients to a list. */ -static int -add_encryption_key (ctrl_t ctrl, const char *name, - void /*FIXME*/ *keylist, int is_cms) -{ - /* FIXME: Decide whether to add a CMS or OpenPGP key and then add - the key to a list. */ - /* int rc = foo_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to); */ - /* if (rc) */ - /* { */ - /* if (recp_required) */ - /* { */ - /* log_error ("can't encrypt to `%s': %s\n", name, gpg_strerror (rc)); */ - /* gpgsm_status2 (ctrl, STATUS_INV_RECP, */ - /* get_inv_recpsgnr_code (rc), name, NULL); */ - /* } */ - /* else */ - /* log_info (_("NOTE: won't be able to encrypt to `%s': %s\n"), */ - /* name, gpg_strerror (rc)); */ - /* } */ - return 0; /* Key is good. */ -} - - int main ( int argc, char **argv) { @@ -664,18 +639,20 @@ main ( int argc, char **argv) /* Parse all given encryption keys. This does a lookup of the keys and stops if any of the given keys was not found. */ +#if 0 /* Currently not implemented. */ if (!nokeysetup) { strlist_t sl; int failed = 0; for (sl = recipients; sl; sl = sl->next) - if (add_encryption_key (&ctrl, sl->d, NULL /* FIXME*/, 0)) + if (check_encryption_key ()) failed = 1; if (failed) g13_exit (1); } - +#endif /*0*/ + /* Dispatch command. */ switch (cmd) { @@ -715,7 +692,7 @@ main ( int argc, char **argv) if (argc != 1) wrong_args ("--create filename"); start_idle_task (); - err = g13_create_container (&ctrl, argv[0]); + err = g13_create_container (&ctrl, argv[0], recipients); if (err) log_error ("error creating a new container: %s <%s>\n", gpg_strerror (err), gpg_strsource (err)); diff --git a/g13/server.c b/g13/server.c index 585b9e7aa..e9b9a0a33 100644 --- a/g13/server.c +++ b/g13/server.c @@ -29,9 +29,9 @@ #include #include "i18n.h" #include "keyblob.h" -#include "./server.h" -#include "./mount.h" - +#include "server.h" +#include "mount.h" +#include "create.h" /* Local data for this server module. A pointer to this is stored in the CTRL object of each connection. */ @@ -42,6 +42,7 @@ struct server_local_s char *containername; /* Malloced active containername. */ + strlist_t recipients; /* List of recipients. */ }; @@ -187,6 +188,8 @@ reset_notify (assuan_context_t ctx) xfree (ctrl->server_local->containername); ctrl->server_local->containername = NULL; + FREE_STRLIST (ctrl->server_local->recipients); + assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); } @@ -359,17 +362,12 @@ static gpg_error_t cmd_recipient (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); - gpg_error_t err; + gpg_error_t err = 0; - (void)ctrl; - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); - /* err = gpgsm_add_to_certlist (ctrl, line, 0, */ - /* &ctrl->server_local->recplist, 0); */ - /* if (err) */ - /* { */ - /* gpgsm_status2 (ctrl, STATUS_INV_RECP, */ - /* get_inv_recpsgnr_code (rc), line, NULL); */ - /* } */ + line = skip_options (line); + + if (!add_to_strlist_try (&ctrl->server_local->recipients, line)) + err = gpg_error_from_syserror (); return leave_cmd (ctx, err); } @@ -386,6 +384,7 @@ cmd_signer (assuan_context_t ctx, char *line) gpg_error_t err; (void)ctrl; + (void)line; err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); return leave_cmd (ctx, err); @@ -402,16 +401,50 @@ cmd_create (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); gpg_error_t err; - - (void)ctrl; + char *p, *pend; + size_t len; /* First we close the active container. */ xfree (ctrl->server_local->containername); ctrl->server_local->containername = NULL; + /* Parse the line. */ + line = skip_options (line); + for (p=line; *p && !spacep (p); p++) + ; + pend = p; + while (spacep(p)) + p++; + if (*p || pend == line) + { + err = gpg_error (GPG_ERR_ASS_SYNTAX); + goto leave; + } + *pend = 0; + /* Unescape the line and check for embedded Nul bytes. */ + len = percent_plus_unescape_inplace (line, 0); + line[len] = 0; + if (!len || memchr (line, 0, len)) + { + err = gpg_error (GPG_ERR_INV_NAME); + goto leave; + } - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + /* Create container. */ + err = g13_create_container (ctrl, line, ctrl->server_local->recipients); + + if (!err) + { + FREE_STRLIST (ctrl->server_local->recipients); + + /* Store the filename. */ + ctrl->server_local->containername = xtrystrdup (line); + if (!ctrl->server_local->containername) + err = gpg_error_from_syserror (); + + } + leave: return leave_cmd (ctx, err); } @@ -617,6 +650,7 @@ g13_server (ctrl_t ctrl) log_info ("Assuan accept problem: %s\n", gpg_strerror (err)); leave: + reset_notify (ctx); /* Release all items hold by SERVER_LOCAL. */ if (ctrl->server_local) { xfree (ctrl->server_local); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 84e37c52f..54984930d 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2009-10-19 Werner Koch + + * strlist.c (add_to_strlist_try): New. + 2009-09-22 Werner Koch * dotlock.h (DOTLOCK): Rename to dotlock_t. Change all users. diff --git a/jnlib/strlist.c b/jnlib/strlist.c index d45a1648a..b31e6213a 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -57,6 +57,25 @@ add_to_strlist( strlist_t *list, const char *string ) } +/* Add STRING to the LIST at the front. This function returns NULL + and sets ERRNO on memory shortage. */ +strlist_t +add_to_strlist_try (strlist_t *list, const char *string) +{ + strlist_t sl; + + sl = jnlib_malloc (sizeof *sl + strlen (string)); + if (sl) + { + sl->flags = 0; + strcpy (sl->d, string); + sl->next = *list; + *list = sl; + } + return sl; +} + + /* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion to UTF-8 is done. This function terminates the process on memory shortage. */ diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 4191624ae..1e2ffa8da 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -30,6 +30,7 @@ typedef struct string_list *strlist_t; void free_strlist (strlist_t sl); strlist_t add_to_strlist (strlist_t *list, const char *string); +strlist_t add_to_strlist_try (strlist_t *list, const char *string); strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); diff --git a/sm/ChangeLog b/sm/ChangeLog index e68d5a749..f7c735913 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2009-10-16 Werner Koch + + * gpgsm.c (default_include_certs): Change to -2. + (DEFAULT_INCLUDE_CERTS): New. + (DEFAULT_CIPHER_ALGO): New. Use instead of hardcoded "3DES". + 2009-09-30 Werner Koch * gpgsm.c (main): Remove obsolete GCRYCTL_DISABLE_INTERNAL_LOCKING. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 17cc78b38..adfe6cdbf 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -402,12 +402,25 @@ static unsigned int debug_value; /* Option --enable-special-filenames */ static int allow_special_filenames; -/* Default value for include-certs. */ -static int default_include_certs = 1; /* Only include the signer's cert. */ +/* Default value for include-certs. We need an extra macro for + gpgconf-list because the variable will be changed by the command + line option. + + It is often cumbersome to locate intermediate certificates, thus by + default we include all certificates in the chain. However we leave + out the root certificate because that would make it too easy for + the recipient to import that root certificate. A root certificate + should be installed only after due checks and thus it won't help to + send it along with each message. */ +#define DEFAULT_INCLUDE_CERTS -2 /* Include all certs but root. */ +static int default_include_certs = DEFAULT_INCLUDE_CERTS; /* Whether the chain mode shall be used for validation. */ static int default_validation_model; +/* The default cipher algo. */ +#define DEFAULT_CIPHER_ALGO "3DES" /*des-EDE3-CBC*/ + static char *build_list (const char *text, const char *(*mapf)(int), int (*chkf)(int)); @@ -897,7 +910,7 @@ main ( int argc, char **argv) /* Note: If you change this default cipher algorithm , please remember to update the Gpgconflist entry as well. */ - opt.def_cipher_algoid = "3DES"; /*des-EDE3-CBC*/ + opt.def_cipher_algoid = DEFAULT_CIPHER_ALGO; opt.homedir = default_homedir (); @@ -1606,14 +1619,16 @@ main ( int argc, char **argv) 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 ("include-certs:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, + DEFAULT_INCLUDE_CERTS); 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); #endif - printf ("cipher-algo:%lu:\"3DES:\n", GC_OPT_FLAG_DEFAULT); + printf ("cipher-algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, + DEFAULT_CIPHER_ALGO); 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);