Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34768367
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
26 KB
Subscribers
None
View Options
diff --git a/src/debug.c b/src/debug.c
index d7604a7c..37baabb0 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1,411 +1,414 @@
/* debug.c - helpful output in desperate situations
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <time.h>
#ifndef HAVE_DOSISH_SYSTEM
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
# include <fcntl.h>
#endif
#include <assert.h>
#include "util.h"
#include "ath.h"
#include "sema.h"
#include "sys-util.h"
#include "debug.h"
/* Lock to serialize initialization of the debug output subsystem and
output of actual debug messages. */
DEFINE_STATIC_LOCK (debug_lock);
/* The amount of detail requested by the user, per environment
variable GPGME_DEBUG. */
static int debug_level;
/* The output stream for the debug messages. */
static FILE *errfp;
/* If not NULL, this malloced string is used instead of the
GPGME_DEBUG envvar. It must have been set before the debug
subsystem has been initialized. Using it later may or may not have
any effect. */
static char *envvar_override;
#ifdef HAVE_TLS
#define FRAME_NR
static __thread int frame_nr = 0;
#endif
void
_gpgme_debug_frame_begin (void)
{
#ifdef FRAME_NR
frame_nr++;
#endif
}
int _gpgme_debug_frame_end (void)
{
#ifdef FRAME_NR
frame_nr--;
#endif
return 0;
}
/* Remove leading and trailing white spaces. */
static char *
trim_spaces (char *str)
{
char *string, *p, *mark;
string = str;
/* Find first non space character. */
for (p = string; *p && isspace (*(unsigned char *) p); p++)
;
/* Move characters. */
for (mark = NULL; (*string = *p); string++, p++)
if (isspace (*(unsigned char *) p))
{
if (!mark)
mark = string;
}
else
mark = NULL;
if (mark)
*mark = '\0'; /* Remove trailing spaces. */
return str;
}
/* This is an internal function to set debug info. The caller must
assure that this function is called only by one thread at a time.
The function may have no effect if called after the debug system
has been initialized. Returns 0 on success. */
int
_gpgme_debug_set_debug_envvar (const char *value)
{
free (envvar_override);
envvar_override = strdup (value);
return !envvar_override;
}
static void
debug_init (void)
{
static int initialized;
LOCK (debug_lock);
if (!initialized)
{
gpgme_error_t err;
char *e;
const char *s1, *s2;;
if (envvar_override)
{
e = strdup (envvar_override);
free (envvar_override);
envvar_override = NULL;
}
else
{
#ifdef HAVE_W32CE_SYSTEM
e = _gpgme_w32ce_get_debug_envvar ();
#else /*!HAVE_W32CE_SYSTEM*/
err = _gpgme_getenv ("GPGME_DEBUG", &e);
if (err)
{
UNLOCK (debug_lock);
return;
}
#endif /*!HAVE_W32CE_SYSTEM*/
}
initialized = 1;
errfp = stderr;
if (e)
{
debug_level = atoi (e);
s1 = strchr (e, PATHSEP_C);
if (s1)
{
#ifndef HAVE_DOSISH_SYSTEM
if (getuid () == geteuid ()
#if defined(HAVE_GETGID) && defined(HAVE_GETEGID)
&& getgid () == getegid ()
#endif
)
{
#endif
char *p;
FILE *fp;
s1++;
if (!(s2 = strchr (s1, PATHSEP_C)))
s2 = s1 + strlen (s1);
p = malloc (s2 - s1 + 1);
if (p)
{
memcpy (p, s1, s2 - s1);
p[s2-s1] = 0;
trim_spaces (p);
fp = fopen (p,"a");
if (fp)
{
setvbuf (fp, NULL, _IOLBF, 0);
errfp = fp;
}
free (p);
}
#ifndef HAVE_DOSISH_SYSTEM
}
#endif
}
free (e);
}
}
UNLOCK (debug_lock);
if (debug_level > 0)
{
_gpgme_debug (DEBUG_INIT, "gpgme_debug: level=%d\n", debug_level);
#ifdef HAVE_W32_SYSTEM
{
const char *name = _gpgme_get_inst_dir ();
_gpgme_debug (DEBUG_INIT, "gpgme_debug: gpgme='%s'\n",
name? name: "?");
}
#endif
}
}
/* This should be called as soon as the locks are initialized. It is
required so that the assuan logging gets conncted to the gpgme log
stream as early as possible. */
void
_gpgme_debug_subsystem_init (void)
{
debug_init ();
}
/* Log the formatted string FORMAT at debug level LEVEL or higher.
*
* Returns: 0
*
* Note that we always return 0 because the old TRACE macro evaluated
* to 0 which issues a warning with newer gcc version about an unused
* values. By using a return value of this function this can be
* avoided. Fixme: It might be useful to check whether the return
* value from the TRACE macros are actually used somewhere.
*/
int
_gpgme_debug (int level, const char *format, ...)
{
va_list arg_ptr;
int saved_errno;
saved_errno = errno;
if (debug_level < level)
return 0;
va_start (arg_ptr, format);
LOCK (debug_lock);
{
#ifdef HAVE_W32CE_SYSTEM
SYSTEMTIME t;
GetLocalTime (&t);
fprintf (errfp, "GPGME %04d-%02d-%02d %02d:%02d:%02d <0x%04llx> ",
t.wYear, t.wMonth, t.wDay,
t.wHour, t.wMinute, t.wSecond,
(unsigned long long) ath_self ());
#else
struct tm *tp;
time_t atime = time (NULL);
tp = localtime (&atime);
fprintf (errfp, "GPGME %04d-%02d-%02d %02d:%02d:%02d <0x%04llx> ",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec,
(unsigned long long) ath_self ());
#endif
}
#ifdef FRAME_NR
{
int indent;
indent = frame_nr > 0? (2 * (frame_nr - 1)):0;
fprintf (errfp, "%*s", indent < 40? indent : 40, "");
}
#endif
vfprintf (errfp, format, arg_ptr);
va_end (arg_ptr);
if(format && *format && format[strlen (format) - 1] != '\n')
putc ('\n', errfp);
UNLOCK (debug_lock);
fflush (errfp);
gpg_err_set_errno (saved_errno);
return 0;
}
/* Start a new debug line in *LINE, logged at level LEVEL or higher,
and starting with the formatted string FORMAT. */
void
_gpgme_debug_begin (void **line, int level, const char *format, ...)
{
va_list arg_ptr;
int res;
if (debug_level < level)
{
/* Disable logging of this line. */
*line = NULL;
return;
}
va_start (arg_ptr, format);
res = gpgrt_vasprintf ((char **) line, format, arg_ptr);
va_end (arg_ptr);
if (res < 0)
*line = NULL;
}
/* Add the formatted string FORMAT to the debug line *LINE. */
void
_gpgme_debug_add (void **line, const char *format, ...)
{
va_list arg_ptr;
char *toadd;
char *result;
int res;
if (!*line)
return;
va_start (arg_ptr, format);
res = gpgrt_vasprintf (&toadd, format, arg_ptr);
va_end (arg_ptr);
if (res < 0)
{
gpgrt_free (*line);
*line = NULL;
}
res = gpgrt_asprintf (&result, "%s%s", *(char **) line, toadd);
gpgrt_free (toadd);
gpgrt_free (*line);
if (res < 0)
*line = NULL;
else
*line = result;
}
/* Finish construction of *LINE and send it to the debug output
stream. */
void
_gpgme_debug_end (void **line)
{
if (!*line)
return;
/* The smallest possible level is 1, so force logging here by
using that. */
_gpgme_debug (1, "%s", *line);
gpgrt_free (*line);
*line = NULL;
}
#define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a'))
void
_gpgme_debug_buffer (int lvl, const char *const fmt,
const char *const func, const char *const buffer,
size_t len)
{
int idx = 0;
int j;
if (!_gpgme_debug_trace ())
return;
+ if (!buffer)
+ return;
+
while (idx < len)
{
char str[51];
char *strp = str;
char *strp2 = &str[34];
for (j = 0; j < 16; j++)
{
unsigned char val;
if (idx < len)
{
val = buffer[idx++];
*(strp++) = TOHEX (val >> 4);
*(strp++) = TOHEX (val % 16);
*(strp2++) = isprint (val) ? val : '.';
}
else
{
*(strp++) = ' ';
*(strp++) = ' ';
}
if (j == 7)
*(strp++) = ' ';
}
*(strp++) = ' ';
*(strp2) = '\0';
_gpgme_debug (lvl, fmt, func, str);
}
}
diff --git a/src/genkey.c b/src/genkey.c
index ffca7e8e..0108aab0 100644
--- a/src/genkey.c
+++ b/src/genkey.c
@@ -1,660 +1,660 @@
/* genkey.c - Key generation.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002, 2003, 2004, 2016 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "gpgme.h"
#include "debug.h"
#include "context.h"
#include "ops.h"
#include "util.h"
typedef struct
{
struct _gpgme_op_genkey_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
/* The error code from certain ERROR status lines or 0. */
gpg_error_t error_code;
/* Flag to indicate that a UID is to be added. */
gpg_error_t uidmode;
/* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter;
} *op_data_t;
static void
release_op_data (void *hook)
{
op_data_t opd = (op_data_t) hook;
if (opd->result.fpr)
free (opd->result.fpr);
if (opd->key_parameter)
gpgme_data_release (opd->key_parameter);
}
gpgme_genkey_result_t
gpgme_op_genkey_result (gpgme_ctx_t ctx)
{
void *hook;
op_data_t opd;
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_genkey_result", ctx);
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL);
opd = hook;
if (err || !opd)
{
TRACE_SUC0 ("result=(null)");
return NULL;
}
TRACE_LOG3 ("fpr = %s, %s, %s", opd->result.fpr,
opd->result.primary ? "primary" : "no primary",
opd->result.sub ? "sub" : "no sub");
TRACE_SUC1 ("result=%p", &opd->result);
return &opd->result;
}
/* Parse an error status line. Return the error location and the
error code. The function may modify ARGS. */
static char *
parse_error (char *args, gpg_error_t *r_err)
{
char *where = strchr (args, ' ');
char *which;
if (where)
{
*where = '\0';
which = where + 1;
where = strchr (which, ' ');
if (where)
*where = '\0';
where = args;
}
else
{
*r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
return NULL;
}
*r_err = atoi (which);
return where;
}
static gpgme_error_t
genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
gpgme_error_t err;
void *hook;
op_data_t opd;
char *loc;
/* Pipe the status code through the progress status handler. */
err = _gpgme_progress_status_handler (ctx, code, args);
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL);
opd = hook;
if (err)
return err;
switch (code)
{
case GPGME_STATUS_KEY_CREATED:
if (args && *args)
{
if (*args == 'B' || *args == 'P')
{
opd->result.primary = 1;
opd->result.uid = 1;
}
if (*args == 'B' || *args == 'S')
opd->result.sub = 1;
if (args[1] == ' ')
{
if (opd->result.fpr)
free (opd->result.fpr);
opd->result.fpr = strdup (&args[2]);
if (!opd->result.fpr)
return gpg_error_from_syserror ();
}
}
break;
case GPGME_STATUS_ERROR:
loc = parse_error (args, &err);
if (!loc)
return err;
if (!opd->error_code)
opd->error_code = err;
break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
if (opd->error_code)
return opd->error_code;
else if (!opd->uidmode && !opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL);
else if (opd->failure_code)
return opd->failure_code;
else if (opd->uidmode == 1)
opd->result.uid = 1; /* We have no status line, thus this hack. */
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
if (ctx->status_cb && !ctx->full_status)
{
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
if (err)
return err;
}
break;
default:
break;
}
return 0;
}
static gpgme_error_t
get_key_parameter (const char *parms, gpgme_data_t *key_parameter)
{
const char *content;
const char *attrib;
const char *endtag;
/* Extract the key parameter from the XML structure. */
parms = strstr (parms, "<GnupgKeyParms ");
if (!parms)
return gpg_error (GPG_ERR_INV_VALUE);
content = strchr (parms, '>');
if (!content)
return gpg_error (GPG_ERR_INV_VALUE);
content++;
attrib = strstr (parms, "format=\"internal\"");
if (!attrib || attrib >= content)
return gpg_error (GPG_ERR_INV_VALUE);
endtag = strstr (content, "</GnupgKeyParms>");
/* FIXME: Check that there are no control statements inside. */
while (content[0] == '\n'
|| (content[0] == '\r' && content[1] == '\n'))
content++;
return gpgme_data_new_from_mem (key_parameter, content,
endtag - content, 1);
}
static gpgme_error_t
genkey_start (gpgme_ctx_t ctx, int synchronous, const char *parms,
gpgme_data_t pubkey, gpgme_data_t seckey)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
err = get_key_parameter (parms, &opd->key_parameter);
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
if (ctx->passphrase_cb)
{
err = _gpgme_engine_set_command_handler
(ctx->engine, _gpgme_passphrase_command_handler, ctx);
if (err)
return err;
}
return _gpgme_engine_op_genkey (ctx->engine,
NULL, NULL, 0, 0, NULL, 0,
opd->key_parameter,
ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
pubkey, seckey);
}
/* Generate a new keypair and add it to the keyring. PUBKEY and
SECKEY should be null for now. PARMS specifies what keys should be
generated. */
gpgme_error_t
gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
gpgme_data_t pubkey, gpgme_data_t seckey)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_genkey_start", ctx,
"pubkey=%p, seckey=%p", pubkey, seckey);
- TRACE_LOGBUF (parms, strlen (parms));
+ TRACE_LOGBUF (parms, parms? strlen (parms):0);
- if (!ctx)
+ if (!ctx || parms)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 0, parms, pubkey, seckey);
return TRACE_ERR (err);
}
/* Generate a new keypair and add it to the keyring. PUBKEY and
SECKEY should be null for now. PARMS specifies what keys should be
generated. */
gpgme_error_t
gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey,
gpgme_data_t seckey)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_genkey", ctx,
"pubkey=%p, seckey=%p", pubkey, seckey);
- TRACE_LOGBUF (parms, strlen (parms));
+ TRACE_LOGBUF (parms, parms? strlen (parms):0);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 1, parms, pubkey, seckey);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
static gpgme_error_t
createkey_start (gpgme_ctx_t ctx, int synchronous,
const char *userid, const char *algo,
unsigned long reserved, unsigned long expires,
gpgme_key_t anchorkey, unsigned int flags)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
if (reserved || anchorkey || !userid)
return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
if (ctx->passphrase_cb)
{
err = _gpgme_engine_set_command_handler
(ctx->engine, _gpgme_passphrase_command_handler, ctx);
if (err)
return err;
}
return _gpgme_engine_op_genkey (ctx->engine,
userid, algo, reserved, expires,
anchorkey, flags,
NULL,
ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
NULL, NULL);
}
gpgme_error_t
gpgme_op_createkey_start (gpgme_ctx_t ctx, const char *userid, const char *algo,
unsigned long reserved, unsigned long expires,
gpgme_key_t anchorkey, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createkey_start", ctx,
"userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createkey_start (ctx, 0,
userid, algo, reserved, expires, anchorkey, flags);
return TRACE_ERR (err);
}
gpgme_error_t
gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,
unsigned long reserved, unsigned long expires,
gpgme_key_t anchorkey, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createkey", ctx,
"userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createkey_start (ctx, 1,
userid, algo, reserved, expires, anchorkey, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
static gpgme_error_t
createsubkey_start (gpgme_ctx_t ctx, int synchronous,
gpgme_key_t key,
const char *algo,
unsigned long reserved, unsigned long expires,
unsigned int flags)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
if (reserved || !key)
return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
if (ctx->passphrase_cb)
{
err = _gpgme_engine_set_command_handler
(ctx->engine, _gpgme_passphrase_command_handler, ctx);
if (err)
return err;
}
return _gpgme_engine_op_genkey (ctx->engine,
NULL, algo, reserved, expires,
key, flags,
NULL,
ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
NULL, NULL);
}
/* Add a subkey to an existing KEY. */
gpgme_error_t
gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
unsigned long reserved, unsigned long expires,
unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey_start", ctx,
"key=%p, algo='%s' flags=0x%x", key, algo, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags);
return TRACE_ERR (err);
}
gpgme_error_t
gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
unsigned long reserved, unsigned long expires,
unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey", ctx,
"key=%p, algo='%s' flags=0x%x", key, algo, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
static gpgme_error_t
addrevuid_start (gpgme_ctx_t ctx, int synchronous, int extraflags,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
if (!key || !userid)
return gpg_error (GPG_ERR_INV_ARG);
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
opd->uidmode = extraflags? 2 : 1;
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
if (ctx->passphrase_cb)
{
err = _gpgme_engine_set_command_handler
(ctx->engine, _gpgme_passphrase_command_handler, ctx);
if (err)
return err;
}
return _gpgme_engine_op_genkey (ctx->engine,
userid, NULL, 0, 0,
key, flags,
NULL,
extraflags,
NULL, NULL);
}
/* Add USERID to an existing KEY. */
gpgme_error_t
gpgme_op_adduid_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid_start", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 0, 0, key, userid, flags);
return TRACE_ERR (err);
}
gpgme_error_t
gpgme_op_adduid (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 1, 0, key, userid, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
/* Revoke USERID from KEY. */
gpgme_error_t
gpgme_op_revuid_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_revuid_start", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 0, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags);
return TRACE_ERR (err);
}
gpgme_error_t
gpgme_op_revuid (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid, unsigned int flags)
{
gpgme_error_t err;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_revuid", ctx,
"uid='%s' flags=0x%x", userid, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = addrevuid_start (ctx, 1, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
/* Set a flag on the USERID of KEY. The only supported flag right now
* is "primary" to mark the primary key. */
static gpg_error_t
set_uid_flag (gpgme_ctx_t ctx, int synchronous,
gpgme_key_t key, const char *userid,
const char *name, const char *value)
{
gpgme_error_t err;
TRACE_BEG4 (DEBUG_CTX, "gpgme_op_set_uid_flag", ctx,
"%d uid='%s' '%s'='%s'", synchronous, userid, name, value);
if (!ctx || !name || !key || !userid)
return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
if (!strcmp (name, "primary"))
{
if (value)
err = gpg_error (GPG_ERR_INV_ARG);
else
err = addrevuid_start (ctx, synchronous,
GENKEY_EXTRAFLAG_SETPRIMARY, key, userid, 0);
}
else
return err = gpg_error (GPG_ERR_UNKNOWN_NAME);
if (synchronous && !err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
/* See set_uid_flag. */
gpgme_error_t
gpgme_op_set_uid_flag_start (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
const char *name, const char *value)
{
return set_uid_flag (ctx, 0, key, userid, name, value);
}
/* See set_uid_flag. This is the synchronous variant. */
gpgme_error_t
gpgme_op_set_uid_flag (gpgme_ctx_t ctx,
gpgme_key_t key, const char *userid,
const char *name, const char *value)
{
return set_uid_flag (ctx, 1, key, userid, name, value);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 25, 7:05 AM (1 d, 18 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
6c/44/d40fd6b3cc9fd8e18102eefcf6aa
Attached To
rM GPGME
Event Timeline
Log In to Comment