Implement /run/user/UID/gnupg based sockets.
[gnupg.git] / sm / gpgsm.c
index 01f33e3..e6fd703 100644 (file)
@@ -1,6 +1,6 @@
 /* gpgsm.c - GnuPG for S/MIME
- * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- *               2010  Free Software Foundation, Inc.
+ * Copyright (C) 2001-2008, 2010  Free Software Foundation, Inc.
+ * Copyright (C) 2001-2008, 2010  Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -32,6 +32,8 @@
 #include <gcrypt.h>
 #include <assuan.h> /* malloc hooks */
 
+#include "passphrase.h"
+#include "../common/shareddefs.h"
 #include "../kbx/keybox.h" /* malloc hooks */
 #include "i18n.h"
 #include "keydb.h"
@@ -99,7 +101,6 @@ enum cmd_and_opt_values {
   oDebugAllowCoreDump,
   oDebugNoChainValidation,
   oDebugIgnoreExpiration,
-  oFixedPassphrase,
   oLogFile,
   oNoLogFile,
   oAuditLog,
@@ -121,6 +122,8 @@ enum cmd_and_opt_values {
   oProtectToolProgram,
   oFakedSystemTime,
 
+  oPassphraseFD,
+  oPinentryMode,
 
   oAssumeArmor,
   oAssumeBase64,
@@ -148,6 +151,7 @@ enum cmd_and_opt_values {
   oWithFingerprint,
   oWithMD5Fingerprint,
   oWithKeygrip,
+  oWithSecret,
   oAnswerYes,
   oAnswerNo,
   oKeyring,
@@ -182,7 +186,8 @@ enum cmd_and_opt_values {
   oIgnoreTimeConflict,
   oNoRandomSeedFile,
   oNoCommonCertsImport,
-  oIgnoreCertExtension
+  oIgnoreCertExtension,
+  oNoAutostart
  };
 
 
@@ -212,7 +217,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aExport, "export", N_("export certificates")),
 
   /* We use -raw and not -p1 for pkcs#1 secret key export so that it
-     won't accidently be used in case -p12 was intended.  */
+     won't accidentally be used in case -p12 was intended.  */
   ARGPARSE_c (aExportSecretKeyP12, "export-secret-key-p12", "@"),
   ARGPARSE_c (aExportSecretKeyP8,  "export-secret-key-p8", "@"),
   ARGPARSE_c (aExportSecretKeyRaw, "export-secret-key-raw", "@"),
@@ -242,6 +247,9 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oP12Charset, "p12-charset", "@"),
 
+  ARGPARSE_s_i (oPassphraseFD,    "passphrase-fd", "@"),
+  ARGPARSE_s_s (oPinentryMode,    "pinentry-mode", "@"),
+
   ARGPARSE_s_n (oAssumeArmor, "assume-armor",
                 N_("assume input is in PEM format")),
   ARGPARSE_s_n (oAssumeBase64, "assume-base64",
@@ -321,7 +329,7 @@ static ARGPARSE_OPTS opts[] = {
                 N_("|SPEC|use this keyserver to lookup keys")),
   ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
 
-  ARGPARSE_p_u (oDebug, "debug", "@"),
+  ARGPARSE_s_s (oDebug, "debug", "@"),
   ARGPARSE_s_s (oDebugLevel, "debug-level",
                 N_("|LEVEL|set the debugging level to LEVEL")),
   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
@@ -330,7 +338,6 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
   ARGPARSE_s_n (oDebugNoChainValidation, "debug-no-chain-validation", "@"),
   ARGPARSE_s_n (oDebugIgnoreExpiration,  "debug-ignore-expiration", "@"),
-  ARGPARSE_s_s (oFixedPassphrase, "fixed-passphrase", "@"),
 
   ARGPARSE_s_i (oStatusFD, "status-fd",
                 N_("|FD|write status info to this FD")),
@@ -383,12 +390,14 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
   ARGPARSE_s_n (oNoRandomSeedFile,  "no-random-seed-file", "@"),
   ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
   ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"),
+  ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
 
   /* Command aliases.  */
   ARGPARSE_c (aListKeys, "list-key", "@"),
@@ -402,6 +411,19 @@ static ARGPARSE_OPTS opts[] = {
 };
 
 
+/* The list of supported debug flags.  */
+static struct debug_flags_s debug_flags [] =
+  {
+    { DBG_X509_VALUE   , "x509"    },
+    { DBG_MPI_VALUE    , "mpi"     },
+    { DBG_CRYPTO_VALUE , "crypto"  },
+    { DBG_MEMORY_VALUE , "memory"  },
+    { DBG_CACHE_VALUE  , "cache"   },
+    { DBG_MEMSTAT_VALUE, "memstat" },
+    { DBG_HASHING_VALUE, "hashing" },
+    { DBG_IPC_VALUE    , "ipc"     },
+    { 0, NULL }
+  };
 
 
 /* Global variable to keep an error count. */
@@ -434,7 +456,7 @@ static int default_include_certs = DEFAULT_INCLUDE_CERTS;
 static int default_validation_model;
 
 /* The default cipher algo.  */
-#define DEFAULT_CIPHER_ALGO "3DES"  /*des-EDE3-CBC*/
+#define DEFAULT_CIPHER_ALGO "AES"
 
 
 static char *build_list (const char *text,
@@ -559,7 +581,7 @@ my_strusage( int level )
       break;
 
     case 31: p = "\nHome: "; break;
-    case 32: p = opt.homedir; break;
+    case 32: p = gnupg_homedir (); break;
     case 33: p = _("\nSupported algorithms:\n"); break;
     case 34:
       if (!ciphers)
@@ -613,7 +635,7 @@ build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
        }
     }
   if (p)
-    p = stpcpy(p, "\n" );
+    strcpy (p, "\n" );
   return list;
 }
 
@@ -634,9 +656,7 @@ set_binary (FILE *fp)
 static void
 wrong_args (const char *text)
 {
-  fputs (_("usage: gpgsm [options] "), stderr);
-  fputs (text, stderr);
-  putc ('\n', stderr);
+  fprintf (stderr, _("usage: %s [options] %s\n"), GPGSM_NAME, text);
   gpgsm_exit (2);
 }
 
@@ -668,11 +688,11 @@ set_debug (void)
   else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
     opt.debug = 0;
   else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
-    opt.debug = DBG_ASSUAN_VALUE;
+    opt.debug = DBG_IPC_VALUE;
   else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
-    opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
+    opt.debug = DBG_IPC_VALUE|DBG_X509_VALUE;
   else if (!strcmp (debug_level, "expert")  || (numok && numlvl <= 8))
-    opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
+    opt.debug = (DBG_IPC_VALUE|DBG_X509_VALUE
                  |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
   else if (!strcmp (debug_level, "guru") || numok)
     {
@@ -704,15 +724,7 @@ set_debug (void)
   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
 
   if (opt.debug)
-    log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n",
-              (opt.debug & DBG_X509_VALUE   )? " x509":"",
-              (opt.debug & DBG_MPI_VALUE    )? " mpi":"",
-              (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"",
-              (opt.debug & DBG_MEMORY_VALUE )? " memory":"",
-              (opt.debug & DBG_CACHE_VALUE  )? " cache":"",
-              (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"",
-              (opt.debug & DBG_HASHING_VALUE)? " hashing":"",
-              (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"" );
+    parse_debug_flag (NULL, &opt.debug, debug_flags);
 }
 
 
@@ -756,7 +768,7 @@ do_add_recipient (ctrl_t ctrl, const char *name,
                          get_inv_recpsgnr_code (rc), name, NULL);
         }
       else
-        log_info (_("NOTE: won't be able to encrypt to '%s': %s\n"),
+        log_info (_("Note: won't be able to encrypt to '%s': %s\n"),
                   name, gpg_strerror (rc));
     }
 }
@@ -860,6 +872,7 @@ parse_keyserver_line (char *line,
     {
       log_info (_("%s:%u: skipping this line\n"), filename, lineno);
       keyserver_list_free (server);
+      server = NULL;
     }
 
   return server;
@@ -904,9 +917,10 @@ main ( int argc, char **argv)
   estream_t auditfp = NULL;
   estream_t htmlauditfp = NULL;
   struct assuan_malloc_hooks malloc_hooks;
-
+  int pwfd = -1;
   /*mtrace();*/
 
+  early_system_init ();
   gnupg_reopen_std (GPGSM_NAME);
   /* trap_unaligned ();*/
   gnupg_rl_initialize ();
@@ -940,6 +954,7 @@ main ( int argc, char **argv)
 
   dotlock_create (NULL, 0); /* Register lockfile cleanup.  */
 
+  opt.autostart = 1;
   opt.session_env = session_env_new ();
   if (!opt.session_env)
     log_fatal ("error allocating session environment block: %s\n",
@@ -949,8 +964,6 @@ main ( int argc, char **argv)
      remember to update the Gpgconflist entry as well.  */
   opt.def_cipher_algoid = DEFAULT_CIPHER_ALGO;
 
-  opt.homedir = default_homedir ();
-
 
   /* First check whether we have a config file on the commandline */
   orig_argc = argc;
@@ -969,9 +982,12 @@ main ( int argc, char **argv)
           default_config = 0;
        }
       else if (pargs.r_opt == oNoOptions)
-        default_config = 0; /* --no-options */
+        {
+          default_config = 0; /* --no-options */
+          opt.no_homedir_creation = 1;
+        }
       else if (pargs.r_opt == oHomedir)
-        opt.homedir = pargs.r.ret_str;
+        gnupg_set_homedir (pargs.r.ret_str);
       else if (pargs.r_opt == aCallProtectTool)
         break; /* This break makes sure that --version and --help are
                   passed to the protect-tool. */
@@ -1006,9 +1022,10 @@ main ( int argc, char **argv)
 
   /* Set the default option file */
   if (default_config )
-    configname = make_filename (opt.homedir, GPGSM_NAME EXTSEP_S "conf", NULL);
+    configname = make_filename (gnupg_homedir (),
+                                GPGSM_NAME EXTSEP_S "conf", NULL);
   /* Set the default policy file */
-  opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
+  opt.policy_file = make_filename (gnupg_homedir (), "policies.txt", NULL);
 
   argc        = orig_argc;
   argv        = orig_argv;
@@ -1025,7 +1042,7 @@ main ( int argc, char **argv)
         if (default_config)
           {
             if (parse_debug)
-              log_info (_("NOTE: no default option file '%s'\n"), configname);
+              log_info (_("Note: no default option file '%s'\n"), configname);
           }
         else
           {
@@ -1139,6 +1156,16 @@ main ( int argc, char **argv)
           opt.p12_charset = pargs.r.ret_str;
           break;
 
+        case oPassphraseFD:
+         pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+         break;
+
+        case oPinentryMode:
+         opt.pinentry_mode = parse_pinentry_mode (pargs.r.ret_str);
+         if (opt.pinentry_mode == -1)
+            log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
+         break;
+
           /* Input encoding selection.  */
         case oAssumeArmor:
           ctrl.autodetect_encoding = 0;
@@ -1235,7 +1262,13 @@ main ( int argc, char **argv)
 
         case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
 
-        case oDebug: debug_value |= pargs.r.ret_ulong; break;
+        case oDebug:
+          if (parse_debug_flag (pargs.r.ret_str, &debug_value, debug_flags))
+            {
+              pargs.r_opt = ARGPARSE_INVALID_ARG;
+              pargs.err = ARGPARSE_PRINT_ERROR;
+            }
+          break;
         case oDebugAll: debug_value = ~0; break;
         case oDebugNone: debug_value = 0; break;
         case oDebugLevel: debug_level = pargs.r.ret_str; break;
@@ -1245,7 +1278,6 @@ main ( int argc, char **argv)
           break;
         case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
         case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
-        case oFixedPassphrase: opt.fixed_passphrase = pargs.r.ret_str; break;
 
         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
         case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
@@ -1270,8 +1302,8 @@ main ( int argc, char **argv)
               goto next_pass;
            }
           break;
-        case oNoOptions: break; /* no-options */
-        case oHomedir: opt.homedir = pargs.r.ret_str; break;
+        case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
+        case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
 
         case oDisplay:
@@ -1333,6 +1365,7 @@ main ( int argc, char **argv)
 
         case oWithKeyData: opt.with_key_data=1; /* fall thru */
         case oWithColons: ctrl.with_colons = 1; break;
+        case oWithSecret: ctrl.with_secret = 1; break;
         case oWithValidation: ctrl.with_validation=1; break;
         case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break;
 
@@ -1413,6 +1446,8 @@ main ( int argc, char **argv)
           add_to_strlist (&opt.ignored_cert_extensions, pargs.r.ret_str);
           break;
 
+        case oNoAutostart: opt.autostart = 0; break;
+
         default:
           pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
           break;
@@ -1432,12 +1467,16 @@ main ( int argc, char **argv)
   configname = NULL;
 
   if (!opt.config_filename)
-    opt.config_filename = make_filename (opt.homedir, GPG_NAME EXTSEP_S "conf",
+    opt.config_filename = make_filename (gnupg_homedir (),
+                                         GPGSM_NAME EXTSEP_S "conf",
                                          NULL);
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
 
+  if (pwfd != -1)      /* Read the passphrase now.  */
+    read_passphrase_from_fd (pwfd);
+
   /* Now that we have the options parsed we need to update the default
      control structure.  */
   gpgsm_init_default_ctrl (&ctrl);
@@ -1464,7 +1503,7 @@ main ( int argc, char **argv)
     log_info (_("WARNING: program may create a core file!\n"));
 
 /*   if (opt.qualsig_approval && !opt.quiet) */
-/*     log_info (_("This software has offically been approved to " */
+/*     log_info (_("This software has officially been approved to " */
 /*                 "create and verify\n" */
 /*                 "qualified signatures according to German law.\n")); */
 
@@ -1491,7 +1530,7 @@ main ( int argc, char **argv)
 
       for (i=0; i < argc; i++)
         if (argv[i][0] == '-' && argv[i][1] == '-')
-          log_info (_("NOTE: '%s' is not considered an option\n"), argv[i]);
+          log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
     }
 
 /*FIXME    if (opt.batch) */
@@ -1501,7 +1540,7 @@ main ( int argc, char **argv)
 
   set_debug ();
 
-  /* Although we alwasy use gpgsm_exit, we better install a regualr
+  /* Although we always use gpgsm_exit, we better install a regualr
      exit handler so that at least the secure memory gets wiped
      out. */
   if (atexit (emergency_cleanup))
@@ -1565,7 +1604,7 @@ main ( int argc, char **argv)
   /* Set the random seed file. */
   if (use_random_seed)
     {
-      char *p = make_filename (opt.homedir, "random_seed", NULL);
+      char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
       xfree(p);
     }
@@ -2044,6 +2083,7 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
   ctrl->include_certs = default_include_certs;
   ctrl->use_ocsp = opt.enable_ocsp;
   ctrl->validation_model = default_validation_model;
+  ctrl->offline = opt.disable_dirmngr;
 }