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