diff --git a/NEWS b/NEWS index b130c450..f01424ca 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ + + * New interfaces gpgme_set_include_certs and gpgme_get_include_certs + to set and get the number of certifications to include in S/MIME + signed messages. + + * Interface changes relative to the 0.3.3 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_set_include_certs NEW +gpgme_get_include_certs NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Noteworthy changes in version 0.3.3 (2002-02-12) ------------------------------------------------ diff --git a/TODO b/TODO index f2e3e3f8..2cf08bc5 100644 --- a/TODO +++ b/TODO @@ -21,6 +21,8 @@ Hey Emacs, this is -*- outline -*- mode! ** Move code common to all engines up from gpg to engine. ** engine operations can return General Error on unknown protocol (it's an internal error, as select_protocol checks already). +** When server mode is implemented properly, more care has to be taken to + release all resources on error (for example to free assuan_cmd). * Operations ** Export status handler need much more work. diff --git a/doc/ChangeLog b/doc/ChangeLog index a9ae183f..e2d625a3 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +2002-02-25 Marcus Brinkmann + + * gpgme.texi (Creating a Signature): Add a note about + certifications to include. + (Included Certifications): New section. + 2002-02-09 Marcus Brinkmann * gpgme.texi (Detailed Results): Remove literal tags. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 777ba223..708110c3 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -138,6 +138,7 @@ Context Attributes * Protocol Selection:: Selecting the protocol used by a context. * @acronym{ASCII} Armor:: Requesting @acronym{ASCII} armored output. * Text Mode:: Choosing canonical text mode. +* Included Certificates:: Including a number of certificates. * Key Listing Mode:: Selecting key listing mode. * Passphrase Callback:: Getting the passphrase from the user. * Progress Meter Callback:: Being informed about the progress. @@ -961,6 +962,7 @@ The function @code{gpgme_release} destroys the context with the handle * Protocol Selection:: Selecting the protocol used by a context. * @acronym{ASCII} Armor:: Requesting @acronym{ASCII} armored output. * Text Mode:: Choosing canonical text mode. +* Included Certificates:: Including a number of certificates. * Key Listing Mode:: Selecting key listing mode. * Passphrase Callback:: Getting the passphrase from the user. * Progress Meter Callback:: Being informed about the progress. @@ -1024,6 +1026,9 @@ Text mode is for example used for the RFC2015 signatures; note that the updated RFC 3156 mandates that the mail user agent does some preparations so that text mode is not needed anymore. +This option is only relevant to the OpenPGP crypto engine, and ignored +by all other engines. + Canonical text mode is disabled if @var{yes} is zero, and enabled otherwise. @end deftypefun @@ -1035,6 +1040,42 @@ valid pointer. @end deftypefun +@node Included Certificates +@subsection Included Certificates +@cindex certificates, included + +@deftypefun void gpgme_set_include_certs (@w{GpgmeCtx @var{ctx}}, @w{int @var{nr_of_certs}}) +The function @code{gpgme_set_include_certs} specifies how many +certificates should be included in an S/MIME signed message. By +default, only the sender's certificate is included. The possible +values of @var{nr_of_certs} are: + +@table @code +@item -2 +Include all certificates except the root certificate. +@item -1 +Include all certificates. +@item 0 +Include no certificates. +@item 1 +Include the sender's certificate only. +@item n +Include the first n certificates of the certificates path, starting +from the sender's certificate. The number @code{n} must be positive. +@end table + +Values of @var{nr_of_certs} smaller than -2 are undefined. + +This option is only relevant to the CMS crypto engine, and ignored +by all other engines. +@end deftypefun + +@deftypefun int gpgme_get_include_certs (@w{GpgmeCtx @var{ctx}}) +The function @code{gpgme_get_include_certs} returns the number of +certificates to include into an S/MIME signed message. +@end deftypefun + + @node Key Listing Mode @subsection Key Listing Mode @cindex key listing mode @@ -2036,6 +2077,10 @@ the data object @var{plain} and returns it in the data object More information about the signatures is available with @code{gpgme_get_op_info}. @xref{Detailed Results}. +If an S/MIME signed message is created using the CMS crypto engine, +the number of certificates to include in the message can be specified +with @code{gpgme_set_include_certs}. @xref{Included Certificates}. + The function returns @code{GPGME_No_Error} if the signature could be created successfully, @code{GPGME_Invalid_Value} if @var{ctx}, @var{plain} or @var{sig} is not a valid pointer, @code{GPGME_No_Data} diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 732ee3e3..16b91887 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,20 @@ +2002-02-25 Marcus Brinkmann + + * context.h (struct gpgme_context_s): New member include_certs. + * gpgme.h (gpgme_set_include_certs): Add prototype. + (gpgme_get_include_certs): Likewise. + * gpgme.c (gpgme_set_include_certs): New function. + (gpgme_get_include_certs): Likewise. + (gpgme_new): Set include_certs to 1 (the default). + * engine.c (_gpgme_engine_op_sign): Accept new argument include_certs, + and pass it to _gpgme_gpgsm_op_sign. + * engine.h (_gpgme_engine_op_sign): Likewise for prototype. + * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Accept new argument + include_certs and handle it. + * engine-gpgsm.h (_gpgme_gpgsm_start): Add new argument include_certs. + * sign.c (gpgme_op_sign_start): Add new argument to + _gpgme_engine_op_sign call. + 2002-02-14 Werner Koch * keylist.c (gpgme_op_keylist_start): Do not use a verbose listing. diff --git a/gpgme/context.h b/gpgme/context.h index bc0839dd..8ecdaf18 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -38,55 +38,67 @@ struct trust_queue_item_s { /* Currently we need it at several places, so we put the definition * into this header file */ -struct gpgme_context_s { - int initialized; - int pending; /* a gpg request is still pending */ +struct gpgme_context_s +{ + int initialized; + /* A gpg request is still pending. */ + int pending; - int use_cms; + int use_cms; - /* At some points we need to remember an error which we can't report - immediately. */ - GpgmeError error; - /* Cancel operation requested. */ - int cancel; + /* At some points we need to remember an error which we can't report + immediately. */ + GpgmeError error; + /* Cancel operation requested. */ + int cancel; - EngineObject engine; /* The running engine process. */ + /* The running engine process. */ + EngineObject engine; - int verbosity; /* level of verbosity to use */ - int use_armor; - int use_textmode; - int keylist_mode; + /* Level of verbosity to use. */ + int verbosity; + int use_armor; + int use_textmode; + int keylist_mode; + int include_certs; - int signers_len; /* The number of keys in signers. */ - int signers_size; /* size of the following array */ - GpgmeKey *signers; + /* The number of keys in signers. */ + int signers_len; + /* Size of the following array. */ + int signers_size; + GpgmeKey *signers; - struct { - VerifyResult verify; - DecryptResult decrypt; - SignResult sign; - EncryptResult encrypt; - PassphraseResult passphrase; - ImportResult import; - DeleteResult delete; - GenKeyResult genkey; - } result; + struct + { + VerifyResult verify; + DecryptResult decrypt; + SignResult sign; + EncryptResult encrypt; + PassphraseResult passphrase; + ImportResult import; + DeleteResult delete; + GenKeyResult genkey; + } result; - GpgmeData notation; /* last signature notation */ - GpgmeData op_info; /* last operation info */ + /* Last signature notation. */ + GpgmeData notation; + /* Last operation info. */ + GpgmeData op_info; - GpgmeKey tmp_key; /* used by keylist.c */ - volatile int key_cond; /* something new is available */ - struct key_queue_item_s *key_queue; - struct trust_queue_item_s *trust_queue; + /* Used by keylist.c. */ + GpgmeKey tmp_key; + /* Something new is available. */ + volatile int key_cond; + struct key_queue_item_s *key_queue; + struct trust_queue_item_s *trust_queue; - GpgmePassphraseCb passphrase_cb; - void *passphrase_cb_value; + GpgmePassphraseCb passphrase_cb; + void *passphrase_cb_value; - GpgmeProgressCb progress_cb; - void *progress_cb_value; + GpgmeProgressCb progress_cb; + void *progress_cb_value; - GpgmeData help_data_1; + GpgmeData help_data_1; }; diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index 3d2b3dbf..1bc688eb 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -591,9 +591,11 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, - int use_textmode, GpgmeCtx ctx /* FIXME */) + int use_textmode, int include_certs, + GpgmeCtx ctx /* FIXME */) { GpgmeError err; + char *assuan_cmd; if (!gpgsm) return mk_error (Invalid_Value); @@ -603,6 +605,13 @@ _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, if (!gpgsm->command) return mk_error (Out_Of_Core); + if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0) + return mk_error (Out_Of_Core); + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, assuan_cmd); + free (assuan_cmd); + if (err) + return err; + gpgsm->input_data = in; err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server, 0); if (err) @@ -979,7 +988,8 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, - int use_textmode, GpgmeCtx ctx /* FIXME */) + int use_textmode, int include_certs, + GpgmeCtx ctx /* FIXME */) { return mk_error (Invalid_Engine); } diff --git a/gpgme/engine-gpgsm.h b/gpgme/engine-gpgsm.h index c302625e..b629ed6f 100644 --- a/gpgme/engine-gpgsm.h +++ b/gpgme/engine-gpgsm.h @@ -53,7 +53,8 @@ GpgmeError _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, - int use_textmode, GpgmeCtx ctx /* FIXME */); + int use_textmode, int include_certs, + GpgmeCtx ctx /* FIXME */); GpgmeError _gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern); GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text); diff --git a/gpgme/engine.c b/gpgme/engine.c index 608340e8..e53327a3 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -437,8 +437,9 @@ _gpgme_engine_op_keylist (EngineObject engine, const char *pattern, int secret_o GpgmeError _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out, - GpgmeSigMode mode, int use_armor, - int use_textmode, GpgmeCtx ctx /* FIXME */) + GpgmeSigMode mode, int use_armor, + int use_textmode, int include_certs, + GpgmeCtx ctx /* FIXME */) { if (!engine) return mk_error (Invalid_Value); @@ -450,7 +451,7 @@ _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out, use_textmode, ctx); case GPGME_PROTOCOL_CMS: return _gpgme_gpgsm_op_sign (engine->engine.gpgsm, in, out, mode, - use_armor, use_textmode, ctx); + use_armor, use_textmode, include_certs, ctx); break; default: break; diff --git a/gpgme/engine.h b/gpgme/engine.h index a9d373e6..7e4acd30 100644 --- a/gpgme/engine.h +++ b/gpgme/engine.h @@ -58,6 +58,7 @@ GpgmeError _gpgme_engine_op_keylist (EngineObject engine, const char *pattern, GpgmeError _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, int use_textmode, + int include_certs, GpgmeCtx ctx /* FIXME */); GpgmeError _gpgme_engine_op_trustlist (EngineObject engine, const char *pattern); diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index c727a516..d904bac1 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -29,6 +29,7 @@ #include "context.h" #include "ops.h" + /** * gpgme_new: * @r_ctx: Returns the new context @@ -51,11 +52,13 @@ gpgme_new (GpgmeCtx *r_ctx) return mk_error (Out_Of_Core); ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL; ctx->verbosity = 1; + ctx->include_certs = 1; *r_ctx = ctx; return 0; } + /** * gpgme_release: * @c: Context to be released. @@ -275,6 +278,41 @@ gpgme_get_textmode (GpgmeCtx ctx) } +/** + * gpgme_set_include_certs: + * @ctx: the context + * + * Set the number of certifications to include in an S/MIME message. + * The default is 1 (only the cert of the sender). -1 means all certs, + * and -2 means all certs except the root cert. + * + * Return value: Boolean whether textmode is to be used. + **/ +void +gpgme_set_include_certs (GpgmeCtx ctx, int nr_of_certs) +{ + if (nr_of_certs < -2) + ctx->include_certs = -2; + else + ctx->include_certs = nr_of_certs; +} + + +/** + * gpgme_get_include_certs: + * @ctx: the context + * + * Get the number of certifications to include in an S/MIME message. + * + * Return value: Boolean whether textmode is to be used. + **/ +int +gpgme_get_include_certs (GpgmeCtx ctx) +{ + return ctx->include_certs; +} + + /** * gpgme_set_keylist_mode: * @ctx: the context diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index a605e283..5c7ff878 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -228,6 +228,12 @@ void gpgme_set_textmode (GpgmeCtx ctx, int yes); /* Return non-zero if text mode is set in CTX. */ int gpgme_get_textmode (GpgmeCtx ctx); +/* Include up to NR_OF_CERTS certificates in an S/MIME message. */ +void gpgme_set_include_certs (GpgmeCtx ctx, int nr_of_certs); + +/* Return the number of certs to include in an S/MIME message. */ +int gpgme_get_include_certs (GpgmeCtx ctx); + /* Set keylist mode in CTX to MODE. */ GpgmeError gpgme_set_keylist_mode (GpgmeCtx ctx, int mode); diff --git a/gpgme/sign.c b/gpgme/sign.c index 328e5192..f63974d1 100644 --- a/gpgme/sign.c +++ b/gpgme/sign.c @@ -214,7 +214,8 @@ gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out, _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity); _gpgme_engine_op_sign (ctx->engine, in, out, mode, ctx->use_armor, - ctx->use_textmode, ctx /* FIXME */); + ctx->use_textmode, ctx->include_certs, + ctx /* FIXME */); /* And kick off the process. */ err = _gpgme_engine_start (ctx->engine, ctx);