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