* base64.c (gpgsm_create_writer): Allow to set the object name

* server.c (cmd_genkey): New.
* certreqgen.c: New.  The parameter handling code has been taken
from gnupg/g10/keygen.c version 1.0.6.
* call-agent.c (gpgsm_agent_genkey): New.
This commit is contained in:
Werner Koch 2002-01-10 19:47:20 +00:00
parent 8bad9e344b
commit dc37fe1849
11 changed files with 802 additions and 56 deletions

View File

@ -1,3 +1,21 @@
2002-01-10 Werner Koch <wk@gnupg.org>
* base64.c (gpgsm_create_writer): Allow to set the object name
2002-01-08 Werner Koch <wk@gnupg.org>
* keydb.c (spacep): Removed because it is now in util.c
* server.c (cmd_genkey): New.
* certreqgen.c: New. The parameter handling code has been taken
from gnupg/g10/keygen.c version 1.0.6.
* call-agent.c (gpgsm_agent_genkey): New.
2002-01-02 Werner Koch <wk@gnupg.org>
* server.c (rc_to_assuan_status): Removed and changed all callers
to use map_to_assuan_status.
2001-12-20 Werner Koch <wk@gnupg.org>
* verify.c (gpgsm_verify): Implemented non-detached signature
@ -126,7 +144,7 @@
* server.c (rc_to_assuan_status): New. Use it for all commands.
Copyright 2001 Free Software Foundation, Inc.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without

View File

@ -41,7 +41,8 @@ gpgsm_SOURCES = \
sign.c \
encrypt.c \
decrypt.c \
import.c
import.c \
certreqgen.c
gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a ../kbx/libkeybox.a \

View File

@ -581,7 +581,8 @@ gpgsm_create_writer (Base64Context *ctx,
{
(*ctx)->u.wparm.fp = fp;
if (ctrl->create_pem)
(*ctx)->u.wparm.pem_name = "CMS OBJECT"; /* fixme */
(*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
: "CMS OBJECT";
rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
}
else

View File

@ -52,6 +52,12 @@ struct cipher_parm_s {
size_t ciphertextlen;
};
struct genkey_parm_s {
ASSUAN_CONTEXT ctx;
const char *sexp;
size_t sexplen;
};
struct membuf {
size_t len;
@ -250,6 +256,9 @@ gpgsm_agent_pksign (const char *keygrip,
return map_assuan_err (rc);
}
*r_buf = get_membuf (&data, r_buflen);
/* FIXME: check that the returned S-Exp is valid! */
return *r_buf? 0 : GNUPG_Out_Of_Core;
}
@ -341,6 +350,65 @@ gpgsm_agent_pkdecrypt (const char *keygrip,
/* Handle a KEYPARMS inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */
static AssuanError
inq_genkey_parms (void *opaque, const char *keyword)
{
struct genkey_parm_s *parm = opaque;
AssuanError rc;
rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
return rc;
}
/* Call the agent to generate a newkey */
int
gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
{
int rc;
struct genkey_parm_s gk_parm;
struct membuf data;
size_t len;
char *buf;
*r_pubkey = NULL;
rc = start_agent ();
if (rc)
return rc;
rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
init_membuf (&data, 1024);
gk_parm.ctx = agent_ctx;
gk_parm.sexp = keyparms;
gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
if (!gk_parm.sexplen)
return GNUPG_Invalid_Value;
rc = assuan_transact (agent_ctx, "GENKEY",
membuf_data_cb, &data,
inq_genkey_parms, &gk_parm);
if (rc)
{
xfree (get_membuf (&data, &len));
return map_assuan_err (rc);
}
buf = get_membuf (&data, &len);
if (!buf)
return GNUPG_Out_Of_Core;
if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
{
xfree (buf);
return GNUPG_Invalid_Sexp;
}
*r_pubkey = buf;
return 0;
}

651
sm/certreqgen.c Normal file
View File

@ -0,0 +1,651 @@
/* certreqgen.c - Generate a key and a certification request
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
The format of the native parameter file is follows:
o Text only, line length is limited to about 1000 chars.
o You must use UTF-8 encoding to specify non-ascii characters.
o Empty lines are ignored.
o Leading and trailing spaces are ignored.
o A hash sign as the first non white space character is a comment line.
o Control statements are indicated by a leading percent sign, the
arguments are separated by white space from the keyword.
o Parameters are specified by a keyword, followed by a colon. Arguments
are separated by white space.
o The first parameter must be "Key-Type", control statements
may be placed anywhere.
o Key generation takes place when either the end of the parameter file
is reached, the next "Key-Type" parameter is encountered or at the
controlstatement "%commit"
o Control statements:
%echo <text>
Print <text>.
%dry-run
Suppress actual key generation (useful for syntax checking).
%commit
Perform the key generation. Note that an implicit commit is done
at the next "Key-Type" parameter.
%certfile <filename>
Do not write the certificate to the keyDB but to <filename>.
This must be given before the first
commit to take place, duplicate specification of the same filename
is ignored, the last filename before a commit is used.
The filename is used until a new filename is used (at commit points)
and all keys are written to that file. If a new filename is given,
this file is created (and overwrites an existing one).
Both control statements must be given.
o The order of the parameters does not matter except for "Key-Type"
which must be the first parameter. The parameters are only for the
generated keyblock and parameters from previous key generations are not
used. Some syntactically checks may be performed.
The currently defined parameters are:
Key-Type: <algo>
Starts a new parameter block by giving the type of the
primary key. The algorithm must be capable of signing.
This is a required parameter. For now the only supported
algorithm is "rsa".
Key-Length: <length-in-bits>
Length of the key in bits. Default is 1024.
Key-Usage: <usage-list>
Space or comma delimited list of key usage, allowed values are
"encrypt" and "sign". This is used to generate the KeyUsage extension.
Please make sure that the algorithm is capable of this usage. Default
is to allow encrypt and sign.
Name-DN: subject name
This is the DN name of the subject in rfc2253 format.
Name-Email: <string>
The ist the email address
Here is an example:
$ cat >foo <<EOF
%echo Generating a standard key
Key-Type: RSA
Key-Length: 1024
Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
Name-Email: joe@foo.bar
# Do a commit here, so that we can later print "done" :-)
%commit
%echo done
EOF
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include <gcrypt.h>
#include <ksba.h>
#include "gpgsm.h"
#include "keydb.h"
#include "i18n.h"
enum para_name {
pKEYTYPE,
pKEYLENGTH,
pKEYUSAGE,
pNAMEDN,
pNAMEEMAIL
};
struct para_data_s {
struct para_data_s *next;
int lnr;
enum para_name key;
union {
unsigned int usage;
char value[1];
} u;
};
struct reqgen_ctrl_s {
int lnr;
int dryrun;
KsbaWriter writer;
};
static int proc_parameters (struct para_data_s *para,
struct reqgen_ctrl_s *outctrl);
static int create_request (struct para_data_s *para,
KsbaConstSexp public,
struct reqgen_ctrl_s *outctrl);
static void
release_parameter_list (struct para_data_s *r)
{
struct para_data_s *r2;
for (; r ; r = r2)
{
r2 = r->next;
xfree(r);
}
}
static struct para_data_s *
get_parameter (struct para_data_s *para, enum para_name key)
{
struct para_data_s *r;
for (r = para; r && r->key != key; r = r->next)
;
return r;
}
static const char *
get_parameter_value (struct para_data_s *para, enum para_name key)
{
struct para_data_s *r = get_parameter (para, key);
return (r && *r->u.value)? r->u.value : NULL;
}
static int
get_parameter_algo (struct para_data_s *para, enum para_name key)
{
struct para_data_s *r = get_parameter (para, key);
if (!r)
return -1;
if (digitp (r->u.value))
return atoi( r->u.value );
return gcry_pk_map_name (r->u.value);
}
/* parse the usage parameter. Returns 0 on success. Note that we
only care about sign and encrypt and don't (yet) allow all the
other X.509 usage to be specified; instead we will use a fixed
mapping to the X.509 usage flags */
static int
parse_parameter_usage (struct para_data_s *para, enum para_name key)
{
struct para_data_s *r = get_parameter (para, key);
char *p, *pn;
unsigned int use;
if (!r)
return 0; /* none (this is an optional parameter)*/
use = 0;
pn = r->u.value;
while ( (p = strsep (&pn, " \t,")) )
{
if (!*p)
;
else if ( !ascii_strcasecmp (p, "sign") )
use |= GCRY_PK_USAGE_SIGN;
else if ( !ascii_strcasecmp (p, "encrypt") )
use |= GCRY_PK_USAGE_ENCR;
else
{
log_error ("line %d: invalid usage list\n", r->lnr);
return -1; /* error */
}
}
r->u.usage = use;
return 0;
}
static unsigned int
get_parameter_uint (struct para_data_s *para, enum para_name key)
{
struct para_data_s *r = get_parameter (para, key);
if (!r)
return 0;
return (unsigned int)strtoul (r->u.value, NULL, 10);
}
/* Read the certificate generation parameters from FP and genereate
(all) certificate requests. */
static int
read_parameters (FILE *fp, KsbaWriter writer)
{
static struct {
const char *name;
enum para_name key;
} keywords[] = {
{ "Key-Type", pKEYTYPE},
{ "Key-Length", pKEYLENGTH },
{ "Key-Usage", pKEYUSAGE },
{ "Name-DN", pNAMEDN },
{ "Name-Email", pNAMEEMAIL },
{ NULL, 0 }
};
char line[1024], *p;
const char *err = NULL;
struct para_data_s *para, *r;
int i;
struct reqgen_ctrl_s outctrl;
memset (&outctrl, 0, sizeof (outctrl));
outctrl.writer = writer;
err = NULL;
para = NULL;
while (fgets (line, DIM(line)-1, fp) )
{
char *keyword, *value;
outctrl.lnr++;
if (*line && line[strlen(line)-1] != '\n')
{
err = "line too long";
break;
}
for (p=line; spacep (p); p++)
;
if (!*p || *p == '#')
continue;
keyword = p;
if (*keyword == '%')
{
for (; !spacep (p); p++)
;
if (*p)
*p++ = 0;
for (; spacep (p); p++)
;
value = p;
trim_trailing_spaces (value);
if (!ascii_strcasecmp (keyword, "%echo"))
log_info ("%s\n", value);
else if (!ascii_strcasecmp (keyword, "%dry-run"))
outctrl.dryrun = 1;
else if (!ascii_strcasecmp( keyword, "%commit"))
{
proc_parameters (para, &outctrl);
/*FIXME: what about error handling */
release_parameter_list (para);
para = NULL;
}
else
log_info ("skipping control `%s' (%s)\n", keyword, value);
continue;
}
if (!(p = strchr (p, ':')) || p == keyword)
{
err = "missing colon";
break;
}
if (*p)
*p++ = 0;
for (; spacep (p); p++)
;
if (!*p)
{
err = "missing argument";
break;
}
value = p;
trim_trailing_spaces (value);
for (i=0; (keywords[i].name
&& ascii_strcasecmp (keywords[i].name, keyword)); i++)
;
if (!keywords[i].name)
{
err = "unknown keyword";
break;
}
if (keywords[i].key != pKEYTYPE && !para)
{
err = "parameter block does not start with \"Key-Type\"";
break;
}
if (keywords[i].key == pKEYTYPE && para)
{
proc_parameters (para, &outctrl);
release_parameter_list (para);
para = NULL;
}
else
{
for (r = para; r && r->key != keywords[i].key; r = r->next)
;
if (r)
{
err = "duplicate keyword";
break;
}
}
r = xtrycalloc (1, sizeof *r + strlen( value ));
if (!r)
{
err = "out of core";
break;
}
r->lnr = outctrl.lnr;
r->key = keywords[i].key;
strcpy (r->u.value, value);
r->next = para;
para = r;
}
if (err)
log_error ("line %d: %s\n", outctrl.lnr, err);
else if (ferror(fp))
log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
else if (para)
{
proc_parameters (para, &outctrl);
/*FIXME: what about error handling */
}
release_parameter_list (para);
return 0;
}
/* check whether there are invalid characters in the email address S */
static int
has_invalid_email_chars (const char *s)
{
int at_seen=0;
static char valid_chars[] = "01234567890_-."
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (; *s; s++)
{
if (*s & 0x80)
return 1;
if (*s == '@')
at_seen++;
else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
return 1;
else if (at_seen && !strchr (valid_chars, *s))
return 1;
}
return at_seen != 1;
}
/* Check that all required parameters are given and perform the action */
static int
proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl)
{
struct para_data_s *r;
const char *s;
int i;
unsigned int nbits;
char numbuf[20];
unsigned char keyparms[100];
int rc;
KsbaSexp public;
/* check that we have all required parameters */
assert (get_parameter (para, pKEYTYPE));
/* We can only use RSA for now. There is a with pkcs-10 on how to
use ElGamal becuase it is expected that a PK algorithm can always
be used for signing. */
i = get_parameter_algo (para, pKEYTYPE);
if (i < 1 || i != GCRY_PK_RSA )
{
r = get_parameter (para, pKEYTYPE);
log_error ("line %d: invalid algorithm\n", r->lnr);
return GNUPG_Invalid_Parameter;
}
/* check the keylength */
if (!get_parameter (para, pKEYLENGTH))
nbits = 1024;
else
nbits = get_parameter_uint (para, pKEYLENGTH);
if (nbits < 512 || nbits > 4096)
{
r = get_parameter (para, pKEYTYPE);
log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n",
r->lnr, nbits);
return GNUPG_Invalid_Parameter;
}
/* check the usage */
if (parse_parameter_usage (para, pKEYUSAGE))
return GNUPG_Invalid_Parameter;
/* check that there is a subject name and that this DN fits our
requirements */
if (!(s=get_parameter_value (para, pNAMEDN)))
{
r = get_parameter (para, pKEYTYPE);
log_error ("line %d: no subject name given\n", r->lnr);
return GNUPG_Invalid_Parameter;
}
/* fixme check s */
/* check that the optional email address is okay */
if ((s=get_parameter_value (para, pNAMEEMAIL)))
{
if (has_invalid_email_chars (s)
|| *s == '@'
|| s[strlen(s)-1] == '@'
|| s[strlen(s)-1] == '.'
|| strstr(s, ".."))
{
r = get_parameter (para, pKEYTYPE);
log_error ("line %d: not a valid email address\n", r->lnr);
return GNUPG_Invalid_Parameter;
}
}
sprintf (numbuf, "%u", nbits);
snprintf (keyparms, DIM (keyparms)-1,
"(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf);
rc = gpgsm_agent_genkey (keyparms, &public);
if (rc)
{
r = get_parameter (para, pKEYTYPE);
log_error ("line %d: key generation failed: %s\n",
r->lnr, gnupg_strerror (rc));
return rc;
}
rc = create_request (para, public, outctrl);
xfree (public);
return rc;
}
/* Parameters are checked, the key pair has been created. Now
generate the request and write it out */
static int
create_request (struct para_data_s *para, KsbaConstSexp public,
struct reqgen_ctrl_s *outctrl)
{
KsbaCertreq cr;
KsbaError err;
GCRY_MD_HD md;
KsbaStopReason stopreason;
int rc = 0;
cr = ksba_certreq_new ();
if (!cr)
return seterr (Out_Of_Core);
md = gcry_md_open (GCRY_MD_SHA1, 0);
if (!md)
{
log_error ("md_open failed: %s\n", gcry_strerror (-1));
rc = map_gcry_err (gcry_errno ());
goto leave;
}
if (DBG_HASHING)
gcry_md_start_debug (md, "cr.cri");
ksba_certreq_set_hash_function (cr, HASH_FNC, md);
ksba_certreq_set_writer (cr, outctrl->writer);
err = ksba_certreq_set_subject (cr, get_parameter_value (para, pNAMEDN));
if (err)
{
log_error ("error setting the subject's name: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
err = ksba_certreq_set_public_key (cr, public);
if (err)
{
log_error ("error setting the public key: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
do
{
err = ksba_certreq_build (cr, &stopreason);
if (err)
{
log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
if (stopreason == KSBA_SR_NEED_SIG)
{
GCRY_SEXP s_pkey;
size_t n;
unsigned char grip[20], hexgrip[41];
char *sigval;
size_t siglen;
n = gcry_sexp_canon_len (public, 0, NULL, NULL);
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
err = GNUPG_Bug;
goto leave;
}
rc = gcry_sexp_sscan (&s_pkey, NULL, public, n);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
rc = map_gcry_err (rc);
goto leave;
}
if ( !gcry_pk_get_keygrip (s_pkey, grip) )
{
rc = seterr (General_Error);
log_error ("can't figure out the keygrip\n");
gcry_sexp_release (s_pkey);
goto leave;
}
gcry_sexp_release (s_pkey);
for (n=0; n < 20; n++)
sprintf (hexgrip+n*2, "%02X", grip[n]);
rc = gpgsm_agent_pksign (hexgrip,
gcry_md_read(md, GCRY_MD_SHA1),
gcry_md_get_algo_dlen (GCRY_MD_SHA1),
GCRY_MD_SHA1,
&sigval, &siglen);
if (rc)
{
log_error ("signing failed: %s\n", gnupg_strerror (rc));
goto leave;
}
err = ksba_certreq_set_sig_val (cr, sigval);
xfree (sigval);
if (err)
{
log_error ("failed to store the sig_val: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
}
}
while (stopreason != KSBA_SR_READY);
leave:
gcry_md_close (md);
ksba_certreq_release (cr);
return rc;
}
/* Create a new key by reading the parameters from in_fd. Multiple
keys may be created */
int
gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp)
{
int rc;
FILE *in_fp;
Base64Context b64writer = NULL;
KsbaWriter writer;
in_fp = fdopen (dup (in_fd), "rb");
if (!in_fp)
{
log_error ("fdopen() failed: %s\n", strerror (errno));
return seterr (IO_Error);
}
ctrl->pem_name = "NEW CERTIFICATE REQUEST";
rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
if (rc)
{
log_error ("can't create writer: %s\n", gnupg_strerror (rc));
goto leave;
}
rc = read_parameters (in_fp, writer);
if (rc)
goto leave;
rc = gpgsm_finish_writer (b64writer);
if (rc)
{
log_error ("write failed: %s\n", gnupg_strerror (rc));
goto leave;
}
log_info ("certificate request created\n");
leave:
gpgsm_destroy_writer (b64writer);
fclose (in_fp);
return rc;
}

View File

@ -447,6 +447,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
}
encparm.fp = data_fp;
ctrl->pem_name = "ENCRYPTED MESSAGE";
rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
if (rc)
{

View File

@ -187,3 +187,7 @@ gpgsm_get_keygrip_hexstring (KsbaCert cert)
}

View File

@ -98,6 +98,7 @@ struct server_control_s {
int create_base64; /* Create base64 encoded output */
int create_pem; /* create PEM output */
const char *pem_name; /* PEM name to use */
};
typedef struct server_control_s *CTRL;
@ -175,6 +176,9 @@ int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
/*-- decrypt.c --*/
int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp);
/*-- certreqgen.c --*/
int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp);
/*-- call-agent.c --*/
int gpgsm_agent_pksign (const char *keygrip,
unsigned char *digest,
@ -184,6 +188,7 @@ int gpgsm_agent_pksign (const char *keygrip,
int gpgsm_agent_pkdecrypt (const char *keygrip,
KsbaConstSexp ciphertext,
char **r_buf, size_t *r_buflen);
int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey);
#endif /*GPGSM_H*/

View File

@ -35,8 +35,6 @@
#define DIRSEP_C '/'
#define spacep(a) ((a) == ' ' || (a) == '\t')
static int active_handles;
typedef enum {
@ -911,7 +909,7 @@ classify_user_id (const char *name,
memset (desc, 0, sizeof *desc);
*force_exact = 0;
/* skip leading spaces. Fixme: what about trailing white space? */
for(s = name; *s && spacep(*s); s++ )
for(s = name; *s && spacep (s); s++ )
;
switch (*s)
@ -957,7 +955,7 @@ classify_user_id (const char *name,
case '/': /* subject's DN */
s++;
if (!*s || spacep (*s))
if (!*s || spacep (s))
return 0; /* no DN or prefixed with a space */
desc->u.name = s;
mode = KEYDB_SEARCH_MODE_SUBJECT;
@ -971,7 +969,7 @@ classify_user_id (const char *name,
if ( *s == '/')
{ /* "#/" indicates an issuer's DN */
s++;
if (!*s || spacep (*s))
if (!*s || spacep (s))
return 0; /* no DN or prefixed with a space */
desc->u.name = s;
mode = KEYDB_SEARCH_MODE_ISSUER;
@ -990,7 +988,7 @@ classify_user_id (const char *name,
else
{
s = si+1;
if (!*s || spacep (*s))
if (!*s || spacep (s))
return 0; /* no DN or prefixed with a space */
desc->u.name = s;
mode = KEYDB_SEARCH_MODE_ISSUER_SN;
@ -1038,7 +1036,7 @@ classify_user_id (const char *name,
}
/* check if a hexadecimal number is terminated by EOS or blank */
if (hexlength && s[hexlength] && !spacep(s[hexlength]))
if (hexlength && s[hexlength] && !spacep (s+hexlength))
{
if (hexprefix) /* a "0x" prefix without correct */
return 0; /* termination is an error */

View File

@ -1,5 +1,5 @@
/* server.c - Server mode and main entry point
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -42,45 +42,6 @@ struct server_local_s {
CERTLIST recplist;
};
/* Map GNUPG_xxx error codes to Assuan status codes */
static int
rc_to_assuan_status (int rc)
{
switch (rc)
{
case 0: break;
case GNUPG_Bad_Certificate: rc = ASSUAN_Bad_Certificate; break;
case GNUPG_Bad_Certificate_Path: rc = ASSUAN_Bad_Certificate_Path; break;
case GNUPG_Missing_Certificate: rc = ASSUAN_Missing_Certificate; break;
case GNUPG_No_Data: rc = ASSUAN_No_Data_Available; break;
case GNUPG_Bad_Signature: rc = ASSUAN_Bad_Signature; break;
case GNUPG_Not_Implemented: rc = ASSUAN_Not_Implemented; break;
case GNUPG_No_Agent: rc = ASSUAN_No_Agent; break;
case GNUPG_Agent_Error: rc = ASSUAN_Agent_Error; break;
case GNUPG_No_Public_Key: rc = ASSUAN_No_Public_Key; break;
case GNUPG_No_Secret_Key: rc = ASSUAN_No_Secret_Key; break;
case GNUPG_Invalid_Data: rc = ASSUAN_Invalid_Data; break;
case GNUPG_Invalid_Name: rc = ASSUAN_Invalid_Name; break;
case GNUPG_Read_Error:
case GNUPG_Write_Error:
case GNUPG_IO_Error:
rc = ASSUAN_Server_IO_Error;
break;
case GNUPG_Out_Of_Core:
case GNUPG_Resource_Limit:
rc = ASSUAN_Server_Resource_Problem;
break;
case GNUPG_Bug:
case GNUPG_Internal_Error:
rc = ASSUAN_Server_Bug;
break;
default:
rc = ASSUAN_Server_Fault;
break;
}
return rc;
}
static void
close_message_fd (CTRL ctrl)
@ -155,7 +116,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
rc = gpgsm_add_to_certlist (line, &ctrl->server_local->recplist);
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
@ -204,7 +165,7 @@ cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
}
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
/* DECRYPT
@ -243,7 +204,7 @@ cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
assuan_close_output_fd (ctx);
}
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
@ -288,7 +249,7 @@ cmd_verify (ASSUAN_CONTEXT ctx, char *line)
assuan_close_output_fd (ctx);
}
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
@ -329,7 +290,7 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line)
assuan_close_output_fd (ctx);
}
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
@ -358,7 +319,7 @@ cmd_import (ASSUAN_CONTEXT ctx, char *line)
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
}
return rc_to_assuan_status (rc);
return map_to_assuan_status (rc);
}
/* MESSAGE FD=<n>
@ -400,6 +361,42 @@ cmd_listkeys (ASSUAN_CONTEXT ctx, char *line)
return 0;
}
/* GENKEY
Read the parameters in native format from the input fd and write a
certificate request to the output.
*/
static int
cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int inp_fd, out_fd;
FILE *out_fp;
int rc;
inp_fd = assuan_get_input_fd (ctx);
if (inp_fd == -1)
return set_error (No_Input, NULL);
out_fd = assuan_get_output_fd (ctx);
if (out_fd == -1)
return set_error (No_Output, NULL);
out_fp = fdopen ( dup(out_fd), "w");
if (!out_fp)
return set_error (General_Error, "fdopen() failed");
rc = gpgsm_genkey (ctrl, inp_fd, out_fp);
fclose (out_fp);
if (!rc)
{
/* close and reset the fds */
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
}
return map_to_assuan_status (rc);
}
@ -423,6 +420,7 @@ register_commands (ASSUAN_CONTEXT ctx)
{ "", ASSUAN_CMD_OUTPUT, NULL },
{ "MESSAGE", 0, cmd_message },
{ "LISTKEYS", 0, cmd_listkeys },
{ "GENKEY", 0, cmd_genkey },
{ NULL }
};
int i, j, rc;

View File

@ -142,6 +142,7 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
ctrl->pem_name = "SIGNED MESSAGE";
rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
if (rc)
{