diff options
Diffstat (limited to 'g10/g10.c')
-rw-r--r-- | g10/g10.c | 433 |
1 files changed, 373 insertions, 60 deletions
@@ -18,6 +18,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +/**************** + * We use cpp to generate the source g10maint.c (IS_G10MAINT) from this + * source; the main difference is, that g10maint can only work with public + * keys and does not need to lock memory or run suid. + */ + #include <config.h> #include <errno.h> #include <stdio.h> @@ -40,11 +46,16 @@ #include "i18n.h" #include "status.h" +#ifndef IS_G10MAINT + #define IS_G10 1 +#endif + static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("\vCommands:\n ") }, + #ifdef IS_G10 { 's', "sign", 0, N_("make a signature")}, { 539, "clearsign", 0, N_("make a clear text signature") }, { 'b', "detach-sign", 0, N_("make a detached signature")}, @@ -55,25 +66,36 @@ static ARGPARSE_OPTS opts[] = { { 'k', "list-keys", 0, N_("list keys")}, { 508, "check-keys",0, N_("check signatures on a key in the keyring")}, { 515, "fingerprint", 0, N_("show the fingerprints")}, - { 521, "list-packets",0,N_("list only the sequence of packets")}, { 503, "gen-key", 0, N_("generate a new key pair")}, { 506, "sign-key" ,0, N_("make a signature on a key in the keyring")}, { 505, "delete-key",0, N_("remove key from the public keyring")}, - { 524, "edit-sig" ,0, N_("edit a key signature")}, + { 524, "edit-key" ,0, N_("edit a key signature")}, { 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")}, { 542, "gen-revoke",0, N_("generate a revocation certificate")}, + #endif { 537, "export" , 0, N_("export keys") }, { 530, "import", 0 , N_("import/merge keys")}, + { 521, "list-packets",0,N_("list only the sequence of packets")}, + #ifdef IS_G10MAINT + { 546, "dearmor", 0, N_("De-Armor a file or stdin") }, + { 547, "enarmor", 0, N_("En-Armor a file or stdin") }, + { 516, "print-mds" , 0, N_("print all message digests")}, + { 513, "gen-prime" , 0, "\r" }, + { 548, "gen-random" , 0, "\r" }, + { 549, "ext-list-keys", 0, "Print a parsable list of keys" }, + #endif { 301, NULL, 0, N_("\v\nOptions:\n ") }, + #ifdef IS_G10 { 'a', "armor", 0, N_("create ascii armored output")}, - { 'o', "output", 2, N_("use as output file")}, { 'u', "local-user",2, N_("use this user-id to sign or decrypt")}, { 'r', "remote-user", 2, N_("use this user-id for encryption")}, - { 'v', "verbose", 0, N_("verbose") }, { 'z', NULL, 1, N_("set compress level (0 disables)") }, { 't', "textmode", 0, N_("use canonical text mode")}, + #endif + { 'o', "output", 2, N_("use as output file")}, + { 'v', "verbose", 0, N_("verbose") }, { 'n', "dry-run", 0, N_("don't make any changes") }, { 500, "batch", 0, N_("batch mode: never ask")}, { 501, "yes", 0, N_("assume yes on most questions")}, @@ -88,18 +110,32 @@ static ARGPARSE_OPTS opts[] = { { 534, "no-comment", 0, N_("do not write comment packets")}, { 535, "completes-needed", 1, N_("(default is 1)")}, { 536, "marginals-needed", 1, N_("(default is 3)")}, + #ifdef IS_G10 { 527, "cipher-algo", 2 , N_("select default cipher algorithm")}, { 528, "pubkey-algo", 2 , N_("select default puplic key algorithm")}, { 529, "digest-algo", 2 , N_("select default message digest algorithm")}, + #endif + #ifdef IS_G10 { 302, NULL, 0, N_("\v\nExamples:\n\n" " -se -r Bob [file] sign and encrypt for user Bob\n" " -sat [file] make a clear text signature\n" " -sb [file] make a detached signature\n" " -k [userid] show keys\n" " -kc [userid] show fingerprint\n" ) }, + #endif /* hidden options */ + #ifdef IS_G10MAINT + { 514, "test" , 0, "\r" }, + { 531, "list-trustdb",0 , "\r"}, + { 533, "list-trust-path",0, "\r"}, + #endif + #ifdef IS_G10 + { 504, "delete-secret-key",0, "\r" }, + { 524, "edit-sig" ,0, "\r"}, /* alias for edit-key */ + { 523, "passphrase-fd",1, "\r" }, + #endif { 532, "quick-random", 0, "\r"}, { 526, "no-verbose", 0, "\r"}, { 538, "trustdb-name", 2, "\r" }, @@ -107,12 +143,12 @@ static ARGPARSE_OPTS opts[] = { { 519, "no-armor", 0, "\r"}, { 520, "no-default-keyring", 0, "\r" }, { 522, "no-greeting", 0, "\r" }, - { 523, "passphrase-fd",1, "\r" }, { 541, "no-operation", 0, "\r" }, /* used by regression tests */ { 543, "no-options", 0, "\r" }, /* shortcut for --options /dev/null */ { 544, "homedir", 2, "\r" }, /* defaults to "~/.gnupg" */ { 545, "no-batch", 0, "\r" }, + {0} }; @@ -120,9 +156,10 @@ static ARGPARSE_OPTS opts[] = { enum cmd_values { aNull = 0, aSym, aStore, aEncr, aKeygen, aSign, aSignEncr, - aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, + aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, aDeleteSecretKey, aKMode, aKModeC, aChangePass, aImport, - aExport, aCheckKeys, aGenRevoke, + aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs, aExtKeyList, + aListTrustDB, aListTrustPath, aDeArmor, aEnArmor, aGenRandom, aTest, aNOP }; @@ -130,6 +167,11 @@ static char *build_list( const char *text, const char *(*mapf)(int), int (*chkf)(int) ); static void set_cmd( enum cmd_values *ret_cmd, enum cmd_values new_cmd ); +#ifdef IS_G10MAINT +static void print_hex( byte *p, size_t n ); +static void print_mds( const char *fname ); +static void do_test(int); +#endif const char * strusage( int level ) @@ -137,21 +179,36 @@ strusage( int level ) static char *digests, *pubkeys, *ciphers; const char *p; switch( level ) { - case 11: p = "gpg (GNUPG)"; break; + case 11: p = + #ifdef IS_G10MAINT + "gpgm (GNUPG)"; + #else + "gpg (GNUPG)"; + #endif + break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _( -"Please report bugs to <[email protected]>.\n" - ); break; + case 19: p = + _("Please report bugs to <[email protected]>.\n"); + break; case 1: - case 40: p = _( -"Usage: gpg [options] [files] (-h for help)" - ); break; - case 41: p = _( -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" - ); break; + case 40: p = + #ifdef IS_G10MAINT + _("Usage: gpgm [options] [files] (-h for help)"); + #else + _("Usage: gpg [options] [files] (-h for help)"); + #endif + break; + case 41: p = + #ifdef IS_G10MAINT + _("Syntax: gpgm [options] [files]\n" + "GNUPG maintenance utility\n"); + #else + _("Syntax: gpg [options] [files]\n" + "sign, check, encrypt or decrypt\n" + "default operation depends on the input data\n"); + #endif + break; case 31: p = "\n"; break; case 32: @@ -223,7 +280,11 @@ i18n_init(void) static void wrong_args( const char *text) { + #ifdef IS_G10MAINT + fputs(_("usage: gpgm [options] "),stderr); + #else fputs(_("usage: gpg [options] "),stderr); + #endif fputs(text,stderr); putc('\n',stderr); g10_exit(2); @@ -313,12 +374,17 @@ main( int argc, char **argv ) enum cmd_values cmd = 0; const char *trustdb_name = NULL; + #ifdef IS_G10MAINT + secmem_init( 0 ); /* disable use of secmem */ + log_set_name("gpgm"); + #else /* Please note that we may running SUID(ROOT), so be very CAREFUL * when adding any stuff between here and the call to * secmem_init() somewhere after the option parsing */ - log_set_name("gpg"); + secure_random_alloc(); /* put random number into secure memory */ + #endif i18n_init(); opt.compress = -1; /* defaults to standard compress level */ opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH; @@ -389,43 +455,77 @@ main( int argc, char **argv ) while( optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) { switch( pargs.r_opt ) { - case 'v': opt.verbose++; opt.list_sigs=1; break; - case 'z': opt.compress = pargs.r.ret_int; break; + + #ifdef IS_G10 case 'a': opt.armor = 1; opt.no_armor=0; break; - case 'd': break; /* it is default */ + case 'b': detached_sig = 1; /* fall trough */ case 'c': set_cmd( &cmd , aSym); break; - case 'o': opt.outfile = pargs.r.ret_str; break; + case 'd': break; /* it is default */ case 'e': set_cmd( &cmd, aEncr); break; - case 'b': detached_sig = 1; /* fall trough */ + case 'k': set_cmd( &cmd, aKMode ); break; + case 'r': /* store the remote users */ + sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); + strcpy(sl->d, pargs.r.ret_str); + sl->next = remusr; + remusr = sl; + break; case 's': set_cmd( &cmd, aSign ); break; - case 't': set_cmd( &cmd , aClearsign); break; + case 't': opt.textmode=1; break; case 'u': /* store the local users */ sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); strcpy(sl->d, pargs.r.ret_str); sl->next = locusr; locusr = sl; break; - case 'r': /* store the remote users */ - sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); - strcpy(sl->d, pargs.r.ret_str); - sl->next = remusr; - remusr = sl; - break; - case 'k': set_cmd( &cmd, aKMode ); break; - case 500: opt.batch = 1; greeting = 0; break; - case 501: opt.answer_yes = 1; break; - case 502: opt.answer_no = 1; break; + case 'z': opt.compress = pargs.r.ret_int; break; case 503: set_cmd( &cmd, aKeygen); break; + case 504: set_cmd( &cmd, aDeleteSecretKey); break; case 505: set_cmd( &cmd, aDeleteKey); break; case 506: set_cmd( &cmd, aSignKey); break; case 507: set_cmd( &cmd, aStore); break; case 508: set_cmd( &cmd, aCheckKeys); opt.check_sigs = 1; opt.list_sigs = 1; break; + case 515: opt.fingerprint = 1; break; + case 523: set_passphrase_fd( pargs.r.ret_int ); break; + case 524: set_cmd( &cmd, aEditSig); break; + case 525: set_cmd( &cmd, aChangePass); break; + case 527: + opt.def_cipher_algo = string_to_cipher_algo(pargs.r.ret_str); + break; + case 528: + opt.def_pubkey_algo = string_to_pubkey_algo(pargs.r.ret_str); + break; + case 529: + opt.def_digest_algo = string_to_digest_algo(pargs.r.ret_str); + break; + case 539: set_cmd( &cmd, aClearsign); break; + case 540: secmem_set_flags( secmem_get_flags() | 1 ); break; + case 542: set_cmd( &cmd, aGenRevoke); break; + #endif /* IS_G10 */ + + #ifdef IS_G10MAINT + case 513: set_cmd( &cmd, aPrimegen); break; + case 514: set_cmd( &cmd, aTest); break; + case 516: set_cmd( &cmd, aPrintMDs); break; + case 531: set_cmd( &cmd, aListTrustDB); break; + case 533: set_cmd( &cmd, aListTrustPath); break; + case 540: break; /* dummy */ + case 546: set_cmd( &cmd, aDeArmor); break; + case 547: set_cmd( &cmd, aEnArmor); break; + case 548: set_cmd( &cmd, aGenRandom); break; + case 549: set_cmd( &cmd, aExtKeyList); break; + #endif /* IS_G10MAINT */ + + case 'o': opt.outfile = pargs.r.ret_str; break; + case 'v': opt.verbose++; opt.list_sigs=1; break; + + case 500: opt.batch = 1; greeting = 0; break; + case 501: opt.answer_yes = 1; break; + case 502: opt.answer_no = 1; break; case 509: add_keyring(pargs.r.ret_str); nrings++; break; case 510: opt.debug |= pargs.r.ret_ulong; break; case 511: opt.debug = ~0; break; case 512: set_status_fd( pargs.r.ret_int ); break; - case 515: opt.fingerprint = 1; break; case 517: add_secret_keyring(pargs.r.ret_str); sec_nrings++; break; case 518: /* config files may not be nested (silently ignore them) */ @@ -439,19 +539,7 @@ main( int argc, char **argv ) case 520: default_keyring = 0; break; case 521: set_cmd( &cmd, aListPackets); break; case 522: greeting = 0; break; - case 523: set_passphrase_fd( pargs.r.ret_int ); break; - case 524: set_cmd( &cmd, aEditSig); break; - case 525: set_cmd( &cmd, aChangePass); break; case 526: opt.verbose = 0; opt.list_sigs=0; break; - case 527: - opt.def_cipher_algo = string_to_cipher_algo(pargs.r.ret_str); - break; - case 528: - opt.def_pubkey_algo = string_to_pubkey_algo(pargs.r.ret_str); - break; - case 529: - opt.def_digest_algo = string_to_digest_algo(pargs.r.ret_str); - break; case 530: set_cmd( &cmd, aImport); break; case 532: quick_random_gen(1); break; case 534: opt.no_comment=1; break; @@ -459,10 +547,7 @@ main( int argc, char **argv ) case 536: opt.marginals_needed = pargs.r.ret_int; break; case 537: set_cmd( &cmd, aExport); break; case 538: trustdb_name = pargs.r.ret_str; break; - case 539: set_cmd( &cmd, aClearsign); break; - case 540: secmem_set_flags( secmem_get_flags() | 1 ); break; case 541: set_cmd( &cmd, aNOP); break; - case 542: set_cmd( &cmd, aGenRevoke); break; case 543: break; /* no-options */ case 544: opt.homedir = pargs.r.ret_str; break; case 545: opt.batch = 0; break; @@ -485,9 +570,11 @@ main( int argc, char **argv ) tty_printf("%s\n", strusage(15) ); } + #ifdef IS_G10 /* initialize the secure memory. */ secmem_init( 16384 ); /* Okay, we are now working under our real uid */ + #endif write_status( STATUS_ENTER ); @@ -505,13 +592,20 @@ main( int argc, char **argv ) opt.verbose = opt.verbose > 1; } + + /* kludge to let -sat generate a clear text signature */ + if( opt.textmode && !detached_sig && opt.armor && cmd == aSign ) + cmd = aClearsign; + if( opt.verbose > 1 ) set_packet_list_mode(1); - if( !sec_nrings || default_keyring ) /* add default secret rings */ - add_secret_keyring("secring.gpg"); - if( !nrings || default_keyring ) /* add default ring */ - add_keyring("pubring.gpg"); + if( cmd != aDeArmor && cmd != aEnArmor ) { + if( !sec_nrings || default_keyring ) /* add default secret rings */ + add_secret_keyring("secring.gpg"); + if( !nrings || default_keyring ) /* add default ring */ + add_keyring("pubring.gpg"); + } if( argc ) { fname_print = fname = *argv; @@ -528,7 +622,16 @@ main( int argc, char **argv ) } } - rc = init_trustdb(1, trustdb_name ); + switch( cmd ) { + case aPrimegen: + case aPrintMDs: + case aGenRandom: + case aDeArmor: + case aEnArmor: + break; + case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break; + default: rc = init_trustdb(1, trustdb_name ); break; + } if( rc ) log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc)); @@ -541,7 +644,7 @@ main( int argc, char **argv ) log_error("%s: store failed: %s\n", fname_print, g10_errstr(rc) ); break; - + #ifdef IS_G10 case aSym: /* encrypt the given file only with the symmetric cipher */ if( argc > 1 ) wrong_args(_("--symmetric [filename]")); @@ -613,15 +716,18 @@ main( int argc, char **argv ) log_error("%s: edit signature failed: %s\n", fname_print, g10_errstr(rc) ); break; + case aDeleteSecretKey: + if( argc != 1 ) + wrong_args(_("--delete-secret-key username")); case aDeleteKey: if( argc != 1 ) wrong_args(_("--delete-key username")); /* note: fname is the user id! */ - if( (rc = delete_key(fname)) ) + if( (rc = delete_key(fname, cmd==aDeleteSecretKey)) ) log_error("%s: delete key failed: %s\n", fname_print, g10_errstr(rc) ); break; - case aChangePass: /* Chnage the passphrase */ + case aChangePass: /* Change the passphrase */ if( argc > 1 ) /* no arg: use default, 1 arg use this one */ wrong_args(_("--change-passphrase [username]")); /* note: fname is the user id! */ @@ -629,6 +735,7 @@ main( int argc, char **argv ) log_error("%s: change passphrase failed: %s\n", fname_print, g10_errstr(rc) ); break; + #endif /* IS_G10 */ case aCheckKeys: case aKMode: /* list keyring */ @@ -672,11 +779,13 @@ main( int argc, char **argv ) wrong_args(_("-k[v][v][v][c] [keyring]") ); break; + #ifdef IS_G10 case aKeygen: /* generate a key (interactive) */ if( argc ) wrong_args(_("--gen-key")); generate_keypair(); break; + #endif case aImport: if( !argc ) { @@ -700,11 +809,107 @@ main( int argc, char **argv ) free_strlist(sl); break; + #ifdef IS_G10 case aGenRevoke: if( argc != 1 ) wrong_args("--gen-revoke user-id"); gen_revoke( *argv ); break; + #endif + + #ifdef IS_G10MAINT + case aDeArmor: + if( argc > 1 ) + wrong_args("--dearmor [file]"); + rc = dearmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("dearmoring failed: %s\n"), g10_errstr(rc)); + break; + + case aEnArmor: + if( argc > 1 ) + wrong_args("--enarmor [file]"); + rc = enarmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("enarmoring failed: %s\n"), g10_errstr(rc)); + break; + + + case aPrimegen: + if( argc == 1 ) { + mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1); + putchar('\n'); + } + else if( argc == 2 ) { + mpi_print( stdout, generate_elg_prime( atoi(argv[0]), + atoi(argv[1]), NULL,NULL ), 1); + putchar('\n'); + } + else if( argc == 3 ) { + MPI g = mpi_alloc(1); + mpi_print( stdout, generate_elg_prime( atoi(argv[0]), + atoi(argv[1]), g, NULL ), 1); + printf("\nGenerator: "); + mpi_print( stdout, g, 1 ); + putchar('\n'); + mpi_free(g); + } + else + usage(1); + break; + + case aGenRandom: + if( argc < 1 || argc > 2 ) + wrong_args("--gen-random level [hex]"); + { + int level = atoi(*argv); + for(;;) { + int c = get_random_byte(level); + if( argc == 1 ) { + printf("%02x", c ); + fflush(stdout); + } + else + putchar(c&0xff); + } + } + break; + + case aPrintMDs: + if( !argc ) + print_mds(NULL); + else { + for(; argc; argc--, argv++ ) + print_mds(*argv); + } + break; + + case aTest: do_test( argc? atoi(*argv): 1 ); break; + + case aListTrustDB: + if( !argc ) + list_trustdb(NULL); + else { + for( ; argc; argc--, argv++ ) + list_trustdb( *argv ); + } + break; + + case aListTrustPath: + if( argc != 2 ) + wrong_args("--list-trust-path [-- -]<maxdepth> <username>"); + list_trust_path( atoi(*argv), argv[1] ); + break; + + case aExtKeyList: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist( &sl, *argv ); + ext_key_list( sl ); + free_strlist(sl); + break; + #endif /* IS_G10MAINT */ + case aNOP: break; @@ -712,6 +917,7 @@ main( int argc, char **argv ) case aListPackets: opt.list_packets=1; default: + /* fixme: g10maint should to regular maintenace tasks here */ if( argc > 1 ) wrong_args(_("[filename]")); if( !(a = iobuf_open(fname)) ) @@ -751,4 +957,111 @@ g10_exit( int rc ) exit(rc ); } +#ifdef IS_G10MAINT +static void +print_hex( byte *p, size_t n ) +{ + int i; + + if( n == 20 ) { + for(i=0; i < n ; i++, i++, p += 2 ) { + if( i == 10 ) + putchar(' '); + printf(" %02X%02X", *p, p[1] ); + } + } + else { + for(i=0; i < n ; i++, p++ ) { + if( i && !(i%8) ) + putchar(' '); + printf(" %02X", *p ); + } + } +} + +static void +print_mds( const char *fname ) +{ + FILE *fp; + char buf[1024]; + size_t n; + MD_HANDLE md; + + if( !fname ) { + fp = stdin; + fname = "[stdin]"; + } + else + fp = fopen( fname, "rb" ); + if( !fp ) { + log_error("%s: %s\n", fname, strerror(errno) ); + return; + } + + md = md_open( DIGEST_ALGO_MD5, 0 ); + md_enable( md, DIGEST_ALGO_RMD160 ); + md_enable( md, DIGEST_ALGO_SHA1 ); + + while( (n=fread( buf, 1, DIM(buf), fp )) ) + md_write( md, buf, n ); + if( ferror(fp) ) + log_error("%s: %s\n", fname, strerror(errno) ); + else { + md_final(md); + printf( "%s: MD5 =", fname ); print_hex(md_read(md, DIGEST_ALGO_MD5), 16 ); + printf("\n%s: RMD160 =", fname ); print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 ); + printf("\n%s: SHA1 =", fname ); print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 ); + putchar('\n'); + } + + + md_close(md); + + if( fp != stdin ) + fclose(fp); +} + + + +static void +do_test(int times) +{ + MPI base[4]; + MPI exp[4]; + MPI t1 = mpi_alloc(50); + MPI t2 = mpi_alloc(50); + MPI t3 = mpi_alloc(50); + MPI tmp= mpi_alloc(50); + MPI m = mpi_alloc(50); + MPI res = mpi_alloc(50); + + mpi_fromstr( m, "0x10000000000000000000000000" ); + base[0] = mpi_alloc_set_ui( 3 ); + mpi_fromstr( base[0], "0x145984358945989898495ffdd13" ); + base[1] = mpi_alloc_set_ui( 5 ); + mpi_fromstr( base[1], "0x000effff9999000000001100001" ); + base[2] = mpi_alloc_set_ui( 2 ); + mpi_fromstr( base[2], "0x499eeeaaaaa0444444545466672" ); + base[3] = NULL; + exp[0] = mpi_alloc_set_ui( 30 ); + exp[1] = mpi_alloc_set_ui( 10 ); + mpi_fromstr( exp[1], "0x3457878888888888aabbbccccc1" ); + exp[2] = mpi_alloc_set_ui( 24 ); + exp[3] = NULL; + + mpi_powm( t1, base[0], exp[0], m ); + mpi_powm( t2, base[1], exp[1], m ); + mpi_powm( t3, base[2], exp[2], m ); + mpi_mulm( tmp, t1, t2, m ); + mpi_mulm( t1, tmp, t3, m ); + log_mpidump("X=", t1 ); + + + mpi_mulpowm( res, base, exp, m ); + log_mpidump("X=", res ); + + + m_check(NULL); +} +#endif /* IS_G10MAINT */ |