Just a Backup. We can now write out a basic signature which in turn
[gnupg.git] / sm / gpgsm.c
1 /* gpgsm.c - GnuPG for S/MIME 
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include <gcrypt.h>
31 #include "gpgsm.h"
32 #include "../assuan/assuan.h" /* malloc hooks */
33 #include "../kbx/keybox.h" /* malloc hooks */
34 #include "i18n.h"
35 #include "keydb.h"
36
37 enum cmd_and_opt_values {
38   aNull = 0,
39   oArmor          = 'a',
40   aDetachedSign = 'b',
41   aSym    = 'c',
42   aDecrypt        = 'd',
43   aEncr   = 'e',
44   oInteractive  = 'i',
45   oKOption        = 'k',
46   oDryRun         = 'n',
47   oOutput         = 'o',
48   oQuiet          = 'q',
49   oRecipient      = 'r',
50   aSign   = 's',
51   oTextmodeShort= 't',
52   oUser   = 'u',
53   oVerbose        = 'v',
54   oCompress       = 'z',
55   oNotation       = 'N',
56   oBatch          = 500,
57   aClearsign,
58   aStore,
59   aKeygen,
60   aSignEncr,
61   aSignKey,
62   aLSignKey,
63   aListPackets,
64   aEditKey,
65   aDeleteKey,
66   aImport,
67   aVerify,
68   aVerifyFiles,
69   aListKeys,
70   aListSigs,
71   aListSecretKeys,
72   aSendKeys,
73   aRecvKeys,
74   aExport,
75   aExportAll,
76   aCheckKeys,
77   aServer,                        
78
79   oEnableSpecialFilenames,
80
81
82   oTextmode,
83   oFingerprint,
84   oWithFingerprint,
85   oAnswerYes,
86   oAnswerNo,
87   oKeyring,
88   oSecretKeyring,
89   oDefaultKey,
90   oDefRecipient,
91   oDefRecipientSelf,
92   oNoDefRecipient,
93   oOptions,
94   oDebug,
95   oDebugAll,
96   oStatusFD,
97   oNoComment,
98   oNoVersion,
99   oEmitVersion,
100   oCompletesNeeded,
101   oMarginalsNeeded,
102   oMaxCertDepth,
103   oLoadExtension,
104   oRFC1991,
105   oOpenPGP,
106   oCipherAlgo,
107   oDigestAlgo,
108   oCompressAlgo,
109   oPasswdFD,
110   oCommandFD,
111   oNoVerbose,
112   oTrustDBName,
113   oNoSecmemWarn,
114   oNoArmor,
115   oNoDefKeyring,
116   oNoGreeting,
117   oNoTTY,
118   oNoOptions,
119   oNoBatch,
120   oHomedir,
121   oWithColons,
122   oWithKeyData,
123   oSkipVerify,
124   oCompressKeys,
125   oCompressSigs,
126   oAlwaysTrust,
127   oRunAsShmCP,
128   oSetFilename,
129   oSetPolicyURL,
130   oUseEmbeddedFilename,
131   oComment,
132   oDefaultComment,
133   oThrowKeyid,
134   oForceV3Sigs,
135   oForceMDC,
136   oS2KMode,
137   oS2KDigest,
138   oS2KCipher,
139   oCharset,
140   oNotDashEscaped,
141   oEscapeFrom,
142   oLockOnce,
143   oLockMultiple,
144   oLockNever,
145   oKeyServer,
146   oEncryptTo,
147   oNoEncryptTo,
148   oLoggerFD,
149   oUtf8Strings,
150   oNoUtf8Strings,
151   oDisableCipherAlgo,
152   oDisablePubkeyAlgo,
153   oAllowNonSelfsignedUID,
154   oAllowFreeformUID,
155   oNoLiteral,
156   oSetFilesize,
157   oHonorHttpProxy,
158   oFastListMode,
159   oListOnly,
160   oIgnoreTimeConflict,
161   oNoRandomSeedFile,
162   oNoAutoKeyRetrieve,
163   oUseAgent,
164   oMergeOnly,
165   oTryAllSecrets,
166   oTrustedKey,
167   oEmuMDEncodeBug,
168   aTest
169  };
170
171
172 static ARGPARSE_OPTS opts[] = {
173
174     { 300, NULL, 0, N_("@Commands:\n ") },
175
176     { aSign, "sign",      256, N_("|[file]|make a signature")},
177     { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
178     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
179     { aEncr, "encrypt",   256, N_("encrypt data")},
180     { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
181     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
182     { aVerify, "verify"   , 256, N_("verify a signature")},
183     { aVerifyFiles, "verify-files" , 256, "@" },
184     { aListKeys, "list-keys", 256, N_("list keys")},
185     { aListKeys, "list-public-keys", 256, "@" },
186     { aListSigs, "list-sigs", 256, N_("list keys and signatures")},
187     { aCheckKeys, "check-sigs",256, N_("check key signatures")},
188     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
189     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
190     { aKeygen,     "gen-key",  256, N_("generate a new key pair")},
191     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
192     { aExport, "export"           , 256, N_("export keys") },
193     { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
194     { aRecvKeys, "recv-keys"     , 256, N_("import keys from a key server") },
195     { aImport, "import",      256     , N_("import/merge keys")},
196     { aServer, "server",      256, N_("run in server mode")},
197     
198
199     { 301, NULL, 0, N_("@\nOptions:\n ") },
200
201     { oArmor, "armor",     0, N_("create ascii armored output")},
202     { oArmor, "armour",     0, "@" },
203     { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
204     { oRecipient, "remote-user", 2, "@"},  /* old option name */
205     { oDefRecipient, "default-recipient" ,2,
206                                   N_("|NAME|use NAME as default recipient")},
207     { oDefRecipientSelf, "default-recipient-self" ,0,
208                                 N_("use the default key as default recipient")},
209     { oNoDefRecipient, "no-default-recipient", 0, "@" },
210     { oEncryptTo, "encrypt-to", 2, "@" },
211     { oNoEncryptTo, "no-encrypt-to", 0, "@" },
212     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
213     { oCompress, NULL,        1, N_("|N|set compress level N (0 disables)") },
214     { oTextmodeShort, NULL,   0, "@"},
215     { oTextmode, "textmode",  0, N_("use canonical text mode")},
216     { oOutput, "output",    2, N_("use as output file")},
217     { oVerbose, "verbose",   0, N_("verbose") },
218     { oQuiet,   "quiet",   0, N_("be somewhat more quiet") },
219     { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
220     { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
221     { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
222     { oDryRun, "dry-run",   0, N_("do not make any changes") },
223   /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
224     { oUseAgent, "use-agent",0, N_("use the gpg-agent")},
225     { oBatch, "batch",     0, N_("batch mode: never ask")},
226     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
227     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
228     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
229     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
230     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
231     { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
232     { oCharset, "charset"   , 2, N_("|NAME|set terminal charset to NAME") },
233     { oOptions, "options"   , 2, N_("read options from file")},
234
235     { oDebug, "debug"     ,4|16, "@"},
236     { oDebugAll, "debug-all" ,0, "@"},
237     { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
238     { oNoComment, "no-comment", 0,   "@"},
239     { oCompletesNeeded, "completes-needed", 1, "@"},
240     { oMarginalsNeeded, "marginals-needed", 1, "@"},
241     { oMaxCertDepth,    "max-cert-depth", 1, "@" },
242     { oTrustedKey, "trusted-key", 2, N_("|KEYID|ulimately trust this key")},
243     { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
244     { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
245     { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")},
246     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
247     { oS2KDigest, "s2k-digest-algo",2,
248                 N_("|NAME|use message digest algorithm NAME for passphrases")},
249     { oS2KCipher, "s2k-cipher-algo",2,
250                 N_("|NAME|use cipher algorithm NAME for passphrases")},
251     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
252     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
253     { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
254     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
255     { oNotation,   "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
256
257     { 302, NULL, 0, N_(
258   "@\n(See the man page for a complete listing of all commands and options)\n"
259                       )},
260
261     { 303, NULL, 0, N_("@\nExamples:\n\n"
262     " -se -r Bob [file]          sign and encrypt for user Bob\n"
263     " --clearsign [file]         make a clear text signature\n"
264     " --detach-sign [file]       make a detached signature\n"
265     " --list-keys [names]        show keys\n"
266     " --fingerprint [names]      show fingerprints\n"  ) },
267
268   /* hidden options */
269     { oNoVerbose, "no-verbose", 0, "@"},
270
271     { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
272
273
274     { oTrustDBName, "trustdb-name", 2, "@" },
275     { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
276     { oNoArmor, "no-armor",   0, "@"},
277     { oNoArmor, "no-armour",   0, "@"},
278     { oNoDefKeyring, "no-default-keyring", 0, "@" },
279     { oNoGreeting, "no-greeting", 0, "@" },
280     { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
281     { oHomedir, "homedir", 2, "@" },   /* defaults to "~/.gnupg" */
282     { oNoBatch, "no-batch", 0, "@" },
283     { oWithColons, "with-colons", 0, "@"},
284     { oWithKeyData,"with-key-data", 0, "@"},
285     { aListKeys, "list-key", 0, "@" }, /* alias */
286     { aListSigs, "list-sig", 0, "@" }, /* alias */
287     { aCheckKeys, "check-sig",0, "@" }, /* alias */
288     { oSkipVerify, "skip-verify",0, "@" },
289     { oCompressKeys, "compress-keys",0, "@"},
290     { oCompressSigs, "compress-sigs",0, "@"},
291     { oAlwaysTrust, "always-trust", 0, "@"},
292     { oNoVersion, "no-version", 0, "@"},
293     { oLockOnce, "lock-once", 0, "@" },
294     { oLockMultiple, "lock-multiple", 0, "@" },
295     { oLockNever, "lock-never", 0, "@" },
296     { oLoggerFD, "logger-fd",1, "@" },
297     { oWithFingerprint, "with-fingerprint", 0, "@" },
298     { oDisableCipherAlgo,  "disable-cipher-algo", 2, "@" },
299     { oDisablePubkeyAlgo,  "disable-pubkey-algo", 2, "@" },
300     { oHonorHttpProxy,"honor-http-proxy", 0, "@" },
301     { oListOnly, "list-only", 0, "@"},
302     { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
303     { oNoRandomSeedFile,  "no-random-seed-file", 0, "@" },
304 {0} };
305
306
307
308 int gpgsm_errors_seen = 0;
309
310 /* It is possible that we are currentlu running under setuid permissions */
311 static int maybe_setuid = 1;
312
313 /* Option --enable-special-filenames */
314 static int allow_special_filenames;
315
316
317 static char *build_list (const char *text,
318                          const char *(*mapf)(int), int (*chkf)(int));
319 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
320                      enum cmd_and_opt_values new_cmd );
321
322 static int check_special_filename (const char *fname);
323 static int open_read (const char *filename);
324
325
326 static int
327 our_pk_test_algo (int algo)
328 {
329   return 1;
330 }
331
332 static int
333 our_cipher_test_algo (int algo)
334 {
335   return 1;
336 }
337
338 static int
339 our_md_test_algo (int algo)
340 {
341   return 1;
342 }
343
344 static const char *
345 my_strusage( int level )
346 {
347   static char *digests, *pubkeys, *ciphers;
348   const char *p;
349
350   switch (level)
351     {
352     case 11: p = "gpgsm (GnuPG)";
353       break;
354     case 13: p = VERSION; break;
355     case 17: p = PRINTABLE_OS_NAME; break;
356     case 19: p = _("Please report bugs to <bug-gnupg@gnu.org>.\n");
357       break;
358     case 1:
359     case 40: p = _("Usage: gpgsm [options] [files] (-h for help)");
360       break;
361     case 41:
362       p = _("Syntax: gpgsm [options] [files]\n"
363             "sign, check, encrypt or decrypt using the S/MIME protocol\n"
364             "default operation depends on the input data\n");
365       break;
366
367     case 31: p = "\nHome: "; break;
368     case 32: p = opt.homedir; break;
369     case 33: p = _("\nSupported algorithms:\n"); break;
370     case 34:
371       if (!ciphers)
372         ciphers = build_list ("Cipher: ", gcry_cipher_algo_name,
373                               our_cipher_test_algo );
374       p = ciphers;
375       break;
376     case 35:
377       if (!pubkeys)
378         pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name,
379                               our_pk_test_algo );
380       p = pubkeys;
381       break;
382     case 36:
383       if (!digests)
384         digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
385       p = digests;
386       break;
387       
388     default: p = NULL; break;
389     }
390   return p;
391 }
392
393
394 static char *
395 build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
396 {
397   int i;
398   size_t n=strlen(text)+2;
399   char *list, *p;
400   
401   if (maybe_setuid) {
402     gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
403   }
404
405   for (i=1; i < 110; i++ )
406     if (!chkf(i))
407       n += strlen(mapf(i)) + 2;
408   list = xmalloc (21 + n);
409   *list = 0;
410   for (p=NULL, i=1; i < 110; i++)
411     {
412       if (!chkf(i))
413         {
414           if( !p )
415             p = stpcpy (list, text );
416           else
417             p = stpcpy (p, ", ");
418           p = stpcpy (p, mapf(i) );
419         }
420     }
421   if (p)
422     p = stpcpy(p, "\n" );
423   return list;
424 }
425
426
427 static void
428 i18n_init(void)
429 {
430 #ifdef USE_SIMPLE_GETTEXT
431   set_gettext_file (PACKAGE);
432 #else
433 # ifdef ENABLE_NLS
434 #  ifdef HAVE_LC_MESSAGES
435   setlocale (LC_TIME, "");
436   setlocale (LC_MESSAGES, "");
437 #  else
438   setlocale (LC_ALL, "" );
439 #  endif
440   bindtextdomain (PACKAGE, GNUPG_LOCALEDIR);
441   textdomain (PACKAGE);
442 # endif
443 #endif
444 }
445
446
447 static void
448 wrong_args (const char *text)
449 {
450   fputs (_("usage: gpgsm [options] "), stderr);
451   fputs (text, stderr);
452   putc ('\n', stderr);
453   gpgsm_exit (2);
454 }
455
456
457 static void
458 set_debug(void)
459 {
460   if (opt.debug & DBG_MPI_VALUE)
461     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
462   if (opt.debug & DBG_CRYPTO_VALUE )
463     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
464 }
465
466
467 static void
468 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
469 {
470   enum cmd_and_opt_values cmd = *ret_cmd;
471
472   if (!cmd || cmd == new_cmd)
473     cmd = new_cmd;
474   else if ( cmd == aSign && new_cmd == aEncr )
475     cmd = aSignEncr;
476   else if ( cmd == aEncr && new_cmd == aSign )
477     cmd = aSignEncr;
478   else if ( (cmd == aSign && new_cmd == aClearsign)
479             || (cmd == aClearsign && new_cmd == aSign) )
480     cmd = aClearsign;
481   else 
482     {
483       log_error(_("conflicting commands\n"));
484       gpgsm_exit(2);
485     }
486
487   *ret_cmd = cmd;
488 }
489
490
491 int
492 main ( int argc, char **argv)
493 {
494   ARGPARSE_ARGS pargs;
495   int orig_argc;
496   char **orig_argv;
497   const char *fname;
498   /*  char *username;*/
499   int may_coredump;
500   STRLIST sl, remusr= NULL, locusr=NULL;
501   STRLIST nrings=NULL;
502   int detached_sig = 0;
503   FILE *configfp = NULL;
504   char *configname = NULL;
505   unsigned configlineno;
506   int parse_debug = 0;
507   int default_config =1;
508   int default_keyring = 1;
509   int greeting = 0;
510   int nogreeting = 0;
511   int use_random_seed = 1;
512   int with_fpr = 0;
513   char *def_cipher_string = NULL;
514   char *def_digest_string = NULL;
515   enum cmd_and_opt_values cmd = 0;
516   struct server_control_s ctrl;
517
518   /* FIXME: trap_unaligned ();*/
519   set_strusage (my_strusage);
520   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
521   /* Please note that we may running SUID(ROOT), so be very CAREFUL
522      when adding any stuff between here and the call to secmem_init()
523      somewhere after the option parsing */
524   /* FIXME: log_set_name ("gpgsm");*/
525   /* check that the libraries are suitable.  Do it here because the
526      option parse may need services of the library */
527   if (!gcry_check_version ( "1.1.4" ) )
528     {
529       log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
530                  VERSION, gcry_check_version (NULL) );
531     }
532
533   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
534
535   may_coredump = 0/* FIXME: disable_core_dumps()*/;
536   
537   /* FIXME: init_signals();*/
538   
539   create_dotlock (NULL); /* register locking cleanup */
540   i18n_init();
541
542 #ifdef __MINGW32__
543   opt.homedir = read_w32_registry_string ( NULL,
544                                            "Software\\GNU\\GnuPG", "HomeDir" );
545 #else
546   opt.homedir = getenv ("GNUPGHOME");
547 #endif
548   if (!opt.homedir || !*opt.homedir ) 
549     {
550       opt.homedir = "~/.gnupg-test" /*fixme: GNUPG_HOMEDIR*/;
551     }
552
553   /* first check whether we have a config file on the commandline */
554   orig_argc = argc;
555   orig_argv = argv;
556   pargs.argc = &argc;
557   pargs.argv = &argv;
558   pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
559   while (arg_parse( &pargs, opts))
560     {
561       if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
562         parse_debug++;
563       else if (pargs.r_opt == oOptions)
564         { /* yes there is one, so we do not try the default one but
565              read the config file when it is encountered at the
566              commandline */
567           default_config = 0;
568         }
569       else if (pargs.r_opt == oNoOptions)
570         default_config = 0; /* --no-options */
571       else if (pargs.r_opt == oHomedir)
572         opt.homedir = pargs.r.ret_str;
573     }
574   
575   
576   /* initialize the secure memory. */
577   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
578   maybe_setuid = 0;
579
580   /* 
581      Now we are now working under our real uid 
582   */
583
584   ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
585   assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
586   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
587
588   /* Setup a default control structure */
589   memset (&ctrl, 0, sizeof ctrl);
590   ctrl.no_server = 1;
591   ctrl.status_fd = -1; /* not status output */
592
593   /* set the default option file */
594   if (default_config )
595     configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
596   
597   argc        = orig_argc;
598   argv        = orig_argv;
599   pargs.argc  = &argc;
600   pargs.argv  = &argv;
601   pargs.flags =  1;  /* do not remove the args */
602
603  next_pass:
604   if (configname) {
605     configlineno = 0;
606     configfp = fopen (configname, "r");
607     if (!configfp)
608       {
609         if (default_config)
610           {
611             if (parse_debug)
612               log_info (_("NOTE: no default option file `%s'\n"), configname);
613           }
614         else 
615           {
616             log_error (_("option file `%s': %s\n"), configname, strerror(errno));
617             gpgsm_exit(2);
618           }
619         xfree(configname);
620         configname = NULL;
621       }
622     if (parse_debug && configname)
623       log_info (_("reading options from `%s'\n"), configname);
624     default_config = 0;
625   }
626
627   while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
628     {
629       switch (pargs.r_opt)
630         {
631         case aServer: 
632           opt.batch = 1;
633           set_cmd (&cmd, aServer);
634           break;
635
636         case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
637         case aImport: set_cmd (&cmd, aImport); break;
638         case aSendKeys: set_cmd (&cmd, aSendKeys); break;
639         case aRecvKeys: set_cmd (&cmd, aRecvKeys); break;
640         case aExport: set_cmd (&cmd, aExport); break;
641         case aListKeys: set_cmd (&cmd, aListKeys); break;
642
643         case aDeleteKey:
644           set_cmd (&cmd, aDeleteKey);
645           greeting=1;
646           break;
647
648         case aDetachedSign:
649           detached_sig = 1;
650           set_cmd (&cmd, aSign ); 
651           break;
652           
653         case aSym: set_cmd (&cmd, aSym); break;
654         case aDecrypt: set_cmd (&cmd, aDecrypt); break;
655         case aEncr: set_cmd (&cmd, aEncr); break;
656         case aSign: set_cmd (&cmd, aSign );  break;
657         case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break;
658         case aClearsign: set_cmd (&cmd, aClearsign); break;
659         case aVerify: set_cmd (&cmd, aVerify); break;
660
661         case oArmor: opt.armor = 1; opt.no_armor=0; break;
662         case oNoArmor: opt.no_armor=1; opt.armor=0; break;
663         case oOutput: opt.outfile = pargs.r.ret_str; break;
664         case oQuiet: opt.quiet = 1; break;
665         case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
666         case oDryRun: opt.dry_run = 1; break;
667
668         case oVerbose:
669           opt.verbose++;
670           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
671           break;
672         case oNoVerbose:
673           opt.verbose = 0;
674           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
675           break;
676           
677         case oBatch: 
678           opt.batch = 1;
679           greeting = 0;
680           break;
681         case oNoBatch: opt.batch = 0; break;
682           
683         case oAnswerYes: opt.answer_yes = 1; break;
684         case oAnswerNo: opt.answer_no = 1; break;
685
686         case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
687
688         case oDebug: opt.debug |= pargs.r.ret_ulong; break;
689         case oDebugAll: opt.debug = ~0; break;
690
691         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
692         case oLoggerFD: /* fixme: log_set_logfile (NULL, pargs.r.ret_int );*/ break;
693         case oWithFingerprint:
694           with_fpr=1; /*fall thru*/
695         case oFingerprint:
696           opt.fingerprint++;
697           break;
698
699         case oOptions:
700           /* config files may not be nested (silently ignore them) */
701           if (!configfp)
702             {
703               xfree(configname);
704               configname = xstrdup (pargs.r.ret_str);
705               goto next_pass;
706             }
707           break;
708         case oNoOptions: break; /* no-options */
709         case oHomedir: opt.homedir = pargs.r.ret_str; break;
710           
711         case oNoDefKeyring: default_keyring = 0; break;
712         case oNoGreeting: nogreeting = 1; break;
713
714         case oDefaultKey:
715           /* fixme:opt.def_secret_key = pargs.r.ret_str;*/
716           break;
717         case oDefRecipient:
718           if (*pargs.r.ret_str)
719             opt.def_recipient = xstrdup (pargs.r.ret_str);
720           break;
721         case oDefRecipientSelf:
722           xfree (opt.def_recipient);
723           opt.def_recipient = NULL;
724           opt.def_recipient_self = 1;
725           break;
726         case oNoDefRecipient:
727           xfree (opt.def_recipient);
728           opt.def_recipient = NULL;
729           opt.def_recipient_self = 0;
730           break;
731
732         case oWithKeyData: opt.with_key_data=1; /* fall thru */
733         case oWithColons: ctrl.with_colons = 1; break;
734
735         case oSkipVerify: opt.skip_verify=1; break;
736
737         case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break;
738         case oEncryptTo: /* store the recipient in the second list */
739           sl = add_to_strlist (&remusr, pargs.r.ret_str);
740           sl->flags = 1;
741           break;
742
743         case oRecipient: /* store the recipient */
744           add_to_strlist ( &remusr, pargs.r.ret_str);
745           break;
746
747         case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
748         case oTextmode: /*fixme:opt.textmode=1;*/  break;
749
750         case oUser: /* store the local users */
751           add_to_strlist ( &locusr, pargs.r.ret_str);
752           break;
753
754         case oNoSecmemWarn:
755           gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); 
756           break;
757
758         case oDisableCipherAlgo: 
759           {
760             int algo = gcry_cipher_map_name (pargs.r.ret_str);
761             gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
762           }
763           break;
764         case oDisablePubkeyAlgo: 
765           {
766             int algo = gcry_pk_map_name (pargs.r.ret_str);
767             gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
768           }
769           break;
770
771         case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
772         case oNoRandomSeedFile: use_random_seed = 0; break;
773
774         case oEnableSpecialFilenames: allow_special_filenames =1; break;
775           
776         default: 
777           pargs.err = configfp? 1:2; 
778           break;
779         }
780     }
781
782   if (configfp)
783     {
784       fclose (configfp);
785       configfp = NULL;
786       xfree (configname);
787       configname = NULL;
788       goto next_pass;
789     }
790   
791   xfree (configname);
792   configname = NULL;
793
794   if (log_get_errorcount(0))
795     gpgsm_exit(2);
796   
797   if (nogreeting)
798     greeting = 0;
799   
800   if (greeting)
801     {
802       fprintf(stderr, "%s %s; %s\n",
803               strusage(11), strusage(13), strusage(14) );
804       fprintf(stderr, "%s\n", strusage(15) );
805     }
806 #  ifdef IS_DEVELOPMENT_VERSION
807   if (!opt.batch)
808     {
809       log_info ("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
810       log_info ("It is only intended for test purposes and should NOT be\n");
811       log_info ("used in a production environment or with production keys!\n");
812     }
813 #  endif
814
815   if (may_coredump && !opt.quiet)
816     log_info (_("WARNING: program may create a core file!\n"));
817   
818 /*FIXME    if (opt.batch) */
819 /*      tty_batchmode (1); */
820
821   gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
822
823   set_debug ();
824   /* FIXME: should set filenames of libgcrypt explicitly
825    * gpg_opt_homedir = opt.homedir; */
826
827   /* must do this after dropping setuid, because string_to...
828    * may try to load an module */
829   if (def_cipher_string) 
830     {
831       opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string);
832       xfree (def_cipher_string);
833       def_cipher_string = NULL;
834       if ( our_cipher_test_algo (opt.def_cipher_algo) )
835         log_error (_("selected cipher algorithm is invalid\n"));
836     }
837   if (def_digest_string)
838     {
839       opt.def_digest_algo = gcry_md_map_name (def_digest_string);
840       xfree (def_digest_string);
841       def_digest_string = NULL;
842       if (our_md_test_algo(opt.def_digest_algo) )
843         log_error (_("selected digest algorithm is invalid\n"));
844     }
845
846   if (log_get_errorcount(0))
847     gpgsm_exit(2);
848   
849   /* set the random seed file */
850   if (use_random_seed) {
851     char *p = make_filename (opt.homedir, "random_seed", NULL);
852 #if 0
853 #warning set_random_seed_file not yet available in Libgcrypt
854     set_random_seed_file(p);
855 #endif
856     xfree(p);
857   }
858
859   if (!cmd && opt.fingerprint && !with_fpr)
860     set_cmd (&cmd, aListKeys);
861   
862   if (!nrings && default_keyring)  /* add default keybox */
863     keydb_add_resource ("pubcerts.kbx", 0, 0);
864   for (sl = nrings; sl; sl = sl->next)
865     keydb_add_resource (sl->d, 0, 0);
866   FREE_STRLIST(nrings);
867   
868   fname = argc? *argv : NULL;
869   
870   switch (cmd)
871     {
872     case aServer:
873       gpgsm_server ();
874       break;
875
876     case aEncr: /* encrypt the given file */
877 #if 0
878       if (argc > 1)
879         wrong_args(_("--encrypt [filename]"));
880       if ((rc = encode_crypt(fname,remusr)) )
881         log_error ("%s: encryption failed: %s\n",
882                    print_fname_stdin(fname), gpg_errstr(rc) );
883       break;
884 #endif
885
886     case aSign: /* sign the given file */
887       /* FIXME: we can only do detached sigs for now and we don't
888          handle --output yet. We should also allow to concatenate
889          multiple files for signins because that is what gpg does.*/
890       if (!argc)
891         gpgsm_sign (&ctrl, 0, 1, stdout); /* create from stdin */
892       else if (argc == 1)
893         gpgsm_sign (&ctrl, open_read (*argv), 1, stdout); /* from file */
894       else
895         wrong_args (_("--sign [datafile]"));
896       break;
897 #if 0
898       sl = NULL;
899       if (detached_sig)
900         { /* sign all files */
901           for (; argc; argc--, argv++ )
902             add_to_strlist ( &sl, *argv );
903         }
904       else
905         {
906           if (argc > 1 )
907             wrong_args (_("--sign [filename]"));
908           if (argc)
909             {
910               sl = xcalloc (1, sizeof *sl + strlen(fname));
911               strcpy(sl->d, fname);
912             }
913         }
914       if ( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
915         log_error ("signing failed: %s\n", gpg_errstr(rc) );
916       free_strlist(sl);
917 #endif
918       break;
919         
920     case aSignEncr: /* sign and encrypt the given file */
921 #if 0
922       if (argc > 1)
923         wrong_args(_("--sign --encrypt [filename]"));
924       if (argc)
925         {
926           sl = xcalloc( 1, sizeof *sl + strlen(fname));
927           strcpy(sl->d, fname);
928         }
929       else
930         sl = NULL;
931
932       if ( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
933         log_error ("%s: sign+encrypt failed: %s\n",
934                    print_fname_stdin(fname), gpg_errstr(rc) );
935       free_strlist(sl);
936 #endif
937       break;
938
939     case aClearsign: /* make a clearsig */
940 #if 0
941       if (argc > 1)
942         wrong_args (_("--clearsign [filename]"));
943       if ( (rc = clearsign_file(fname, locusr, NULL)) )
944         log_error ("%s: clearsign failed: %s\n",
945                    print_fname_stdin(fname), gpg_errstr(rc) );
946 #endif
947       break;
948
949     case aVerify:
950       if (!argc)
951         gpgsm_verify (&ctrl, 0, -1); /* normal signature from stdin */
952       else if (argc == 1)
953         gpgsm_verify (&ctrl, open_read (*argv), -1); /* normal signature */
954       else if (argc == 2) /* detached signature (sig, detached) */
955         gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1])); 
956       else
957         wrong_args (_("--verify [signature [detached_data]]"));
958       break;
959
960     case aVerifyFiles:
961 /*        if ((rc = verify_files( argc, argv ))) */
962 /*          log_error ("verify files failed: %s\n", gpg_errstr(rc) ); */
963       break;
964
965     case aDecrypt:
966 /*        if (argc > 1) */
967 /*          wrong_args (_("--decrypt [filename]")); */
968 /*        if ((rc = decrypt_message( fname ) )) */
969 /*          log_error ("decrypt_message failed: %s\n", gpg_errstr(rc) ); */
970       break;
971
972     case aDeleteKey:
973       if (argc != 1)
974         wrong_args(_("--delete-key user-id"));
975 /*        username = make_username (fname); */
976 /*        if( (rc = delete_key(username)) ) */
977 /*          log_error ("%s: delete key failed: %s\n", username, gpg_errstr(rc) ); */
978 /*        xfree(username); */
979       break;
980
981     case aListKeys:
982       for (sl=NULL; argc; argc--, argv++)
983         add_to_strlist (&sl, *argv);
984       gpgsm_list_keys (&ctrl, sl, stdout);
985       free_strlist(sl);
986       break;
987
988     case aListSecretKeys:
989       sl = NULL;
990       for( ; argc; argc--, argv++ )
991         add_to_strlist (&sl, *argv);
992 /*        secret_key_list ( sl ); */
993       free_strlist(sl);
994       break;
995
996     case aKeygen: /* generate a key */
997 /*        if (opt.batch) */
998 /*          { */
999 /*            if (argc > 1) */
1000 /*              wrong_args("--gen-key [parameterfile]"); */
1001 /*            generate_keypair (argc? *argv : NULL); */
1002 /*      } */
1003 /*        else */
1004 /*          { */
1005 /*            if (argc) */
1006 /*              wrong_args ("--gen-key"); */
1007 /*            generate_keypair(NULL); */
1008 /*      } */
1009       break;
1010
1011     case aImport:
1012       if (!argc)
1013         gpgsm_import (&ctrl, 0);
1014       else
1015         {
1016           for (; argc; argc--, argv++)
1017             gpgsm_import (&ctrl, open_read (*argv));
1018         }
1019       break;
1020       
1021     case aExport:
1022     case aSendKeys:
1023     case aRecvKeys:
1024 /*        sl = NULL; */
1025 /*        for ( ; argc; argc--, argv++ ) */
1026 /*          add_to_strlist (&sl, *argv); */
1027 /*        if ( cmd == aSendKeys ) */
1028 /*          ldap_export (sl); */
1029 /*        else if (cmd == aRecvKeys ) */
1030 /*          ldap_import (sl); */
1031 /*        else */
1032 /*          export_pubkeys (sl, (cmd == aExport)); */
1033 /*        free_strlist (sl); */
1034       break;
1035
1036       default:
1037         if (argc > 1)
1038           wrong_args(_("[filename]"));
1039         /* Issue some output for the unix newbie */
1040         if ( !fname && !opt.outfile && isatty( fileno(stdin) )
1041             && isatty (fileno(stdout) ) && isatty (fileno(stderr) ) )
1042           log_info (_("Go ahead and type your message ...\n"));
1043         
1044 #if 0
1045         if ( !(a = iobuf_open(fname)) )
1046           log_error (_("can't open `%s'\n"), print_fname_stdin(fname));
1047         else
1048           {
1049             if (!opt.no_armor) 
1050               iobuf_close(a);
1051         }
1052 #endif
1053         break;
1054     }
1055   
1056   /* cleanup */
1057   FREE_STRLIST(remusr);
1058   FREE_STRLIST(locusr);
1059   gpgsm_exit(0);
1060   return 8; /*NEVER REACHED*/
1061 }
1062
1063
1064 void
1065 gpgsm_exit (int rc)
1066 {
1067   #if 0
1068 #warning no update_random_seed_file
1069   update_random_seed_file();
1070   #endif
1071 #if 0
1072   /* at this time a bit annoying */
1073   if (opt.debug & DBG_MEMSTAT_VALUE)
1074     {
1075       gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
1076       gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
1077     }
1078   if (opt.debug)
1079     gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
1080 #endif
1081   gcry_control (GCRYCTL_TERM_SECMEM );
1082   rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
1083   exit (rc);
1084 }
1085
1086
1087 /* Check whether the filename has the form "-&nnnn", where n is a
1088    non-zero number.  Returns this number or -1 if it is not the case.  */
1089 static int
1090 check_special_filename (const char *fname)
1091 {
1092   if (allow_special_filenames
1093       && fname && *fname == '-' && fname[1] == '&' ) {
1094     int i;
1095     
1096     fname += 2;
1097     for (i=0; isdigit (fname[i]); i++ )
1098       ;
1099     if ( !fname[i] ) 
1100       return atoi (fname);
1101   }
1102   return -1;
1103 }
1104
1105
1106
1107 /* Open the FILENAME for read and return the fieldescriptor.  Stop
1108    with an error message in case of problems.  "-" denotes stdin and
1109    if special filenames are allowed the given fd is opend instead. */
1110 static int 
1111 open_read (const char *filename)
1112 {
1113   int fd;
1114
1115   if (filename[0] == '-' && !filename[1])
1116     return 0; /* stdin */
1117   fd = check_special_filename (filename);
1118   if (fd != -1)
1119     return fd;
1120   fd = open (filename, O_RDONLY);
1121   if (fd == -1)
1122     {
1123       log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
1124       gpgsm_exit (2);
1125     }
1126   return fd;
1127 }