mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Support DSA2.
Support Camellia for testing. More audit stuff.
This commit is contained in:
parent
c8b76e5621
commit
bae4b256c7
@ -1,3 +1,7 @@
|
||||
2007-12-12 Werner Koch <wk@g10code.com>
|
||||
|
||||
* configure.ac (USE_CAMELLIA): Define by new option --enable-camellia.
|
||||
|
||||
2007-12-03 Werner Koch <wk@g10code.com>
|
||||
|
||||
* configure.ac: Add test gt_LC_MESSAGES..
|
||||
|
8
NEWS
8
NEWS
@ -14,6 +14,14 @@ Noteworthy changes in version 2.0.8
|
||||
* The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
|
||||
pinentry.
|
||||
|
||||
* Allow encryption using Elgamal keys with the algorithm id 20.
|
||||
|
||||
* Fixed the auto creation of the key stub for smartcards.
|
||||
|
||||
* Fixed a rare bug in decryption using the OpenPGP card.
|
||||
|
||||
* Creating DSA2 keys is now possible.
|
||||
|
||||
|
||||
Noteworthy changes in version 2.0.7 (2007-09-10)
|
||||
------------------------------------------------
|
||||
|
2
TODO
2
TODO
@ -91,7 +91,7 @@
|
||||
** issue a NO_SECKEY xxxx if a -u key was not found.
|
||||
|
||||
|
||||
* When switching to libgcrypt 1.3
|
||||
* When switching to libgcrypt 1.4
|
||||
** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md
|
||||
Remove the extra test for a valid algorithm as libgcrypt will do it
|
||||
then in gcry_md_algo_info.
|
||||
|
@ -1,3 +1,9 @@
|
||||
2007-12-11 Werner Koch <wk@g10code.com>
|
||||
|
||||
* asshelp.c (send_pinentry_environment): Allow using of old
|
||||
gpg-agents not capabale of the xauthority and pinentry_user_data
|
||||
options.
|
||||
|
||||
2007-12-04 Werner Koch <wk@g10code.com>
|
||||
|
||||
* Makefile.am (t_helpfile_LDADD, module_maint_tests): New.
|
||||
|
@ -172,6 +172,8 @@ send_pinentry_environment (assuan_context_t ctx,
|
||||
{
|
||||
err = send_one_option (ctx, errsource, "xauthority",
|
||||
opt_xauthority ? opt_xauthority : dft_xauthority);
|
||||
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
|
||||
err = 0;
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@ -183,6 +185,8 @@ send_pinentry_environment (assuan_context_t ctx,
|
||||
err = send_one_option (ctx, errsource, "pinentry-user-data",
|
||||
opt_pinentry_user_data ?
|
||||
opt_pinentry_user_data : dft_pinentry_user_data);
|
||||
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
|
||||
err = 0;
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
347
common/audit.c
347
common/audit.c
@ -449,9 +449,9 @@ writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
|
||||
|
||||
if (ctx->use_html && format && oktext)
|
||||
{
|
||||
if (!strcmp (oktext, "OK") || !strcmp (oktext, "Yes"))
|
||||
if (!strcmp (oktext, "Yes"))
|
||||
color = "green";
|
||||
else if (!strcmp (oktext, "FAIL") || !strcmp (oktext, "No"))
|
||||
else if (!strcmp (oktext, "No"))
|
||||
color = "red";
|
||||
}
|
||||
|
||||
@ -648,42 +648,20 @@ get_cert_subject (ksba_cert_t cert, int idx)
|
||||
}
|
||||
|
||||
|
||||
/* List the chain of certificates from STARTITEM up to STOPEVENT. The
|
||||
certifcates are written out as comments. */
|
||||
/* List the given certificiate. If CERT is NULL, this is a NOP. */
|
||||
static void
|
||||
list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
|
||||
list_cert (audit_ctx_t ctx, ksba_cert_t cert, int with_subj)
|
||||
{
|
||||
log_item_t item;
|
||||
char *name;
|
||||
int idx;
|
||||
|
||||
startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
|
||||
if (!startitem)
|
||||
name = get_cert_name (cert);
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
if (with_subj)
|
||||
{
|
||||
writeout_li (ctx, gpg_strerror (GPG_ERR_MISSING_CERT)
|
||||
, _("Certificate chain"));
|
||||
return;
|
||||
}
|
||||
writeout_li (ctx, "OK", _("Certificate chain"));
|
||||
item = find_next_log_item (ctx, startitem,
|
||||
AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
|
||||
if (!item)
|
||||
writeout_rem (ctx, "%s", _("root certificate missing"));
|
||||
else
|
||||
{
|
||||
name = get_cert_name (item->cert);
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
}
|
||||
item = startitem;
|
||||
while ( ((item = find_next_log_item (ctx, item,
|
||||
AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
|
||||
{
|
||||
name = get_cert_name (item->cert);
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
enter_li (ctx);
|
||||
for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
|
||||
for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
|
||||
{
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
@ -693,8 +671,142 @@ list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
|
||||
}
|
||||
|
||||
|
||||
/* List the chain of certificates from STARTITEM up to STOPEVENT. The
|
||||
certifcates are written out as comments. */
|
||||
static void
|
||||
list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
|
||||
{
|
||||
log_item_t item;
|
||||
|
||||
startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
|
||||
writeout_li (ctx, startitem? "Yes":"No", _("Certificate chain available"));
|
||||
if (!startitem)
|
||||
return;
|
||||
|
||||
item = find_next_log_item (ctx, startitem,
|
||||
AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
|
||||
if (!item)
|
||||
writeout_rem (ctx, "%s", _("root certificate missing"));
|
||||
else
|
||||
{
|
||||
list_cert (ctx, item->cert, 0);
|
||||
}
|
||||
item = startitem;
|
||||
while ( ((item = find_next_log_item (ctx, item,
|
||||
AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
|
||||
{
|
||||
list_cert (ctx, item->cert, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Process a verification operation. */
|
||||
/* Process an encrypt operation's log. */
|
||||
static void
|
||||
proc_type_encrypt (audit_ctx_t ctx)
|
||||
{
|
||||
log_item_t loopitem, item;
|
||||
int recp_no, idx;
|
||||
char numbuf[35];
|
||||
int algo;
|
||||
char *name;
|
||||
|
||||
item = find_log_item (ctx, AUDIT_ENCRYPTION_DONE, 0);
|
||||
writeout_li (ctx, item?"Yes":"No", "%s", _("Data encryption succeeded"));
|
||||
|
||||
enter_li (ctx);
|
||||
|
||||
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
|
||||
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
|
||||
|
||||
item = find_log_item (ctx, AUDIT_SESSION_KEY, 0);
|
||||
writeout_li (ctx, item? "Yes":"No", "%s", _("Session key created"));
|
||||
if (item)
|
||||
{
|
||||
algo = gcry_cipher_map_name (item->string);
|
||||
if (algo)
|
||||
writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
|
||||
else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
|
||||
writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
|
||||
else if (item->string)
|
||||
writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
|
||||
else
|
||||
writeout_rem (ctx, _("seems to be not encrypted"));
|
||||
}
|
||||
|
||||
item = find_log_item (ctx, AUDIT_GOT_RECIPIENTS, 0);
|
||||
snprintf (numbuf, sizeof numbuf, "%d",
|
||||
item && item->have_intvalue? item->intvalue : 0);
|
||||
writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
|
||||
|
||||
/* Loop over all recipients. */
|
||||
loopitem = NULL;
|
||||
recp_no = 0;
|
||||
while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_ENCRYPTED_TO, 0)))
|
||||
{
|
||||
recp_no++;
|
||||
writeout_li (ctx, NULL, _("Recipient %d"), recp_no);
|
||||
if (loopitem->cert)
|
||||
{
|
||||
name = get_cert_name (loopitem->cert);
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
enter_li (ctx);
|
||||
for (idx=0; (name = get_cert_subject (loopitem->cert, idx)); idx++)
|
||||
{
|
||||
writeout_rem (ctx, "%s", name);
|
||||
xfree (name);
|
||||
}
|
||||
leave_li (ctx);
|
||||
}
|
||||
}
|
||||
|
||||
leave_li (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Process a sign operation's log. */
|
||||
static void
|
||||
proc_type_sign (audit_ctx_t ctx)
|
||||
{
|
||||
log_item_t item;
|
||||
|
||||
item = NULL;
|
||||
writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
|
||||
|
||||
enter_li (ctx);
|
||||
|
||||
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
|
||||
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
|
||||
|
||||
|
||||
leave_li (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Process a decrypt operation's log. */
|
||||
static void
|
||||
proc_type_decrypt (audit_ctx_t ctx)
|
||||
{
|
||||
log_item_t item;
|
||||
|
||||
item = NULL;
|
||||
writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded"));
|
||||
|
||||
enter_li (ctx);
|
||||
|
||||
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
|
||||
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
|
||||
|
||||
|
||||
leave_li (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Process a verification operation's log. */
|
||||
static void
|
||||
proc_type_verify (audit_ctx_t ctx)
|
||||
{
|
||||
@ -702,13 +814,12 @@ proc_type_verify (audit_ctx_t ctx)
|
||||
int signo, count, idx;
|
||||
char numbuf[35];
|
||||
|
||||
/* If there is at least one signature status we claim that the
|
||||
verifciation succeeded. This does not mean that the data has
|
||||
verified okay. */
|
||||
item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
|
||||
writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
|
||||
enter_li (ctx);
|
||||
|
||||
writeout_li (ctx, "fixme", "%s", _("Signature verification"));
|
||||
enter_li (ctx);
|
||||
|
||||
writeout_li (ctx, "fixme", "%s", _("Gpg-Agent ready"));
|
||||
writeout_li (ctx, "fixme", "%s", _("Dirmngr ready"));
|
||||
|
||||
item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG);
|
||||
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
|
||||
@ -721,19 +832,14 @@ proc_type_verify (audit_ctx_t ctx)
|
||||
goto leave;
|
||||
|
||||
item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
|
||||
if (item)
|
||||
writeout_li (ctx, "OK", "%s", _("Parsing signature"));
|
||||
else
|
||||
writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded"));
|
||||
if (!item)
|
||||
{
|
||||
item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG);
|
||||
if (item)
|
||||
{
|
||||
writeout_li (ctx,"FAIL", "%s", _("Parsing signature"));
|
||||
writeout_rem (ctx, _("Bad hash algorithm: %s"),
|
||||
item->string? item->string:"?");
|
||||
}
|
||||
else
|
||||
writeout_li (ctx, "FAIL", "%s", _("Parsing signature") );
|
||||
writeout_rem (ctx, _("Bad hash algorithm: %s"),
|
||||
item->string? item->string:"?");
|
||||
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -761,19 +867,30 @@ proc_type_verify (audit_ctx_t ctx)
|
||||
AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG);
|
||||
if (item && item->have_err)
|
||||
{
|
||||
writeout_li (ctx, item->err? "FAIL":"OK",
|
||||
_("Validation of certificate chain"));
|
||||
writeout_li (ctx, item->err? "No":"Yes",
|
||||
_("Certificate chain valid"));
|
||||
if (item->err)
|
||||
writeout_rem (ctx, "%s", gpg_strerror (item->err));
|
||||
}
|
||||
|
||||
/* Show whether the root certificate is fine. */
|
||||
writeout_li (ctx, "No", "%s", _("Root certificate trustworthy"));
|
||||
add_helptag (ctx, "gpgsm.root-cert-not-trusted");
|
||||
item = find_next_log_item (ctx, loopitem,
|
||||
AUDIT_ROOT_TRUSTED, AUDIT_CHAIN_STATUS);
|
||||
if (item)
|
||||
{
|
||||
writeout_li (ctx, item->err?"No":"Yes", "%s",
|
||||
_("Root certificate trustworthy"));
|
||||
if (item->err)
|
||||
{
|
||||
add_helptag (ctx, "gpgsm.root-cert-not-trusted");
|
||||
writeout_rem (ctx, "%s", gpg_strerror (item->err));
|
||||
list_cert (ctx, item->cert, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Show result of the CRL/OCSP check. */
|
||||
writeout_li (ctx, "-", "%s", _("CRL/OCSP check of certificates"));
|
||||
add_helptag (ctx, "gpgsm.ocsp-problem");
|
||||
/* add_helptag (ctx, "gpgsm.ocsp-problem"); */
|
||||
|
||||
|
||||
leave_li (ctx);
|
||||
@ -805,8 +922,6 @@ proc_type_verify (audit_ctx_t ctx)
|
||||
}
|
||||
leave_li (ctx);
|
||||
}
|
||||
|
||||
leave_li (ctx);
|
||||
leave_li (ctx);
|
||||
}
|
||||
|
||||
@ -818,16 +933,24 @@ void
|
||||
audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
|
||||
{
|
||||
int idx;
|
||||
int maxlen;
|
||||
size_t n;
|
||||
log_item_t item;
|
||||
helptag_t helptag;
|
||||
|
||||
if (getenv ("use_html"))
|
||||
use_html = 1;
|
||||
|
||||
const char *s;
|
||||
int show_raw = 0;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
/* We use an environment variable to include some debug info in the
|
||||
log. */
|
||||
if ((s = getenv ("gnupg_debug_audit")))
|
||||
{
|
||||
show_raw = 1;
|
||||
if (!strcmp (s, "html"))
|
||||
use_html = 1;
|
||||
}
|
||||
|
||||
assert (!ctx->outstream);
|
||||
ctx->outstream = out;
|
||||
ctx->use_html = use_html;
|
||||
@ -843,51 +966,87 @@ audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
|
||||
if (show_raw)
|
||||
{
|
||||
n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
|
||||
if (n > maxlen)
|
||||
maxlen = n;
|
||||
int maxlen;
|
||||
|
||||
for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
|
||||
{
|
||||
n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
|
||||
if (n > maxlen)
|
||||
maxlen = n;
|
||||
}
|
||||
|
||||
if (use_html)
|
||||
es_fputs ("<pre>\n", out);
|
||||
for (idx=0; idx < ctx->logused; idx++)
|
||||
{
|
||||
es_fprintf (out, "log: %-*s",
|
||||
maxlen, event2str (ctx->log[idx].event));
|
||||
if (ctx->log[idx].have_intvalue)
|
||||
es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
|
||||
if (ctx->log[idx].string)
|
||||
{
|
||||
es_fputs (" s=`", out);
|
||||
writeout (ctx, ctx->log[idx].string);
|
||||
es_fputs ("'", out);
|
||||
}
|
||||
if (ctx->log[idx].cert)
|
||||
es_fprintf (out, " has_cert");
|
||||
if (ctx->log[idx].have_err)
|
||||
{
|
||||
es_fputs (" err=`", out);
|
||||
writeout (ctx, gpg_strerror (ctx->log[idx].err));
|
||||
es_fputs ("'", out);
|
||||
}
|
||||
es_fputs ("\n", out);
|
||||
}
|
||||
if (use_html)
|
||||
es_fputs ("</pre>\n", out);
|
||||
else
|
||||
es_fputs ("\n", out);
|
||||
}
|
||||
|
||||
if (use_html)
|
||||
es_fputs ("<pre>\n", out);
|
||||
for (idx=0; idx < ctx->logused; idx++)
|
||||
{
|
||||
es_fprintf (out, "log: %-*s",
|
||||
maxlen, event2str (ctx->log[idx].event));
|
||||
if (ctx->log[idx].have_intvalue)
|
||||
es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
|
||||
if (ctx->log[idx].string)
|
||||
{
|
||||
es_fputs (" s=`", out);
|
||||
writeout (ctx, ctx->log[idx].string);
|
||||
es_fputs ("'", out);
|
||||
}
|
||||
if (ctx->log[idx].cert)
|
||||
es_fprintf (out, " has_cert");
|
||||
if (ctx->log[idx].have_err)
|
||||
{
|
||||
es_fputs (" err=`", out);
|
||||
writeout (ctx, gpg_strerror (ctx->log[idx].err));
|
||||
es_fputs ("'", out);
|
||||
}
|
||||
es_fputs ("\n", out);
|
||||
}
|
||||
if (use_html)
|
||||
es_fputs ("</pre>\n", out);
|
||||
else
|
||||
es_fputs ("\n", out);
|
||||
|
||||
enter_li (ctx);
|
||||
switch (ctx->type)
|
||||
{
|
||||
case AUDIT_TYPE_NONE:
|
||||
writeout_para (ctx, _("Audit of this operation is not supported."));
|
||||
writeout_li (ctx, NULL, _("Unknown operation"));
|
||||
break;
|
||||
case AUDIT_TYPE_ENCRYPT:
|
||||
proc_type_encrypt (ctx);
|
||||
break;
|
||||
case AUDIT_TYPE_SIGN:
|
||||
proc_type_sign (ctx);
|
||||
break;
|
||||
case AUDIT_TYPE_DECRYPT:
|
||||
proc_type_decrypt (ctx);
|
||||
break;
|
||||
case AUDIT_TYPE_VERIFY:
|
||||
proc_type_verify (ctx);
|
||||
break;
|
||||
}
|
||||
item = find_log_item (ctx, AUDIT_AGENT_READY, 0);
|
||||
if (item && item->have_err)
|
||||
{
|
||||
writeout_li (ctx, item->err? "No":"Yes", "%s", _("Gpg-Agent usable"));
|
||||
if (item->err)
|
||||
{
|
||||
writeout_rem (ctx, "%s", gpg_strerror (item->err));
|
||||
add_helptag (ctx, "gnupg.agent-problem");
|
||||
}
|
||||
}
|
||||
item = find_log_item (ctx, AUDIT_DIRMNGR_READY, 0);
|
||||
if (item && item->have_err)
|
||||
{
|
||||
writeout_li (ctx, item->err? "No":"Yes", "%s", _("Dirmngr usable"));
|
||||
if (item->err)
|
||||
{
|
||||
writeout_rem (ctx, "%s", gpg_strerror (item->err));
|
||||
add_helptag (ctx, "gnupg.dirmngr-problem");
|
||||
}
|
||||
}
|
||||
leave_li (ctx);
|
||||
|
||||
|
||||
/* Show the help from the collected help tags. */
|
||||
|
@ -31,6 +31,9 @@ typedef struct audit_ctx_s *audit_ctx_t;
|
||||
typedef enum
|
||||
{
|
||||
AUDIT_TYPE_NONE = 0, /* No type set. */
|
||||
AUDIT_TYPE_ENCRYPT, /* Data encryption. */
|
||||
AUDIT_TYPE_SIGN, /* Signature creation. */
|
||||
AUDIT_TYPE_DECRYPT, /* Data decryption. */
|
||||
AUDIT_TYPE_VERIFY /* Signature verification. */
|
||||
}
|
||||
audit_type_t;
|
||||
@ -49,6 +52,16 @@ typedef enum
|
||||
now. This indicates that all parameters are okay and we can
|
||||
start to process the actual data. */
|
||||
|
||||
AUDIT_AGENT_READY, /* err */
|
||||
/* Indicates whether the gpg-agent is available. For some
|
||||
operations the agent is not required and thus no such event
|
||||
will be logged. */
|
||||
|
||||
AUDIT_DIRMNGR_READY, /* err */
|
||||
/* Indicates whether the Dirmngr is available. For some
|
||||
operations the Dirmngr is not required and thus no such event
|
||||
will be logged. */
|
||||
|
||||
AUDIT_GOT_DATA,
|
||||
/* Data to be processed has been seen. */
|
||||
|
||||
@ -122,6 +135,28 @@ typedef enum
|
||||
AUDIT_CHAIN_STATUS, /* err */
|
||||
/* Tells the final status of the chain validation. */
|
||||
|
||||
AUDIT_ROOT_TRUSTED, /* cert, err */
|
||||
/* Tells whether the root certificate is trusted. This event is
|
||||
emmited durcing chain validation. */
|
||||
|
||||
AUDIT_GOT_RECIPIENTS, /* int */
|
||||
/* Records the number of recipients to be used for encryption.
|
||||
This includes the recipients set by --encrypt-to but records 0
|
||||
if no real recipient has been given. */
|
||||
|
||||
AUDIT_SESSION_KEY, /* string */
|
||||
/* Mark the creation or availibility of the session key. The
|
||||
parameter is the algorithm ID. */
|
||||
|
||||
AUDIT_ENCRYPTED_TO, /* cert, err */
|
||||
/* Records the certificate used for encryption and whether the
|
||||
session key could be encrypted to it (err==0). */
|
||||
|
||||
AUDIT_ENCRYPTION_DONE,
|
||||
/* Encryption succeeded. */
|
||||
|
||||
|
||||
|
||||
|
||||
AUDIT_LAST_EVENT /* Marker for parsing this list. */
|
||||
}
|
||||
|
22
configure.ac
22
configure.ac
@ -73,6 +73,7 @@ have_libusb=no
|
||||
use_bzip2=yes
|
||||
use_exec=yes
|
||||
disable_keyserver_path=no
|
||||
use_camellia=no
|
||||
|
||||
|
||||
GNUPG_BUILD_PROGRAM(gpg, yes)
|
||||
@ -172,6 +173,21 @@ AC_ARG_ENABLE(bzip2,
|
||||
use_bzip2=$enableval)
|
||||
AC_MSG_RESULT($use_bzip2)
|
||||
|
||||
# Check whether testing support for Camellia has been requested
|
||||
AC_MSG_CHECKING([whether to enable the CAMELLIA cipher for gpg])
|
||||
AC_ARG_ENABLE(camellia,
|
||||
AC_HELP_STRING([--enable-camellia],[enable the CAMELLIA cipher for gpg]),
|
||||
use_camellia=$enableval)
|
||||
AC_MSG_RESULT($use_camellia)
|
||||
if test x"$use_camellia" = xyes ; then
|
||||
AC_DEFINE(USE_CAMELLIA,1,[Define to include the CAMELLIA cipher into gpg])
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** The Camellia cipher for gpg is for testing only and
|
||||
*** is NOT for production use!
|
||||
***]])
|
||||
fi
|
||||
|
||||
|
||||
# Configure option to allow or disallow execution of external
|
||||
# programs, like a photo viewer.
|
||||
@ -1417,4 +1433,10 @@ echo "
|
||||
gpg-check-pattern will not be build.
|
||||
"
|
||||
fi
|
||||
if test x"$use_camellia" = xyes ; then
|
||||
echo
|
||||
echo "WARNING: The Camellia cipher for gpg is for testing only"
|
||||
echo " and is NOT for production use!"
|
||||
echo
|
||||
fi
|
||||
|
||||
|
@ -272,6 +272,6 @@ Eine Leerzeile beendet die Eingabe.
|
||||
|
||||
|
||||
# Local variables:
|
||||
# mode: fundamental
|
||||
# mode: default-generic
|
||||
# coding: utf-8
|
||||
# End:
|
||||
|
40
doc/help.txt
40
doc/help.txt
@ -52,6 +52,44 @@ configured passphrase constraints.
|
||||
.
|
||||
|
||||
|
||||
.gnupg.agent-problem
|
||||
# There was a problem accessing or starting the agent.
|
||||
It was either not possible to connect to a running Gpg-Agent or a
|
||||
communication problem with a running agent occurred.
|
||||
|
||||
The system uses a background process, called Gpg-Agent, for processing
|
||||
private keys and to ask for passphrases. The agent is usually started
|
||||
when the user logs in and runs as long the user is logged in. In case
|
||||
that no agent is available, the system tries to start one on the fly
|
||||
but that version of the agent is somewhat limited in functionality and
|
||||
thus may lead to little problems.
|
||||
|
||||
You probably need to ask your administrator on how to solve the
|
||||
problem. As a workaround you might try to log out and in to your
|
||||
session and see whether this helps. If this helps please tell the
|
||||
administrator anyway because this indicates a bug in the software.
|
||||
.
|
||||
|
||||
|
||||
.gnupg.dirmngr-problem
|
||||
# There was a problen accessing the dirmngr.
|
||||
It was either not possible to connect to a running Dirmngr or a
|
||||
communication problem with a running Dirmngr occurred.
|
||||
|
||||
To lookup certificate revocation lists (CRLs), performing OCSP
|
||||
validation and to lookup keys through LDAP servers, the system uses an
|
||||
external service program named Dirmngr. The Dirmngr is usually running
|
||||
as a system service (daemon) and does not need any attention by the
|
||||
user. In case of problems the system might start its own copy of the
|
||||
Dirmngr on a per request base; this is a workaround and yields limited
|
||||
performance.
|
||||
|
||||
If you encounter this problem, you should ask your system
|
||||
administrator how to proceed. As an interim solution you may try to
|
||||
disable CRL checking in gpgsm's configuration.
|
||||
.
|
||||
|
||||
|
||||
.gpg.edit_ownertrust.value
|
||||
# The help identies prefixed with "gpg." used to be hard coded in gpg
|
||||
# but may now be overridden by help texts from this file.
|
||||
@ -312,6 +350,6 @@ your system administrator whether you should trust this certificate.
|
||||
|
||||
|
||||
# Local variables:
|
||||
# mode: fundamental
|
||||
# mode: default-generic
|
||||
# coding: utf-8
|
||||
# End:
|
||||
|
@ -1,6 +1,30 @@
|
||||
2007-12-12 Werner Koch <wk@g10code.com>
|
||||
|
||||
* misc.c (map_cipher_openpgp_to_gcry): New. Used to map Camellia
|
||||
algorithms to Gcrypt.
|
||||
(openpgp_cipher_test_algo): Call new map function. Replace
|
||||
all remaining calls to gcry_cipher_test_algo by a call to this.
|
||||
(openpgp_cipher_algo_name): New. Replace all remaining calls to
|
||||
gcry_cipher_algo_name by a call to this.
|
||||
(map_cipher_gcry_to_openpgp): New.
|
||||
(string_to_cipher_algo): Use it.
|
||||
* gpg.c (main): Print a warning if Camellia support is build in.
|
||||
|
||||
* gpg.c (print_algo_names): New. From the 1.4 branch by David.
|
||||
(list_config): Use it here for the "ciphername" and "digestname"
|
||||
config items so we can get a script-parseable list of the names.
|
||||
|
||||
* parse-packet.c (parse_onepass_sig): Sigclass is hex, so include
|
||||
the 0x.
|
||||
|
||||
* sign.c (match_dsa_hash): Remove conditional builds dending on
|
||||
USE_SHAxxx. We don't need this becuase it can be expected that
|
||||
libgcrypt provides it. However we need to runtime test for SHA244
|
||||
becuase that is only available with libgcrypt 2.4.
|
||||
|
||||
2007-12-11 Werner Koch <wk@g10code.com>
|
||||
|
||||
* mainproc.c (proc_pubkey_enc): Allo type 20 Elgamal key for
|
||||
* mainproc.c (proc_pubkey_enc): Allow type 20 Elgamal key for
|
||||
decryption.
|
||||
|
||||
2007-12-10 Werner Koch <wk@g10code.com>
|
||||
|
@ -244,7 +244,7 @@ encode_simple( const char *filename, int mode, int use_seskey )
|
||||
|
||||
if(opt.verbose)
|
||||
log_info(_("using cipher %s\n"),
|
||||
gcry_cipher_algo_name (cfx.dek->algo));
|
||||
openpgp_cipher_algo_name (cfx.dek->algo));
|
||||
|
||||
cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
|
||||
}
|
||||
@ -558,7 +558,7 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
|
||||
opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
|
||||
log_info(_("WARNING: forcing symmetric cipher %s (%d)"
|
||||
" violates recipient preferences\n"),
|
||||
gcry_cipher_algo_name (opt.def_cipher_algo),
|
||||
openpgp_cipher_algo_name (opt.def_cipher_algo),
|
||||
opt.def_cipher_algo);
|
||||
|
||||
cfx.dek->algo = opt.def_cipher_algo;
|
||||
@ -750,7 +750,7 @@ encrypt_filter( void *opaque, int control,
|
||||
NULL)!=opt.def_cipher_algo)
|
||||
log_info(_("forcing symmetric cipher %s (%d) "
|
||||
"violates recipient preferences\n"),
|
||||
gcry_cipher_algo_name (opt.def_cipher_algo),
|
||||
openpgp_cipher_algo_name (opt.def_cipher_algo),
|
||||
opt.def_cipher_algo);
|
||||
|
||||
efx->cfx.dek->algo = opt.def_cipher_algo;
|
||||
@ -847,7 +847,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
|
||||
char *ustr = get_user_id_string_native (enc->keyid);
|
||||
log_info(_("%s/%s encrypted for: \"%s\"\n"),
|
||||
gcry_pk_algo_name (enc->pubkey_algo),
|
||||
gcry_cipher_algo_name (dek->algo),
|
||||
openpgp_cipher_algo_name (dek->algo),
|
||||
ustr );
|
||||
xfree(ustr);
|
||||
}
|
||||
|
@ -88,8 +88,9 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
|
||||
|
||||
if ( opt.verbose && !dek->algo_info_printed )
|
||||
{
|
||||
if (!gcry_cipher_test_algo (dek->algo))
|
||||
log_info (_("%s encrypted data\n"), gcry_cipher_algo_name (dek->algo));
|
||||
if (!openpgp_cipher_test_algo (dek->algo))
|
||||
log_info (_("%s encrypted data\n"),
|
||||
openpgp_cipher_algo_name (dek->algo));
|
||||
else
|
||||
log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
|
||||
dek->algo_info_printed = 1;
|
||||
|
49
g10/gpg.c
49
g10/gpg.c
@ -791,7 +791,7 @@ my_strusage( int level )
|
||||
case 35:
|
||||
if( !ciphers )
|
||||
ciphers = build_list(_("Cipher: "), 'S',
|
||||
gcry_cipher_algo_name,
|
||||
openpgp_cipher_algo_name,
|
||||
openpgp_cipher_test_algo );
|
||||
p = ciphers;
|
||||
break;
|
||||
@ -1384,6 +1384,24 @@ print_algo_numbers(int (*checker)(int))
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_algo_names(int (*checker)(int),const char *(*mapper)(int))
|
||||
{
|
||||
int i,first=1;
|
||||
|
||||
for(i=0;i<=110;i++)
|
||||
{
|
||||
if(!checker(i))
|
||||
{
|
||||
if(first)
|
||||
first=0;
|
||||
else
|
||||
printf(";");
|
||||
printf("%s",mapper(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In the future, we can do all sorts of interesting configuration
|
||||
output here. For now, just give "group" as the Enigmail folks need
|
||||
it, and pubkey, cipher, hash, and compress as they may be useful
|
||||
@ -1450,6 +1468,14 @@ list_config(char *items)
|
||||
any=1;
|
||||
}
|
||||
|
||||
if (show_all || !ascii_strcasecmp (name,"ciphername"))
|
||||
{
|
||||
printf ("cfg:ciphername:");
|
||||
print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
|
||||
printf ("\n");
|
||||
any = 1;
|
||||
}
|
||||
|
||||
if(show_all
|
||||
|| ascii_strcasecmp(name,"digest")==0
|
||||
|| ascii_strcasecmp(name,"hash")==0)
|
||||
@ -1460,6 +1486,16 @@ list_config(char *items)
|
||||
any=1;
|
||||
}
|
||||
|
||||
if (show_all
|
||||
|| !ascii_strcasecmp(name,"digestname")
|
||||
|| !ascii_strcasecmp(name,"hashname"))
|
||||
{
|
||||
printf ("cfg:digestname:");
|
||||
print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
|
||||
printf("\n");
|
||||
any=1;
|
||||
}
|
||||
|
||||
if(show_all || ascii_strcasecmp(name,"compress")==0)
|
||||
{
|
||||
printf("cfg:compress:");
|
||||
@ -2864,6 +2900,15 @@ main (int argc, char **argv )
|
||||
log_set_prefix (NULL, 1|2|4);
|
||||
}
|
||||
|
||||
#ifdef USE_CAMELLIA
|
||||
/* We better also print a runtime warning if people build it with
|
||||
support for Camellia (which is not yet defined by OpenPGP). */
|
||||
log_info ("WARNING: This version has been built with support for the "
|
||||
"Camellia cipher.\n");
|
||||
log_info (" It is for testing only and is NOT for production "
|
||||
"use!\n");
|
||||
#endif
|
||||
|
||||
if (opt.verbose > 2)
|
||||
log_info ("using character set `%s'\n", get_native_charset ());
|
||||
|
||||
@ -3129,7 +3174,7 @@ main (int argc, char **argv )
|
||||
if(opt.def_cipher_algo
|
||||
&& !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL))
|
||||
{
|
||||
badalg = gcry_cipher_algo_name (opt.def_cipher_algo);
|
||||
badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
|
||||
badtype = PREFTYPE_SYM;
|
||||
}
|
||||
else if(opt.def_digest_algo
|
||||
|
@ -602,9 +602,9 @@ check_prefs(KBNODE keyblock)
|
||||
if (openpgp_cipher_test_algo (prefs->value))
|
||||
{
|
||||
const char *algo =
|
||||
(gcry_cipher_test_algo (prefs->value)
|
||||
(openpgp_cipher_test_algo (prefs->value)
|
||||
? num
|
||||
: gcry_cipher_algo_name (prefs->value));
|
||||
: openpgp_cipher_algo_name (prefs->value));
|
||||
if(!problem)
|
||||
check_prefs_warning(pk);
|
||||
log_info(_(" \"%s\": preference for cipher"
|
||||
|
@ -2325,9 +2325,10 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
|
||||
tty_printf (", ");
|
||||
any = 1;
|
||||
/* We don't want to display strings for experimental algos */
|
||||
if (!gcry_cipher_test_algo (prefs[i].value)
|
||||
if (!openpgp_cipher_test_algo (prefs[i].value)
|
||||
&& prefs[i].value < 100 )
|
||||
tty_printf ("%s", gcry_cipher_algo_name (prefs[i].value));
|
||||
tty_printf ("%s",
|
||||
openpgp_cipher_algo_name (prefs[i].value));
|
||||
else
|
||||
tty_printf ("[%d]", prefs[i].value);
|
||||
if (prefs[i].value == CIPHER_ALGO_3DES )
|
||||
@ -2337,7 +2338,7 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
|
||||
if (!des_seen) {
|
||||
if (any)
|
||||
tty_printf (", ");
|
||||
tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES));
|
||||
tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
|
||||
}
|
||||
tty_printf ("\n ");
|
||||
tty_printf (_("Digest: "));
|
||||
|
@ -83,6 +83,7 @@ u16 checksum_mpi( gcry_mpi_t a );
|
||||
u32 buffer_to_u32( const byte *buffer );
|
||||
const byte *get_session_marker( size_t *rlen );
|
||||
int openpgp_cipher_test_algo( int algo );
|
||||
const char *openpgp_cipher_algo_name (int algo);
|
||||
int openpgp_pk_test_algo( int algo );
|
||||
int openpgp_pk_test_algo2 ( int algo, unsigned int use );
|
||||
int openpgp_pk_algo_usage ( int algo );
|
||||
|
@ -274,9 +274,9 @@ proc_symkey_enc( CTX c, PACKET *pkt )
|
||||
else if(!c->dek)
|
||||
{
|
||||
int algo = enc->cipher_algo;
|
||||
const char *s = gcry_cipher_algo_name (algo);
|
||||
const char *s = openpgp_cipher_algo_name (algo);
|
||||
|
||||
if (!gcry_cipher_test_algo (algo))
|
||||
if (!openpgp_cipher_test_algo (algo))
|
||||
{
|
||||
if(!opt.quiet)
|
||||
{
|
||||
@ -524,8 +524,8 @@ proc_encrypted( CTX c, PACKET *pkt )
|
||||
algo = opt.def_cipher_algo;
|
||||
if ( algo )
|
||||
log_info (_("assuming %s encrypted data\n"),
|
||||
gcry_cipher_algo_name (algo));
|
||||
else if ( gcry_cipher_test_algo (CIPHER_ALGO_IDEA) )
|
||||
openpgp_cipher_algo_name (algo));
|
||||
else if ( openpgp_cipher_test_algo (CIPHER_ALGO_IDEA) )
|
||||
{
|
||||
algo = opt.def_cipher_algo;
|
||||
if (!algo)
|
||||
@ -533,7 +533,7 @@ proc_encrypted( CTX c, PACKET *pkt )
|
||||
idea_cipher_warn(1);
|
||||
log_info (_("IDEA cipher unavailable, "
|
||||
"optimistically attempting to use %s instead\n"),
|
||||
gcry_cipher_algo_name (algo));
|
||||
openpgp_cipher_algo_name (algo));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
55
g10/misc.c
55
g10/misc.c
@ -301,7 +301,7 @@ print_cipher_algo_note( int algo )
|
||||
{
|
||||
warn=1;
|
||||
log_info (_("WARNING: using experimental cipher algorithm %s\n"),
|
||||
gcry_cipher_algo_name (algo));
|
||||
openpgp_cipher_algo_name (algo));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,6 +324,33 @@ print_digest_algo_note( int algo )
|
||||
gcry_md_algo_name (algo));
|
||||
}
|
||||
|
||||
|
||||
/* Map OpenPGP algo numbers to those used by Libgcrypt. We need to do
|
||||
this for algorithms we implemented in Libgcrypt after they become
|
||||
part of OpenPGP. */
|
||||
static int
|
||||
map_cipher_openpgp_to_gcry (int algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
case CIPHER_ALGO_CAMELLIA128: return 310;
|
||||
case CIPHER_ALGO_CAMELLIA256: return 312;
|
||||
default: return algo;
|
||||
}
|
||||
}
|
||||
|
||||
/* The inverse fucntion of above. */
|
||||
static int
|
||||
map_cipher_gcry_to_openpgp (int algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
case 310: return CIPHER_ALGO_CAMELLIA128;
|
||||
case 312: return CIPHER_ALGO_CAMELLIA256;
|
||||
default: return algo;
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* Wrapper around the libgcrypt function with additonal checks on
|
||||
* the OpenPGP contraints for the algo ID.
|
||||
@ -331,12 +358,32 @@ print_digest_algo_note( int algo )
|
||||
int
|
||||
openpgp_cipher_test_algo( int algo )
|
||||
{
|
||||
/* 5 and 6 are marked reserved by rfc2440bis. */
|
||||
/* (5 and 6 are marked reserved by rfc4880.) */
|
||||
if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 )
|
||||
return gpg_error (GPG_ERR_CIPHER_ALGO);
|
||||
return gcry_cipher_test_algo (algo);
|
||||
|
||||
/* Camellia is not yet defined for OpenPGP thus only allow it if
|
||||
requested. */
|
||||
#ifndef USE_CAMELLIA
|
||||
if (algo == CIPHER_ALGO_CAMELLIA128
|
||||
|| algo == CIPHER_ALGO_CAMELLIA256)
|
||||
return gpg_error (GPG_ERR_CIPHER_ALGO);
|
||||
#endif
|
||||
|
||||
return gcry_cipher_test_algo (map_cipher_openpgp_to_gcry (algo));
|
||||
}
|
||||
|
||||
/* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a
|
||||
string representation of the algorithm name. For unknown algorithm
|
||||
IDs this function returns "?". */
|
||||
const char *
|
||||
openpgp_cipher_algo_name (int algo)
|
||||
{
|
||||
return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
openpgp_pk_test_algo( int algo )
|
||||
{
|
||||
@ -690,7 +737,7 @@ string_to_cipher_algo (const char *string)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = gcry_cipher_map_name (string);
|
||||
val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
|
||||
if (!val && string && (string[0]=='S' || string[0]=='s'))
|
||||
{
|
||||
char *endptr;
|
||||
|
@ -1588,8 +1588,10 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
ops->keyid[1] = read_32(inp); pktlen -= 4;
|
||||
ops->last = iobuf_get_noeof(inp); pktlen--;
|
||||
if( list_mode )
|
||||
fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n"
|
||||
"\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
|
||||
fprintf (listfp,
|
||||
":onepass_sig packet: keyid %08lX%08lX\n"
|
||||
"\tversion %d, sigclass 0x%02x, digest %d, pubkey %d, "
|
||||
"last=%d\n",
|
||||
(ulong)ops->keyid[0], (ulong)ops->keyid[1],
|
||||
version, ops->sig_class,
|
||||
ops->digest_algo, ops->pubkey_algo, ops->last );
|
||||
|
@ -282,7 +282,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
|
||||
&& !opt.quiet
|
||||
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
|
||||
log_info (_("WARNING: cipher algorithm %s not found in recipient"
|
||||
" preferences\n"), gcry_cipher_algo_name (dek->algo));
|
||||
" preferences\n"), openpgp_cipher_algo_name (dek->algo));
|
||||
if (!rc) {
|
||||
KBNODE k;
|
||||
|
||||
|
16
g10/sign.c
16
g10/sign.c
@ -345,22 +345,24 @@ match_dsa_hash (unsigned int qbytes)
|
||||
{
|
||||
if (qbytes <= 20)
|
||||
return DIGEST_ALGO_SHA1;
|
||||
#ifdef USE_SHA256
|
||||
if (qbytes <= 28)
|
||||
|
||||
/* SHA244 is only available with libgcrypt 1.4 - thus do a runtime
|
||||
test. */
|
||||
if (qbytes <= 28 && !gcry_md_test_algo (DIGEST_ALGO_SHA224))
|
||||
return DIGEST_ALGO_SHA224;
|
||||
|
||||
if (qbytes <= 32)
|
||||
return DIGEST_ALGO_SHA256;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHA512
|
||||
if (qbytes <= 48)
|
||||
return DIGEST_ALGO_SHA384;
|
||||
|
||||
if (qbytes <= 64)
|
||||
return DIGEST_ALGO_SHA512;
|
||||
#endif
|
||||
|
||||
return DEFAULT_DIGEST_ALGO;
|
||||
/* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong
|
||||
answer we have if the larger SHAs aren't there. */
|
||||
answer we have if a digest larger than 512 bits is requested. */
|
||||
}
|
||||
|
||||
|
||||
@ -1258,7 +1260,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
|
||||
algo = default_cipher_algo();
|
||||
if (!opt.quiet || !opt.batch)
|
||||
log_info (_("%s encryption will be used\n"),
|
||||
gcry_cipher_algo_name (algo) );
|
||||
openpgp_cipher_algo_name (algo) );
|
||||
cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
|
||||
|
||||
if (!cfx.dek || !cfx.dek->keylen) {
|
||||
|
@ -1,3 +1,7 @@
|
||||
2007-12-12 Werner Koch <wk@g10code.com>
|
||||
|
||||
* cipher.h (CIPHER_ALGO_CAMELLIA128, CIPHER_ALGO_CAMELLIA256): New.
|
||||
|
||||
2006-09-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* errors.h, http.h, memory.h, mpi.h, util.h, i18n.h: Removed.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* cipher.h - Definitions for OpenPGP
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2006,
|
||||
* 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -44,6 +45,9 @@
|
||||
#define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192
|
||||
#define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256
|
||||
#define CIPHER_ALGO_TWOFISH /* 10 */ GCRY_CIPHER_TWOFISH /* 256 bit */
|
||||
/* Note: Camellia ids don't match those used by libgcrypt. */
|
||||
#define CIPHER_ALGO_CAMELLIA128 11
|
||||
#define CIPHER_ALGO_CAMELLIA256 12
|
||||
#define CIPHER_ALGO_DUMMY 110 /* No encryption at all. */
|
||||
|
||||
#define PUBKEY_ALGO_RSA /* 1 */ GCRY_PK_RSA
|
||||
@ -66,8 +70,8 @@
|
||||
#define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256
|
||||
#define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384
|
||||
#define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512
|
||||
/* SHA224 is as of now only defined in the libgcrypt SVN; thus we
|
||||
can't use that macro. */
|
||||
/* SHA224 is only available in libgcrypt 1.4.0; thus we
|
||||
can't use the GCRY macro here. */
|
||||
#define DIGEST_ALGO_SHA224 /* 11 */ 11 /* GCRY_MD_SHA224 */
|
||||
|
||||
#define COMPRESS_ALGO_NONE 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
2007-12-10 Werner Koch <wk@g10code.com>
|
||||
|
||||
* app-openpgp.c (do_decipher): Take care of cryptograms shiorther
|
||||
* app-openpgp.c (do_decipher): Take care of cryptograms shorter
|
||||
that 128 bytes. Fixes bug#851.
|
||||
|
||||
2007-11-14 Werner Koch <wk@g10code.com>
|
||||
|
@ -2461,7 +2461,7 @@ do_decipher (app_t app, const char *keyidstr,
|
||||
|
||||
/* We might encounter a couple of leading zeroes in the
|
||||
cryptogram. Due to internal use of MPIs thease leading
|
||||
zeroes are stripped. However the OpenPGp card expects
|
||||
zeroes are stripped. However the OpenPGP card expects
|
||||
exactly 128 bytes for the cryptogram (for a 1k key). Thus we
|
||||
need to fix it up. We do this for up to 16 leading zero
|
||||
bytes; a cryptogram with more than this is with a very high
|
||||
|
17
sm/ChangeLog
17
sm/ChangeLog
@ -1,3 +1,20 @@
|
||||
2007-12-11 Werner Koch <wk@g10code.com>
|
||||
|
||||
* certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED.
|
||||
|
||||
* server.c (cmd_sign, cmd_decrypt, cmd_encrypt): Start audit log.
|
||||
(cmd_recipient): Start audit session.
|
||||
|
||||
* gpgsm.c (main): Revamp creation of the audit log.
|
||||
|
||||
* gpgsm.h (struct server_control_s): Add AGENT_SEEN and DIRMNGR_SEEN.
|
||||
* call-agent.c (start_agent): Record an audit event.
|
||||
* call-dirmngr.c (start_dirmngr): Ditto. Add new arg CTRL and pass
|
||||
it from all callers.
|
||||
(prepare_dirmngr): New helper for start_dirmngr.
|
||||
|
||||
* encrypt.c (gpgsm_encrypt): Add calls to audit_log.
|
||||
|
||||
2007-12-03 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpgsm.c (main): All gnupg_reopen_std.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* call-agent.c - divert operations to the agent
|
||||
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2001, 2002, 2003, 2005,
|
||||
* 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -69,13 +70,14 @@ struct learn_parm_s
|
||||
static int
|
||||
start_agent (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (agent_ctx)
|
||||
return 0; /* fixme: We need a context for each thread or serialize
|
||||
the access to the agent (which is suitable given that
|
||||
the agent is not MT. */
|
||||
|
||||
|
||||
return start_new_gpg_agent (&agent_ctx,
|
||||
rc = 0; /* fixme: We need a context for each thread or
|
||||
serialize the access to the agent (which is
|
||||
suitable given that the agent is not MT. */
|
||||
else
|
||||
rc = start_new_gpg_agent (&agent_ctx,
|
||||
GPG_ERR_SOURCE_DEFAULT,
|
||||
opt.homedir,
|
||||
opt.agent_program,
|
||||
@ -84,7 +86,13 @@ start_agent (ctrl_t ctrl)
|
||||
opt.xauthority, opt.pinentry_user_data,
|
||||
opt.verbose, DBG_ASSUAN,
|
||||
gpgsm_status2, ctrl);
|
||||
if (!ctrl->agent_seen)
|
||||
{
|
||||
ctrl->agent_seen = 1;
|
||||
audit_log_ok (ctrl->audit, AUDIT_AGENT_READY, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* call-dirmngr.c - communication with the dromngr
|
||||
* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -134,13 +134,32 @@ get_membuf (struct membuf *mb, size_t *len)
|
||||
}
|
||||
|
||||
|
||||
/* This fucntion prepares the dirmngr for a new session. The
|
||||
audit-events option is used so that other dirmngr clients won't get
|
||||
disturbed by such events. */
|
||||
static void
|
||||
prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
|
||||
{
|
||||
if (!ctrl->dirmngr_seen)
|
||||
{
|
||||
ctrl->dirmngr_seen = 1;
|
||||
if (!err)
|
||||
{
|
||||
err = assuan_transact (ctx, "OPTION audit-events=1",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
|
||||
err = 0; /* Allow the use of old dirmngr versions. */
|
||||
}
|
||||
audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Try to connect to the agent via socket or fork it off and work by
|
||||
pipes. Handle the server's initial greeting */
|
||||
static int
|
||||
start_dirmngr (void)
|
||||
start_dirmngr (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
char *infostr, *p;
|
||||
@ -148,8 +167,11 @@ start_dirmngr (void)
|
||||
int try_default = 0;
|
||||
|
||||
if (dirmngr_ctx)
|
||||
return 0; /* fixme: We need a context for each thread or serialize
|
||||
the access to the dirmngr */
|
||||
{
|
||||
prepare_dirmngr (ctrl, dirmngr_ctx, 0);
|
||||
return 0; /* fixme: We need a context for each thread or serialize
|
||||
the access to the dirmngr */
|
||||
}
|
||||
/* Note: if you change this to multiple connections, you also need
|
||||
to take care of the implicit option sending caching. */
|
||||
|
||||
@ -220,7 +242,7 @@ start_dirmngr (void)
|
||||
log_error (_("malformed DIRMNGR_INFO environment variable\n"));
|
||||
xfree (infostr);
|
||||
force_pipe_server = 1;
|
||||
return start_dirmngr ();
|
||||
return start_dirmngr (ctrl);
|
||||
}
|
||||
*p++ = 0;
|
||||
pid = atoi (p);
|
||||
@ -233,7 +255,7 @@ start_dirmngr (void)
|
||||
prot);
|
||||
xfree (infostr);
|
||||
force_pipe_server = 1;
|
||||
return start_dirmngr ();
|
||||
return start_dirmngr (ctrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -251,11 +273,13 @@ start_dirmngr (void)
|
||||
{
|
||||
log_error (_("can't connect to the dirmngr - trying fall back\n"));
|
||||
force_pipe_server = 1;
|
||||
return start_dirmngr ();
|
||||
return start_dirmngr (ctrl);
|
||||
}
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
}
|
||||
|
||||
prepare_dirmngr (ctrl, ctx, rc);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
|
||||
@ -424,7 +448,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
|
||||
struct isvalid_status_parm_s stparm;
|
||||
|
||||
|
||||
rc = start_dirmngr ();
|
||||
rc = start_dirmngr (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -691,7 +715,7 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
|
||||
struct lookup_parm_s parm;
|
||||
size_t len;
|
||||
|
||||
rc = start_dirmngr ();
|
||||
rc = start_dirmngr (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -821,7 +845,7 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
|
||||
size_t len;
|
||||
struct run_command_parm_s parm;
|
||||
|
||||
rc = start_dirmngr ();
|
||||
rc = start_dirmngr (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -1127,6 +1127,8 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
|
||||
associated with that specific root certificate. */
|
||||
istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
|
||||
rootca_flags);
|
||||
audit_log_cert (ctrl->audit, AUDIT_ROOT_TRUSTED,
|
||||
subject_cert, istrusted_rc);
|
||||
/* If the chain model extended attribute is used, make sure
|
||||
that our chain model flag is set. */
|
||||
if (has_validation_model_chain (subject_cert, listmode, listfp))
|
||||
|
20
sm/encrypt.c
20
sm/encrypt.c
@ -1,5 +1,5 @@
|
||||
/* encrypt.c - Encrypt a message
|
||||
* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -318,9 +318,12 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
int recpno;
|
||||
FILE *data_fp = NULL;
|
||||
certlist_t cl;
|
||||
int count;
|
||||
|
||||
memset (&encparm, 0, sizeof encparm);
|
||||
|
||||
audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);
|
||||
|
||||
/* Check that the certificate list is not empty and that at least
|
||||
one certificate is not flagged as encrypt_to; i.e. is a real
|
||||
recipient. */
|
||||
@ -331,10 +334,15 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
{
|
||||
log_error(_("no valid recipients given\n"));
|
||||
gpgsm_status (ctrl, STATUS_NO_RECP, "0");
|
||||
audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
|
||||
rc = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
for (count = 0, cl = recplist; cl; cl = cl->next)
|
||||
count++;
|
||||
audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);
|
||||
|
||||
kh = keydb_new (0);
|
||||
if (!kh)
|
||||
{
|
||||
@ -385,6 +393,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
audit_log (ctrl->audit, AUDIT_GOT_DATA);
|
||||
|
||||
/* We are going to create enveloped data with uninterpreted data as
|
||||
inner content */
|
||||
err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
|
||||
@ -432,6 +442,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
rc = out_of_core ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);
|
||||
|
||||
/* Gather certificates of recipients, encrypt the session key for
|
||||
each and store them in the CMS object */
|
||||
@ -442,6 +454,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
rc = encrypt_dek (dek, cl->cert, &encval);
|
||||
if (rc)
|
||||
{
|
||||
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
|
||||
log_error ("encryption failed for recipient no. %d: %s\n",
|
||||
recpno, gpg_strerror (rc));
|
||||
goto leave;
|
||||
@ -450,6 +463,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
err = ksba_cms_add_recipient (cms, cl->cert);
|
||||
if (err)
|
||||
{
|
||||
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
|
||||
log_error ("ksba_cms_add_recipient failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
rc = err;
|
||||
@ -459,6 +473,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
|
||||
err = ksba_cms_set_enc_val (cms, recpno, encval);
|
||||
xfree (encval);
|
||||
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
|
||||
if (err)
|
||||
{
|
||||
log_error ("ksba_cms_set_enc_val failed: %s\n",
|
||||
@ -466,7 +481,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
rc = err;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Main control loop for encryption. */
|
||||
recpno = 0;
|
||||
@ -496,6 +511,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
|
||||
log_error ("write failed: %s\n", gpg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
|
||||
log_info ("encrypted data created\n");
|
||||
|
||||
leave:
|
||||
|
47
sm/gpgsm.c
47
sm/gpgsm.c
@ -848,6 +848,7 @@ main ( int argc, char **argv)
|
||||
certlist_t signerlist = NULL;
|
||||
int do_not_setup_keys = 0;
|
||||
int recp_required = 0;
|
||||
estream_t auditfp = NULL;
|
||||
|
||||
/*mtrace();*/
|
||||
|
||||
@ -1482,6 +1483,26 @@ main ( int argc, char **argv)
|
||||
keydb_add_resource (sl->d, 0, 0, NULL);
|
||||
FREE_STRLIST(nrings);
|
||||
|
||||
|
||||
/* Prepare the audit log feature for certain commands. */
|
||||
if (auditlog)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case aEncr:
|
||||
case aSign:
|
||||
case aDecrypt:
|
||||
case aVerify:
|
||||
audit_release (ctrl.audit);
|
||||
ctrl.audit = audit_new ();
|
||||
auditfp = open_es_fwrite (auditlog);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!do_not_setup_keys)
|
||||
{
|
||||
for (sl = locusr; sl ; sl = sl->next)
|
||||
@ -1528,6 +1549,7 @@ main ( int argc, char **argv)
|
||||
|
||||
fname = argc? *argv : NULL;
|
||||
|
||||
/* Dispatch command. */
|
||||
switch (cmd)
|
||||
{
|
||||
case aGPGConfList:
|
||||
@ -1650,7 +1672,6 @@ main ( int argc, char **argv)
|
||||
case aVerify:
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
estream_t auditfp = NULL;
|
||||
|
||||
set_binary (stdin);
|
||||
if (argc == 2 && opt.outfile)
|
||||
@ -1658,13 +1679,6 @@ main ( int argc, char **argv)
|
||||
else if (opt.outfile)
|
||||
fp = open_fwrite (opt.outfile);
|
||||
|
||||
if (auditlog)
|
||||
{
|
||||
audit_release (ctrl.audit);
|
||||
ctrl.audit = audit_new ();
|
||||
auditfp = open_es_fwrite (auditlog);
|
||||
}
|
||||
|
||||
if (!argc)
|
||||
gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
|
||||
else if (argc == 1)
|
||||
@ -1674,16 +1688,8 @@ main ( int argc, char **argv)
|
||||
else
|
||||
wrong_args ("--verify [signature [detached_data]]");
|
||||
|
||||
if (auditlog)
|
||||
{
|
||||
audit_print_result (ctrl.audit, auditfp, 0);
|
||||
audit_release (ctrl.audit);
|
||||
ctrl.audit = NULL;
|
||||
}
|
||||
|
||||
if (fp && fp != stdout)
|
||||
fclose (fp);
|
||||
es_fclose (auditfp);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1846,6 +1852,15 @@ main ( int argc, char **argv)
|
||||
log_error ("invalid command (there is no implicit command)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Print the audit result if needed. */
|
||||
if (auditlog && auditfp)
|
||||
{
|
||||
audit_print_result (ctrl.audit, auditfp, 0);
|
||||
audit_release (ctrl.audit);
|
||||
ctrl.audit = NULL;
|
||||
es_fclose (auditfp);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
gpgsm_release_certlist (recplist);
|
||||
|
@ -152,6 +152,10 @@ struct server_control_s
|
||||
struct server_local_s *server_local;
|
||||
|
||||
audit_ctx_t audit; /* NULL or a context for the audit subsystem. */
|
||||
int agent_seen; /* Flag indicating that the gpg-agent has been
|
||||
accessed. */
|
||||
int dirmngr_seen; /* Flag indicating that the dirmngr has been
|
||||
accessed. */
|
||||
|
||||
int with_colons; /* Use column delimited output format */
|
||||
int with_chain; /* Include the certifying certs in a listing */
|
||||
|
23
sm/server.c
23
sm/server.c
@ -366,7 +366,14 @@ cmd_recipient (assuan_context_t ctx, char *line)
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
|
||||
rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0);
|
||||
if (!ctrl->audit)
|
||||
rc = start_audit_session (ctrl);
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
if (!rc)
|
||||
rc = gpgsm_add_to_certlist (ctrl, line, 0,
|
||||
&ctrl->server_local->recplist, 0);
|
||||
if (rc)
|
||||
{
|
||||
gpg_err_code_t r = gpg_err_code (rc);
|
||||
@ -477,6 +484,8 @@ cmd_encrypt (assuan_context_t ctx, char *line)
|
||||
rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
|
||||
&ctrl->server_local->recplist, 1);
|
||||
}
|
||||
if (!rc)
|
||||
rc = ctrl->audit? 0 : start_audit_session (ctrl);
|
||||
if (!rc)
|
||||
rc = gpgsm_encrypt (assuan_get_pointer (ctx),
|
||||
ctrl->server_local->recplist,
|
||||
@ -492,6 +501,7 @@ cmd_encrypt (assuan_context_t ctx, char *line)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* DECRYPT
|
||||
|
||||
This performs the decrypt operation after doing some check on the
|
||||
@ -517,7 +527,10 @@ cmd_decrypt (assuan_context_t ctx, char *line)
|
||||
out_fp = fdopen (dup(out_fd), "w");
|
||||
if (!out_fp)
|
||||
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
||||
rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
|
||||
|
||||
rc = start_audit_session (ctrl);
|
||||
if (!rc)
|
||||
rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
|
||||
fclose (out_fp);
|
||||
|
||||
/* close and reset the fd */
|
||||
@ -600,8 +613,10 @@ cmd_sign (assuan_context_t ctx, char *line)
|
||||
if (!out_fp)
|
||||
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
||||
|
||||
rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
|
||||
inp_fd, detached, out_fp);
|
||||
rc = start_audit_session (ctrl);
|
||||
if (!rc)
|
||||
rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
|
||||
inp_fd, detached, out_fp);
|
||||
fclose (out_fp);
|
||||
|
||||
/* close and reset the fd */
|
||||
|
Loading…
x
Reference in New Issue
Block a user