2003-04-24  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.texi (Generating Keys): Document changed gpgme_op_genkey
	and new gpgme_op_genkey_result function.  Document
	GpgmeGenKeyResult data type.

gpgme/
2003-04-24  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.h (struct _gpgme_op_genkey_result): New structure.
	(GpgmeGenKeyResult): New type.
	(gpgme_op_genkey): Drop last argument.
	(gpgme_op_genkey_result): New function.
	* genkey.c: Do not include "util.h", but "gpgme.h".
	(struct genkey_result): Replace with ...
	(op_data_t): ... this new type.
	(release_genkey_result): Replace with ...
	(release_op_data): ... this new function.
	(gpgme_op_genkey_result): New function.
	(genkey_status_handler): Rewritten using new op_data_t type.
	(get_key_parameter): New function.
	(_gpgme_op_genkey_start): Renamed to
	(genkey_start): ... this and rewritten.
	(gpgme_op_genkey_start): Use genkey_start instead
	_gpgme_op_genkey_start.
	(gpgme_op_genkey): Rewritten.  Remove FPR argument.

tests/
2003-04-24  Marcus Brinkmann  <marcus@g10code.de>

	* gpg/t-genkey.c: Rewritten to match new semantics.
This commit is contained in:
Marcus Brinkmann 2003-04-24 17:16:28 +00:00
parent e927e5c617
commit 671edce1ae
8 changed files with 305 additions and 220 deletions

15
NEWS
View File

@ -46,6 +46,12 @@ Noteworthy changes in version 0.4.1 (unreleased)
GPGME_No_Passphrase have been renamed to GPGME_No_UserID, GPGME_No_Passphrase have been renamed to GPGME_No_UserID,
GPGME_Invalid_UserID and GPGME_Bad_Passphrase resp. GPGME_Invalid_UserID and GPGME_Bad_Passphrase resp.
* The FPR argument to gpgme_op_genkey was removed. Instead, use the
gpgme_op_genkey_result function to retrieve a GpgmeGenKeyResult
pointer to a structure which contains the fingerprint. This also
works with gpgme_op_genkey. The structure also provides other
information about the generated keys.
* Interface changes relative to the 0.4.0 release: * Interface changes relative to the 0.4.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpgmeIOCb CHANGED: Return type from void to GpgmeError. GpgmeIOCb CHANGED: Return type from void to GpgmeError.
@ -61,9 +67,12 @@ gpgme_get_engine_info CHANGED: Return info structure instead XML.
gpgme_get_protocol_name NEW gpgme_get_protocol_name NEW
GpgmePassphraseCb CHANGED: Return error value, new argument. GpgmePassphraseCb CHANGED: Return error value, new argument.
gpgme_cancel REMOVED: Return error in callback directly. gpgme_cancel REMOVED: Return error in callback directly.
GPGME_No_Recipients CHANGED: GPGME_No_UserID GPGME_No_Recipients CHANGED: Now GPGME_No_UserID.
GPGME_Invalid_Recipient CHANGED: GPGME_Invalid_UserID GPGME_Invalid_Recipient CHANGED: Now GPGME_Invalid_UserID.
GPGME_No_Passphrase CHANGED: GPGME_Bad_Passphrase GPGME_No_Passphrase CHANGED: Now GPGME_Bad_Passphrase.
gpgme_op_genkey CHANGED: FPR argument dropped.
gpgme_op_genkey_result NEW
GpgmeGenKeyResult NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 0.4.0 (2002-12-23) Noteworthy changes in version 0.4.0 (2002-12-23)

View File

@ -1,5 +1,9 @@
2003-04-24 Marcus Brinkmann <marcus@g10code.de> 2003-04-24 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Generating Keys): Document changed gpgme_op_genkey
and new gpgme_op_genkey_result function. Document
GpgmeGenKeyResult data type.
* gpgme.texi (Error Values): Rename GPGME_No_Passphrase to * gpgme.texi (Error Values): Rename GPGME_No_Passphrase to
GPGME_Bad_Passphrase. GPGME_Bad_Passphrase.
* gpgme.texi (Decrypt): Likewise. * gpgme.texi (Decrypt): Likewise.

View File

@ -2115,7 +2115,7 @@ The function @code{gpgme_key_release} is an alias for
@cindex key, creation @cindex key, creation
@cindex key ring, add @cindex key ring, add
@deftypefun GpgmeError gpgme_op_genkey (@w{GpgmeCtx @var{ctx}}, @w{const char *@var{parms}}, @w{GpgmeData @var{pubkey}}, @w{GpgmeData @var{seckey}}, @w{char **@var{fpr}}) @deftypefun GpgmeError gpgme_op_genkey (@w{GpgmeCtx @var{ctx}}, @w{const char *@var{parms}}, @w{GpgmeData @var{pubkey}}, @w{GpgmeData @var{seckey}})
The function @code{gpgme_op_genkey} generates a new key pair in the The function @code{gpgme_op_genkey} generates a new key pair in the
context @var{ctx} and puts it into the standard key ring if both context @var{ctx} and puts it into the standard key ring if both
@var{pubkey} and @var{seckey} are @code{NULL}. In this case the @var{pubkey} and @var{seckey} are @code{NULL}. In this case the
@ -2130,8 +2130,8 @@ the data object will contain the secret key.
Note that not all crypto engines support this interface equally. Note that not all crypto engines support this interface equally.
GnuPG does not support @var{pubkey} and @var{subkey}, they should be GnuPG does not support @var{pubkey} and @var{subkey}, they should be
both @code{NULL}, and the key pair will be added to the standard key both @code{NULL}, and the key pair will be added to the standard key
ring. GpgSM does only support @var{pubkey}, the secret key will be ring. GpgSM only supports @var{pubkey}, the secret key will be stored
stored by @command{gpg-agent}. GpgSM expects @var{pubkey} being not by @command{gpg-agent}. GpgSM expects @var{pubkey} being not
@code{NULL}. @code{NULL}.
The argument @var{parms} specifies parameters for the key in an XML The argument @var{parms} specifies parameters for the key in an XML
@ -2168,12 +2168,8 @@ for now is ``internal''. The content of the @code{GnupgKeyParms}
container is passed verbatim to GnuPG. Control statements are not container is passed verbatim to GnuPG. Control statements are not
allowed. allowed.
If @var{fpr} is not a null pointer, the function succeeds, and the After the operation completed successfully, the result can be
crypto engine supports it, *@var{fpr} will contain a string with the retrieved with @code{gpgme_op_genkey_result}.
fingerprint of the key, allocated with @code{malloc}. If both a
primary and a sub key was generated, the fingerprint of the primary
key will be returned. If the crypto engine does not provide the
fingerprint, *@var{fpr} will be a null pointer.
The function returns @code{GPGME_No_Error} if the operation could be The function returns @code{GPGME_No_Error} if the operation could be
started successfully, @code{GPGME_Invalid_Value} if @var{parms} is not started successfully, @code{GPGME_Invalid_Value} if @var{parms} is not
@ -2193,6 +2189,39 @@ a valid XML string, and @code{GPGME_Not_Supported} if @var{pubkey} or
@var{seckey} is not @code{NULL}. @var{seckey} is not @code{NULL}.
@end deftypefun @end deftypefun
@deftp {Data type} {GpgmeGenKeyResult}
This is a pointer to a structure used to store the result of a
@code{gpgme_op_genkey} operation. After successfully generating a
key, you can retrieve the pointer to the result with
@code{gpgme_op_genkey_result}. The structure contains the following
members:
@table @code
@item unsigned int primary : 1
This is a flag that is set to 1 if a primary key was created and to 0
if not.
@item unsigned int sub : 1
This is a flag that is set to 1 if a subkey was created and to 0
if not.
@item char *fpr
This is the fingerprint of the key that was created. If both a
primary and a sub key were generated, the fingerprint of the primary
key will be returned. If the crypto engine does not provide the
fingerprint, @code{fpr} will be a null pointer.
@end table
@end deftp
@deftypefun GpgmeGenKeyResult gpgme_op_genkey_result (@w{GpgmeCtx @var{ctx}})
The function @code{gpgme_op_genkey_result} returns a
@code{GpgmeGenKeyResult} pointer to a structure holding the result of
a @code{gpgme_op_genkey} operation. The pointer is only valid if the
last operation on the context was a @code{gpgme_op_genkey} or
@code{gpgme_op_genkey_start} operation, and if this operation finished
successfully. The returned pointer is only valid until the next
operation is started on the context.
@end deftypefun
@node Exporting Keys @node Exporting Keys
@subsection Exporting Keys @subsection Exporting Keys

View File

@ -1,5 +1,23 @@
2003-04-24 Marcus Brinkmann <marcus@g10code.de> 2003-04-24 Marcus Brinkmann <marcus@g10code.de>
* gpgme.h (struct _gpgme_op_genkey_result): New structure.
(GpgmeGenKeyResult): New type.
(gpgme_op_genkey): Drop last argument.
(gpgme_op_genkey_result): New function.
* genkey.c: Do not include "util.h", but "gpgme.h".
(struct genkey_result): Replace with ...
(op_data_t): ... this new type.
(release_genkey_result): Replace with ...
(release_op_data): ... this new function.
(gpgme_op_genkey_result): New function.
(genkey_status_handler): Rewritten using new op_data_t type.
(get_key_parameter): New function.
(_gpgme_op_genkey_start): Renamed to
(genkey_start): ... this and rewritten.
(gpgme_op_genkey_start): Use genkey_start instead
_gpgme_op_genkey_start.
(gpgme_op_genkey): Rewritten. Remove FPR argument.
* context.h (struct gpgme_context_s): Remove member verbosity. * context.h (struct gpgme_context_s): Remove member verbosity.
* gpgme.c (gpgme_new): Do not set member verbosity. * gpgme.c (gpgme_new): Do not set member verbosity.
* engine.h (_gpgme_engine_set_verbosity): Remove prototype. * engine.h (_gpgme_engine_set_verbosity): Remove prototype.

View File

@ -24,39 +24,60 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "util.h" #include "gpgme.h"
#include "context.h" #include "context.h"
#include "ops.h" #include "ops.h"
struct genkey_result typedef struct
{ {
int created_primary : 1; struct _gpgme_op_genkey_result result;
int created_sub : 1;
char *fpr; /* The key parameters passed to the crypto engine. */
}; GpgmeData key_parameter;
typedef struct genkey_result *GenKeyResult; } *op_data_t;
static void static void
release_genkey_result (void *hook) release_op_data (void *hook)
{ {
GenKeyResult result = (GenKeyResult) hook; op_data_t opd = (op_data_t) hook;
if (result->fpr) if (opd->result.fpr)
free (result->fpr); free (opd->result.fpr);
if (opd->key_parameter)
gpgme_data_release (opd->key_parameter);
} }
static GpgmeError GpgmeGenKeyResult
genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args) gpgme_op_genkey_result (GpgmeCtx ctx)
{ {
GenKeyResult result; op_data_t opd;
GpgmeError err = _gpgme_progress_status_handler (ctx, code, args); GpgmeError err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &opd, -1, NULL);
if (err || !opd)
return NULL;
return &opd->result;
}
static GpgmeError
genkey_status_handler (void *priv, GpgmeStatusCode code, char *args)
{
GpgmeCtx ctx = (GpgmeCtx) priv;
GpgmeError err;
op_data_t opd;
/* Pipe the status code through the progress status handler. */
err = _gpgme_progress_status_handler (ctx, code, args);
if (err) if (err)
return err; return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &result, err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &opd,
sizeof (*result), release_genkey_result); -1, NULL);
if (err) if (err)
return err; return err;
@ -66,15 +87,15 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
if (args && *args) if (args && *args)
{ {
if (*args == 'B' || *args == 'P') if (*args == 'B' || *args == 'P')
result->created_primary = 1; opd->result.primary = 1;
if (*args == 'B' || *args == 'S') if (*args == 'B' || *args == 'S')
result->created_sub = 1; opd->result.sub = 1;
if (args[1] == ' ') if (args[1] == ' ')
{ {
if (result->fpr) if (opd->result.fpr)
free (result->fpr); free (opd->result.fpr);
result->fpr = strdup (&args[2]); opd->result.fpr = strdup (&args[2]);
if (!result->fpr) if (!opd->result.fpr)
return GPGME_Out_Of_Core; return GPGME_Out_Of_Core;
} }
} }
@ -82,8 +103,7 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
case GPGME_STATUS_EOF: case GPGME_STATUS_EOF:
/* FIXME: Should return some more useful error value. */ /* FIXME: Should return some more useful error value. */
if (!result->created_primary if (!opd->result.primary && !opd->result.sub)
&& !result->created_sub)
return GPGME_General_Error; return GPGME_General_Error;
break; break;
@ -95,139 +115,84 @@ genkey_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
static GpgmeError static GpgmeError
_gpgme_op_genkey_start (GpgmeCtx ctx, int synchronous, const char *parms, get_key_parameter (const char *parms, GpgmeData *key_parameter)
GpgmeData pubkey, GpgmeData seckey)
{ {
int err = 0; const char *content;
const char *s, *s2, *sx; const char *attrib;
const char *endtag;
err = _gpgme_op_reset (ctx, synchronous); /* Extract the key parameter from the XML structure. */
if (err) parms = strstr (parms, "<GnupgKeyParms ");
goto leave; if (!parms)
return GPGME_Invalid_Value;
gpgme_data_release (ctx->help_data_1); content = strchr (parms, '>');
ctx->help_data_1 = NULL; if (!content)
return GPGME_Invalid_Value;
content++;
if ((parms = strstr (parms, "<GnupgKeyParms ")) attrib = strstr (parms, "format=\"internal\"");
&& (s = strchr (parms, '>')) if (!attrib || attrib >= content)
&& (sx = strstr (parms, "format=\"internal\"")) return GPGME_Invalid_Value;
&& sx < s
&& (s2 = strstr (s+1, "</GnupgKeyParms>")))
{
/* FIXME: Check that there are no control statements inside. */
s++; /* Skip '>'. */
while (*s == '\n')
s++;
err = gpgme_data_new_from_mem (&ctx->help_data_1, s, s2-s, 1);
}
else
err = GPGME_Invalid_Value;
if (err) endtag = strstr (content, "</GnupgKeyParms>");
goto leave; /* FIXME: Check that there are no control statements inside. */
while (*content == '\n')
content++;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx); return gpgme_data_new_from_mem (key_parameter, content,
endtag - content, 0);
err = _gpgme_engine_op_genkey (ctx->engine, ctx->help_data_1, ctx->use_armor,
pubkey, seckey);
leave:
if (err)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
return err;
} }
/** static GpgmeError
* gpgme_op_genkey: genkey_start (GpgmeCtx ctx, int synchronous, const char *parms,
* @c: the context GpgmeData pubkey, GpgmeData seckey)
* @parms: XML string with the key parameters {
* @pubkey: Returns the public key GpgmeError err;
* @seckey: Returns the secret key op_data_t opd;
* err = _gpgme_op_reset (ctx, synchronous);
* Generate a new key and store the key in the default keyrings if if (err)
* both @pubkey and @seckey are NULL. If @pubkey and @seckey are return err;
* given, the newly created key will be returned in these data
* objects. This function just starts the gheneration and does not err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &opd,
* wait for completion. sizeof (*opd), release_op_data);
* if (err)
* Here is an example on how @parms should be formatted; for deatils return err;
* see the file doc/DETAILS from the GnuPG distribution.
* err = get_key_parameter (parms, &opd->key_parameter);
* <literal> if (err)
* <![CDATA[ return err;
* <GnupgKeyParms format="internal">
* Key-Type: DSA _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
* Key-Length: 1024
* Subkey-Type: ELG-E return _gpgme_engine_op_genkey (ctx->engine, opd->key_parameter,
* Subkey-Length: 1024 ctx->use_armor, pubkey, seckey);
* Name-Real: Joe Tester }
* Name-Comment: with stupid passphrase
* Name-Email: joe@foo.bar
* Expire-Date: 0 /* Generate a new keypair and add it to the keyring. PUBKEY and
* Passphrase: abc SECKEY should be null for now. PARMS specifies what keys should be
* </GnupgKeyParms> generated. */
* ]]>
* </literal>
*
* Strings should be given in UTF-8 encoding. The format we support
* for now is only "internal". The content of the
* &lt;GnupgKeyParms&gt; container is passed verbatim to GnuPG.
* Control statements are not allowed.
*
* Return value: 0 for success or an error code
**/
GpgmeError GpgmeError
gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms, gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey) GpgmeData pubkey, GpgmeData seckey)
{ {
return _gpgme_op_genkey_start (ctx, 0, parms, pubkey, seckey); return genkey_start (ctx, 0, parms, pubkey, seckey);
} }
/** /* Generate a new keypair and add it to the keyring. PUBKEY and
* gpgme_op_genkey: SECKEY should be null for now. PARMS specifies what keys should be
* @c: the context generated. */
* @parms: XML string with the key parameters
* @pubkey: Returns the public key
* @seckey: Returns the secret key
* @fpr: Returns the fingerprint of the key.
*
* Generate a new key and store the key in the default keyrings if both
* @pubkey and @seckey are NULL. If @pubkey and @seckey are given, the newly
* created key will be returned in these data objects.
* See gpgme_op_genkey_start() for a description of @parms.
*
* Return value: 0 for success or an error code
**/
GpgmeError GpgmeError
gpgme_op_genkey (GpgmeCtx ctx, const char *parms, gpgme_op_genkey (GpgmeCtx ctx, const char *parms, GpgmeData pubkey,
GpgmeData pubkey, GpgmeData seckey, GpgmeData seckey)
char **fpr)
{ {
GpgmeError err = _gpgme_op_genkey_start (ctx, 1, parms, pubkey, seckey); GpgmeError err;
err = genkey_start (ctx, 1, parms, pubkey, seckey);
if (!err) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
if (!err && fpr)
{
GenKeyResult result;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, (void **) &result,
-1, NULL);
if (err)
return err;
if (result && result->fpr)
{
*fpr = strdup (result->fpr);
if (!*fpr)
return GPGME_Out_Of_Core;
}
else
*fpr = NULL;
}
return err; return err;
} }

View File

@ -756,17 +756,36 @@ GpgmeError gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeError gpgme_op_export (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeError gpgme_op_export (GpgmeCtx ctx, GpgmeRecipients recp,
GpgmeData keydata); GpgmeData keydata);
/* Key generation. */
struct _gpgme_op_genkey_result
{
/* A primary key was generated. */
unsigned int primary : 1;
/* A sub key was generated. */
unsigned int sub : 1;
/* Internal to GPGME, do not use. */
unsigned int _unused : 30;
/* The fingerprint of the generated key. */
char *fpr;
};
typedef struct _gpgme_op_genkey_result *GpgmeGenKeyResult;
/* Generate a new keypair and add it to the keyring. PUBKEY and /* Generate a new keypair and add it to the keyring. PUBKEY and
SECKEY should be null for now. PARMS specifies what keys should be SECKEY should be null for now. PARMS specifies what keys should be
generated. On success, if *FPR is non-null, it contains a generated. */
malloc()'ed string with the fingerprint of the generated key on
success. */
GpgmeError gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms, GpgmeError gpgme_op_genkey_start (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey); GpgmeData pubkey, GpgmeData seckey);
GpgmeError gpgme_op_genkey (GpgmeCtx ctx, const char *parms, GpgmeError gpgme_op_genkey (GpgmeCtx ctx, const char *parms,
GpgmeData pubkey, GpgmeData seckey, GpgmeData pubkey, GpgmeData seckey);
char **fpr);
/* Retrieve a pointer to the result of the genkey operation. */
GpgmeGenKeyResult gpgme_op_genkey_result (GpgmeCtx ctx);
/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret /* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
keys are also deleted. */ keys are also deleted. */
GpgmeError gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, GpgmeError gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key,

View File

@ -1,3 +1,7 @@
2003-04-24 Marcus Brinkmann <marcus@g10code.de>
* gpg/t-genkey.c: Rewritten to match new semantics.
2003-02-06 Marcus Brinkmann <marcus@g10code.de> 2003-02-06 Marcus Brinkmann <marcus@g10code.de>
* gpg/t-decrypt.c (passphrase_cb): Fix to new prototype. * gpg/t-decrypt.c (passphrase_cb): Fix to new prototype.

View File

@ -1,84 +1,121 @@
/* t-genkey.c - regression test /* t-genkey.c - regression test
* Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 g10 Code GmbH Copyright (C) 2001, 2003 g10 Code GmbH
*
* This file is part of GPGME. This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify GPGME is free software; you can redistribute it and/or modify it
* it under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful, GPGME is distributed in the hope that it will be useful, but
* but WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* GNU General Public License for more details. General Public License for more details.
*
* You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software along with GPGME; if not, write to the Free Software Foundation,
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <gpgme.h> #include <gpgme.h>
#define fail_if_err(a) do { if(a) { \ #define fail_if_err(err) \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \ do \
__FILE__, __LINE__, gpgme_strerror(a)); \ { \
exit (1); } \ if (err) \
} while(0) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror (err)); \
exit (1); \
} \
} \
while (0)
/* True if progress function printed something on the screen. */
int progress_called;
static void static void
progress ( void *self, const char *what, int type, int current, int total) progress (void *self, const char *what, int type, int current, int total)
{ {
fprintf (stderr, "progress `%s' %d %d %d\n", what, type, current, total); if (!strcmp (what, "primegen") && !current && !total
&& (type == '.' || type == '+' || type == '!'
|| type == '^' || type == '<' || type == '>'))
{
printf ("%c", type);
fflush (stdout);
progress_called = 1;
}
else
{
fprintf (stderr, "unknown progress `%s' %d %d %d\n", what, type,
current, total);
exit (1);
}
} }
int int
main (int argc, char **argv ) main (int argc, char **argv)
{ {
GpgmeCtx ctx; GpgmeCtx ctx;
GpgmeError err; GpgmeError err;
const char *format; const char *parms = "<GnupgKeyParms format=\"internal\">\n"
char *parms; "Key-Type: DSA\n"
int count = 0; "Key-Length: 1024\n"
"Subkey-Type: ELG-E\n"
"Subkey-Length: 1024\n"
"Name-Real: Joe Tester\n"
"Name-Comment: (pp=abc)\n"
"Name-Email: joe@foo.bar\n"
"Expire-Date: 0\n"
"Passphrase: abc\n"
"</GnupgKeyParms>\n";
GpgmeGenKeyResult result;
do { err = gpgme_new (&ctx);
err = gpgme_new (&ctx); fail_if_err (err);
fail_if_err (err);
gpgme_set_progress_cb (ctx, progress, NULL); gpgme_set_progress_cb (ctx, progress, NULL);
format = "<GnupgKeyParms format=\"internal\">\n" err = gpgme_op_genkey (ctx, parms, NULL, NULL);
"Key-Type: DSA\n" fail_if_err (err);
"Key-Length: 1024\n"
"Subkey-Type: ELG-E\n"
"Subkey-Length: 1024\n"
"Name-Real: Joe Tester\n"
"Name-Comment: (pp=abc,try=%d)\n"
"Name-Email: joe@foo.bar\n"
"Expire-Date: 0\n"
"Passphrase: abc\n"
"</GnupgKeyParms>\n";
parms = malloc ( strlen (format) + 1 + 20 );
if (!parms)
exit (8);
sprintf (parms, format, ++count );
err = gpgme_op_genkey (ctx, parms, NULL, NULL, NULL);
fail_if_err (err);
free (parms);
gpgme_release (ctx); result = gpgme_op_genkey_result (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) ); if (!result)
{
fprintf (stderr, "%s:%d: gpgme_op_genkey_result returns NULL\n",
__FILE__, __LINE__);
exit (1);
}
if (progress_called)
printf ("\n");
return 0; printf ("Generated key: %s (%s)\n", result->fpr ? result->fpr : "none",
result->primary ? (result->sub ? "primary, sub" : "primary")
: (result->sub ? "sub" : "none"));
if (strlen (result->fpr) != 40)
{
fprintf (stderr, "%s:%d: generated key has unexpected fingerprint\n",
__FILE__, __LINE__);
exit (1);
}
if (!result->primary)
{
fprintf (stderr, "%s:%d: primary key was not generated\n",
__FILE__, __LINE__);
exit (1);
}
if (!result->sub)
{
fprintf (stderr, "%s:%d: sub key was not generated\n",
__FILE__, __LINE__);
exit (1);
}
gpgme_release (ctx);
return 0;
} }