mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Implemented encryption in server mode.
Allow to specify a recipient on the commandline There is still a default hardwired recipient if none has been set.
This commit is contained in:
parent
f463880562
commit
6a8c47bd29
@ -32,6 +32,7 @@ gpgsm_SOURCES = \
|
||||
call-agent.c \
|
||||
fingerprint.c \
|
||||
base64.c \
|
||||
certlist.c \
|
||||
certdump.c \
|
||||
certcheck.c \
|
||||
certpath.c \
|
||||
|
88
sm/certlist.c
Normal file
88
sm/certlist.c
Normal file
@ -0,0 +1,88 @@
|
||||
/* certlist.c - build list of certificates
|
||||
* Copyright (C) 2001 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
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
int
|
||||
gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
|
||||
{
|
||||
int rc;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
KEYDB_HANDLE kh = NULL;
|
||||
KsbaCert cert = NULL;
|
||||
|
||||
/* fixme: check that we identify excactly one cert with the name */
|
||||
rc = keydb_classify_name (name, &desc);
|
||||
if (!rc)
|
||||
{
|
||||
kh = keydb_new (0);
|
||||
if (!kh)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
rc = keydb_search (kh, &desc, 1);
|
||||
if (!rc)
|
||||
rc = keydb_get_cert (kh, &cert);
|
||||
if (!rc)
|
||||
{
|
||||
CERTLIST cl = xtrycalloc (1, sizeof *cl);
|
||||
if (!cl)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
cl->cert = cert; cert = NULL;
|
||||
cl->next = *listaddr;
|
||||
*listaddr = cl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keydb_release (kh);
|
||||
ksba_cert_release (cert);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
gpgsm_release_certlist (CERTLIST list)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
CERTLIST cl = list->next;
|
||||
ksba_cert_release (list->cert);
|
||||
xfree (list);
|
||||
list = cl;
|
||||
}
|
||||
}
|
||||
|
10
sm/decrypt.c
10
sm/decrypt.c
@ -36,6 +36,7 @@
|
||||
|
||||
struct decrypt_filter_parm_s {
|
||||
int algo;
|
||||
int mode;
|
||||
int blklen;
|
||||
GCRY_CIPHER_HD hd;
|
||||
char iv[16];
|
||||
@ -110,7 +111,7 @@ prepare_decryption (const char *hexkeygrip, const char *enc_val,
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex ("session key:", seskey+n, seskeylen-n);
|
||||
|
||||
parm->hd = gcry_cipher_open (parm->algo, GCRY_CIPHER_MODE_CBC, 0);
|
||||
parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0);
|
||||
if (!parm->hd)
|
||||
{
|
||||
rc = gcry_errno ();
|
||||
@ -311,23 +312,24 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
|
||||
rc = map_ksba_err (err);
|
||||
goto leave;
|
||||
}
|
||||
log_debug ("ksba_cms_parse - stop reason %d\n", stopreason);
|
||||
|
||||
if (stopreason == KSBA_SR_BEGIN_DATA
|
||||
|| stopreason == KSBA_SR_DETACHED_DATA)
|
||||
{
|
||||
int algo;
|
||||
int algo, mode;
|
||||
const char *algoid;
|
||||
|
||||
algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
|
||||
algo = gcry_cipher_map_name (algoid);
|
||||
if (!algo)
|
||||
mode = gcry_cipher_mode_from_oid (algoid);
|
||||
if (!algo || !mode)
|
||||
{
|
||||
log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
|
||||
rc = GNUPG_Unsupported_Algorithm;
|
||||
goto leave;
|
||||
}
|
||||
dfparm.algo = algo;
|
||||
dfparm.mode = mode;
|
||||
dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
|
||||
if (dfparm.blklen > sizeof (dfparm.helpblock))
|
||||
return GNUPG_Bug;
|
||||
|
69
sm/encrypt.c
69
sm/encrypt.c
@ -62,17 +62,25 @@ static KsbaCert
|
||||
get_default_recipient (void)
|
||||
{
|
||||
const char key[] =
|
||||
"CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=#44FC7373656C646F7266#,C=DE";
|
||||
"/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=#44FC7373656C646F7266#,C=DE";
|
||||
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
KsbaCert cert = NULL;
|
||||
KEYDB_HANDLE kh = NULL;
|
||||
int rc;
|
||||
|
||||
rc = keydb_classify_name (key, &desc);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to find recipient: %s\n", gnupg_strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kh = keydb_new (0);
|
||||
if (!kh)
|
||||
return NULL;
|
||||
|
||||
rc = keydb_search_subject (kh, key);
|
||||
rc = keydb_search (kh, &desc, 1);
|
||||
if (rc)
|
||||
{
|
||||
log_debug ("failed to find default certificate: rc=%d\n", rc);
|
||||
@ -96,10 +104,11 @@ get_default_recipient (void)
|
||||
static int
|
||||
init_dek (DEK dek)
|
||||
{
|
||||
int rc=0, i;
|
||||
int rc=0, mode, i;
|
||||
|
||||
dek->algo = gcry_cipher_map_name (dek->algoid);
|
||||
if (!dek->algo)
|
||||
mode = gcry_cipher_mode_from_oid (dek->algoid);
|
||||
if (!dek->algo || !mode)
|
||||
{
|
||||
log_error ("unsupported algorithm `%s'\n", dek->algoid);
|
||||
return GNUPG_Unsupported_Algorithm;
|
||||
@ -119,10 +128,7 @@ init_dek (DEK dek)
|
||||
return GNUPG_Unsupported_Algorithm;
|
||||
}
|
||||
|
||||
|
||||
dek->chd = gcry_cipher_open (dek->algo,
|
||||
GCRY_CIPHER_MODE_CBC,
|
||||
GCRY_CIPHER_SECURE);
|
||||
dek->chd = gcry_cipher_open (dek->algo, mode, GCRY_CIPHER_SECURE);
|
||||
if (!dek->chd)
|
||||
{
|
||||
log_error ("failed to create cipher context: %s\n", gcry_strerror (-1));
|
||||
@ -369,9 +375,10 @@ encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
||||
/* Perform an encrypt operation.
|
||||
|
||||
Encrypt the data received on DATA-FD and write it to OUT_FP. The
|
||||
recipients are hardwired for now. */
|
||||
recipients are take from the certificate given in recplist; if this
|
||||
is NULL it will be encrypted for a default recipient */
|
||||
int
|
||||
gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
|
||||
{
|
||||
int rc = 0;
|
||||
Base64Context b64writer = NULL;
|
||||
@ -385,9 +392,12 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
DEK dek = NULL;
|
||||
int recpno;
|
||||
FILE *data_fp = NULL;
|
||||
|
||||
struct certlist_s help_recplist;
|
||||
CERTLIST cl;
|
||||
|
||||
memset (&encparm, 0, sizeof encparm);
|
||||
help_recplist.next = NULL;
|
||||
help_recplist.cert = NULL;
|
||||
kh = keydb_new (0);
|
||||
if (!kh)
|
||||
{
|
||||
@ -396,6 +406,19 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* If no recipient list is given, use a default one */
|
||||
if (!recplist)
|
||||
{
|
||||
help_recplist.cert = get_default_recipient ();
|
||||
if (!help_recplist.cert)
|
||||
{
|
||||
log_error ("no default recipient found\n");
|
||||
rc = seterr (General_Error);
|
||||
goto leave;
|
||||
}
|
||||
recplist = &help_recplist;
|
||||
}
|
||||
|
||||
data_fp = fdopen ( dup (data_fd), "rb");
|
||||
if (!data_fp)
|
||||
{
|
||||
@ -458,7 +481,7 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
dek->algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/
|
||||
dek->algoid = opt.def_cipher_algoid;
|
||||
rc = init_dek (dek);
|
||||
}
|
||||
if (rc)
|
||||
@ -490,40 +513,27 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
|
||||
/* gather certificates of recipients, encrypt the session key for
|
||||
each and store them in the CMS object */
|
||||
for (recpno = 0; recpno < 1; recpno++)
|
||||
for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
|
||||
{
|
||||
KsbaCert cert;
|
||||
char *encval;
|
||||
|
||||
/* fixme: get the recipients out of the arguments passed to us */
|
||||
cert = get_default_recipient ();
|
||||
if (!cert)
|
||||
{
|
||||
log_error ("no default recipient found\n");
|
||||
rc = seterr (General_Error);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = encrypt_dek (dek, cert, &encval);
|
||||
rc = encrypt_dek (dek, cl->cert, &encval);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("encryption failed for recipient no. %d: %s\n",
|
||||
recpno, gnupg_strerror (rc));
|
||||
ksba_cert_release (cert);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = ksba_cms_add_recipient (cms, cert);
|
||||
err = ksba_cms_add_recipient (cms, cl->cert);
|
||||
if (err)
|
||||
{
|
||||
log_error ("ksba_cms_add_recipient failed: %s\n",
|
||||
ksba_strerror (err));
|
||||
rc = map_ksba_err (err);
|
||||
xfree (encval);
|
||||
ksba_cert_release (cert);
|
||||
goto leave;
|
||||
}
|
||||
cert = NULL; /* cms does now own the certificate */
|
||||
|
||||
err = ksba_cms_set_enc_val (cms, recpno, encval);
|
||||
xfree (encval);
|
||||
@ -547,7 +557,6 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
rc = map_ksba_err (err);
|
||||
goto leave;
|
||||
}
|
||||
log_debug ("ksba_cms_build - stop reason %d\n", stopreason);
|
||||
}
|
||||
while (stopreason != KSBA_SR_READY);
|
||||
|
||||
@ -576,5 +585,7 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp)
|
||||
if (data_fp)
|
||||
fclose (data_fp);
|
||||
xfree (encparm.buffer);
|
||||
if (help_recplist.cert)
|
||||
ksba_cert_release (help_recplist.cert);
|
||||
return rc;
|
||||
}
|
||||
|
40
sm/gpgsm.c
40
sm/gpgsm.c
@ -512,10 +512,10 @@ main ( int argc, char **argv)
|
||||
int nogreeting = 0;
|
||||
int use_random_seed = 1;
|
||||
int with_fpr = 0;
|
||||
char *def_cipher_string = NULL;
|
||||
char *def_digest_string = NULL;
|
||||
enum cmd_and_opt_values cmd = 0;
|
||||
struct server_control_s ctrl;
|
||||
CERTLIST recplist = NULL;
|
||||
|
||||
/* FIXME: trap_unaligned ();*/
|
||||
set_strusage (my_strusage);
|
||||
@ -541,6 +541,7 @@ main ( int argc, char **argv)
|
||||
create_dotlock (NULL); /* register locking cleanup */
|
||||
i18n_init();
|
||||
|
||||
opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/
|
||||
#ifdef __MINGW32__
|
||||
opt.homedir = read_w32_registry_string ( NULL,
|
||||
"Software\\GNU\\GnuPG", "HomeDir" );
|
||||
@ -762,6 +763,10 @@ main ( int argc, char **argv)
|
||||
gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
|
||||
break;
|
||||
|
||||
case oCipherAlgo:
|
||||
opt.def_cipher_algoid = pargs.r.ret_str;
|
||||
break;
|
||||
|
||||
case oDisableCipherAlgo:
|
||||
{
|
||||
int algo = gcry_cipher_map_name (pargs.r.ret_str);
|
||||
@ -780,6 +785,8 @@ main ( int argc, char **argv)
|
||||
|
||||
case oEnableSpecialFilenames: allow_special_filenames =1; break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
pargs.err = configfp? 1:2;
|
||||
break;
|
||||
@ -832,16 +839,12 @@ main ( int argc, char **argv)
|
||||
/* FIXME: should set filenames of libgcrypt explicitly
|
||||
* gpg_opt_homedir = opt.homedir; */
|
||||
|
||||
/* must do this after dropping setuid, because string_to...
|
||||
* may try to load an module */
|
||||
if (def_cipher_string)
|
||||
{
|
||||
opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string);
|
||||
xfree (def_cipher_string);
|
||||
def_cipher_string = NULL;
|
||||
if ( our_cipher_test_algo (opt.def_cipher_algo) )
|
||||
/* must do this after dropping setuid, because the mapping functions
|
||||
may try to load an module and we may have disabled an algorithm */
|
||||
if ( !gcry_cipher_map_name (opt.def_cipher_algoid)
|
||||
|| !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
|
||||
log_error (_("selected cipher algorithm is invalid\n"));
|
||||
}
|
||||
|
||||
if (def_digest_string)
|
||||
{
|
||||
opt.def_digest_algo = gcry_md_map_name (def_digest_string);
|
||||
@ -876,6 +879,18 @@ main ( int argc, char **argv)
|
||||
keydb_add_resource (sl->d, 0, 0);
|
||||
FREE_STRLIST(nrings);
|
||||
|
||||
for (sl = remusr; sl; sl = sl->next)
|
||||
{
|
||||
int rc = gpgsm_add_to_certlist (sl->d, &recplist);
|
||||
if (rc)
|
||||
log_error (_("can't encrypt to `%s': %s\n"),
|
||||
sl->d, gnupg_strerror (rc));
|
||||
}
|
||||
if (log_get_errorcount(0))
|
||||
gpgsm_exit(1); /* must stop for invalid recipients */
|
||||
|
||||
|
||||
|
||||
fname = argc? *argv : NULL;
|
||||
|
||||
switch (cmd)
|
||||
@ -886,9 +901,9 @@ main ( int argc, char **argv)
|
||||
|
||||
case aEncr: /* encrypt the given file */
|
||||
if (!argc)
|
||||
gpgsm_encrypt (&ctrl, 0, stdout); /* from stdin */
|
||||
gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
|
||||
else if (argc == 1)
|
||||
gpgsm_encrypt (&ctrl, open_read (*argv), stdout); /* from file */
|
||||
gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */
|
||||
else
|
||||
wrong_args (_("--encrypt [datafile]"));
|
||||
break;
|
||||
@ -1066,6 +1081,7 @@ main ( int argc, char **argv)
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
gpgsm_release_certlist (recplist);
|
||||
FREE_STRLIST(remusr);
|
||||
FREE_STRLIST(locusr);
|
||||
gpgsm_exit(0);
|
||||
|
20
sm/gpgsm.h
20
sm/gpgsm.h
@ -48,7 +48,9 @@ struct {
|
||||
int armor; /* force base64 armoring (see also ctrl.with_base64) */
|
||||
int no_armor; /* don't try to figure out whether data is base64 armored*/
|
||||
|
||||
int def_cipher_algo; /* cipher algorithm to use if nothing else is know */
|
||||
const char *def_cipher_algoid; /* cipher algorithm to use if
|
||||
nothing else is specified */
|
||||
|
||||
int def_digest_algo; /* Ditto for hash algorithm */
|
||||
int def_compress_algo; /* Ditto for compress algorithm */
|
||||
|
||||
@ -100,10 +102,16 @@ struct server_control_s {
|
||||
};
|
||||
typedef struct server_control_s *CTRL;
|
||||
|
||||
/* data structure osed in base64.c */
|
||||
/* data structure used in base64.c */
|
||||
typedef struct base64_context_s *Base64Context;
|
||||
|
||||
|
||||
struct certlist_s {
|
||||
struct certlist_s *next;
|
||||
KsbaCert cert;
|
||||
};
|
||||
typedef struct certlist_s *CERTLIST;
|
||||
|
||||
/*-- gpgsm.c --*/
|
||||
void gpgsm_exit (int rc);
|
||||
|
||||
@ -143,6 +151,10 @@ int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo,
|
||||
/*-- certpath.c --*/
|
||||
int gpgsm_validate_path (KsbaCert cert);
|
||||
|
||||
/*-- cetlist.c --*/
|
||||
int gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr);
|
||||
void gpgsm_release_certlist (CERTLIST list);
|
||||
|
||||
/*-- keylist.c --*/
|
||||
void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp);
|
||||
|
||||
@ -156,7 +168,7 @@ int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd);
|
||||
int gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp);
|
||||
|
||||
/*-- encrypt.c --*/
|
||||
int gpgsm_encrypt (CTRL ctrl, int in_fd, FILE *out_fp);
|
||||
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);
|
||||
@ -174,3 +186,5 @@ int gpgsm_agent_pkdecrypt (const char *keygrip,
|
||||
|
||||
#endif /*GPGSM_H*/
|
||||
|
||||
|
||||
|
||||
|
275
sm/keydb.c
275
sm/keydb.c
@ -35,6 +35,8 @@
|
||||
|
||||
#define DIRSEP_C '/'
|
||||
|
||||
#define spacep(a) ((a) == ' ' || (a) == '\t')
|
||||
|
||||
static int active_handles;
|
||||
|
||||
typedef enum {
|
||||
@ -859,4 +861,277 @@ keydb_search_subject (KEYDB_HANDLE hd, const char *name)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hextobyte (const unsigned char *s)
|
||||
{
|
||||
int c;
|
||||
|
||||
if( *s >= '0' && *s <= '9' )
|
||||
c = 16 * (*s - '0');
|
||||
else if ( *s >= 'A' && *s <= 'F' )
|
||||
c = 16 * (10 + *s - 'A');
|
||||
else if ( *s >= 'a' && *s <= 'f' )
|
||||
c = 16 * (10 + *s - 'a');
|
||||
else
|
||||
return -1;
|
||||
s++;
|
||||
if ( *s >= '0' && *s <= '9' )
|
||||
c += *s - '0';
|
||||
else if ( *s >= 'A' && *s <= 'F' )
|
||||
c += 10 + *s - 'A';
|
||||
else if ( *s >= 'a' && *s <= 'f' )
|
||||
c += 10 + *s - 'a';
|
||||
else
|
||||
return -1;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
classify_user_id (const char *name,
|
||||
KEYDB_SEARCH_DESC *desc,
|
||||
int *force_exact )
|
||||
{
|
||||
const char *s;
|
||||
int hexprefix = 0;
|
||||
int hexlength;
|
||||
int mode = 0;
|
||||
|
||||
/* clear the structure so that the mode field is set to zero unless
|
||||
* we set it to the correct value right at the end of this function */
|
||||
memset (desc, 0, sizeof *desc);
|
||||
*force_exact = 0;
|
||||
/* skip leading spaces. Fixme: what about trailing white space? */
|
||||
for(s = name; *s && spacep(*s); s++ )
|
||||
;
|
||||
|
||||
switch (*s)
|
||||
{
|
||||
case 0: /* empty string is an error */
|
||||
return 0;
|
||||
|
||||
case '.': /* an email address, compare from end */
|
||||
mode = KEYDB_SEARCH_MODE_MAILEND;
|
||||
s++;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '<': /* an email address */
|
||||
mode = KEYDB_SEARCH_MODE_MAIL;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '@': /* part of an email address */
|
||||
mode = KEYDB_SEARCH_MODE_MAILSUB;
|
||||
s++;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '=': /* exact compare */
|
||||
mode = KEYDB_SEARCH_MODE_EXACT;
|
||||
s++;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '*': /* case insensitive substring search */
|
||||
mode = KEYDB_SEARCH_MODE_SUBSTR;
|
||||
s++;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '+': /* compare individual words */
|
||||
mode = KEYDB_SEARCH_MODE_WORDS;
|
||||
s++;
|
||||
desc->u.name = s;
|
||||
break;
|
||||
|
||||
case '/': /* subject's DN */
|
||||
s++;
|
||||
if (!*s || spacep (*s))
|
||||
return 0; /* no DN or prefixed with a space */
|
||||
desc->u.name = s;
|
||||
mode = KEYDB_SEARCH_MODE_SUBJECT;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
{
|
||||
const char *si;
|
||||
|
||||
s++;
|
||||
if ( *s == '/')
|
||||
{ /* "#/" indicates an issuer's DN */
|
||||
s++;
|
||||
if (!*s || spacep (*s))
|
||||
return 0; /* no DN or prefixed with a space */
|
||||
desc->u.name = s;
|
||||
mode = KEYDB_SEARCH_MODE_ISSUER;
|
||||
}
|
||||
else
|
||||
{ /* serialnumber + optional issuer ID */
|
||||
for (si=s; *si && *si != '/'; si++)
|
||||
{
|
||||
if (!strchr("01234567890abcdefABCDEF", *si))
|
||||
return 0; /* invalid digit in serial number*/
|
||||
}
|
||||
desc->sn = s;
|
||||
desc->sn_is_string = 1;
|
||||
if (!*si)
|
||||
mode = KEYDB_SEARCH_MODE_SN;
|
||||
else
|
||||
{
|
||||
s = si+1;
|
||||
if (!*s || spacep (*s))
|
||||
return 0; /* no DN or prefixed with a space */
|
||||
desc->u.name = s;
|
||||
mode = KEYDB_SEARCH_MODE_ISSUER_SN;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ':': /*Unified fingerprint */
|
||||
{
|
||||
const char *se, *si;
|
||||
int i;
|
||||
|
||||
se = strchr (++s,':');
|
||||
if (!se)
|
||||
return 0;
|
||||
for (i=0,si=s; si < se; si++, i++ )
|
||||
{
|
||||
if (!strchr("01234567890abcdefABCDEF", *si))
|
||||
return 0; /* invalid digit */
|
||||
}
|
||||
if (i != 32 && i != 40)
|
||||
return 0; /* invalid length of fpr*/
|
||||
for (i=0,si=s; si < se; i++, si +=2)
|
||||
desc->u.fpr[i] = hextobyte(si);
|
||||
for (; i < 20; i++)
|
||||
desc->u.fpr[i]= 0;
|
||||
s = se + 1;
|
||||
mode = KEYDB_SEARCH_MODE_FPR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (s[0] == '0' && s[1] == 'x')
|
||||
{
|
||||
hexprefix = 1;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
hexlength = strspn(s, "0123456789abcdefABCDEF");
|
||||
if (hexlength >= 8 && s[hexlength] =='!')
|
||||
{
|
||||
*force_exact = 1;
|
||||
hexlength++; /* just for the following check */
|
||||
}
|
||||
|
||||
/* check if a hexadecimal number is terminated by EOS or blank */
|
||||
if (hexlength && s[hexlength] && !spacep(s[hexlength]))
|
||||
{
|
||||
if (hexprefix) /* a "0x" prefix without correct */
|
||||
return 0; /* termination is an error */
|
||||
/* The first chars looked like a hex number, but really is
|
||||
not */
|
||||
hexlength = 0;
|
||||
}
|
||||
|
||||
if (*force_exact)
|
||||
hexlength--; /* remove the bang */
|
||||
|
||||
if (hexlength == 8
|
||||
|| (!hexprefix && hexlength == 9 && *s == '0'))
|
||||
{ /* short keyid */
|
||||
unsigned long kid;
|
||||
if (hexlength == 9)
|
||||
s++;
|
||||
kid = strtoul( s, NULL, 16 );
|
||||
desc->u.kid[4] = kid >> 24;
|
||||
desc->u.kid[5] = kid >> 16;
|
||||
desc->u.kid[6] = kid >> 8;
|
||||
desc->u.kid[7] = kid;
|
||||
mode = KEYDB_SEARCH_MODE_SHORT_KID;
|
||||
}
|
||||
else if (hexlength == 16
|
||||
|| (!hexprefix && hexlength == 17 && *s == '0'))
|
||||
{ /* complete keyid */
|
||||
unsigned long kid0, kid1;
|
||||
char buf[9];
|
||||
if (hexlength == 17)
|
||||
s++;
|
||||
mem2str(buf, s, 9 );
|
||||
kid0 = strtoul (buf, NULL, 16);
|
||||
kid1 = strtoul (s+8, NULL, 16);
|
||||
desc->u.kid[0] = kid0 >> 24;
|
||||
desc->u.kid[1] = kid0 >> 16;
|
||||
desc->u.kid[2] = kid0 >> 8;
|
||||
desc->u.kid[3] = kid0;
|
||||
desc->u.kid[4] = kid1 >> 24;
|
||||
desc->u.kid[5] = kid1 >> 16;
|
||||
desc->u.kid[6] = kid1 >> 8;
|
||||
desc->u.kid[7] = kid1;
|
||||
mode = KEYDB_SEARCH_MODE_LONG_KID;
|
||||
}
|
||||
else if (hexlength == 32
|
||||
|| (!hexprefix && hexlength == 33 && *s == '0'))
|
||||
{ /* md5 fingerprint */
|
||||
int i;
|
||||
if (hexlength == 33)
|
||||
s++;
|
||||
memset(desc->u.fpr+16, 0, 4);
|
||||
for (i=0; i < 16; i++, s+=2)
|
||||
{
|
||||
int c = hextobyte(s);
|
||||
if (c == -1)
|
||||
return 0;
|
||||
desc->u.fpr[i] = c;
|
||||
}
|
||||
mode = KEYDB_SEARCH_MODE_FPR16;
|
||||
}
|
||||
else if (hexlength == 40
|
||||
|| (!hexprefix && hexlength == 41 && *s == '0'))
|
||||
{ /* sha1/rmd160 fingerprint */
|
||||
int i;
|
||||
if (hexlength == 41)
|
||||
s++;
|
||||
for (i=0; i < 20; i++, s+=2)
|
||||
{
|
||||
int c = hextobyte(s);
|
||||
if (c == -1)
|
||||
return 0;
|
||||
desc->u.fpr[i] = c;
|
||||
}
|
||||
mode = KEYDB_SEARCH_MODE_FPR20;
|
||||
}
|
||||
else if (!hexprefix)
|
||||
{ /* default is substring search */
|
||||
*force_exact = 0;
|
||||
desc->u.name = s;
|
||||
mode = KEYDB_SEARCH_MODE_SUBSTR;
|
||||
}
|
||||
else
|
||||
{ /* hex number with a prefix but a wrong length */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
desc->mode = mode;
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
|
||||
{
|
||||
int dummy;
|
||||
KEYDB_SEARCH_DESC dummy_desc;
|
||||
|
||||
if (!desc)
|
||||
desc = &dummy_desc;
|
||||
|
||||
if (!classify_user_id (name, desc, &dummy))
|
||||
return GNUPG_Invalid_Name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,8 @@ int keydb_search_issuer_sn (KEYDB_HANDLE hd,
|
||||
const char *issuer, const unsigned char *serial);
|
||||
int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer);
|
||||
|
||||
int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
|
||||
|
||||
|
||||
#endif /*GNUPG_KEYDB_H*/
|
||||
|
||||
|
30
sm/server.c
30
sm/server.c
@ -40,6 +40,7 @@ static FILE *statusfp;
|
||||
struct server_local_s {
|
||||
ASSUAN_CONTEXT assuan_ctx;
|
||||
int message_fd;
|
||||
CERTLIST recplist;
|
||||
};
|
||||
|
||||
/* Map GNUPG_xxx error codes to Assuan status codes */
|
||||
@ -60,6 +61,7 @@ rc_to_assuan_status (int rc)
|
||||
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:
|
||||
@ -81,10 +83,13 @@ rc_to_assuan_status (int rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reset_notify (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
gpgsm_release_certlist (ctrl->server_local->recplist);
|
||||
ctrl->server_local->recplist = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -131,13 +136,16 @@ output_notify (ASSUAN_CONTEXT ctx, const char *line)
|
||||
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 ENCRYPT command. */
|
||||
cumulative until a RESET or an successful ENCRYPT command. */
|
||||
static int
|
||||
cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
|
||||
rc = gpgsm_add_to_certlist (line, &ctrl->server_local->recplist);
|
||||
|
||||
return set_error (Not_Implemented, "fixme");
|
||||
return rc_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
@ -157,6 +165,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
|
||||
static int
|
||||
cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int inp_fd, out_fd;
|
||||
FILE *out_fp;
|
||||
int rc;
|
||||
@ -171,9 +180,16 @@ 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), inp_fd, out_fp);
|
||||
rc = gpgsm_encrypt (assuan_get_pointer (ctx),
|
||||
ctrl->server_local->recplist,
|
||||
inp_fd, out_fp);
|
||||
fclose (out_fp);
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
gpgsm_release_certlist (ctrl->server_local->recplist);
|
||||
ctrl->server_local->recplist = NULL;
|
||||
}
|
||||
return rc_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
@ -181,9 +197,9 @@ cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
|
||||
This performs the decrypt operation after doing some check on the
|
||||
internal state. (e.g. that only needed data has been set). Because
|
||||
it utilises the GPG-Agent for the session key decryption, there is
|
||||
it utilizes the GPG-Agent for the session key decryption, there is
|
||||
no need to ask the client for a protecting passphrase - GpgAgent
|
||||
does take care of this but requesting this from the user. */
|
||||
does take care of this by requesting this from the user. */
|
||||
static int
|
||||
cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
@ -412,6 +428,8 @@ gpgsm_server (void)
|
||||
}
|
||||
}
|
||||
|
||||
gpgsm_release_certlist (ctrl.server_local->recplist);
|
||||
ctrl.server_local->recplist = NULL;
|
||||
|
||||
assuan_deinit_pipe_server (ctx);
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
|
||||
rc = map_ksba_err (err);
|
||||
goto leave;
|
||||
}
|
||||
cert = NULL; /* cms does now own the certificate */
|
||||
ksba_cert_release (cert); cert = NULL;
|
||||
|
||||
/* fixme: We might want to include a list of certificate which are
|
||||
put as info into the signed data object - maybe we should add a
|
||||
@ -270,7 +270,6 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
|
||||
rc = map_ksba_err (err);
|
||||
goto leave;
|
||||
}
|
||||
log_debug ("ksba_cms_build - stop reason %d\n", stopreason);
|
||||
|
||||
if (stopreason == KSBA_SR_BEGIN_DATA)
|
||||
{ /* hash the data and store the message digest */
|
||||
|
@ -227,7 +227,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd)
|
||||
rc = map_ksba_err (err);
|
||||
goto leave;
|
||||
}
|
||||
log_debug ("ksba_cms_parse - stop reason %d\n", stopreason);
|
||||
|
||||
if (stopreason == KSBA_SR_NEED_HASH)
|
||||
{
|
||||
is_detached = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user