* server.c (gpgsm_server): Add arg DEFAULT_RECPLIST.

(cmd_encrypt): Add all enrypt-to marked certs to the list.
* encrypt.c (gpgsm_encrypt): Check that real recipients are
available.
* gpgsm.c (main): Make the --encrypt-to and --no-encrypt-to
options work.  Pass the list of recients to gpgsm_server.
* gpgsm.h (certlist_s): Add field IS_ENCRYPT_TO.
(opt): Add NO_ENCRYPT_TO.
* certlist.c (gpgsm_add_to_certlist): New arg IS_ENCRYPT_TO.
Changed all callers and ignore duplicate entries.
(is_cert_in_certlist): New.
(gpgsm_add_cert_to_certlist): New.
This commit is contained in:
Werner Koch 2003-12-17 17:12:14 +00:00
parent aac9cea6da
commit 711c4853d6
7 changed files with 203 additions and 87 deletions

9
NEWS
View File

@ -1,8 +1,8 @@
Noteworthy changes in version 1.9.3 (unreleased)
------------------------------------------------
* New options --{enable,disable}-ocsp to validate keys using OCSP
This requires a not yet released DirMngr 0.5.1. Default is
* New gpgsm options --{enable,disable}-ocsp to validate keys using
OCSP. This requires a not yet released DirMngr 0.5.1. Default is
disabled.
* The --log-file option may now be used to print logs to a socket.
@ -10,6 +10,11 @@ Noteworthy changes in version 1.9.3 (unreleased)
not work on all systems and falls back to stderr if there is a
problem with the socket.
* The options --encrypt-to and --no-encrypt-to now work the same in
gpgsm as in gpg. Note, they are also used in server mode.
* Duplicated recipients are now silently removed in gpgsm.
Noteworthy changes in version 1.9.2 (2003-11-17)
------------------------------------------------

View File

@ -1,5 +1,18 @@
2003-12-17 Werner Koch <wk@gnupg.org>
* server.c (gpgsm_server): Add arg DEFAULT_RECPLIST.
(cmd_encrypt): Add all enrypt-to marked certs to the list.
* encrypt.c (gpgsm_encrypt): Check that real recipients are
available.
* gpgsm.c (main): Make the --encrypt-to and --no-encrypt-to
options work. Pass the list of recients to gpgsm_server.
* gpgsm.h (certlist_s): Add field IS_ENCRYPT_TO.
(opt): Add NO_ENCRYPT_TO.
* certlist.c (gpgsm_add_to_certlist): New arg IS_ENCRYPT_TO.
Changed all callers and ignore duplicate entries.
(is_cert_in_certlist): New.
(gpgsm_add_cert_to_certlist): New.
* certdump.c (gpgsm_print_serial): Cleaned up cast use in strtoul.
(gpgsm_dump_serial): Ditto.

View File

@ -131,14 +131,54 @@ same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert)
return tmp;
}
/* Return true if CERT is already contained in CERTLIST. */
static int
is_cert_in_certlist (ksba_cert_t cert, certlist_t certlist)
{
const unsigned char *img_a, *img_b;
size_t len_a, len_b;
img_a = ksba_cert_get_image (cert, &len_a);
if (img_a)
{
for ( ; certlist; certlist = certlist->next)
{
img_b = ksba_cert_get_image (certlist->cert, &len_b);
if (img_b && len_a == len_b && !memcmp (img_a, img_b, len_a))
return 1; /* Already contained. */
}
}
return 0;
}
/* Add CERT to the list of certificates at CERTADDR but avoid
duplicates. */
int
gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
certlist_t *listaddr, int is_encrypt_to)
{
if (!is_cert_in_certlist (cert, *listaddr))
{
certlist_t cl = xtrycalloc (1, sizeof *cl);
if (!cl)
return OUT_OF_CORE (errno);
cl->cert = cert;
ksba_cert_ref (cert);
cl->next = *listaddr;
cl->is_encrypt_to = is_encrypt_to;
*listaddr = cl;
}
return 0;
}
/* Add a certificate to a list of certificate and make sure that it is
a valid certificate. With SECRET set to true a secret key must be
available for the certificate. */
available for the certificate. IS_ENCRYPT_TO sets the corresponding
flag in the new create LISTADDR item. */
int
gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
CERTLIST *listaddr)
CERTLIST *listaddr, int is_encrypt_to)
{
int rc;
KEYDB_SEARCH_DESC desc;
@ -224,31 +264,35 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
xfree (subject);
xfree (issuer);
if (!rc && secret)
if (!rc && !is_cert_in_certlist (cert, *listaddr))
{
char *p;
rc = gpg_error (GPG_ERR_NO_SECKEY);
p = gpgsm_get_keygrip_hexstring (cert);
if (p)
if (!rc && secret)
{
if (!gpgsm_agent_havekey (p))
rc = 0;
xfree (p);
char *p;
rc = gpg_error (GPG_ERR_NO_SECKEY);
p = gpgsm_get_keygrip_hexstring (cert);
if (p)
{
if (!gpgsm_agent_havekey (p))
rc = 0;
xfree (p);
}
}
}
if (!rc)
rc = gpgsm_validate_chain (ctrl, cert, NULL);
if (!rc)
{
CERTLIST cl = xtrycalloc (1, sizeof *cl);
if (!cl)
rc = OUT_OF_CORE (errno);
else
if (!rc)
rc = gpgsm_validate_chain (ctrl, cert, NULL);
if (!rc)
{
cl->cert = cert; cert = NULL;
cl->next = *listaddr;
*listaddr = cl;
CERTLIST cl = xtrycalloc (1, sizeof *cl);
if (!cl)
rc = OUT_OF_CORE (errno);
else
{
cl->cert = cert; cert = NULL;
cl->next = *listaddr;
cl->is_encrypt_to = is_encrypt_to;
*listaddr = cl;
}
}
}
}

View File

@ -306,7 +306,13 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
memset (&encparm, 0, sizeof encparm);
if (!recplist)
/* 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. */
for (cl = recplist; cl; cl = cl->next)
if (!cl->is_encrypt_to)
break;
if (!cl)
{
log_error(_("no valid recipients given\n"));
gpgsm_status (ctrl, STATUS_NO_RECP, "0");
@ -412,7 +418,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
goto leave;
}
/* gather certificates of recipients, encrypt the session key for
/* Gather certificates of recipients, encrypt the session key for
each and store them in the CMS object */
for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
{
@ -447,7 +453,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
}
}
/* main control loop for encryption */
/* Main control loop for encryption. */
recpno = 0;
do
{

View File

@ -277,10 +277,10 @@ static ARGPARSE_OPTS opts[] = {
{ oDefRecipientSelf, "default-recipient-self" ,0,
N_("use the default key as default recipient")},
{ oNoDefRecipient, "no-default-recipient", 0, "@" },
#endif
{ oEncryptTo, "encrypt-to", 2, "@" },
{ oNoEncryptTo, "no-encrypt-to", 0, "@" },
#endif
{ oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
#if 0
@ -585,6 +585,31 @@ set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
}
/* Helper to add recipients to a list. */
static void
do_add_recipient (ctrl_t ctrl, const char *name,
certlist_t *recplist, int is_encrypt_to)
{
int rc = gpgsm_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to);
if (rc)
{
log_error (_("can't encrypt to `%s': %s\n"), name, gpg_strerror (rc));
gpgsm_status2 (ctrl, STATUS_INV_RECP,
gpg_err_code (rc) == -1? "1":
gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
"0",
name, NULL);
}
}
int
main ( int argc, char **argv)
{
@ -953,8 +978,8 @@ main ( int argc, char **argv)
case oSkipVerify: opt.skip_verify=1; break;
case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break;
case oEncryptTo: /* store the recipient in the second list */
case oNoEncryptTo: opt.no_encrypt_to = 1; break;
case oEncryptTo: /* Store the recipient in the second list */
sl = add_to_strlist (&remusr, pargs.r.ret_str);
sl->flags = 1;
break;
@ -1107,7 +1132,7 @@ main ( int argc, char **argv)
for (sl = locusr; sl; sl = sl->next)
{
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist);
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0);
if (rc)
{
log_error (_("can't sign using `%s': %s\n"),
@ -1127,27 +1152,22 @@ main ( int argc, char **argv)
sl->d, NULL);
}
}
/* Build the recipient list. We first add the regular ones and then
the encrypt-to ones because the underlying function will silenty
ignore duplicates and we can't allow to keep a duplicate which is
flagged as encrypt-to as the actually encrypt function would then
complain about no (regular) recipients. */
for (sl = remusr; sl; sl = sl->next)
if (!(sl->flags & 1))
do_add_recipient (&ctrl, sl->d, &recplist, 0);
if (!opt.no_encrypt_to)
{
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist);
if (rc)
{
log_error (_("can't encrypt to `%s': %s\n"),
sl->d, gpg_strerror (rc));
gpgsm_status2 (&ctrl, STATUS_INV_RECP,
gpg_err_code (rc) == -1? "1":
gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
"0",
sl->d, NULL);
}
}
for (sl = remusr; sl; sl = sl->next)
if ((sl->flags & 1))
do_add_recipient (&ctrl, sl->d, &recplist, 1);
}
if (log_get_errorcount(0))
gpgsm_exit(1); /* must stop for invalid recipients */
@ -1165,7 +1185,7 @@ main ( int argc, char **argv)
sleep (debug_wait);
log_debug ("... okay\n");
}
gpgsm_server ();
gpgsm_server (recplist);
break;
case aCallDirmngr:

View File

@ -72,6 +72,8 @@ struct {
char *def_recipient; /* userID of the default recipient */
int def_recipient_self; /* The default recipient is the default key */
int no_encrypt_to; /* Ignore all as encrypt to marked recipients. */
char *local_user; /* NULL or argument to -u */
int always_trust; /* Trust the given keys even if there is no
@ -135,6 +137,7 @@ struct server_control_s {
int use_ocsp; /* Set to true if OCSP should be used. */
};
typedef struct server_control_s *CTRL;
typedef struct server_control_s *ctrl_t;
/* data structure used in base64.c */
typedef struct base64_context_s *Base64Context;
@ -143,22 +146,26 @@ typedef struct base64_context_s *Base64Context;
struct certlist_s {
struct certlist_s *next;
ksba_cert_t cert;
int is_encrypt_to; /* True if the certificate has been set through
the --encrypto-to option. */
};
typedef struct certlist_s *CERTLIST;
typedef struct certlist_s *certlist_t;
/*-- gpgsm.c --*/
void gpgsm_exit (int rc);
void gpgsm_init_default_ctrl (struct server_control_s *ctrl);
/*-- server.c --*/
void gpgsm_server (void);
void gpgsm_status (CTRL ctrl, int no, const char *text);
void gpgsm_status2 (CTRL ctrl, int no, ...);
void gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text,
void gpgsm_server (certlist_t default_recplist);
void gpgsm_status (ctrl_t ctrl, int no, const char *text);
void gpgsm_status2 (ctrl_t ctrl, int no, ...);
void gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text,
gpg_err_code_t ec);
/*-- fingerprint --*/
char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len);
char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo,
char *array, int *r_len);
char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo);
char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo);
unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert);
@ -169,10 +176,10 @@ char *gpgsm_get_certid (ksba_cert_t cert);
/*-- base64.c --*/
int gpgsm_create_reader (Base64Context *ctx,
CTRL ctrl, FILE *fp, ksba_reader_t *r_reader);
ctrl_t ctrl, FILE *fp, ksba_reader_t *r_reader);
void gpgsm_destroy_reader (Base64Context ctx);
int gpgsm_create_writer (Base64Context *ctx,
CTRL ctrl, FILE *fp, ksba_writer_t *r_writer);
ctrl_t ctrl, FILE *fp, ksba_writer_t *r_writer);
int gpgsm_finish_writer (Base64Context ctx);
void gpgsm_destroy_writer (Base64Context ctx);
@ -201,7 +208,8 @@ int gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo,
/*-- certchain.c --*/
int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
int gpgsm_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t r_exptime);
int gpgsm_basic_cert_check (ksba_cert_t cert);
/*-- certlist.c --*/
@ -210,41 +218,43 @@ int gpgsm_cert_use_encrypt_p (ksba_cert_t cert);
int gpgsm_cert_use_verify_p (ksba_cert_t cert);
int gpgsm_cert_use_decrypt_p (ksba_cert_t cert);
int gpgsm_cert_use_cert_p (ksba_cert_t cert);
int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
CERTLIST *listaddr);
void gpgsm_release_certlist (CERTLIST list);
int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert,
certlist_t *listaddr, int is_encrypt_to);
int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
certlist_t *listaddr, int is_encrypt_to);
void gpgsm_release_certlist (certlist_t list);
int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert);
/*-- keylist.c --*/
void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode);
void gpgsm_list_keys (ctrl_t ctrl, STRLIST names, FILE *fp, unsigned int mode);
/*-- import.c --*/
int gpgsm_import (CTRL ctrl, int in_fd);
int gpgsm_import_files (CTRL ctrl, int nfiles, char **files,
int gpgsm_import (ctrl_t ctrl, int in_fd);
int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files,
int (*of)(const char *fname));
/*-- export.c --*/
void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp);
void gpgsm_export (ctrl_t ctrl, STRLIST names, FILE *fp);
/*-- delete.c --*/
int gpgsm_delete (CTRL ctrl, STRLIST names);
int gpgsm_delete (ctrl_t ctrl, STRLIST names);
/*-- verify.c --*/
int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp);
int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp);
/*-- sign.c --*/
int gpgsm_get_default_cert (ksba_cert_t *r_cert);
int gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
int gpgsm_sign (ctrl_t ctrl, CERTLIST signerlist,
int data_fd, int detached, FILE *out_fp);
/*-- encrypt.c --*/
int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
int gpgsm_encrypt (ctrl_t ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
/*-- decrypt.c --*/
int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp);
int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp);
/*-- certreqgen.c --*/
int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp);
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
/*-- call-agent.c --*/
int gpgsm_agent_pksign (const char *keygrip,
@ -264,9 +274,9 @@ int gpgsm_agent_passwd (const char *hexkeygrip);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp);
int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names,
void (*cb)(void*, ksba_cert_t), void *cb_value);
int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
int argc, char **argv);

View File

@ -39,12 +39,13 @@ static FILE *statusfp;
/* Data used to assuciate an Assuan context with local server data */
struct server_local_s {
ASSUAN_CONTEXT assuan_ctx;
assuan_context_t assuan_ctx;
int message_fd;
int list_internal;
int list_external;
CERTLIST recplist;
CERTLIST signerlist;
certlist_t recplist;
certlist_t signerlist;
certlist_t default_recplist; /* As set by main() - don't release. */
};
@ -233,7 +234,7 @@ output_notify (ASSUAN_CONTEXT ctx, const char *line)
way of specification [we will support this]. If this is a valid and
trusted recipient the server does respond with OK, otherwise the
return is an ERR with the reason why the recipient can't be used,
the encryption will then not be done for this recipient. IF the
the encryption will then not be done for this recipient. If the
policy is not to encrypt at all if not all recipients are valid, the
client has to take care of this. All RECIPIENT commands are
cumulative until a RESET or an successful ENCRYPT command. */
@ -243,7 +244,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist);
rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0);
if (rc)
{
gpg_err_code_t r = gpg_err_code (rc);
@ -286,7 +287,8 @@ cmd_signer (ASSUAN_CONTEXT ctx, char *line)
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist);
rc = gpgsm_add_to_certlist (ctrl, line, 1,
&ctrl->server_local->signerlist, 0);
if (rc)
{
gpg_err_code_t r = gpg_err_code (rc);
@ -325,6 +327,7 @@ static int
cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
certlist_t cl;
int inp_fd, out_fd;
FILE *out_fp;
int rc;
@ -339,14 +342,26 @@ cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
out_fp = fdopen ( dup(out_fd), "w");
if (!out_fp)
return set_error (General_Error, "fdopen() failed");
rc = gpgsm_encrypt (assuan_get_pointer (ctx),
ctrl->server_local->recplist,
inp_fd, out_fp);
/* Now add all encrypt-to marked recipients from the default
list. */
rc = 0;
if (!opt.no_encrypt_to)
{
for (cl=ctrl->server_local->recplist; !rc && cl; cl = cl->next)
if (cl->is_encrypt_to)
rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
&ctrl->server_local->recplist, 1);
}
if (!rc)
rc = gpgsm_encrypt (assuan_get_pointer (ctx),
ctrl->server_local->recplist,
inp_fd, out_fp);
fclose (out_fp);
gpgsm_release_certlist (ctrl->server_local->recplist);
ctrl->server_local->recplist = NULL;
/* close and reset the fd */
/* Close and reset the fd */
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
@ -755,9 +770,11 @@ register_commands (ASSUAN_CONTEXT ctx)
return 0;
}
/* Startup the server */
/* Startup the server. DEFAULT_RECPLIST is the list of recipients as
set from the command line or config file. We only require those
marked as encrypt-to. */
void
gpgsm_server (void)
gpgsm_server (certlist_t default_recplist)
{
int rc;
int filedes[2];
@ -799,6 +816,7 @@ gpgsm_server (void)
ctrl.server_local->message_fd = -1;
ctrl.server_local->list_internal = 1;
ctrl.server_local->list_external = 0;
ctrl.server_local->default_recplist = default_recplist;
if (DBG_ASSUAN)
assuan_set_log_stream (ctx, log_get_stream ());