s/AES/AES128/ in diagnostics and --list-config
[gnupg.git] / tools / symcryptrun.c
1 /* symcryptrun.c - Tool to call simple symmetric encryption tools.
2  *      Copyright (C) 2005, 2007 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 /* Sometimes simple encryption tools are already in use for a long
22    time and there is a desire to integrate them into the GnuPG
23    framework.  The protocols and encryption methods might be
24    non-standard or not even properly documented, so that a
25    full-fledged encryption tool with an interface like gpg is not
26    doable.  This simple wrapper program provides a solution: It
27    operates by calling the encryption/decryption module and providing
28    the passphrase for a key (or even the key directly) using the
29    standard pinentry mechanism through gpg-agent.  */
30
31 /* This program is invoked in the following way:
32
33    symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE \
34      [--decrypt | --encrypt]
35
36    For encryption, the plain text must be provided on STDIN, and the
37    ciphertext will be output to STDOUT.  For decryption vice versa.
38
39    CLASS can currently only be "confucius".
40
41    PROGRAM must be the path to the crypto engine.
42
43    KEYFILE must contain the secret key, which may be protected by a
44    passphrase.  The passphrase is retrieved via the pinentry program.
45
46
47    The GPG Agent _must_ be running before starting symcryptrun.
48
49    The possible exit status codes:
50
51    0    Success
52    1    Some error occured
53    2    No valid passphrase was provided
54    3    The operation was canceled by the user
55
56    Other classes may be added in the future.  */
57
58 #define SYMC_BAD_PASSPHRASE     2
59 #define SYMC_CANCELED           3
60
61 \f
62 #include <config.h>
63
64 #include <unistd.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <errno.h>
69 #include <assert.h>
70 #include <signal.h>
71 #include <sys/stat.h>
72 #include <sys/types.h>
73 #include <sys/wait.h>
74 #ifdef HAVE_PTY_H
75 #include <pty.h>
76 #endif
77 #include <ctype.h>
78 #ifdef HAVE_LOCALE_H
79 #include <locale.h>
80 #endif
81 #ifdef HAVE_LANGINFO_CODESET
82 #include <langinfo.h>
83 #endif
84 #include <gpg-error.h>
85
86 #define JNLIB_NEED_LOG_LOGV
87 #include "i18n.h"
88 #include "../common/util.h"
89 #include "mkdtemp.h"
90
91 /* FIXME: Bah.  For spwq_secure_free.  */
92 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
93 #include "../common/simple-pwquery.h"
94
95 \f
96 /* From simple-gettext.c.  */
97
98 /* We assume to have `unsigned long int' value with at least 32 bits.  */
99 #define HASHWORDBITS 32
100
101 /* The so called `hashpjw' function by P.J. Weinberger
102    [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
103    1986, 1987 Bell Telephone Laboratories, Inc.]  */
104
105 static __inline__ ulong
106 hash_string( const char *str_param )
107 {
108     unsigned long int hval, g;
109     const char *str = str_param;
110
111     hval = 0;
112     while (*str != '\0')
113     {
114         hval <<= 4;
115         hval += (unsigned long int) *str++;
116         g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
117         if (g != 0)
118         {
119           hval ^= g >> (HASHWORDBITS - 8);
120           hval ^= g;
121         }
122     }
123     return hval;
124 }
125
126 \f
127 /* Constants to identify the commands and options. */
128 enum cmd_and_opt_values
129   {
130     aNull = 0,
131     oQuiet      = 'q',
132     oVerbose    = 'v',
133
134     oNoVerbose  = 500,
135     oOptions,
136     oNoOptions,
137     oLogFile,
138     oHomedir,
139     oClass,
140     oProgram,
141     oKeyfile,
142     oDecrypt,
143     oEncrypt,
144     oInput
145   };
146
147
148 /* The list of commands and options.  */
149 static ARGPARSE_OPTS opts[] =
150   {
151     { 301, NULL, 0, N_("@\nCommands:\n ") },
152
153     { oDecrypt, "decrypt", 0, N_("decryption modus") },
154     { oEncrypt, "encrypt", 0, N_("encryption modus") },
155     
156     { 302, NULL, 0, N_("@\nOptions:\n ") },
157     
158     { oClass, "class", 2, N_("tool class (confucius)") },
159     { oProgram, "program", 2, N_("program filename") },
160
161     { oKeyfile, "keyfile", 2, N_("secret key file (required)") },
162     { oInput, "inputfile", 2, N_("input file name (default stdin)") },
163     { oVerbose, "verbose",  0, N_("verbose") },
164     { oQuiet, "quiet",      0, N_("quiet") },
165     { oLogFile, "log-file", 2, N_("use a log file for the server") },
166     { oOptions,  "options"  , 2, N_("|FILE|read options from FILE") },
167
168     /* Hidden options.  */
169     { oNoVerbose, "no-verbose",  0, "@" },
170     { oHomedir, "homedir", 2, "@" },   
171     { oNoOptions, "no-options", 0, "@" },/* shortcut for --options /dev/null */
172
173     {0}
174   };
175
176
177 /* We keep all global options in the structure OPT.  */
178 struct
179 {
180   int verbose;          /* Verbosity level.  */
181   int quiet;            /* Be extra quiet.  */
182   const char *homedir;  /* Configuration directory name */
183
184   char *class;
185   char *program;
186   char *keyfile;
187   char *input;
188 } opt;
189
190 \f
191 /* Print usage information and and provide strings for help.  */
192 static const char *
193 my_strusage (int level)
194 {
195   const char *p;
196
197   switch (level)
198     {
199     case 11: p = "symcryptrun (GnuPG)";
200       break;
201     case 13: p = VERSION; break;
202     case 17: p = PRINTABLE_OS_NAME; break;
203     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
204
205     case 1:
206     case 40: p = _("Usage: symcryptrun [options] (-h for help)");
207       break;
208     case 41:
209       p = _("Syntax: symcryptrun --class CLASS --program PROGRAM "
210             "--keyfile KEYFILE [options...] COMMAND [inputfile]\n"
211             "Call a simple symmetric encryption tool\n");
212       break;
213     case 31: p = "\nHome: "; break;
214     case 32: p = opt.homedir; break;
215     case 33: p = "\n"; break;
216
217     default: p = NULL; break;
218     }
219   return p;
220 }
221
222
223 \f
224 /* This is in the GNU C library in unistd.h.  */
225
226 #ifndef TEMP_FAILURE_RETRY
227 /* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno'
228    set to EINTR.  */
229
230 # define TEMP_FAILURE_RETRY(expression) \
231   (__extension__                                                              \
232     ({ long int __result;                                                     \
233        do __result = (long int) (expression);                                 \
234        while (__result == -1L && errno == EINTR);                             \
235        __result; }))
236 #endif
237
238 /* Include the implementation of map_spwq_error.  */
239 MAP_SPWQ_ERROR_IMPL
240
241 /* Unlink a file, and shred it if SHRED is true.  */
242 int
243 remove_file (char *name, int shred)
244 {
245   if (!shred)
246     return unlink (name);
247   else
248     {
249       int status;
250       pid_t pid;
251
252       pid = fork ();
253       if (pid == 0)
254         {
255           /* Child.  */
256           
257           /* -f forces file to be writable, and -u unlinks it afterwards.  */
258           char *args[] = { SHRED, "-uf", name, NULL };
259           
260           execv (SHRED, args);
261           _exit (127);
262         }
263       else if (pid < 0)
264         {
265           /* Fork failed.  */
266           status = -1;
267         }
268       else
269         {
270           /* Parent.  */
271           
272           if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
273             status = -1;
274         }
275       
276       if (!WIFEXITED (status))
277         {
278           log_error (_("%s on %s aborted with status %i\n"),
279                      SHRED, name, status);
280           unlink (name);
281           return 1;
282         }
283       else if (WEXITSTATUS (status))
284         {
285           log_error (_("%s on %s failed with status %i\n"), SHRED, name,
286                      WEXITSTATUS (status));
287           unlink (name);
288           return 1;
289         }
290
291       return 0;
292     }
293 }
294
295 \f
296 /* Class Confucius.
297
298    "Don't worry that other people don't know you;
299    worry that you don't know other people."            Analects--1.16.  */
300
301 /* Create temporary directory with mode 0700.  Returns a dynamically
302    allocated string with the filename of the directory.  */
303 static char *
304 confucius_mktmpdir (void)
305 {
306   char *name, *p;
307
308   p = getenv ("TMPDIR");
309   if (!p || !*p)
310     p = "/tmp";
311   if (p[strlen (p) - 1] == '/')
312     name = xstrconcat (p, "gpg-XXXXXX", NULL);
313   else
314     name = xstrconcat (p, "/", "gpg-XXXXXX", NULL);
315   if (!name || !mkdtemp (name))
316     {
317       log_error (_("can't create temporary directory `%s': %s\n"),
318                  name?name:"", strerror (errno));
319       return NULL;
320     }
321
322   return name;
323 }
324
325
326 /* Buffer size for I/O operations.  */
327 #define CONFUCIUS_BUFSIZE 4096
328
329 /* Buffer size for output lines.  */
330 #define CONFUCIUS_LINESIZE 4096
331
332
333 /* Copy the file IN to OUT, either of which may be "-".  If PLAIN is
334    true, and the copying fails, and OUT is not STDOUT, then shred the
335    file instead unlinking it.  */
336 static int
337 confucius_copy_file (char *infile, char *outfile, int plain)
338 {
339   FILE *in;
340   int in_is_stdin = 0;
341   FILE *out;
342   int out_is_stdout = 0;
343   char data[CONFUCIUS_BUFSIZE];
344   ssize_t data_len;
345
346   if (infile[0] == '-' && infile[1] == '\0')
347     {
348       /* FIXME: Is stdin in binary mode?  */
349       in = stdin;
350       in_is_stdin = 1;
351     }
352   else
353     {
354       in = fopen (infile, "rb");
355       if (!in)
356         {
357           log_error (_("could not open %s for writing: %s\n"),
358                      infile, strerror (errno));
359           return 1;
360         }
361     }
362
363   if (outfile[0] == '-' && outfile[1] == '\0')
364     {
365       /* FIXME: Is stdout in binary mode?  */
366       out = stdout;
367       out_is_stdout = 1;
368     }
369   else
370     {
371       out = fopen (outfile, "wb");
372       if (!out)
373         {
374           log_error (_("could not open %s for writing: %s\n"),
375                      infile, strerror (errno));
376           return 1;
377         }
378     }
379
380   /* Now copy the data.  */
381   while ((data_len = fread (data, 1, sizeof (data), in)) > 0)
382     {
383       if (fwrite (data, 1, data_len, out) != data_len)
384         {
385           log_error (_("error writing to %s: %s\n"), outfile,
386                      strerror (errno));
387           goto copy_err;
388         }
389     }
390   if (data_len < 0 || ferror (in))
391     {
392       log_error (_("error reading from %s: %s\n"), infile, strerror (errno));
393       goto copy_err;
394     }
395
396   /* Close IN if appropriate.  */
397   if (!in_is_stdin && fclose (in) && ferror (in))
398     {
399       log_error (_("error closing %s: %s\n"), infile, strerror (errno));
400       goto copy_err;
401     }
402
403   /* Close OUT if appropriate.  */
404   if (!out_is_stdout && fclose (out) && ferror (out))
405     {
406       log_error (_("error closing %s: %s\n"), infile, strerror (errno));
407       goto copy_err;
408     }
409
410   return 0;
411
412  copy_err:
413   if (!out_is_stdout)
414     remove_file (outfile, plain);
415
416   return 1;
417 }
418
419
420 /* Get a passphrase in secure storage (if possible).  If AGAIN is
421    true, then this is a repeated attempt.  If CANCELED is not a null
422    pointer, it will be set to true or false, depending on if the user
423    canceled the operation or not.  On error (including cancelation), a
424    null pointer is returned.  The passphrase must be deallocated with
425    confucius_drop_pass.  CACHEID is the ID to be used for passphrase
426    caching and can be NULL to disable caching.  */
427 char *
428 confucius_get_pass (const char *cacheid, int again, int *canceled)
429 {
430   int err;
431   char *pw;
432   char *orig_codeset;
433
434   if (canceled)
435     *canceled = 0;
436   
437   orig_codeset = i18n_switchto_utf8 ();
438   pw = simple_pwquery (cacheid,
439                        again ? _("does not match - try again"):NULL,
440                        _("Passphrase:"), NULL, 0, &err);
441   err = map_spwq_error (err);
442   i18n_switchback (orig_codeset);
443
444   if (!pw)
445     {
446       if (err)
447         log_error (_("error while asking for the passphrase: %s\n"),
448                    gpg_strerror (err));
449       else
450         {
451           log_info (_("cancelled\n"));
452           if (canceled)
453             *canceled = 1;
454         }      
455     }
456
457   return pw;
458 }
459
460
461 /* Drop a passphrase retrieved with confucius_get_pass.  */
462 void
463 confucius_drop_pass (char *pass)
464 {
465   if (pass)
466     spwq_secure_free (pass);
467 }
468
469
470 /* Run a confucius crypto engine.  If MODE is oEncrypt, encryption is
471    requested.  If it is oDecrypt, decryption is requested.  INFILE and
472    OUTFILE are the temporary files used in the process.  */
473 int
474 confucius_process (int mode, char *infile, char *outfile,
475                    int argc, char *argv[])
476 {
477   char **args;
478   int cstderr[2];
479   int master;
480   int slave;
481   int res;
482   pid_t pid;
483   pid_t wpid;
484   int tries = 0;
485   char cacheid[40];
486
487   signal (SIGPIPE, SIG_IGN);
488
489   if (!opt.program)
490     {
491       log_error (_("no --program option provided\n"));
492       return 1;
493     }
494
495   if (mode != oDecrypt && mode != oEncrypt)
496     {
497       log_error (_("only --decrypt and --encrypt are supported\n"));
498       return 1;
499     }
500
501   if (!opt.keyfile)
502     {
503       log_error (_("no --keyfile option provided\n"));
504       return 1;
505     }
506
507   /* Generate a hash from the keyfile name for caching.  */
508   snprintf (cacheid, sizeof (cacheid), "confucius:%lu",
509             hash_string (opt.keyfile));
510   cacheid[sizeof (cacheid) - 1] = '\0';
511   args = malloc (sizeof (char *) * (10 + argc));
512   if (!args)
513     {
514       log_error (_("cannot allocate args vector\n"));
515       return 1;
516     }
517   args[0] = opt.program;
518   args[1] = (mode == oEncrypt) ? "-m1" : "-m2";
519   args[2] = "-q";
520   args[3] = infile;
521   args[4] = "-z";
522   args[5] = outfile;
523   args[6] = "-s";
524   args[7] = opt.keyfile;
525   args[8] = (mode == oEncrypt) ? "-af" : "-f";
526   args[9 + argc] = NULL;
527   while (argc--)
528     args[9 + argc] = argv[argc];
529
530   if (pipe (cstderr) < 0)
531     {
532       log_error (_("could not create pipe: %s\n"), strerror (errno));
533       free (args);
534       return 1;
535     }
536
537   if (openpty (&master, &slave, NULL, NULL, NULL) == -1)
538     {
539       log_error (_("could not create pty: %s\n"), strerror (errno));
540       close (cstderr[0]);
541       close (cstderr[1]);
542       free (args);
543       return -1;
544     }
545
546   /* We don't want to deal with the worst case scenarios.  */
547   assert (master > 2);
548   assert (slave > 2);
549   assert (cstderr[0] > 2);
550   assert (cstderr[1] > 2);
551
552   pid = fork ();
553   if (pid < 0)
554     {
555       log_error (_("could not fork: %s\n"), strerror (errno));
556       close (master);
557       close (slave);
558       close (cstderr[0]);
559       close (cstderr[1]);
560       free (args);
561       return 1;
562     }
563   else if (pid == 0) 
564     {
565       /* Child.  */
566
567       /* Close the parent ends.  */
568       close (master);
569       close (cstderr[0]);
570
571       /* Change controlling terminal.  */
572       if (login_tty (slave))
573         {
574           /* It's too early to output a debug message.  */
575           _exit (1);
576         }
577
578       dup2 (cstderr[1], 2);
579       close (cstderr[1]);
580
581       /* Now kick off the engine program.  */
582       execv (opt.program, args);
583       log_error (_("execv failed: %s\n"), strerror (errno));
584       _exit (1);
585     }
586   else
587     {
588       /* Parent.  */
589       char buffer[CONFUCIUS_LINESIZE];
590       int buffer_len = 0;
591       fd_set fds;
592       int slave_closed = 0;
593       int stderr_closed = 0;
594
595       close (slave);
596       close (cstderr[1]);
597       free (args);
598
599       /* Listen on the output FDs.  */
600       do
601         {
602           FD_ZERO (&fds);
603
604           if (!slave_closed)
605             FD_SET (master, &fds);
606           if (!stderr_closed)
607             FD_SET (cstderr[0], &fds);
608
609           res = select (FD_SETSIZE, &fds, NULL, NULL, NULL);
610           if (res < 0)
611             {
612               log_error (_("select failed: %s\n"), strerror (errno));
613
614               kill (pid, SIGTERM);
615               close (master);
616               close (cstderr[0]);
617               return 1;
618             }
619
620           if (FD_ISSET (cstderr[0], &fds))
621             {
622               /* We got some output on stderr.  This is just passed
623                  through via the logging facility.  */
624
625               res = read (cstderr[0], &buffer[buffer_len],
626                           sizeof (buffer) - buffer_len - 1);
627               if (res < 0)
628                 {
629                   log_error (_("read failed: %s\n"), strerror (errno));
630
631                   kill (pid, SIGTERM);
632                   close (master);
633                   close (cstderr[0]);
634                   return 1;
635                 }
636               else  
637                 {
638                   char *newline;
639
640                   buffer_len += res;
641                   for (;;)
642                     {
643                       buffer[buffer_len] = '\0';
644                       newline = strchr (buffer, '\n');
645                       if (newline)
646                         {
647                           *newline = '\0';
648                           log_error ("%s\n", buffer);
649                           buffer_len -= newline + 1 - buffer;
650                           memmove (buffer, newline + 1, buffer_len);
651                         }
652                       else if (buffer_len == sizeof (buffer) - 1)
653                         {
654                           /* Overflow.  */
655                           log_error ("%s\n", buffer);
656                           buffer_len = 0;
657                         }
658                       else
659                         break;
660                     }
661
662                   if (res == 0)
663                     stderr_closed = 1;
664                 }
665             }
666           else if (FD_ISSET (master, &fds))
667             {
668               char data[512];
669
670               res = read (master, data, sizeof (data));
671               if (res < 0)
672                 {
673                   if (errno == EIO)
674                     {
675                       /* Slave-side close leads to readable fd and
676                          EIO.  */
677                       slave_closed = 1;
678                     }
679                   else
680                     {
681                       log_error (_("pty read failed: %s\n"), strerror (errno));
682
683                       kill (pid, SIGTERM);
684                       close (master);
685                       close (cstderr[0]);
686                       return 1;
687                     }
688                 }
689               else if (res == 0)
690                 /* This never seems to be what happens on slave-side
691                    close.  */
692                 slave_closed = 1;
693               else
694                 {
695                   /* Check for password prompt.  */
696                   if (data[res - 1] == ':')
697                     {
698                       char *pass;
699                       int canceled;
700
701                       /* If this is not the first attempt, the
702                          passphrase seems to be wrong, so clear the
703                          cache.  */
704                       if (tries)
705                         simple_pwclear (cacheid);
706
707                       pass = confucius_get_pass (cacheid,
708                                                  tries ? 1 : 0, &canceled);
709                       if (!pass)
710                         {
711                           kill (pid, SIGTERM);
712                           close (master);
713                           close (cstderr[0]);
714                           return canceled ? SYMC_CANCELED : 1;
715                         }
716                       write (master, pass, strlen (pass));
717                       write (master, "\n", 1);
718                       confucius_drop_pass (pass);
719
720                       tries++;
721                     }
722                 }
723             }
724         }
725       while (!stderr_closed || !slave_closed);
726
727       close (master);
728       close (cstderr[0]);
729
730       wpid = waitpid (pid, &res, 0);
731       if (wpid < 0)
732         {
733           log_error (_("waitpid failed: %s\n"), strerror (errno));
734
735           kill (pid, SIGTERM);
736           /* State of cached password is unclear.  Just remove it.  */
737           simple_pwclear (cacheid);
738           return 1;
739         }
740       else
741         {
742           /* Shouldn't happen, as we don't use WNOHANG.  */
743           assert (wpid != 0);
744
745           if (!WIFEXITED (res))
746             {
747               log_error (_("child aborted with status %i\n"), res);
748
749               /* State of cached password is unclear.  Just remove it.  */
750               simple_pwclear (cacheid);
751
752               return 1;
753             }
754
755           if (WEXITSTATUS (res))
756             {
757               /* The passphrase was wrong.  Remove it from the cache.  */
758               simple_pwclear (cacheid);
759
760               /* We probably exceeded our number of attempts at guessing
761                  the password.  */
762               if (tries >= 3)
763                 return SYMC_BAD_PASSPHRASE;
764               else
765                 return 1;
766             }
767
768           return 0;
769         }
770     }
771
772   /* Not reached.  */
773 }
774
775
776 /* Class confucius main program.  If MODE is oEncrypt, encryption is
777    requested.  If it is oDecrypt, decryption is requested.  The other
778    parameters are taken from the global option data.  */
779 int
780 confucius_main (int mode, int argc, char *argv[])
781 {
782   int res;
783   char *tmpdir;
784   char *infile;
785   int infile_from_stdin = 0;
786   char *outfile;
787
788   tmpdir = confucius_mktmpdir ();
789   if (!tmpdir)
790     return 1;
791
792   if (opt.input && !(opt.input[0] == '-' && opt.input[1] == '\0'))
793     infile = xstrdup (opt.input);
794   else
795     {
796       infile_from_stdin = 1;
797
798       /* TMPDIR + "/" + "in" + "\0".  */
799       infile = malloc (strlen (tmpdir) + 1 + 2 + 1);
800       if (!infile)
801         {
802           log_error (_("cannot allocate infile string: %s\n"),
803                      strerror (errno));
804           rmdir (tmpdir);
805           return 1;
806         }
807       strcpy (infile, tmpdir);
808       strcat (infile, "/in");
809     }
810
811   /* TMPDIR + "/" + "out" + "\0".  */
812   outfile = malloc (strlen (tmpdir) + 1 + 3 + 1);
813   if (!outfile)
814     {
815       log_error (_("cannot allocate outfile string: %s\n"), strerror (errno));
816       free (infile);
817       rmdir (tmpdir);
818       return 1;
819     }
820   strcpy (outfile, tmpdir);
821   strcat (outfile, "/out");
822
823   if (infile_from_stdin)
824     {
825       /* Create INFILE and fill it with content.  */
826       res = confucius_copy_file ("-", infile, mode == oEncrypt);
827       if (res)
828         {
829           free (outfile);
830           free (infile);
831           rmdir (tmpdir);
832           return res;
833         }
834     }
835
836   /* Run the engine and thus create the output file, handling
837      passphrase retrieval.  */
838   res = confucius_process (mode, infile, outfile, argc, argv);
839   if (res)
840     {
841       remove_file (outfile, mode == oDecrypt);
842       if (infile_from_stdin)
843         remove_file (infile, mode == oEncrypt);
844       free (outfile);
845       free (infile);
846       rmdir (tmpdir);
847       return res;
848     }
849
850   /* Dump the output file to stdout.  */
851   res = confucius_copy_file (outfile, "-", mode == oDecrypt);
852   if (res)
853     {
854       remove_file (outfile, mode == oDecrypt);
855       if (infile_from_stdin)
856         remove_file (infile, mode == oEncrypt);
857       free (outfile);
858       free (infile);
859       rmdir (tmpdir);
860       return res;
861     }
862   
863   remove_file (outfile, mode == oDecrypt);
864   if (infile_from_stdin)
865     remove_file (infile, mode == oEncrypt);
866   free (outfile);
867   free (infile);
868   rmdir (tmpdir);
869   return 0;
870 }
871
872 \f
873 /* symcryptrun's entry point.  */
874 int
875 main (int argc, char **argv)
876 {
877   ARGPARSE_ARGS pargs;
878   int orig_argc;
879   char **orig_argv;
880   FILE *configfp = NULL;
881   char *configname = NULL;
882   unsigned configlineno; 
883   int mode = 0;
884   int res;
885   char *logfile = NULL;
886   int default_config = 1;
887
888   set_strusage (my_strusage);
889   log_set_prefix ("symcryptrun", 1);
890
891   /* Make sure that our subsystems are ready.  */
892   i18n_init();
893   init_common_subsystems (&argc, &argv);
894
895   opt.homedir = default_homedir ();
896
897   /* Check whether we have a config file given on the commandline */
898   orig_argc = argc;
899   orig_argv = argv;
900   pargs.argc = &argc;
901   pargs.argv = &argv;
902   pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
903   while (arg_parse( &pargs, opts))
904     {
905       if (pargs.r_opt == oOptions)
906         { /* Yes there is one, so we do not try the default one, but
907              read the option file when it is encountered at the
908              commandline */
909           default_config = 0;
910         }
911       else if (pargs.r_opt == oNoOptions)
912         default_config = 0; /* --no-options */
913       else if (pargs.r_opt == oHomedir)
914         opt.homedir = pargs.r.ret_str;
915     }
916
917   if (default_config)
918     configname = make_filename (opt.homedir, "symcryptrun.conf", NULL );
919   
920   argc = orig_argc;
921   argv = orig_argv;
922   pargs.argc = &argc;
923   pargs.argv = &argv;
924   pargs.flags= 1;  /* do not remove the args */
925  next_pass:
926   if (configname)
927     {
928       configlineno = 0;
929       configfp = fopen (configname, "r");
930       if (!configfp)
931         {
932           if (!default_config)
933             {
934               log_error (_("option file `%s': %s\n"),
935                          configname, strerror(errno) );
936               exit(1);
937             }
938           xfree (configname); 
939           configname = NULL;
940         }
941       default_config = 0;
942     }
943
944   /* Parse the command line. */
945   while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
946     {
947       switch (pargs.r_opt)
948         {
949         case oDecrypt:   mode = oDecrypt; break;
950         case oEncrypt:   mode = oEncrypt; break;
951
952         case oQuiet:     opt.quiet = 1; break;
953         case oVerbose:   opt.verbose++; break;
954         case oNoVerbose: opt.verbose = 0; break;
955           
956         case oClass:    opt.class = pargs.r.ret_str; break;
957         case oProgram:  opt.program = pargs.r.ret_str; break;
958         case oKeyfile:  opt.keyfile = pargs.r.ret_str; break;
959         case oInput:    opt.input = pargs.r.ret_str; break;
960
961         case oLogFile:  logfile = pargs.r.ret_str; break;
962
963         case oOptions:
964           /* Config files may not be nested (silently ignore them) */
965           if (!configfp)
966             {
967                 xfree(configname);
968                 configname = xstrdup(pargs.r.ret_str);
969                 goto next_pass;
970             }
971           break;
972         case oNoOptions: break; /* no-options */
973         case oHomedir: /* Ignore this option here. */; break;
974
975         default : pargs.err = configfp? 1:2; break;
976         }
977     }
978   if (configfp)
979     {
980       fclose( configfp );
981       configfp = NULL;
982       configname = NULL;
983       goto next_pass;
984     }
985   xfree (configname);
986   configname = NULL;
987
988   if (!mode)
989     log_error (_("either %s or %s must be given\n"),
990                "--decrypt", "--encrypt");
991
992   if (log_get_errorcount (0))
993     exit (1);
994
995   if (logfile)
996     log_set_file (logfile);
997
998   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
999   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
1000     {
1001       log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
1002                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
1003     }
1004   setup_libgcrypt_logging ();
1005   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1006
1007   /* Tell simple-pwquery about the the standard socket name.  */
1008   {
1009     char *tmp = make_filename (opt.homedir, "S.gpg-agent", NULL);
1010     simple_pw_set_socket (tmp);
1011     xfree (tmp);
1012   }
1013
1014   if (!opt.class)
1015     {
1016       log_error (_("no class provided\n"));
1017       res = 1;
1018     }
1019   else if (!strcmp (opt.class, "confucius"))
1020     {
1021       res = confucius_main (mode, argc, argv);
1022     }
1023   else
1024     {
1025       log_error (_("class %s is not supported\n"), opt.class);
1026       res = 1;
1027     }
1028
1029   return res;
1030 }