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