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