diff options
Diffstat (limited to '')
-rw-r--r-- | gpgme/sign.c | 463 |
1 files changed, 186 insertions, 277 deletions
diff --git a/gpgme/sign.c b/gpgme/sign.c index 2f0de1d1..dc53b7b0 100644 --- a/gpgme/sign.c +++ b/gpgme/sign.c @@ -38,12 +38,7 @@ struct sign_result_s { - int no_passphrase; int okay; - void *last_pw_handle; - char *userid_hint; - char *passphrase_info; - int bad_passphrase; GpgmeData xmlinfo; }; @@ -53,311 +48,230 @@ _gpgme_release_sign_result (SignResult result) if (!result) return; gpgme_data_release (result->xmlinfo); - xfree (result->userid_hint); - xfree (result->passphrase_info); xfree (result); } -/* parse the args and save the information +/* Parse the args and save the information * <type> <pubkey algo> <hash algo> <class> <timestamp> <key fpr> * in an XML structure. With args of NULL the xml structure is closed. */ static void append_xml_siginfo (GpgmeData *rdh, char *args) { - GpgmeData dh; - char helpbuf[100]; - int i; - char *s; - unsigned long ul; - - if ( !*rdh ) { - if (gpgme_data_new (rdh)) { - return; /* fixme: We are ignoring out-of-core */ + GpgmeData dh; + char helpbuf[100]; + int i; + char *s; + unsigned long ul; + + if (!*rdh) + { + if (gpgme_data_new (rdh)) + { + return; /* fixme: We are ignoring out-of-core */ } - dh = *rdh; - _gpgme_data_append_string (dh, "<GnupgOperationInfo>\n"); + dh = *rdh; + _gpgme_data_append_string (dh, "<GnupgOperationInfo>\n"); } - else { - dh = *rdh; - _gpgme_data_append_string (dh, " </signature>\n"); + else + { + dh = *rdh; + _gpgme_data_append_string (dh, " </signature>\n"); } - if (!args) { /* just close the XML containter */ - _gpgme_data_append_string (dh, "</GnupgOperationInfo>\n"); - return; + if (!args) + { + /* Just close the XML containter. */ + _gpgme_data_append_string (dh, "</GnupgOperationInfo>\n"); + return; } - _gpgme_data_append_string (dh, " <signature>\n"); + _gpgme_data_append_string (dh, " <signature>\n"); - _gpgme_data_append_string (dh, - *args == 'D'? " <detached/>\n": - *args == 'C'? " <cleartext/>\n": - *args == 'S'? " <standard/>\n":""); - SKIP_TOKEN_OR_RETURN (args); - - sprintf (helpbuf, " <algo>%d</algo>\n", atoi (args)); - _gpgme_data_append_string (dh, helpbuf); - SKIP_TOKEN_OR_RETURN (args); - - i = atoi (args); - sprintf (helpbuf, " <hashalgo>%d</hashalgo>\n", atoi (args)); - _gpgme_data_append_string (dh, helpbuf); - switch (i) { - case 1: s = "pgp-md5"; break; - case 2: s = "pgp-sha1"; break; - case 3: s = "pgp-ripemd160"; break; - case 5: s = "pgp-md2"; break; - case 6: s = "pgp-tiger192"; break; - case 7: s = "pgp-haval-5-160"; break; - case 8: s = "pgp-sha256"; break; - case 9: s = "pgp-sha384"; break; - case 10: s = "pgp-sha512"; break; - default: s = "pgp-unknown"; break; + _gpgme_data_append_string (dh, + *args == 'D' ? " <detached/>\n" : + *args == 'C' ? " <cleartext/>\n" : + *args == 'S' ? " <standard/>\n" : ""); + SKIP_TOKEN_OR_RETURN (args); + + sprintf (helpbuf, " <algo>%d</algo>\n", atoi (args)); + _gpgme_data_append_string (dh, helpbuf); + SKIP_TOKEN_OR_RETURN (args); + + i = atoi (args); + sprintf (helpbuf, " <hashalgo>%d</hashalgo>\n", atoi (args)); + _gpgme_data_append_string (dh, helpbuf); + switch (i) + { + case 1: s = "pgp-md5"; break; + case 2: s = "pgp-sha1"; break; + case 3: s = "pgp-ripemd160"; break; + case 5: s = "pgp-md2"; break; + case 6: s = "pgp-tiger192"; break; + case 7: s = "pgp-haval-5-160"; break; + case 8: s = "pgp-sha256"; break; + case 9: s = "pgp-sha384"; break; + case 10: s = "pgp-sha512"; break; + default: s = "pgp-unknown"; break; } - sprintf (helpbuf, " <micalg>%s</micalg>\n", s); - _gpgme_data_append_string (dh,helpbuf); - SKIP_TOKEN_OR_RETURN (args); + sprintf (helpbuf, " <micalg>%s</micalg>\n", s); + _gpgme_data_append_string (dh,helpbuf); + SKIP_TOKEN_OR_RETURN (args); - sprintf (helpbuf, " <sigclass>%.2s</sigclass>\n", args); - _gpgme_data_append_string (dh, helpbuf); - SKIP_TOKEN_OR_RETURN (args); - - ul = strtoul (args, NULL, 10); - sprintf (helpbuf, " <created>%lu</created>\n", ul); - _gpgme_data_append_string (dh, helpbuf); - SKIP_TOKEN_OR_RETURN (args); - - /* count the length of the finperprint */ - for (i=0; args[i] && args[i] != ' '; i++) - ; - _gpgme_data_append_string (dh, " <fpr>"); - _gpgme_data_append (dh, args, i); - _gpgme_data_append_string (dh, "</fpr>\n"); + sprintf (helpbuf, " <sigclass>%.2s</sigclass>\n", args); + _gpgme_data_append_string (dh, helpbuf); + SKIP_TOKEN_OR_RETURN (args); + + ul = strtoul (args, NULL, 10); + sprintf (helpbuf, " <created>%lu</created>\n", ul); + _gpgme_data_append_string (dh, helpbuf); + SKIP_TOKEN_OR_RETURN (args); + + /* Count the length of the finperprint. */ + for (i = 0; args[i] && args[i] != ' '; i++) + ; + _gpgme_data_append_string (dh, " <fpr>"); + _gpgme_data_append (dh, args, i); + _gpgme_data_append_string (dh, "</fpr>\n"); } - - static void sign_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) { - if (ctx->out_of_core) - return; - if (!ctx->result.sign) - { - ctx->result.sign = xtrycalloc (1, sizeof *ctx->result.sign); - if (!ctx->result.sign) - { - ctx->out_of_core = 1; - return; - } - } - - switch (code) { - case STATUS_EOF: - if (ctx->result.sign->okay) { - append_xml_siginfo (&ctx->result.sign->xmlinfo, NULL); - _gpgme_set_op_info (ctx, ctx->result.sign->xmlinfo); - ctx->result.sign->xmlinfo = NULL; - } - break; - - case STATUS_USERID_HINT: - xfree (ctx->result.sign->userid_hint); - if (!(ctx->result.sign->userid_hint = xtrystrdup (args)) ) - ctx->out_of_core = 1; - break; - - case STATUS_BAD_PASSPHRASE: - ctx->result.sign->bad_passphrase++; - break; - - case STATUS_GOOD_PASSPHRASE: - ctx->result.sign->bad_passphrase = 0; - break; - - case STATUS_NEED_PASSPHRASE: - case STATUS_NEED_PASSPHRASE_SYM: - xfree (ctx->result.sign->passphrase_info); - if (!(ctx->result.sign->passphrase_info = xtrystrdup (args)) ) - ctx->out_of_core = 1; - break; - - case STATUS_MISSING_PASSPHRASE: - DEBUG0 ("missing passphrase - stop\n"); - ctx->result.sign->no_passphrase = 1; - break; - - case STATUS_SIG_CREATED: - /* fixme: we have no error return for multiple signatures */ - append_xml_siginfo (&ctx->result.sign->xmlinfo, args); - ctx->result.sign->okay =1; - break; - - default: - break; + if (ctx->out_of_core) + return; + if (!ctx->result.sign) + { + ctx->result.sign = xtrycalloc (1, sizeof *ctx->result.sign); + if (!ctx->result.sign) + { + ctx->out_of_core = 1; + return; + } } -} -static const char * -command_handler ( void *opaque, GpgStatusCode code, const char *key ) -{ - GpgmeCtx c = opaque; - - if (!c->result.sign) - { - c->result.sign = xtrycalloc (1, sizeof *c->result.sign); - if (!c->result.sign) - { - c->out_of_core = 1; - return NULL; - } - } - - if ( !code ) { - /* We have been called for cleanup */ - if ( c->passphrase_cb ) { - /* Fixme: take the key in account */ - c->passphrase_cb (c->passphrase_cb_value, 0, - &c->result.sign->last_pw_handle ); + switch (code) + { + case STATUS_EOF: + if (ctx->result.sign->okay) + { + append_xml_siginfo (&ctx->result.sign->xmlinfo, NULL); + _gpgme_set_op_info (ctx, ctx->result.sign->xmlinfo); + ctx->result.sign->xmlinfo = NULL; } - - return NULL; - } + break; - if ( !key || !c->passphrase_cb ) - return NULL; - - if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) { - const char *userid_hint = c->result.sign->userid_hint; - const char *passphrase_info = c->result.sign->passphrase_info; - int bad_passphrase = c->result.sign->bad_passphrase; - char *buf; - const char *s; - - c->result.sign->bad_passphrase = 0; - if (!userid_hint) - userid_hint = "[User ID hint missing]"; - if (!passphrase_info) - passphrase_info = "[passphrase info missing]"; - buf = xtrymalloc ( 20 + strlen (userid_hint) - + strlen (passphrase_info) + 3); - if (!buf) { - c->out_of_core = 1; - return NULL; - } - sprintf (buf, "%s\n%s\n%s", - bad_passphrase? "TRY_AGAIN":"ENTER", - userid_hint, passphrase_info ); + case STATUS_SIG_CREATED: + /* FIXME: We have no error return for multiple signatures. */ + append_xml_siginfo (&ctx->result.sign->xmlinfo, args); + ctx->result.sign->okay =1; + break; - s = c->passphrase_cb (c->passphrase_cb_value, - buf, &c->result.sign->last_pw_handle ); - xfree (buf); - return s; + default: + break; } - - return NULL; } - GpgmeError -gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out, - GpgmeSigMode mode ) +gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out, + GpgmeSigMode mode) { - int rc = 0; - int i; - GpgmeKey key; - - fail_on_pending_request( c ); - c->pending = 1; + GpgmeError err = 0; + int i; + GpgmeKey key; - _gpgme_release_result (c); - c->out_of_core = 0; + fail_on_pending_request (ctx); + ctx->pending = 1; + _gpgme_release_result (ctx); + ctx->out_of_core = 0; - if ( mode != GPGME_SIG_MODE_NORMAL - && mode != GPGME_SIG_MODE_DETACH - && mode != GPGME_SIG_MODE_CLEAR ) - return mk_error (Invalid_Value); + if (mode != GPGME_SIG_MODE_NORMAL + && mode != GPGME_SIG_MODE_DETACH + && mode != GPGME_SIG_MODE_CLEAR) + return mk_error (Invalid_Value); - /* create a process object */ - _gpgme_gpg_release (c->gpg); - c->gpg = NULL; - rc = _gpgme_gpg_new ( &c->gpg ); - if (rc) - goto leave; - - _gpgme_gpg_set_status_handler ( c->gpg, sign_status_handler, c ); - if (c->passphrase_cb) { - rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c ); - if (rc) - goto leave; + /* Create a process object. */ + _gpgme_gpg_release (ctx->gpg); + ctx->gpg = NULL; + err = _gpgme_gpg_new (&ctx->gpg); + if (err) + goto leave; + + _gpgme_gpg_set_status_handler (ctx->gpg, sign_status_handler, ctx); + + err = _gpgme_passphrase_start (ctx); + if (err) + goto leave; + + /* Build the commandline. */ + if (mode == GPGME_SIG_MODE_CLEAR) + _gpgme_gpg_add_arg (ctx->gpg, "--clearsign"); + else + { + _gpgme_gpg_add_arg (ctx->gpg, "--sign"); + if (mode == GPGME_SIG_MODE_DETACH) + _gpgme_gpg_add_arg (ctx->gpg, "--detach"); + if (ctx->use_armor) + _gpgme_gpg_add_arg (ctx->gpg, "--armor"); + if (ctx->use_textmode) + _gpgme_gpg_add_arg (ctx->gpg, "--textmode"); } - - /* build the commandline */ - if ( mode == GPGME_SIG_MODE_CLEAR ) { - _gpgme_gpg_add_arg ( c->gpg, "--clearsign" ); - } - else { - _gpgme_gpg_add_arg ( c->gpg, "--sign" ); - if ( mode == GPGME_SIG_MODE_DETACH ) - _gpgme_gpg_add_arg ( c->gpg, "--detach" ); - if ( c->use_armor ) - _gpgme_gpg_add_arg ( c->gpg, "--armor" ); - if ( c->use_textmode ) - _gpgme_gpg_add_arg ( c->gpg, "--textmode" ); - } - for (i=0; i < c->verbosity; i++) - _gpgme_gpg_add_arg ( c->gpg, "--verbose" ); - for (i=0; (key = gpgme_signers_enum (c, i)); i++ ) { - const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, - NULL, 0); - if (s) { - _gpgme_gpg_add_arg (c->gpg, "-u"); - _gpgme_gpg_add_arg (c->gpg, s); - } + for (i = 0; i < ctx->verbosity; i++) + _gpgme_gpg_add_arg (ctx->gpg, "--verbose"); + for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++) + { + const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, + NULL, 0); + if (s) + { + _gpgme_gpg_add_arg (ctx->gpg, "-u"); + _gpgme_gpg_add_arg (ctx->gpg, s); + } gpgme_key_unref (key); } - - /* Check the supplied data */ - if ( gpgme_data_get_type (in) == GPGME_DATA_TYPE_NONE ) { - rc = mk_error (No_Data); - goto leave; + /* Check the supplied data. */ + if (gpgme_data_get_type (in) == GPGME_DATA_TYPE_NONE) + { + err = mk_error (No_Data); + goto leave; } - _gpgme_data_set_mode (in, GPGME_DATA_MODE_OUT ); - if ( !out || gpgme_data_get_type (out) != GPGME_DATA_TYPE_NONE ) { - rc = mk_error (Invalid_Value); - goto leave; + _gpgme_data_set_mode (in, GPGME_DATA_MODE_OUT); + if (!out || gpgme_data_get_type (out) != GPGME_DATA_TYPE_NONE) + { + err = mk_error (Invalid_Value); + goto leave; } - _gpgme_data_set_mode (out, GPGME_DATA_MODE_IN ); - - /* tell the gpg object about the data */ - _gpgme_gpg_add_data ( c->gpg, in, 0 ); - _gpgme_gpg_add_data ( c->gpg, out, 1 ); + _gpgme_data_set_mode (out, GPGME_DATA_MODE_IN); - /* and kick off the process */ - rc = _gpgme_gpg_spawn ( c->gpg, c ); + /* Tell the gpg object about the data. */ + _gpgme_gpg_add_data (ctx->gpg, in, 0); + _gpgme_gpg_add_data (ctx->gpg, out, 1); + /* And kick off the process. */ + err = _gpgme_gpg_spawn (ctx->gpg, ctx); + leave: - if (rc) { - c->pending = 0; - _gpgme_gpg_release ( c->gpg ); c->gpg = NULL; + if (err) + { + ctx->pending = 0; + _gpgme_gpg_release (ctx->gpg); + ctx->gpg = NULL; } - return rc; + return err; } - /** * gpgme_op_sign: - * @c: The context + * @ctx: The context * @in: Data to be signed * @out: Detached signature * @mode: Signature creation mode * * Create a detached signature for @in and write it to @out. * The data will be signed using either the default key or the ones - * defined through @c. + * defined through @ctx. * The defined modes for signature create are: * <literal> * GPGME_SIG_MODE_NORMAL (or 0) @@ -370,31 +284,26 @@ gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out, * Return value: 0 on success or an error code. **/ GpgmeError -gpgme_op_sign (GpgmeCtx c, GpgmeData in, GpgmeData out, GpgmeSigMode mode) +gpgme_op_sign (GpgmeCtx ctx, GpgmeData in, GpgmeData out, GpgmeSigMode mode) { - GpgmeError err = gpgme_op_sign_start ( c, in, out, mode ); - if ( !err ) { - gpgme_wait (c, 1); - if (!c->result.sign) - err = mk_error (General_Error); - else if (c->out_of_core) - err = mk_error (Out_Of_Core); - else { - if (c->result.sign->no_passphrase) - err = mk_error (No_Passphrase); - else if (!c->result.sign->okay) + GpgmeError err = gpgme_op_sign_start (ctx, in, out, mode); + if (!err) + { + gpgme_wait (ctx, 1); + if (!ctx->result.sign) + err = mk_error (General_Error); + else if (ctx->out_of_core) + err = mk_error (Out_Of_Core); + else + { + err = _gpgme_passphrase_result (ctx); + if (! err) + { + if (!ctx->result.sign->okay) err = mk_error (No_Data); /* Hmmm: choose a better error? */ - } - c->pending = 0; + } + } + ctx->pending = 0; } - return err; + return err; } - - - - - - - - - |