diff --git a/common/iobuf.c b/common/iobuf.c index ab8368b54..62cde27f9 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1,2961 +1,3059 @@ /* iobuf.c - File Handling for OpenPGP. * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008, * 2009, 2010, 2011 Free Software Foundation, Inc. - * Copyright (C) 2015 g10 Code GmbH + * Copyright (C) 2015, 2023 g10 Code GmbH * * This file is part of GnuPG. * * This file is free software; you can redistribute it and/or modify * it under the terms of either * * - the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at * your option) any later version. * * or * * - the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at * your option) any later version. * * or both in parallel, as here. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later) */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_W32_SYSTEM # ifdef HAVE_WINSOCK2_H # include # endif # include #endif #ifdef __riscos__ # include # include #endif /* __riscos__ */ #include #include "util.h" #include "sysutils.h" #include "iobuf.h" /*-- Begin configurable part. --*/ /* The standard size of the internal buffers. */ #define DEFAULT_IOBUF_BUFFER_SIZE (64*1024) /* To avoid a potential DoS with compression packets we better limit the number of filters in a chain. */ #define MAX_NESTING_FILTER 64 /* The threshold for switching to use external buffers directly instead of the internal buffers. */ #define IOBUF_ZEROCOPY_THRESHOLD_SIZE 1024 /*-- End configurable part. --*/ /* The size of the iobuffers. This can be changed using the * iobuf_set_buffer_size function. */ static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE; #ifdef HAVE_W32_SYSTEM # define FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE)) # define FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE)) #else /*!HAVE_W32_SYSTEM*/ # define FD_FOR_STDIN (0) # define FD_FOR_STDOUT (1) #endif /*!HAVE_W32_SYSTEM*/ /* The context used by the file filter. */ typedef struct { gnupg_fd_t fp; /* Open file pointer or handle. */ int keep_open; int no_cache; int eof_seen; int delayed_rc; int print_only_name; /* Flags indicating that fname is not a real file. */ + char peeked[32]; /* Read ahead buffer. */ + byte npeeked; /* Number of bytes valid in peeked. */ + byte upeeked; /* Number of bytes used from peeked. */ char fname[1]; /* Name of the file. */ } file_filter_ctx_t; /* The context used by the estream filter. */ typedef struct { estream_t fp; /* Open estream handle. */ int keep_open; int no_cache; int eof_seen; int use_readlimit; /* Take care of the readlimit. */ size_t readlimit; /* Number of bytes left to read. */ int print_only_name; /* Flags indicating that fname is not a real file. */ char fname[1]; /* Name of the file. */ } file_es_filter_ctx_t; /* Object to control the "close cache". */ struct close_cache_s { struct close_cache_s *next; gnupg_fd_t fp; char fname[1]; }; typedef struct close_cache_s *close_cache_t; static close_cache_t close_cache; int iobuf_debug_mode; #ifdef HAVE_W32_SYSTEM typedef struct { int sock; int keep_open; int no_cache; int eof_seen; int print_only_name; /* Flag indicating that fname is not a real file. */ char fname[1]; /* Name of the file */ } sock_filter_ctx_t; #endif /*HAVE_W32_SYSTEM*/ /* The first partial length header block must be of size 512 to make * it easier (and more efficient) we use a min. block size of 512 for * all chunks (but the last one) */ #define OP_MIN_PARTIAL_CHUNK 512 #define OP_MIN_PARTIAL_CHUNK_2POW 9 /* The context we use for the block filter (used to handle OpenPGP length information header). */ typedef struct { int use; size_t size; size_t count; int partial; /* 1 = partial header, 2 in last partial packet. */ char *buffer; /* Used for partial header. */ size_t buflen; /* Used size of buffer. */ int first_c; /* First character of a partial header (which is > 0). */ int eof; } block_filter_ctx_t; /* Local prototypes. */ static int underflow (iobuf_t a, int clear_pending_eof); static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target); static int translate_file_handle (int fd, int for_write); /* Sends any pending data to the filter's FILTER function. Note: this works on the filter and not on the whole pipeline. That is, iobuf_flush doesn't necessarily cause data to be written to any underlying file; it just causes any data buffered at the filter A to be sent to A's filter function. If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the buffer by iobuf_buffer_size. May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters. */ static int filter_flush (iobuf_t a); /* This is a replacement for strcmp. Under W32 it does not distinguish between backslash and slash. */ static int fd_cache_strcmp (const char *a, const char *b) { #ifdef HAVE_DOSISH_SYSTEM for (; *a && *b; a++, b++) { if (*a != *b && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) ) break; } return *(const unsigned char *)a - *(const unsigned char *)b; #else return strcmp (a, b); #endif } /* * Invalidate (i.e. close) a cached iobuf */ static int fd_cache_invalidate (const char *fname) { close_cache_t cc; int rc = 0; log_assert (fname); if (DBG_IOBUF) log_debug ("fd_cache_invalidate (%s)\n", fname); for (cc = close_cache; cc; cc = cc->next) { if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname)) { if (DBG_IOBUF) log_debug (" did (%s)\n", cc->fname); #ifdef HAVE_W32_SYSTEM if (!CloseHandle (cc->fp)) rc = -1; #else rc = close (cc->fp); #endif cc->fp = GNUPG_INVALID_FD; } } return rc; } /* Try to sync changes to the disk. This is to avoid data loss during a system crash in write/close/rename cycle on some file systems. */ static int fd_cache_synchronize (const char *fname) { int err = 0; #ifdef HAVE_FSYNC close_cache_t cc; if (DBG_IOBUF) log_debug ("fd_cache_synchronize (%s)\n", fname); for (cc=close_cache; cc; cc = cc->next ) { if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname)) { if (DBG_IOBUF) log_debug (" did (%s)\n", cc->fname); err = fsync (cc->fp); } } #else (void)fname; #endif /*HAVE_FSYNC*/ return err; } static gnupg_fd_t direct_open (const char *fname, const char *mode, int mode700) { #ifdef HAVE_W32_SYSTEM unsigned long da, cd, sm; HANDLE hfile; (void)mode700; /* Note, that we do not handle all mode combinations */ /* According to the ReactOS source it seems that open() of the * standard MSW32 crt does open the file in shared mode which is * something new for MS applications ;-) */ if (strchr (mode, '+')) { if (fd_cache_invalidate (fname)) return GNUPG_INVALID_FD; da = GENERIC_READ | GENERIC_WRITE; cd = OPEN_EXISTING; sm = FILE_SHARE_READ | FILE_SHARE_WRITE; } else if (strchr (mode, 'w')) { if (fd_cache_invalidate (fname)) return GNUPG_INVALID_FD; da = GENERIC_WRITE; cd = CREATE_ALWAYS; sm = FILE_SHARE_WRITE; } else { da = GENERIC_READ; cd = OPEN_EXISTING; sm = FILE_SHARE_READ; } /* We always use the Unicode version because it supports file names * longer than MAX_PATH. (requires gpgrt 1.45) */ if (1) { wchar_t *wfname = gpgrt_fname_to_wchar (fname); if (wfname) { hfile = CreateFileW (wfname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); xfree (wfname); } else hfile = INVALID_HANDLE_VALUE; } return hfile; #else /*!HAVE_W32_SYSTEM*/ int oflag; int cflag = S_IRUSR | S_IWUSR; if (!mode700) cflag |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* Note, that we do not handle all mode combinations */ if (strchr (mode, '+')) { if (fd_cache_invalidate (fname)) return GNUPG_INVALID_FD; oflag = O_RDWR; } else if (strchr (mode, 'w')) { if (fd_cache_invalidate (fname)) return GNUPG_INVALID_FD; oflag = O_WRONLY | O_CREAT | O_TRUNC; } else { oflag = O_RDONLY; } #ifdef O_BINARY if (strchr (mode, 'b')) oflag |= O_BINARY; #endif #ifdef __riscos__ { struct stat buf; /* Don't allow iobufs on directories */ if (!stat (fname, &buf) && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode)) return __set_errno (EISDIR); } #endif return open (fname, oflag, cflag); #endif /*!HAVE_W32_SYSTEM*/ } /* * Instead of closing an FD we keep it open and cache it for later reuse * Note that this caching strategy only works if the process does not chdir. */ static void fd_cache_close (const char *fname, gnupg_fd_t fp) { close_cache_t cc; log_assert (fp); if (!fname || !*fname) { #ifdef HAVE_W32_SYSTEM CloseHandle (fp); #else close (fp); #endif if (DBG_IOBUF) log_debug ("fd_cache_close (%d) real\n", (int)fp); return; } /* try to reuse a slot */ for (cc = close_cache; cc; cc = cc->next) { if (cc->fp == GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname)) { cc->fp = fp; if (DBG_IOBUF) log_debug ("fd_cache_close (%s) used existing slot\n", fname); return; } } /* add a new one */ if (DBG_IOBUF) log_debug ("fd_cache_close (%s) new slot created\n", fname); cc = xcalloc (1, sizeof *cc + strlen (fname)); strcpy (cc->fname, fname); cc->fp = fp; cc->next = close_cache; close_cache = cc; } /* * Do a direct_open on FNAME but first try to reuse one from the fd_cache */ static gnupg_fd_t fd_cache_open (const char *fname, const char *mode) { close_cache_t cc; log_assert (fname); for (cc = close_cache; cc; cc = cc->next) { if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname)) { gnupg_fd_t fp = cc->fp; cc->fp = GNUPG_INVALID_FD; if (DBG_IOBUF) log_debug ("fd_cache_open (%s) using cached fp\n", fname); #ifdef HAVE_W32_SYSTEM if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff) { log_error ("rewind file failed on handle %p: ec=%d\n", fp, (int) GetLastError ()); fp = GNUPG_INVALID_FD; } #else if (lseek (fp, 0, SEEK_SET) == (off_t) - 1) { log_error ("can't rewind fd %d: %s\n", fp, strerror (errno)); fp = GNUPG_INVALID_FD; } #endif return fp; } } if (DBG_IOBUF) log_debug ("fd_cache_open (%s) not cached\n", fname); return direct_open (fname, mode, 0); } static int file_filter (void *opaque, int control, iobuf_t chain, byte * buf, size_t * ret_len) { file_filter_ctx_t *a = opaque; gnupg_fd_t f = a->fp; size_t size = *ret_len; size_t nbytes = 0; int rc = 0; (void)chain; /* Not used. */ if (control == IOBUFCTRL_UNDERFLOW) { log_assert (size); /* We need a buffer. */ - if (a->eof_seen) + if (a->npeeked > a->upeeked) + { + nbytes = a->npeeked - a->upeeked; + if (nbytes > size) + nbytes = size; + memcpy (buf, a->peeked + a->upeeked, nbytes); + a->upeeked += nbytes; + *ret_len = nbytes; + } + else if (a->eof_seen) { rc = -1; *ret_len = 0; } else if (a->delayed_rc) { rc = a->delayed_rc; a->delayed_rc = 0; if (rc == -1) a->eof_seen = -1; *ret_len = 0; } else { #ifdef HAVE_W32_SYSTEM unsigned long nread; nbytes = 0; if (!ReadFile (f, buf, size, &nread, NULL)) { int ec = (int) GetLastError (); if (ec != ERROR_BROKEN_PIPE) { rc = gpg_error_from_errno (ec); log_error ("%s: read error: ec=%d\n", a->fname, ec); } } else if (!nread) { a->eof_seen = 1; rc = -1; } else { nbytes = nread; } #else int n; nbytes = 0; read_more: do { n = read (f, buf + nbytes, size - nbytes); } while (n == -1 && errno == EINTR); if (n > 0) { nbytes += n; if (nbytes < size) goto read_more; } else if (!n) /* eof */ { if (nbytes) a->delayed_rc = -1; else { a->eof_seen = 1; rc = -1; } } else /* error */ { rc = gpg_error_from_syserror (); if (gpg_err_code (rc) != GPG_ERR_EPIPE) log_error ("%s: read error: %s\n", a->fname, gpg_strerror (rc)); if (nbytes) { a->delayed_rc = rc; rc = 0; } } #endif *ret_len = nbytes; } } else if (control == IOBUFCTRL_FLUSH) { if (size) { #ifdef HAVE_W32_SYSTEM byte *p = buf; unsigned long n; nbytes = size; do { if (size && !WriteFile (f, p, nbytes, &n, NULL)) { int ec = (int) GetLastError (); rc = gpg_error_from_errno (ec); log_error ("%s: write error: ec=%d\n", a->fname, ec); break; } p += n; nbytes -= n; } while (nbytes); nbytes = p - buf; #else byte *p = buf; int n; nbytes = size; do { do { n = write (f, p, nbytes); } while (n == -1 && errno == EINTR); if (n > 0) { p += n; nbytes -= n; } } while (n != -1 && nbytes); if (n == -1) { rc = gpg_error_from_syserror (); log_error ("%s: write error: %s\n", a->fname, strerror (errno)); } nbytes = p - buf; #endif } *ret_len = nbytes; } else if (control == IOBUFCTRL_INIT) { a->eof_seen = 0; a->delayed_rc = 0; a->keep_open = 0; a->no_cache = 0; + a->npeeked = 0; + a->upeeked = 0; + } + else if (control == IOBUFCTRL_PEEK) + { + /* Peek on the input. */ +#ifdef HAVE_W32_SYSTEM + unsigned long nread; + + nbytes = 0; + if (!ReadFile (f, a->peeked, sizeof a->peeked, &nread, NULL)) + { + int ec = (int) GetLastError (); + if (ec != ERROR_BROKEN_PIPE) + { + rc = gpg_error_from_errno (ec); + log_error ("%s: read error: ec=%d\n", a->fname, ec); + } + a->npeeked = 0; + } + else if (!nread) + { + a->eof_seen = 1; + a->npeeked = 0; + } + else + { + a->npeeked = nread; + } + +#else /* Unix */ + + int n; + + peek_more: + do + { + n = read (f, a->peeked + a->npeeked, sizeof a->peeked - a->npeeked); + } + while (n == -1 && errno == EINTR); + if (n > 0) + { + a->npeeked += n; + if (a->npeeked < sizeof a->peeked) + goto peek_more; + } + else if (!n) /* eof */ + { + if (a->npeeked) + a->delayed_rc = -1; + else + a->eof_seen = 1; + } + else /* error */ + { + rc = gpg_error_from_syserror (); + if (gpg_err_code (rc) != GPG_ERR_EPIPE) + log_error ("%s: read error: %s\n", a->fname, gpg_strerror (rc)); + if (a->npeeked) + a->delayed_rc = rc; + } +#endif /* Unix */ + + size = a->npeeked < size? a->npeeked : size; + memcpy (buf, a->peeked, size); + *ret_len = size; + rc = 0; /* Return success - the user needs to check ret_len. */ } else if (control == IOBUFCTRL_DESC) { mem2str (buf, "file_filter(fd)", *ret_len); } else if (control == IOBUFCTRL_FREE) { if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT) { if (DBG_IOBUF) log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f)); if (!a->keep_open) fd_cache_close (a->no_cache ? NULL : a->fname, f); } xfree (a); /* We can free our context now. */ } return rc; } /* Similar to file_filter but using the estream system. */ static int file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf, size_t * ret_len) { file_es_filter_ctx_t *a = opaque; estream_t f = a->fp; size_t size = *ret_len; size_t nbytes = 0; int rc = 0; (void)chain; /* Not used. */ if (control == IOBUFCTRL_UNDERFLOW) { log_assert (size); /* We need a buffer. */ if (a->eof_seen) { rc = -1; *ret_len = 0; } else if (a->use_readlimit) { nbytes = 0; if (!a->readlimit) { /* eof */ a->eof_seen = 1; rc = -1; } else { if (size > a->readlimit) size = a->readlimit; rc = es_read (f, buf, size, &nbytes); if (rc == -1) { /* error */ rc = gpg_error_from_syserror (); log_error ("%s: read error: %s\n", a->fname,strerror (errno)); } else if (!nbytes) { /* eof */ a->eof_seen = 1; rc = -1; } else a->readlimit -= nbytes; } *ret_len = nbytes; } else { nbytes = 0; rc = es_read (f, buf, size, &nbytes); if (rc == -1) { /* error */ rc = gpg_error_from_syserror (); log_error ("%s: read error: %s\n", a->fname, strerror (errno)); } else if (!nbytes) { /* eof */ a->eof_seen = 1; rc = -1; } *ret_len = nbytes; } } else if (control == IOBUFCTRL_FLUSH) { if (size) { byte *p = buf; size_t nwritten; nbytes = size; do { nwritten = 0; if (es_write (f, p, nbytes, &nwritten)) { rc = gpg_error_from_syserror (); log_error ("%s: write error: %s\n", a->fname, strerror (errno)); break; } p += nwritten; nbytes -= nwritten; } while (nbytes); nbytes = p - buf; } *ret_len = nbytes; } else if (control == IOBUFCTRL_INIT) { a->eof_seen = 0; a->no_cache = 0; } else if (control == IOBUFCTRL_DESC) { mem2str (buf, "estream_filter", *ret_len); } else if (control == IOBUFCTRL_FREE) { if (f != es_stdin && f != es_stdout) { if (DBG_IOBUF) log_debug ("%s: es_fclose %p\n", a->fname, f); if (!a->keep_open) es_fclose (f); } f = NULL; xfree (a); /* We can free our context now. */ } return rc; } #ifdef HAVE_W32_SYSTEM /* Because network sockets are special objects under Lose32 we have to use a dedicated filter for them. */ static int sock_filter (void *opaque, int control, iobuf_t chain, byte * buf, size_t * ret_len) { sock_filter_ctx_t *a = opaque; size_t size = *ret_len; size_t nbytes = 0; int rc = 0; (void)chain; if (control == IOBUFCTRL_UNDERFLOW) { log_assert (size); /* need a buffer */ if (a->eof_seen) { rc = -1; *ret_len = 0; } else { int nread; nread = recv (a->sock, buf, size, 0); if (nread == SOCKET_ERROR) { int ec = (int) WSAGetLastError (); rc = gpg_error_from_errno (ec); log_error ("socket read error: ec=%d\n", ec); } else if (!nread) { a->eof_seen = 1; rc = -1; } else { nbytes = nread; } *ret_len = nbytes; } } else if (control == IOBUFCTRL_FLUSH) { if (size) { byte *p = buf; int n; nbytes = size; do { n = send (a->sock, p, nbytes, 0); if (n == SOCKET_ERROR) { int ec = (int) WSAGetLastError (); rc = gpg_error_from_errno (ec); log_error ("socket write error: ec=%d\n", ec); break; } p += n; nbytes -= n; } while (nbytes); nbytes = p - buf; } *ret_len = nbytes; } else if (control == IOBUFCTRL_INIT) { a->eof_seen = 0; a->keep_open = 0; a->no_cache = 0; } else if (control == IOBUFCTRL_DESC) { mem2str (buf, "sock_filter", *ret_len); } else if (control == IOBUFCTRL_FREE) { if (!a->keep_open) closesocket (a->sock); xfree (a); /* we can free our context now */ } return rc; } #endif /*HAVE_W32_SYSTEM*/ /**************** * This is used to implement the block write mode. * Block reading is done on a byte by byte basis in readbyte(), * without a filter */ static int block_filter (void *opaque, int control, iobuf_t chain, byte * buffer, size_t * ret_len) { block_filter_ctx_t *a = opaque; char *buf = (char *)buffer; size_t size = *ret_len; int c, needed, rc = 0; char *p; if (control == IOBUFCTRL_UNDERFLOW) { size_t n = 0; p = buf; log_assert (size); /* need a buffer */ if (a->eof) /* don't read any further */ rc = -1; while (!rc && size) { if (!a->size) { /* get the length bytes */ if (a->partial == 2) { a->eof = 1; if (!n) rc = -1; break; } else if (a->partial) { /* These OpenPGP introduced huffman like encoded length * bytes are really a mess :-( */ if (a->first_c) { c = a->first_c; a->first_c = 0; } else if ((c = iobuf_get (chain)) == -1) { log_error ("block_filter: 1st length byte missing\n"); rc = GPG_ERR_BAD_DATA; break; } if (c < 192) { a->size = c; a->partial = 2; if (!a->size) { a->eof = 1; if (!n) rc = -1; break; } } else if (c < 224) { a->size = (c - 192) * 256; if ((c = iobuf_get (chain)) == -1) { log_error ("block_filter: 2nd length byte missing\n"); rc = GPG_ERR_BAD_DATA; break; } a->size += c + 192; a->partial = 2; if (!a->size) { a->eof = 1; if (!n) rc = -1; break; } } else if (c == 255) { size_t len = 0; int i; for (i = 0; i < 4; i++) if ((c = iobuf_get (chain)) == -1) break; else len = ((len << 8) | c); if (i < 4) { log_error ("block_filter: invalid 4 byte length\n"); rc = GPG_ERR_BAD_DATA; break; } a->size = len; a->partial = 2; if (!a->size) { a->eof = 1; if (!n) rc = -1; break; } } else { /* Next partial body length. */ a->size = 1 << (c & 0x1f); } /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */ } else BUG (); } while (!rc && size && a->size) { needed = size < a->size ? size : a->size; c = iobuf_read (chain, p, needed); if (c < needed) { if (c == -1) c = 0; log_error ("block_filter %p: read error (size=%lu,a->size=%lu)\n", a, (ulong) size + c, (ulong) a->size + c); rc = GPG_ERR_BAD_DATA; } else { size -= c; a->size -= c; p += c; n += c; } } } *ret_len = n; } else if (control == IOBUFCTRL_FLUSH) { if (a->partial) { /* the complicated openpgp scheme */ size_t blen, n, nbytes = size + a->buflen; log_assert (a->buflen <= OP_MIN_PARTIAL_CHUNK); if (nbytes < OP_MIN_PARTIAL_CHUNK) { /* not enough to write a partial block out; so we store it */ if (!a->buffer) a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK); memcpy (a->buffer + a->buflen, buf, size); a->buflen += size; } else { /* okay, we can write out something */ /* do this in a loop to use the most efficient block lengths */ p = buf; do { /* find the best matching block length - this is limited * by the size of the internal buffering */ for (blen = OP_MIN_PARTIAL_CHUNK * 2, c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes; blen *= 2, c++) ; blen /= 2; c--; /* write the partial length header */ log_assert (c <= 0x1f); /*;-) */ c |= 0xe0; iobuf_put (chain, c); if ((n = a->buflen)) { /* write stuff from the buffer */ log_assert (n == OP_MIN_PARTIAL_CHUNK); if (iobuf_write (chain, a->buffer, n)) rc = gpg_error_from_syserror (); a->buflen = 0; nbytes -= n; } if ((n = nbytes) > blen) n = blen; if (n && iobuf_write (chain, p, n)) rc = gpg_error_from_syserror (); p += n; nbytes -= n; } while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK); /* store the rest in the buffer */ if (!rc && nbytes) { log_assert (!a->buflen); log_assert (nbytes < OP_MIN_PARTIAL_CHUNK); if (!a->buffer) a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK); memcpy (a->buffer, p, nbytes); a->buflen = nbytes; } } } else BUG (); } else if (control == IOBUFCTRL_INIT) { if (DBG_IOBUF) log_debug ("init block_filter %p\n", a); if (a->partial) a->count = 0; else if (a->use == IOBUF_INPUT) a->count = a->size = 0; else a->count = a->size; /* force first length bytes */ a->eof = 0; a->buffer = NULL; a->buflen = 0; } else if (control == IOBUFCTRL_DESC) { mem2str (buf, "block_filter", *ret_len); } else if (control == IOBUFCTRL_FREE) { if (a->use == IOBUF_OUTPUT) { /* write the end markers */ if (a->partial) { u32 len; /* write out the remaining bytes without a partial header * the length of this header may be 0 - but if it is * the first block we are not allowed to use a partial header * and frankly we can't do so, because this length must be * a power of 2. This is _really_ complicated because we * have to check the possible length of a packet prior * to it's creation: a chain of filters becomes complicated * and we need a lot of code to handle compressed packets etc. * :-((((((( */ /* construct header */ len = a->buflen; /*log_debug("partial: remaining length=%u\n", len ); */ if (len < 192) rc = iobuf_put (chain, len); else if (len < 8384) { if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192))) rc = iobuf_put (chain, ((len - 192) % 256)); } else { /* use a 4 byte header */ if (!(rc = iobuf_put (chain, 0xff))) if (!(rc = iobuf_put (chain, (len >> 24) & 0xff))) if (!(rc = iobuf_put (chain, (len >> 16) & 0xff))) if (!(rc = iobuf_put (chain, (len >> 8) & 0xff))) rc = iobuf_put (chain, len & 0xff); } if (!rc && len) rc = iobuf_write (chain, a->buffer, len); if (rc) { log_error ("block_filter: write error: %s\n", strerror (errno)); rc = gpg_error_from_syserror (); } xfree (a->buffer); a->buffer = NULL; a->buflen = 0; } else BUG (); } else if (a->size) { log_error ("block_filter: pending bytes!\n"); } if (DBG_IOBUF) log_debug ("free block_filter %p\n", a); xfree (a); /* we can free our context now */ } return rc; } /* Change the default size for all IOBUFs to KILOBYTE. This needs to * be called before any iobufs are used and can only be used once. * Returns the current value. Using 0 has no effect except for * returning the current value. */ unsigned int iobuf_set_buffer_size (unsigned int kilobyte) { static int used; if (!used && kilobyte) { if (kilobyte < 4) kilobyte = 4; else if (kilobyte > 16*1024) kilobyte = 16*1024; iobuf_buffer_size = kilobyte * 1024; used = 1; } return iobuf_buffer_size / 1024; } #define MAX_IOBUF_DESC 32 /* * Fill the buffer by the description of iobuf A. * The buffer size should be MAX_IOBUF_DESC (or larger). * Returns BUF as (const char *). */ static const char * iobuf_desc (iobuf_t a, byte *buf) { size_t len = MAX_IOBUF_DESC; if (! a || ! a->filter) memcpy (buf, "?", 2); else a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL, buf, &len); return buf; } static void print_chain (iobuf_t a) { if (!DBG_IOBUF) return; for (; a; a = a->chain) { byte desc[MAX_IOBUF_DESC]; log_debug ("iobuf chain: %d.%d '%s' filter_eof=%d start=%d len=%d\n", a->no, a->subno, iobuf_desc (a, desc), a->filter_eof, (int) a->d.start, (int) a->d.len); } } int iobuf_print_chain (iobuf_t a) { print_chain (a); return 0; } iobuf_t iobuf_alloc (int use, size_t bufsize) { iobuf_t a; static int number = 0; log_assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP); if (bufsize == 0) { log_bug ("iobuf_alloc() passed a bufsize of 0!\n"); bufsize = iobuf_buffer_size; } a = xcalloc (1, sizeof *a); a->use = use; a->d.buf = xmalloc (bufsize); a->d.size = bufsize; a->e_d.buf = NULL; a->e_d.len = 0; a->e_d.used = 0; a->e_d.preferred = 0; a->no = ++number; a->subno = 0; a->real_fname = NULL; return a; } int iobuf_close (iobuf_t a) { iobuf_t a_chain; size_t dummy_len = 0; int rc = 0; for (; a; a = a_chain) { byte desc[MAX_IOBUF_DESC]; int rc2 = 0; a_chain = a->chain; if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a))) log_error ("filter_flush failed on close: %s\n", gpg_strerror (rc)); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: close '%s'\n", a->no, a->subno, iobuf_desc (a, desc)); if (a->filter && (rc2 = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain, NULL, &dummy_len))) log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc)); if (! rc && rc2) /* Whoops! An error occurred. Save it in RC if we haven't already recorded an error. */ rc = rc2; xfree (a->real_fname); if (a->d.buf) { memset (a->d.buf, 0, a->d.size); /* erase the buffer */ xfree (a->d.buf); } xfree (a); } return rc; } int iobuf_cancel (iobuf_t a) { const char *s; iobuf_t a2; int rc; #if defined(HAVE_W32_SYSTEM) || defined(__riscos__) char *remove_name = NULL; #endif if (a && a->use == IOBUF_OUTPUT) { s = iobuf_get_real_fname (a); if (s && *s) { #if defined(HAVE_W32_SYSTEM) || defined(__riscos__) remove_name = xstrdup (s); #else remove (s); #endif } } /* send a cancel message to all filters */ for (a2 = a; a2; a2 = a2->chain) { size_t dummy = 0; if (a2->filter) a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy); } rc = iobuf_close (a); #if defined(HAVE_W32_SYSTEM) || defined(__riscos__) if (remove_name) { /* Argg, MSDOS does not allow removing open files. So * we have to do it here */ gnupg_remove (remove_name); xfree (remove_name); } #endif return rc; } iobuf_t iobuf_temp (void) { return iobuf_alloc (IOBUF_OUTPUT_TEMP, iobuf_buffer_size); } iobuf_t iobuf_temp_with_content (const char *buffer, size_t length) { iobuf_t a; int i; a = iobuf_alloc (IOBUF_INPUT_TEMP, length); log_assert (length == a->d.size); /* memcpy (a->d.buf, buffer, length); */ for (i=0; i < length; i++) a->d.buf[i] = buffer[i]; a->d.len = length; return a; } int iobuf_is_pipe_filename (const char *fname) { if (!fname || (*fname=='-' && !fname[1]) ) return 1; return check_special_filename (fname, 0, 1) != -1; } static iobuf_t do_open (const char *fname, int special_filenames, int use, const char *opentype, int mode700) { iobuf_t a; gnupg_fd_t fp; file_filter_ctx_t *fcx; size_t len = 0; int print_only = 0; int fd; byte desc[MAX_IOBUF_DESC]; log_assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT); if (special_filenames /* NULL or '-'. */ && (!fname || (*fname == '-' && !fname[1]))) { if (use == IOBUF_INPUT) { fp = FD_FOR_STDIN; fname = "[stdin]"; } else { fp = FD_FOR_STDOUT; fname = "[stdout]"; } print_only = 1; } else if (!fname) return NULL; else if (special_filenames && (fd = check_special_filename (fname, 0, 1)) != -1) return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1), opentype); else { if (use == IOBUF_INPUT) fp = fd_cache_open (fname, opentype); else fp = direct_open (fname, opentype, mode700); if (fp == GNUPG_INVALID_FD) return NULL; } a = iobuf_alloc (use, iobuf_buffer_size); fcx = xmalloc (sizeof *fcx + strlen (fname)); fcx->fp = fp; fcx->print_only_name = print_only; strcpy (fcx->fname, fname); if (!print_only) a->real_fname = xstrdup (fname); a->filter = file_filter; a->filter_ov = fcx; file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n", a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp)); return a; } iobuf_t iobuf_open (const char *fname) { return do_open (fname, 1, IOBUF_INPUT, "rb", 0); } iobuf_t iobuf_create (const char *fname, int mode700) { return do_open (fname, 1, IOBUF_OUTPUT, "wb", mode700); } iobuf_t iobuf_openrw (const char *fname) { return do_open (fname, 0, IOBUF_OUTPUT, "r+b", 0); } static iobuf_t do_iobuf_fdopen (int fd, const char *mode, int keep_open) { iobuf_t a; gnupg_fd_t fp; file_filter_ctx_t *fcx; size_t len = 0; fp = INT2FD (fd); a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT, iobuf_buffer_size); fcx = xmalloc (sizeof *fcx + 20); fcx->fp = fp; fcx->print_only_name = 1; fcx->keep_open = keep_open; sprintf (fcx->fname, "[fd %d]", fd); a->filter = file_filter; a->filter_ov = fcx; file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: fdopen%s '%s'\n", a->no, a->subno, keep_open? "_nc":"", fcx->fname); iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL); return a; } iobuf_t iobuf_fdopen (int fd, const char *mode) { return do_iobuf_fdopen (fd, mode, 0); } iobuf_t iobuf_fdopen_nc (int fd, const char *mode) { return do_iobuf_fdopen (fd, mode, 1); } iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open, size_t readlimit) { iobuf_t a; file_es_filter_ctx_t *fcx; size_t len = 0; a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT, iobuf_buffer_size); fcx = xtrymalloc (sizeof *fcx + 30); fcx->fp = estream; fcx->print_only_name = 1; fcx->keep_open = keep_open; fcx->readlimit = readlimit; fcx->use_readlimit = !!readlimit; snprintf (fcx->fname, 30, "[fd %p]", estream); a->filter = file_es_filter; a->filter_ov = fcx; file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: esopen%s '%s'\n", a->no, a->subno, keep_open? "_nc":"", fcx->fname); return a; } iobuf_t iobuf_sockopen (int fd, const char *mode) { iobuf_t a; #ifdef HAVE_W32_SYSTEM sock_filter_ctx_t *scx; size_t len; a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT, iobuf_buffer_size); scx = xmalloc (sizeof *scx + 25); scx->sock = fd; scx->print_only_name = 1; sprintf (scx->fname, "[sock %d]", fd); a->filter = sock_filter; a->filter_ov = scx; sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname); iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL); #else a = iobuf_fdopen (fd, mode); #endif return a; } int iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval) { byte desc[MAX_IOBUF_DESC]; if (cmd == IOBUF_IOCTL_KEEP_OPEN) { /* Keep system filepointer/descriptor open. This was used in the past by http.c; this ioctl is not directly used anymore. */ if (DBG_IOBUF) log_debug ("iobuf-%d.%d: ioctl '%s' keep_open=%d\n", a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc), intval); for (; a; a = a->chain) if (!a->chain && a->filter == file_filter) { file_filter_ctx_t *b = a->filter_ov; b->keep_open = intval; return 0; } #ifdef HAVE_W32_SYSTEM else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; b->keep_open = intval; return 0; } #endif } else if (cmd == IOBUF_IOCTL_INVALIDATE_CACHE) { if (DBG_IOBUF) log_debug ("iobuf-*.*: ioctl '%s' invalidate\n", ptrval ? (char *) ptrval : "?"); if (!a && !intval && ptrval) { if (fd_cache_invalidate (ptrval)) return -1; return 0; } } else if (cmd == IOBUF_IOCTL_NO_CACHE) { if (DBG_IOBUF) log_debug ("iobuf-%d.%d: ioctl '%s' no_cache=%d\n", a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc), intval); for (; a; a = a->chain) if (!a->chain && a->filter == file_filter) { file_filter_ctx_t *b = a->filter_ov; b->no_cache = intval; return 0; } #ifdef HAVE_W32_SYSTEM else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; b->no_cache = intval; return 0; } #endif } else if (cmd == IOBUF_IOCTL_FSYNC) { /* Do a fsync on the open fd and return any errors to the caller of iobuf_ioctl. Note that we work on a file name here. */ if (DBG_IOBUF) log_debug ("iobuf-*.*: ioctl '%s' fsync\n", ptrval? (const char*)ptrval:""); if (!a && !intval && ptrval) { return fd_cache_synchronize (ptrval); } } + else if (cmd == IOBUF_IOCTL_PEEK) + { + /* Peek at a justed opened file. Use this only directly after a + * file has been opened for reading. Don't use it after you did + * a seek. This works only if just file filter has been + * pushed. Expects a buffer wit size INTVAL at PTRVAL and returns + * the number of bytes put into the buffer. */ + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: ioctl '%s' peek\n", + a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc)); + if (a->filter == file_filter && ptrval && intval) + { + file_filter_ctx_t *fcx = a->filter_ov; + size_t len = intval; + + if (!file_filter (fcx, IOBUFCTRL_PEEK, NULL, ptrval, &len)) + return (int)len; + } + } return -1; } /**************** * Register an i/o filter. */ int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov) { return iobuf_push_filter2 (a, f, ov, 0); } int iobuf_push_filter2 (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov, int rel_ov) { iobuf_t b; size_t dummy_len = 0; int rc = 0; if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a))) return rc; if (a->subno >= MAX_NESTING_FILTER) { log_error ("i/o filter too deeply nested - corrupted data?\n"); return GPG_ERR_BAD_DATA; } /* We want to create a new filter and put it in front of A. A simple implementation would do: b = iobuf_alloc (...); b->chain = a; return a; This is a bit problematic: A is the head of the pipeline and there are potentially many pointers to it. Requiring the caller to update all of these pointers is a burden. An alternative implementation would add a level of indirection. For instance, we could use a pipeline object, which contains a pointer to the first filter in the pipeline. This is not what we do either. Instead, we allocate a new buffer (B) and copy the first filter's state into that and use the initial buffer (A) for the new filter. One limitation of this approach is that it is not practical to maintain a pointer to a specific filter's state. Before: A | v 0x100 0x200 +----------+ +----------+ | filter x |--------->| filter y |---->.... +----------+ +----------+ After: B | v 0x300 +----------+ A | filter x | | +----------+ v 0x100 ^ v 0x200 +----------+ +----------+ | filter w | | filter y |---->.... +----------+ +----------+ Note: filter x's address changed from 0x100 to 0x300, but A still points to the head of the pipeline. */ b = xmalloc (sizeof *b); memcpy (b, a, sizeof *b); /* fixme: it is stupid to keep a copy of the name at every level * but we need the name somewhere because the name known by file_filter * may have been released when we need the name of the file */ b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL; /* remove the filter stuff from the new stream */ a->filter = NULL; a->filter_ov = NULL; a->filter_ov_owner = 0; a->filter_eof = 0; if (a->use == IOBUF_OUTPUT_TEMP) /* A TEMP filter buffers any data sent to it; it does not forward any data down the pipeline. If we add a new filter to the pipeline, it shouldn't also buffer data. It should send it downstream to be buffered. Thus, the correct type for a filter added in front of an IOBUF_OUTPUT_TEMP filter is IOBUF_OUPUT, not IOBUF_OUTPUT_TEMP. */ { a->use = IOBUF_OUTPUT; /* When pipeline is written to, the temp buffer's size is increased accordingly. We don't need to allocate a 10 MB buffer for a non-terminal filter. Just use the default size. */ a->d.size = iobuf_buffer_size; } else if (a->use == IOBUF_INPUT_TEMP) /* Same idea as above. */ { a->use = IOBUF_INPUT; a->d.size = iobuf_buffer_size; } /* The new filter (A) gets a new buffer. If the pipeline is an output or temp pipeline, then giving the buffer to the new filter means that data that was written before the filter was pushed gets sent to the filter. That's clearly wrong. If the pipeline is an input pipeline, then giving the buffer to the new filter (A) means that data that has read from (B), but not yet read from the pipeline won't be processed by the new filter (A)! That's certainly not what we want. */ a->d.buf = xmalloc (a->d.size); a->d.len = 0; a->d.start = 0; /* disable nlimit for the new stream */ a->ntotal = b->ntotal + b->nbytes; a->nlimit = a->nbytes = 0; a->nofast = 0; /* make a link from the new stream to the original stream */ a->chain = b; /* setup the function on the new stream */ a->filter = f; a->filter_ov = ov; a->filter_ov_owner = rel_ov; a->subno = b->subno + 1; if (DBG_IOBUF) { byte desc[MAX_IOBUF_DESC]; log_debug ("iobuf-%d.%d: push '%s'\n", a->no, a->subno, iobuf_desc (a, desc)); print_chain (a); } /* now we can initialize the new function if we have one */ if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain, NULL, &dummy_len))) log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc)); return rc; } /**************** * Remove an i/o filter. */ int iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov) { iobuf_t b; size_t dummy_len = 0; int rc = 0; byte desc[MAX_IOBUF_DESC]; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, iobuf_desc (a, desc)); if (a->use == IOBUF_INPUT_TEMP || a->use == IOBUF_OUTPUT_TEMP) { /* This should be the last filter in the pipeline. */ log_assert (! a->chain); return 0; } if (!a->filter) { /* this is simple */ b = a->chain; log_assert (b); xfree (a->d.buf); xfree (a->real_fname); memcpy (a, b, sizeof *a); xfree (b); return 0; } for (b = a; b; b = b->chain) if (b->filter == f && (!ov || b->filter_ov == ov)) break; if (!b) log_bug ("iobuf_pop_filter(): filter function not found\n"); /* flush this stream if it is an output stream */ if (a->use == IOBUF_OUTPUT && (rc = filter_flush (b))) { log_error ("filter_flush failed in iobuf_pop_filter: %s\n", gpg_strerror (rc)); return rc; } /* and tell the filter to free it self */ if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain, NULL, &dummy_len))) { log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc)); return rc; } if (b->filter_ov && b->filter_ov_owner) { xfree (b->filter_ov); b->filter_ov = NULL; } /* and see how to remove it */ if (a == b && !b->chain) log_bug ("can't remove the last filter from the chain\n"); else if (a == b) { /* remove the first iobuf from the chain */ /* everything from b is copied to a. This is save because * a flush has been done on the to be removed entry */ b = a->chain; xfree (a->d.buf); xfree (a->real_fname); memcpy (a, b, sizeof *a); xfree (b); if (DBG_IOBUF) log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno); } else if (!b->chain) { /* remove the last iobuf from the chain */ log_bug ("Ohh jeee, trying to remove a head filter\n"); } else { /* remove an intermediate iobuf from the chain */ log_bug ("Ohh jeee, trying to remove an intermediate filter\n"); } return rc; } /**************** * read underflow: read at least one byte into the buffer and return * the first byte or -1 on EOF. */ static int underflow (iobuf_t a, int clear_pending_eof) { return underflow_target (a, clear_pending_eof, 1); } /**************** * read underflow: read TARGET bytes into the buffer and return * the first byte or -1 on EOF. */ static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target) { size_t len; int rc; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: underflow: buffer size: %d; still buffered: %d => space for %d bytes\n", a->no, a->subno, (int) a->d.size, (int) (a->d.len - a->d.start), (int) (a->d.size - (a->d.len - a->d.start))); if (a->use == IOBUF_INPUT_TEMP) /* By definition, there isn't more data to read into the buffer. */ return -1; log_assert (a->use == IOBUF_INPUT); a->e_d.used = 0; /* If there is still some buffered data, then move it to the start of the buffer and try to fill the end of the buffer. (This is useful if we are called from iobuf_peek().) */ log_assert (a->d.start <= a->d.len); a->d.len -= a->d.start; if (a->d.len) memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len); a->d.start = 0; if (a->d.len < target && a->filter_eof) /* The last time we tried to read from this filter, we got an EOF. We couldn't return the EOF, because there was buffered data. Since there is no longer any buffered data, return the error. */ { if (DBG_IOBUF) log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n", a->no, a->subno); if (! clear_pending_eof) return -1; if (a->chain) /* A filter follows this one. Free this filter. */ { iobuf_t b = a->chain; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: filter popped (pending EOF returned)\n", a->no, a->subno); xfree (a->d.buf); xfree (a->real_fname); memcpy (a, b, sizeof *a); xfree (b); print_chain (a); } else a->filter_eof = 0; /* for the top level filter */ return -1; /* return one(!) EOF */ } if (a->d.len == 0 && a->error) /* The last time we tried to read from this filter, we got an error. We couldn't return the error, because there was buffered data. Since there is no longer any buffered data, return the error. */ { if (DBG_IOBUF) log_debug ("iobuf-%d.%d: pending error (%s) returned\n", a->no, a->subno, gpg_strerror (a->error)); return -1; } if (a->filter && ! a->filter_eof && ! a->error) /* We have a filter function and the last time we tried to read we didn't get an EOF or an error. Try to fill the buffer. */ { /* Be careful to account for any buffered data. */ len = a->d.size - a->d.len; if (a->e_d.preferred && a->d.len < IOBUF_ZEROCOPY_THRESHOLD_SIZE && (IOBUF_ZEROCOPY_THRESHOLD_SIZE - a->d.len) < len) { if (DBG_IOBUF) log_debug ("iobuf-%d.%d: limit buffering as external drain is " "preferred\n", a->no, a->subno); len = IOBUF_ZEROCOPY_THRESHOLD_SIZE - a->d.len; } if (len == 0) /* There is no space for more data. Don't bother calling A->FILTER. */ rc = 0; else { /* If no buffered data and drain buffer has been setup, and drain * buffer is largish, read data directly to drain buffer. */ if (a->d.len == 0 && a->e_d.buf && a->e_d.len >= IOBUF_ZEROCOPY_THRESHOLD_SIZE) { len = a->e_d.len; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes, to external drain)\n", a->no, a->subno, (ulong)len); rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, a->e_d.buf, &len); a->e_d.used = len; len = 0; } else { if (DBG_IOBUF) log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n", a->no, a->subno, (ulong)len); rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, &a->d.buf[a->d.len], &len); } } a->d.len += len; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: A->FILTER() returned rc=%d (%s), read %lu bytes%s\n", a->no, a->subno, rc, rc == 0 ? "ok" : rc == -1 ? "EOF" : gpg_strerror (rc), (ulong)(a->e_d.used ? a->e_d.used : len), a->e_d.used ? " (to external buffer)" : ""); /* if( a->no == 1 ) */ /* log_hexdump (" data:", a->d.buf, len); */ if (rc == -1) /* EOF. */ { size_t dummy_len = 0; /* Tell the filter to free itself */ if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain, NULL, &dummy_len))) log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc)); /* Free everything except for the internal buffer. */ if (a->filter_ov && a->filter_ov_owner) xfree (a->filter_ov); a->filter_ov = NULL; a->filter = NULL; a->filter_eof = 1; if (clear_pending_eof && a->d.len == 0 && a->e_d.used == 0 && a->chain) /* We don't need to keep this filter around at all: - we got an EOF - we have no buffered data - a filter follows this one. Unlink this filter. */ { iobuf_t b = a->chain; if (DBG_IOBUF) log_debug ("iobuf-%d.%d: pop in underflow (nothing buffered, got EOF)\n", a->no, a->subno); xfree (a->d.buf); xfree (a->real_fname); memcpy (a, b, sizeof *a); xfree (b); print_chain (a); return -1; } else if (a->d.len == 0 && a->e_d.used == 0) /* We can't unlink this filter (it is the only one in the pipeline), but we can immediately return EOF. */ return -1; } else if (rc) /* Record the error. */ { a->error = rc; if (a->d.len == 0 && a->e_d.used == 0) /* There is no buffered data. Immediately return EOF. */ return -1; } } log_assert (a->d.start <= a->d.len); if (a->e_d.used > 0) return 0; if (a->d.start < a->d.len) return a->d.buf[a->d.start++]; /* EOF. */ return -1; } static int filter_flush (iobuf_t a) { int external_used = 0; byte *src_buf; size_t src_len; size_t len; int rc; a->e_d.used = 0; if (a->use == IOBUF_OUTPUT_TEMP) { /* increase the temp buffer */ size_t newsize = a->d.size + iobuf_buffer_size; if (DBG_IOBUF) log_debug ("increasing temp iobuf from %lu to %lu\n", (ulong) a->d.size, (ulong) newsize); a->d.buf = xrealloc (a->d.buf, newsize); a->d.size = newsize; return 0; } else if (a->use != IOBUF_OUTPUT) log_bug ("flush on non-output iobuf\n"); else if (!a->filter) log_bug ("filter_flush: no filter\n"); if (a->d.len == 0 && a->e_d.buf && a->e_d.len > 0) { src_buf = a->e_d.buf; src_len = a->e_d.len; external_used = 1; } else { src_buf = a->d.buf; src_len = a->d.len; external_used = 0; } len = src_len; rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, src_buf, &len); if (!rc && len != src_len) { log_info ("filter_flush did not write all!\n"); rc = GPG_ERR_INTERNAL; } else if (rc) a->error = rc; a->d.len = 0; if (external_used) a->e_d.used = len; return rc; } int iobuf_readbyte (iobuf_t a) { int c; if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP) { log_bug ("iobuf_readbyte called on a non-INPUT pipeline!\n"); return -1; } log_assert (a->d.start <= a->d.len); if (a->nlimit && a->nbytes >= a->nlimit) return -1; /* forced EOF */ if (a->d.start < a->d.len) { c = a->d.buf[a->d.start++]; } else if ((c = underflow (a, 1)) == -1) return -1; /* EOF */ log_assert (a->d.start <= a->d.len); /* Note: if underflow doesn't return EOF, then it returns the first byte that was read and advances a->d.start appropriately. */ a->nbytes++; return c; } int iobuf_read (iobuf_t a, void *buffer, unsigned int buflen) { unsigned char *buf = (unsigned char *)buffer; int c, n; if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP) { log_bug ("iobuf_read called on a non-INPUT pipeline!\n"); return -1; } if (a->nlimit) { /* Handle special cases. */ for (n = 0; n < buflen; n++) { if ((c = iobuf_readbyte (a)) == -1) { if (!n) return -1; /* eof */ break; } if (buf) { *buf = c; buf++; } } return n; } a->e_d.buf = NULL; a->e_d.len = 0; /* Hint for how full to fill iobuf internal drain buffer. */ a->e_d.preferred = (a->use != IOBUF_INPUT_TEMP) && (buf && buflen >= IOBUF_ZEROCOPY_THRESHOLD_SIZE); n = 0; do { if (n < buflen && a->d.start < a->d.len) /* Drain the buffer. */ { unsigned size = a->d.len - a->d.start; if (size > buflen - n) size = buflen - n; if (buf) memcpy (buf, a->d.buf + a->d.start, size); n += size; a->d.start += size; if (buf) buf += size; } if (n < buflen) /* Draining the internal buffer didn't fill BUFFER. Call underflow to read more data into the filter's internal buffer. */ { if (a->use != IOBUF_INPUT_TEMP && buf && n < buflen) { /* Setup external drain buffer for faster moving of data * (avoid memcpy). */ a->e_d.buf = buf; a->e_d.len = (buflen - n) / IOBUF_ZEROCOPY_THRESHOLD_SIZE * IOBUF_ZEROCOPY_THRESHOLD_SIZE; if (a->e_d.len == 0) a->e_d.buf = NULL; if (a->e_d.buf && DBG_IOBUF) log_debug ("iobuf-%d.%d: reading to external buffer, %lu bytes\n", a->no, a->subno, (ulong)a->e_d.len); } if ((c = underflow (a, 1)) == -1) /* EOF. If we managed to read something, don't return EOF now. */ { a->e_d.buf = NULL; a->e_d.len = 0; a->nbytes += n; return n ? n : -1 /*EOF*/; } if (a->e_d.buf && a->e_d.used > 0) { /* Drain buffer was used, 'c' only contains return code * 0 or -1. */ n += a->e_d.used; buf += a->e_d.used; } else { if (buf) *buf++ = c; n++; } a->e_d.buf = NULL; a->e_d.len = 0; } } while (n < buflen); a->nbytes += n; return n; } int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen) { int n = 0; log_assert (buflen > 0); log_assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP); if (buflen > a->d.size) /* We can't peek more than we can buffer. */ buflen = a->d.size; /* Try to fill the internal buffer with enough data to satisfy the request. */ while (buflen > a->d.len - a->d.start) { if (underflow_target (a, 0, buflen) == -1) /* EOF. We can't read any more. */ break; /* Underflow consumes the first character (it's the return value). unget() it by resetting the "file position". */ log_assert (a->d.start == 1); a->d.start = 0; } n = a->d.len - a->d.start; if (n > buflen) n = buflen; if (n == 0) /* EOF. */ return -1; memcpy (buf, &a->d.buf[a->d.start], n); return n; } int iobuf_writebyte (iobuf_t a, unsigned int c) { int rc; if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP) { log_bug ("iobuf_writebyte called on an input pipeline!\n"); return -1; } if (a->d.len == a->d.size) if ((rc=filter_flush (a))) return rc; log_assert (a->d.len < a->d.size); a->d.buf[a->d.len++] = c; return 0; } int iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen) { const unsigned char *buf = (const unsigned char *)buffer; int rc; if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP) { log_bug ("iobuf_write called on an input pipeline!\n"); return -1; } a->e_d.buf = NULL; a->e_d.len = 0; /* Hint for how full to fill iobuf internal drain buffer. */ a->e_d.preferred = (a->use != IOBUF_OUTPUT_TEMP) && (buflen >= IOBUF_ZEROCOPY_THRESHOLD_SIZE); do { if ((a->use != IOBUF_OUTPUT_TEMP) && a->d.len == 0 && buflen >= IOBUF_ZEROCOPY_THRESHOLD_SIZE) { /* Setup external drain buffer for faster moving of data * (avoid memcpy). */ a->e_d.buf = (byte *)buf; a->e_d.len = buflen / IOBUF_ZEROCOPY_THRESHOLD_SIZE * IOBUF_ZEROCOPY_THRESHOLD_SIZE; if (a->e_d.len == 0) a->e_d.buf = NULL; if (a->e_d.buf && DBG_IOBUF) log_debug ("iobuf-%d.%d: writing from external buffer, %lu bytes\n", a->no, a->subno, (ulong)a->e_d.len); } if (a->e_d.buf == NULL && buflen && a->d.len < a->d.size) { unsigned size; if (a->e_d.preferred && a->d.len < IOBUF_ZEROCOPY_THRESHOLD_SIZE) size = IOBUF_ZEROCOPY_THRESHOLD_SIZE - a->d.len; else size = a->d.size - a->d.len; if (size > buflen) size = buflen; memcpy (a->d.buf + a->d.len, buf, size); buflen -= size; buf += size; a->d.len += size; } if (buflen) { rc = filter_flush (a); if (rc) { a->e_d.buf = NULL; a->e_d.len = 0; return rc; } } if (a->e_d.buf && a->e_d.used > 0) { buf += a->e_d.used; buflen -= a->e_d.used; } a->e_d.buf = NULL; a->e_d.len = 0; } while (buflen); return 0; } int iobuf_writestr (iobuf_t a, const char *buf) { if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP) { log_bug ("iobuf_writestr called on an input pipeline!\n"); return -1; } return iobuf_write (a, buf, strlen (buf)); } int iobuf_write_temp (iobuf_t dest, iobuf_t source) { log_assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP); log_assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP); iobuf_flush_temp (source); return iobuf_write (dest, source->d.buf, source->d.len); } size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen) { byte desc[MAX_IOBUF_DESC]; size_t n; while (1) { int rc = filter_flush (a); if (rc) log_bug ("Flushing iobuf %d.%d (%s) from iobuf_temp_to_buffer failed. Ignoring.\n", a->no, a->subno, iobuf_desc (a, desc)); if (! a->chain) break; a = a->chain; } n = a->d.len; if (n > buflen) n = buflen; memcpy (buffer, a->d.buf, n); return n; } /* Copies the data from the input iobuf SOURCE to the output iobuf DEST until either an error is encountered or EOF is reached. Returns the number of bytes copies or (size_t)(-1) on error. */ size_t iobuf_copy (iobuf_t dest, iobuf_t source) { char *temp; size_t temp_size; size_t nread; size_t nwrote = 0; size_t max_read = 0; int err; log_assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP); log_assert (dest->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP); if (iobuf_error (dest)) return (size_t)(-1); /* Use iobuf buffer size for temporary buffer. */ temp_size = iobuf_set_buffer_size(0) * 1024; temp = xmalloc (temp_size); while (1) { nread = iobuf_read (source, temp, temp_size); if (nread == -1) /* EOF. */ break; if (nread > max_read) max_read = nread; err = iobuf_write (dest, temp, nread); if (err) break; nwrote += nread; } /* Burn the buffer. */ if (max_read) wipememory (temp, max_read); xfree (temp); return nwrote; } void iobuf_flush_temp (iobuf_t temp) { if (temp->use == IOBUF_INPUT || temp->use == IOBUF_INPUT_TEMP) log_bug ("iobuf_flush_temp called on an input pipeline!\n"); while (temp->chain) iobuf_pop_filter (temp, temp->filter, NULL); } void iobuf_set_limit (iobuf_t a, off_t nlimit) { if (nlimit) a->nofast = 1; else a->nofast = 0; a->nlimit = nlimit; a->ntotal += a->nbytes; a->nbytes = 0; } off_t iobuf_get_filelength (iobuf_t a, int *overflow) { if (overflow) *overflow = 0; /* Hmmm: file_filter may have already been removed */ for ( ; a->chain; a = a->chain ) ; if (a->filter != file_filter) return 0; { file_filter_ctx_t *b = a->filter_ov; gnupg_fd_t fp = b->fp; #if defined(HAVE_W32_SYSTEM) ulong size; static int (* __stdcall get_file_size_ex) (void *handle, LARGE_INTEGER *r_size); static int get_file_size_ex_initialized; if (!get_file_size_ex_initialized) { void *handle; handle = dlopen ("kernel32.dll", RTLD_LAZY); if (handle) { get_file_size_ex = dlsym (handle, "GetFileSizeEx"); if (!get_file_size_ex) dlclose (handle); } get_file_size_ex_initialized = 1; } if (get_file_size_ex) { /* This is a newer system with GetFileSizeEx; we use this then because it seem that GetFileSize won't return a proper error in case a file is larger than 4GB. */ LARGE_INTEGER exsize; if (get_file_size_ex (fp, &exsize)) { if (!exsize.u.HighPart) return exsize.u.LowPart; if (overflow) *overflow = 1; return 0; } } else { if ((size=GetFileSize (fp, NULL)) != 0xffffffff) return size; } log_error ("GetFileSize for handle %p failed: %s\n", fp, w32_strerror (-1)); #else /*!HAVE_W32_SYSTEM*/ { struct stat st; if ( !fstat (fp, &st) ) return st.st_size; log_error("fstat() failed: %s\n", strerror(errno) ); } #endif /*!HAVE_W32_SYSTEM*/ } return 0; } int iobuf_get_fd (iobuf_t a) { for (; a->chain; a = a->chain) ; if (a->filter != file_filter) return -1; { file_filter_ctx_t *b = a->filter_ov; gnupg_fd_t fp = b->fp; return FD2INT (fp); } } off_t iobuf_tell (iobuf_t a) { return a->ntotal + a->nbytes; } #if !defined(HAVE_FSEEKO) && !defined(fseeko) #ifdef HAVE_LIMITS_H # include #endif #ifndef LONG_MAX # define LONG_MAX ((long) ((unsigned long) -1 >> 1)) #endif #ifndef LONG_MIN # define LONG_MIN (-1 - LONG_MAX) #endif /**************** * A substitute for fseeko, for hosts that don't have it. */ static int fseeko (FILE * stream, off_t newpos, int whence) { while (newpos != (long) newpos) { long pos = newpos < 0 ? LONG_MIN : LONG_MAX; if (fseek (stream, pos, whence) != 0) return -1; newpos -= pos; whence = SEEK_CUR; } return fseek (stream, (long) newpos, whence); } #endif int iobuf_seek (iobuf_t a, off_t newpos) { file_filter_ctx_t *b = NULL; if (a->use == IOBUF_OUTPUT || a->use == IOBUF_INPUT) { /* Find the last filter in the pipeline. */ for (; a->chain; a = a->chain) ; if (a->filter != file_filter) return -1; b = a->filter_ov; #ifdef HAVE_W32_SYSTEM if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff) { log_error ("SetFilePointer failed on handle %p: ec=%d\n", b->fp, (int) GetLastError ()); return -1; } #else if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1) { log_error ("can't lseek: %s\n", strerror (errno)); return -1; } #endif /* Discard the buffer it is not a temp stream. */ a->d.len = 0; } a->d.start = 0; a->nbytes = 0; a->nlimit = 0; a->nofast = 0; a->ntotal = newpos; a->error = 0; /* It is impossible for A->CHAIN to be non-NULL. If A is an INPUT or OUTPUT buffer, then we find the last filter, which is defined as A->CHAIN being NULL. If A is a TEMP filter, then A must be the only filter in the pipe: when iobuf_push_filter adds a filter to the front of a pipeline, it sets the new filter to be an OUTPUT filter if the pipeline is an OUTPUT or TEMP pipeline and to be an INPUT filter if the pipeline is an INPUT pipeline. Thus, only the last filter in a TEMP pipeline can be a */ /* remove filters, but the last */ if (a->chain) log_debug ("iobuf_pop_filter called in iobuf_seek - please report\n"); while (a->chain) iobuf_pop_filter (a, a->filter, NULL); return 0; } const char * iobuf_get_real_fname (iobuf_t a) { if (a->real_fname) return a->real_fname; /* the old solution */ for (; a; a = a->chain) if (!a->chain && a->filter == file_filter) { file_filter_ctx_t *b = a->filter_ov; return b->print_only_name ? NULL : b->fname; } return NULL; } const char * iobuf_get_fname (iobuf_t a) { for (; a; a = a->chain) if (!a->chain && a->filter == file_filter) { file_filter_ctx_t *b = a->filter_ov; return b->fname; } return NULL; } const char * iobuf_get_fname_nonnull (iobuf_t a) { const char *fname; fname = iobuf_get_fname (a); return fname? fname : "[?]"; } /**************** * Enable or disable partial body length mode (RFC 4880 4.2.2.4). * * If LEN is 0, this disables partial block mode by popping the * partial body length filter, which must be the most recently * added filter. * * If LEN is non-zero, it pushes a partial body length filter. If * this is a read filter, LEN must be the length byte from the first * chunk and A should be position just after this first partial body * length header. */ void iobuf_set_partial_body_length_mode (iobuf_t a, size_t len) { if (!len) /* Disable partial body length mode. */ { if (a->use == IOBUF_INPUT) log_debug ("iobuf_pop_filter called in set_partial_block_mode" " - please report\n"); log_assert (a->filter == block_filter); iobuf_pop_filter (a, block_filter, NULL); } else /* Enabled partial body length mode. */ { block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx); ctx->use = a->use; ctx->partial = 1; ctx->size = 0; ctx->first_c = len; iobuf_push_filter (a, block_filter, ctx); } } unsigned int iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, unsigned *length_of_buffer, unsigned *max_length) { int c; char *buffer = (char *)*addr_of_buffer; unsigned length = *length_of_buffer; unsigned nbytes = 0; unsigned maxlen = *max_length; char *p; /* The code assumes that we have space for at least a newline and a NUL character in the buffer. This requires at least 2 bytes. We don't complicate the code by handling the stupid corner case, but simply assert that it can't happen. */ log_assert (!buffer || length >= 2 || maxlen >= 2); if (!buffer || length <= 1) /* must allocate a new buffer */ { length = 256 <= maxlen ? 256 : maxlen; buffer = xrealloc (buffer, length); *addr_of_buffer = (unsigned char *)buffer; *length_of_buffer = length; } p = buffer; while (1) { if (!a->nofast && a->d.start < a->d.len && nbytes < length - 1) /* Fast path for finding '\n' by using standard C library's optimized memchr. */ { unsigned size = a->d.len - a->d.start; byte *newline_pos; if (size > length - 1 - nbytes) size = length - 1 - nbytes; newline_pos = memchr (a->d.buf + a->d.start, '\n', size); if (newline_pos) { /* Found newline, copy buffer and return. */ size = (newline_pos - (a->d.buf + a->d.start)) + 1; memcpy (p, a->d.buf + a->d.start, size); p += size; nbytes += size; a->d.start += size; a->nbytes += size; break; } else { /* No newline, copy buffer and continue. */ memcpy (p, a->d.buf + a->d.start, size); p += size; nbytes += size; a->d.start += size; a->nbytes += size; } } else { c = iobuf_readbyte (a); if (c == -1) break; *p++ = c; nbytes++; if (c == '\n') break; } if (nbytes == length - 1) /* We don't have enough space to add a \n and a \0. Increase the buffer size. */ { if (length == maxlen) /* We reached the buffer's size limit! */ { /* Skip the rest of the line. */ while ((c = iobuf_get (a)) != -1 && c != '\n') ; /* p is pointing at the last byte in the buffer. We always terminate the line with "\n\0" so overwrite the previous byte with a \n. */ log_assert (p > buffer); p[-1] = '\n'; /* Indicate truncation. */ *max_length = 0; break; } length += length < 1024 ? 256 : 1024; if (length > maxlen) length = maxlen; buffer = xrealloc (buffer, length); *addr_of_buffer = (unsigned char *)buffer; *length_of_buffer = length; p = buffer + nbytes; } } /* Add the terminating NUL. */ *p = 0; /* Return the number of characters written to the buffer including the newline, but not including the terminating NUL. */ return nbytes; } static int translate_file_handle (int fd, int for_write) { #if defined(HAVE_W32_SYSTEM) { int x; (void)for_write; if (fd == 0) x = (int) GetStdHandle (STD_INPUT_HANDLE); else if (fd == 1) x = (int) GetStdHandle (STD_OUTPUT_HANDLE); else if (fd == 2) x = (int) GetStdHandle (STD_ERROR_HANDLE); else x = fd; if (x == -1) log_debug ("GetStdHandle(%d) failed: ec=%d\n", fd, (int) GetLastError ()); fd = x; } #else (void)for_write; #endif return fd; } void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial) { if ( partial ) { for (;;) { if (a->nofast || a->d.start >= a->d.len) { if (iobuf_readbyte (a) == -1) { break; } } else { unsigned long count = a->d.len - a->d.start; a->nbytes += count; a->d.start = a->d.len; } } } else { unsigned long remaining = n; while (remaining > 0) { if (a->nofast || a->d.start >= a->d.len) { if (iobuf_readbyte (a) == -1) { break; } --remaining; } else { unsigned long count = a->d.len - a->d.start; if (count > remaining) { count = remaining; } a->nbytes += count; a->d.start += count; remaining -= count; } } } } diff --git a/common/iobuf.h b/common/iobuf.h index f527fbf16..c132c2f3c 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -1,643 +1,645 @@ /* iobuf.h - I/O buffer * Copyright (C) 1998, 1999, 2000, 2001, 2003, * 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * * This file is free software; you can redistribute it and/or modify * it under the terms of either * * - the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at * your option) any later version. * * or * * - the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at * your option) any later version. * * or both in parallel, as here. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef GNUPG_COMMON_IOBUF_H #define GNUPG_COMMON_IOBUF_H /* An iobuf is basically a filter in a pipeline. Consider the following command, which consists of three filters that are chained together: $ cat file | base64 --decode | gunzip The first filter reads the file from the file system and sends that data to the second filter. The second filter decodes base64-encoded data and sends the data to the third and last filter. The last filter decompresses the data and the result is displayed on the terminal. The iobuf system works in the same way where each iobuf is a filter and the individual iobufs can be chained together. There are number of predefined filters. iobuf_open(), for instance, creates a filter that reads from a specified file. And, iobuf_temp_with_content() creates a filter that returns some specified contents. There are also filters for writing content. iobuf_openrw opens a file for writing. iobuf_temp creates a filter that writes data to a fixed-sized buffer. To chain filters together, you use the iobuf_push_filter() function. The filters are chained together using the chain field in the iobuf_t. A pipeline can only be used for reading (IOBUF_INPUT) or for writing (IOBUF_OUTPUT / IOBUF_OUTPUT_TEMP). When reading, data flows from the last filter towards the first. That is, the user calls iobuf_read(), the module reads from the first filter, which gets its input from the second filter, etc. When writing, data flows from the first filter towards the last. In this case, when the user calls iobuf_write(), the data is written to the first filter, which writes the transformed data to the second filter, etc. An iobuf_t contains some state about the filter. For instance, it indicates if the filter has already returned EOF (filter_eof) and the next filter in the pipeline, if any (chain). It also contains a function pointer, filter. This is a generic function. It is called when input is needed or output is available. In this case it is passed a pointer to some filter-specific persistent state (filter_ov), the actual operation, the next filter in the chain, if any, and a buffer that either contains the contents to write, if the pipeline is setup to write data, or is the place to store data, if the pipeline is setup to read data. Unlike a Unix pipeline, an IOBUF pipeline can return EOF multiple times. This is similar to the following: { cat file1; cat file2; } | grep foo However, instead of grep seeing a single stream, grep would see each byte stream followed by an EOF marker. (When a filter returns EOF, the EOF is returned to the user exactly once and then the filter is removed from the pipeline.) */ /* For estream_t. */ #include #include "../common/types.h" #include "../common/sysutils.h" #define DBG_IOBUF iobuf_debug_mode /* Filter control modes. */ enum { IOBUFCTRL_INIT = 1, IOBUFCTRL_FREE = 2, IOBUFCTRL_UNDERFLOW = 3, IOBUFCTRL_FLUSH = 4, IOBUFCTRL_DESC = 5, IOBUFCTRL_CANCEL = 6, + IOBUFCTRL_PEEK = 7, IOBUFCTRL_USER = 16 }; /* Command codes for iobuf_ioctl. */ typedef enum { IOBUF_IOCTL_KEEP_OPEN = 1, /* Uses intval. */ IOBUF_IOCTL_INVALIDATE_CACHE = 2, /* Uses ptrval. */ IOBUF_IOCTL_NO_CACHE = 3, /* Uses intval. */ - IOBUF_IOCTL_FSYNC = 4 /* Uses ptrval. */ + IOBUF_IOCTL_FSYNC = 4, /* Uses ptrval. */ + IOBUF_IOCTL_PEEK = 5 /* Uses intval and ptrval. */ } iobuf_ioctl_t; enum iobuf_use { /* Pipeline is in input mode. The data flows from the end to the beginning. That is, when reading from the pipeline, the first filter gets its input from the second filter, etc. */ IOBUF_INPUT, /* Pipeline is in input mode. The last filter in the pipeline is a temporary buffer from which the data is "read". */ IOBUF_INPUT_TEMP, /* Pipeline is in output mode. The data flows from the beginning to the end. That is, when writing to the pipeline, the user writes to the first filter, which transforms the data and sends it to the second filter, etc. */ IOBUF_OUTPUT, /* Pipeline is in output mode. The last filter in the pipeline is a temporary buffer that grows as necessary. */ IOBUF_OUTPUT_TEMP }; typedef struct iobuf_struct *iobuf_t; typedef struct iobuf_struct *IOBUF; /* Compatibility with gpg 1.4. */ /* fixme: we should hide most of this stuff */ struct iobuf_struct { /* The type of filter. Either IOBUF_INPUT, IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP. */ enum iobuf_use use; /* nlimit can be changed using iobuf_set_limit. If non-zero, it is the number of additional bytes that can be read from the filter before EOF is forcefully returned. */ off_t nlimit; /* nbytes if the number of bytes that have been read (using iobuf_get / iobuf_readbyte / iobuf_read) since the last call to iobuf_set_limit. */ off_t nbytes; /* The number of bytes read prior to the last call to iobuf_set_limit. Thus, the total bytes read (i.e., the position of stream) is ntotal + nbytes. */ off_t ntotal; /* Whether we need to read from the filter one byte at a time or whether we can do bulk reads. We need to read one byte at a time if a limit (set via iobuf_set_limit) is active. */ int nofast; /* A buffer for unread/unwritten data. For an output pipeline (IOBUF_OUTPUT), this is the data that has not yet been written to the filter. Consider a simple pipeline consisting of a single stage, which writes to a file. When you write to the pipeline (iobuf_writebyte or iobuf_write), the data is first stored in this buffer. Only when the buffer is full or you call iobuf_flush() is FILTER actually called and the data written to the file. For an input pipeline (IOBUF_INPUT), this is the data that has been read from this filter, but not yet been read from the preceding filter (or the user, if this filter is the head of the pipeline). Again, consider a simple pipeline consisting of a single stage. This stage reads from a file. If you read a single byte (iobuf_get) and the buffer is empty, then FILTER is called to fill the buffer. In this case, a single byte is not requested, but the whole buffer is filled (if possible). */ struct { /* Size of the buffer. */ size_t size; /* Number of bytes at the beginning of the buffer that have already been consumed. (In other words: the index of the first byte that hasn't been consumed.) This is only non-zero for input filters. */ size_t start; /* The number of bytes in the buffer including any bytes that have been consumed. */ size_t len; /* The buffer itself. */ byte *buf; } d; /* A external drain buffer for reading/writting data skipping internal draint buffer D.BUF. This allows zerocopy operation reducing processing overhead across filter stack. Used when by iobuf_read/iobuf_write when internal buffer has been depleted and remaining external buffer length is large enough. */ struct { /* The external buffer provided by iobuf_read/iobuf_write caller. */ byte *buf; /* The number of bytes in the external buffer. */ size_t len; /* The number of bytes that were consumed from the external buffer. */ size_t used; /* Gives hint for processing that the external buffer is preferred and that internal buffer should be consumed early. */ int preferred; } e_d; /* When FILTER is called to read some data, it may read some data and then return EOF. We can't return the EOF immediately. Instead, we note that we observed the EOF and when the buffer is finally empty, we return the EOF. */ int filter_eof; /* Like filter_eof, when FILTER is called to read some data, it may read some data and then return an error. We can't return the error (in the form of an EOF) immediately. Instead, we note that we observed the error and when the buffer is finally empty, we return the EOF. */ int error; /* The callback function to read data from the filter, etc. See iobuf_filter_push for details. */ int (*filter) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len); /* An opaque pointer that can be used for local filter state. This is passed as the first parameter to FILTER. */ void *filter_ov; /* Whether the iobuf code should free(filter_ov) when destroying the filter. */ int filter_ov_owner; /* When using iobuf_open, iobuf_create, iobuf_openrw to open a file, the file's name is saved here. This is used to delete the file when an output pipeline (IOBUF_OUPUT) is canceled (iobuf_cancel). */ char *real_fname; /* The next filter in the pipeline. */ iobuf_t chain; /* This field is for debugging. Each time a filter is allocated (via iobuf_alloc()), a monotonically increasing counter is incremented and this field is set to the new value. This field should only be accessed via the iobuf_io macro. */ int no; /* The number of filters in the pipeline following (not including) this one. When you call iobuf_push_filter or iobuf_push_filter2, this value is used to check the length of the pipeline if the pipeline already contains 65 stages then these functions fail. This amount of nesting typically indicates corrupted data or an active denial of service attack. */ int subno; }; extern int iobuf_debug_mode; /* Change the default size for all IOBUFs to KILOBYTE. This needs to * be called before any iobufs are used and can only be used once. * Returns the current value. Using 0 has no effect except for * returning the current value. */ unsigned int iobuf_set_buffer_size (unsigned int kilobyte); /* Returns whether the specified filename corresponds to a pipe. In particular, this function checks if FNAME is "-" and, if special filenames are enabled (see check_special_filename), whether FNAME is a special filename. */ int iobuf_is_pipe_filename (const char *fname); /* Allocate a new filter. This filter doesn't have a function assigned to it. Thus you need to manually set IOBUF->FILTER and IOBUF->FILTER_OV, if required. This function is intended to help create a new primary source or primary sink, i.e., the last filter in the pipeline. USE is IOBUF_INPUT, IOBUF_INPUT_TEMP, IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP. BUFSIZE is the desired internal buffer size (that is, the size of the typical read / write request). */ iobuf_t iobuf_alloc (int use, size_t bufsize); /* Create an output filter that simply buffers data written to it. This is useful for collecting data for later processing. The buffer can be written to in the usual way (iobuf_write, etc.). The data can later be extracted using iobuf_write_temp() or iobuf_temp_to_buffer(). */ iobuf_t iobuf_temp (void); /* Create an input filter that contains some data for reading. */ iobuf_t iobuf_temp_with_content (const char *buffer, size_t length); /* Create an input file filter that reads from a file. If FNAME is '-', reads from stdin. If special filenames are enabled (iobuf_enable_special_filenames), then interprets special filenames. */ iobuf_t iobuf_open (const char *fname); /* Create an output file filter that writes to a file. If FNAME is NULL or '-', writes to stdout. If special filenames are enabled (iobuf_enable_special_filenames), then interprets special filenames. If FNAME is not NULL, '-' or a special filename, the file is opened for writing. If the file exists, it is truncated. If MODE700 is TRUE, the file is created with mode 600. Otherwise, mode 666 is used. */ iobuf_t iobuf_create (const char *fname, int mode700); /* Create an output file filter that writes to a specified file. Neither '-' nor special file names are recognized. */ iobuf_t iobuf_openrw (const char *fname); /* Create a file filter using an existing file descriptor. If MODE contains the letter 'w', creates an output filter. Otherwise, creates an input filter. Note: MODE must reflect the file descriptors actual mode! When the filter is destroyed, the file descriptor is closed. */ iobuf_t iobuf_fdopen (int fd, const char *mode); /* Like iobuf_fdopen, but doesn't close the file descriptor when the filter is destroyed. */ iobuf_t iobuf_fdopen_nc (int fd, const char *mode); /* Create a filter using an existing estream. If MODE contains the letter 'w', creates an output filter. Otherwise, creates an input filter. If KEEP_OPEN is TRUE, then the stream is not closed when the filter is destroyed. Otherwise, the stream is closed when the filter is destroyed. If READLIMIT is not 0 this gives a limit on the number of bytes to read from estream. */ iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open, size_t readlimit); /* Create a filter using an existing socket. On Windows creates a special socket filter. On non-Windows systems simply, this simply calls iobuf_fdopen. */ iobuf_t iobuf_sockopen (int fd, const char *mode); /* Set various options / perform different actions on a PIPELINE. See the IOBUF_IOCTL_* macros above. */ int iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval); /* Close a pipeline. The filters in the pipeline are first flushed using iobuf_flush, if they are output filters, and then IOBUFCTRL_FREE is called on each filter. If any filter returns a non-zero value in response to the IOBUFCTRL_FREE, that first such non-zero value is returned. Note: processing is not aborted in this case. If all filters are freed successfully, 0 is returned. */ int iobuf_close (iobuf_t iobuf); /* Calls IOBUFCTRL_CANCEL on each filter in the pipeline. Then calls io_close() on the pipeline. Finally, if the pipeline is an output pipeline, deletes the file. Returns the result of calling iobuf_close on the pipeline. */ int iobuf_cancel (iobuf_t iobuf); /* Add a new filter to the front of a pipeline. A is the head of the pipeline. F is the filter implementation. OV is an opaque pointer that is passed to F and is normally used to hold any internal state, such as a file pointer. Note: you may only maintain a reference to an iobuf_t as a reference to the head of the pipeline. That is, don't think about setting a pointer in OV to point to the filter's iobuf_t. This is because when we add a new filter to a pipeline, we memcpy the state in A into new buffer. This has the advantage that there is no need to update any references to the pipeline when a filter is added or removed, but it also means that a filter's state moves around in memory. The behavior of the filter function is determined by the value of the control parameter: IOBUFCTRL_INIT: Called this value just before the filter is linked into the pipeline. This can be used to initialize internal data structures. IOBUFCTRL_FREE: Called with this value just before the filter is removed from the pipeline. Normally used to release internal data structures, close a file handle, etc. IOBUFCTRL_UNDERFLOW: Called with this value to fill the passed buffer with more data. *LEN is the size of the buffer. Before returning, it should be set to the number of bytes which were written into the buffer. The function must return 0 to indicate success, -1 on EOF and a GPG_ERR_xxxxx code for any error. Note: this function may both return data and indicate an error or EOF. In this case, it simply writes the data to BUF, sets *LEN and returns the appropriate return code. The implication is that if an error occurs and no data has yet been written, it is essential that *LEN be set to 0! IOBUFCTRL_FLUSH: Called with this value to write out any collected data. *LEN is the number of bytes in BUF that need to be written out. Returns 0 on success and a GPG_ERR_* code otherwise. *LEN must be set to the number of bytes that were written out. IOBUFCTRL_CANCEL: Called with this value when iobuf_cancel() is called on the pipeline. IOBUFCTRL_DESC: Called with this value to get a human-readable description of the filter. *LEN is the size of the buffer. The description is filled into BUF, NUL-terminated. Always returns 0. */ int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov); /* This variant of iobuf_push_filter allows the called to indicate that OV should be freed when this filter is freed. That is, if REL_OV is TRUE, then when the filter is popped or freed OV will be freed after the filter function is called with control set to IOBUFCTRL_FREE. */ int iobuf_push_filter2 (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov, int rel_ov); /* Pop the top filter. The top filter must have the filter function F and the cookie OV. The cookie check is ignored if OV is NULL. */ int iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov); /* Used for debugging. Prints out the chain using log_debug if IOBUF_DEBUG_MODE is not 0. */ int iobuf_print_chain (iobuf_t a); /* Indicate that some error occurred on the specified filter. */ #define iobuf_set_error(a) do { (a)->error = 1; } while(0) /* Return any pending error on filter A. */ #define iobuf_error(a) ((a)->error) /* Limit the amount of additional data that may be read from the filter. That is, if you've already read 100 bytes from A and you set the limit to 50, then you can read up to an additional 50 bytes (i.e., a total of 150 bytes) before EOF is forcefully returned. Setting NLIMIT to 0 removes any active limit. Note: using iobuf_seek removes any currently enforced limit! */ void iobuf_set_limit (iobuf_t a, off_t nlimit); /* Returns the number of bytes that have been read from the pipeline. Note: the result is undefined for IOBUF_OUTPUT and IOBUF_OUTPUT_TEMP pipelines! */ off_t iobuf_tell (iobuf_t a); /* There are two cases: - If A is an INPUT or OUTPUT pipeline, then the last filter in the pipeline is found. If that is not a file filter, -1 is returned. Otherwise, an fseek(..., SEEK_SET) is performed on the file descriptor. - If A is a TEMP pipeline and the *first* (and thus only filter) is a TEMP filter, then the "file position" is effectively unchanged. That is, data is appended to the buffer and the seek does not cause the size of the buffer to grow. If no error occurred, then any limit previous set by iobuf_set_limit() is cleared. Further, any error on the filter (the file filter or the temp filter) is cleared. Returns 0 on success and -1 if an error occurs. */ int iobuf_seek (iobuf_t a, off_t newpos); /* Read a single byte. If a filter has no more data, returns -1 to indicate the EOF. Generally, you don't want to use this function, but instead prefer the iobuf_get macro, which is faster if there is data in the internal buffer. */ int iobuf_readbyte (iobuf_t a); /* Get a byte from the iobuf; must check for eof prior to this function. This function returns values in the range 0 .. 255 or -1 to indicate EOF. iobuf_get_noeof() does not return -1 to indicate EOF, but masks the returned value to be in the range 0 .. 255. */ #define iobuf_get(a) \ ( ((a)->nofast || (a)->d.start >= (a)->d.len )? \ iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) ) #define iobuf_get_noeof(a) (iobuf_get((a))&0xff) /* Fill BUF with up to BUFLEN bytes. If a filter has no more data, returns -1 to indicate the EOF. Otherwise returns the number of bytes read. */ int iobuf_read (iobuf_t a, void *buf, unsigned buflen); /* Read a line of input (including the '\n') from the pipeline. The semantics are the same as for fgets(), but if the buffer is too short a larger one will be allocated up to *MAX_LENGTH and the end of the line except the trailing '\n' discarded. (Thus, *ADDR_OF_BUFFER must be allocated using malloc().) If the buffer is enlarged, then *LENGTH_OF_BUFFER will be updated to reflect the new size. If the line is truncated, then *MAX_LENGTH will be set to 0. If *ADDR_OF_BUFFER is NULL, a buffer is allocated using malloc(). A line is considered a byte stream ending in a '\n'. Returns the number of characters written to the buffer (i.e., excluding any discarded characters due to truncation). Thus, use this instead of strlen(buffer) to determine the length of the string as this is unreliable if the input contains NUL characters. EOF is indicated by a line of length zero. The last LF may be missing due to an EOF. */ unsigned iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, unsigned *length_of_buffer, unsigned *max_length); /* Read up to BUFLEN bytes from pipeline A. Note: this function can't return more than the pipeline's internal buffer size. The return value is the number of bytes actually written to BUF. If the filter returns EOF, then this function returns -1. This function does not clear any pending EOF. That is, if the pipeline consists of two filters and the first one returns EOF during the peek, then the subsequent iobuf_read* will still return EOF before returning the data from the second filter. */ int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen); /* Write a byte to the pipeline. Returns 0 on success and an error code otherwise. */ int iobuf_writebyte (iobuf_t a, unsigned c); /* Alias for iobuf_writebyte. */ #define iobuf_put(a,c) iobuf_writebyte(a,c) /* Write a sequence of bytes to the pipeline. Returns 0 on success and an error code otherwise. */ int iobuf_write (iobuf_t a, const void *buf, unsigned buflen); /* Write a string (not including the NUL terminator) to the pipeline. Returns 0 on success and an error code otherwise. */ int iobuf_writestr (iobuf_t a, const char *buf); /* Flushes the pipeline removing all filters but the sink (the last filter) in the process. */ void iobuf_flush_temp (iobuf_t temp); /* Flushes the pipeline SOURCE removing all filters but the sink (the last filter) in the process (i.e., it calls iobuf_flush_temp(source)) and then writes the data to the pipeline DEST. Note: this doesn't free (iobuf_close()) SOURCE. Both SOURCE and DEST must be output pipelines. */ int iobuf_write_temp (iobuf_t dest, iobuf_t source); /* Flushes each filter in the pipeline (i.e., sends any buffered data to the filter by calling IOBUFCTRL_FLUSH). Then, copies up to the first BUFLEN bytes from the last filter's internal buffer (which will only be non-empty if it is a temp filter) to the buffer BUFFER. Returns the number of bytes actually copied. */ size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen); /* Copies the data from the input iobuf SOURCE to the output iobuf DEST until either an error is encountered or EOF is reached. Returns the number of bytes successfully written. If an error occurred, then any buffered bytes are not returned to SOURCE and are effectively lost. To check if an error occurred, use iobuf_error. */ size_t iobuf_copy (iobuf_t dest, iobuf_t source); /* Return the size of any underlying file. This only works with file_filter based pipelines. On Win32, it is sometimes not possible to determine the size of files larger than 4GB. In this case, *OVERFLOW (if not NULL) is set to 1. Otherwise, *OVERFLOW is set to 0. */ off_t iobuf_get_filelength (iobuf_t a, int *overflow); #define IOBUF_FILELENGTH_LIMIT 0xffffffff /* Return the file descriptor designating the underlying file. This only works with file_filter based pipelines. */ int iobuf_get_fd (iobuf_t a); /* Return the real filename, if available. This only supports pipelines that end in file filters. Returns NULL if not available. */ const char *iobuf_get_real_fname (iobuf_t a); /* Return the filename or a description thereof. For instance, for iobuf_open("-"), this will return "[stdin]". This only supports pipelines that end in file filters. Returns NULL if not available. */ const char *iobuf_get_fname (iobuf_t a); /* Like iobuf_getfname, but instead of returning NULL if no description is available, return "[?]". */ const char *iobuf_get_fname_nonnull (iobuf_t a); /* Pushes a filter on the pipeline that interprets the datastream as an OpenPGP data block whose length is encoded using partial body length headers (see Section 4.2.2.4 of RFC 4880). Concretely, it just returns / writes the data and finishes the packet with an EOF. */ void iobuf_set_partial_body_length_mode (iobuf_t a, size_t len); /* If PARTIAL is set, then read from the pipeline until the first EOF is returned. If PARTIAL is 0, then read up to N bytes or until the first EOF is returned. Recall: a filter can return EOF. In this case, it and all preceding filters are popped from the pipeline and the next read is from the following filter (which may or may not return EOF). */ void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial); #define iobuf_where(a) "[don't know]" /* Each time a filter is allocated (via iobuf_alloc()), a monotonically increasing counter is incremented and this field is set to the new value. This macro returns that number. */ #define iobuf_id(a) ((a)->no) #define iobuf_get_temp_buffer(a) ( (a)->d.buf ) #define iobuf_get_temp_length(a) ( (a)->d.len ) /* Whether the filter uses an in-memory buffer. */ #define iobuf_is_temp(a) ( (a)->use == IOBUF_OUTPUT_TEMP ) #endif /*GNUPG_COMMON_IOBUF_H*/ diff --git a/common/miscellaneous.c b/common/miscellaneous.c index df6b68784..60ac4b4df 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -1,794 +1,777 @@ /* miscellaneous.c - Stuff not fitting elsewhere * Copyright (C) 2003, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * * This file is free software; you can redistribute it and/or modify * it under the terms of either * * - the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at * your option) any later version. * * or * * - the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at * your option) any later version. * * or both in parallel, as here. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include "util.h" #include "iobuf.h" #include "i18n.h" /* Used by libgcrypt for logging. */ static void my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) { (void)dummy; /* Map the log levels. */ switch (level) { case GCRY_LOG_CONT: level = GPGRT_LOGLVL_CONT; break; case GCRY_LOG_INFO: level = GPGRT_LOGLVL_INFO; break; case GCRY_LOG_WARN: level = GPGRT_LOGLVL_WARN; break; case GCRY_LOG_ERROR:level = GPGRT_LOGLVL_ERROR; break; case GCRY_LOG_FATAL:level = GPGRT_LOGLVL_FATAL; break; case GCRY_LOG_BUG: level = GPGRT_LOGLVL_BUG; break; case GCRY_LOG_DEBUG:level = GPGRT_LOGLVL_DEBUG; break; default: level = GPGRT_LOGLVL_ERROR; break; } log_logv (level, fmt, arg_ptr); } /* This function is called by libgcrypt on a fatal error. */ static void my_gcry_fatalerror_handler (void *opaque, int rc, const char *text) { (void)opaque; log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc)); abort (); } /* This function is called by libgcrypt if it ran out of core and there is no way to return that error to the caller. We do our own function here to make use of our logging functions. */ static int my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags) { static int been_here; /* Used to protect against recursive calls. */ (void)opaque; if (!been_here) { been_here = 1; if ( (flags & 1) ) log_fatal (_("out of core in secure memory " "while allocating %lu bytes"), (unsigned long)req_n); else log_fatal (_("out of core while allocating %lu bytes"), (unsigned long)req_n); } return 0; /* Let libgcrypt call its own fatal error handler. Actually this will turn out to be my_gcry_fatalerror_handler. */ } /* Setup libgcrypt to use our own logging functions. Should be used early at startup. */ void setup_libgcrypt_logging (void) { gcry_set_log_handler (my_gcry_logger, NULL); gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL); gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL); } /* Print an out of core message and let the process die. The printed * error is taken from ERRNO. */ void xoutofcore (void) { gpg_error_t err = gpg_error_from_syserror (); log_fatal (_("error allocating enough memory: %s\n"), gpg_strerror (err)); abort (); /* Never called; just to make the compiler happy. */ } /* Wrapper around gpgrt_reallocarray. */ void * xreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size) { void *p = gpgrt_reallocarray (a, oldnmemb, nmemb, size); if (!p) xoutofcore (); return p; } /* A wrapper around gcry_cipher_algo_name to return the string "AES-128" instead of "AES". Given that we have an alias in libgcrypt for it, it does not harm to too much to return this other string. Some users complained that we print "AES" but "AES192" and "AES256". We can't fix that in libgcrypt but it is pretty safe to do it in an application. */ const char * gnupg_cipher_algo_name (int algo) { const char *s; s = gcry_cipher_algo_name (algo); if (!strcmp (s, "AES")) s = "AES128"; return s; } void obsolete_option (const char *configname, unsigned int configlineno, const char *name) { if (configname) log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"), configname, configlineno, name); else log_info (_("WARNING: \"%s%s\" is an obsolete option - it has no effect\n"), "--", name); } /* Decide whether the filename is stdout or a real filename and return * an appropriate string. */ const char * print_fname_stdout (const char *s) { if( !s || (*s == '-' && !s[1]) ) return "[stdout]"; return s; } /* Decide whether the filename is stdin or a real filename and return * an appropriate string. */ const char * print_fname_stdin (const char *s) { if( !s || (*s == '-' && !s[1]) ) return "[stdin]"; return s; } static int do_print_utf8_buffer (estream_t stream, const void *buffer, size_t length, const char *delimiters, size_t *bytes_written) { const char *p = buffer; size_t i; /* We can handle plain ascii simpler, so check for it first. */ for (i=0; i < length; i++ ) { if ( (p[i] & 0x80) ) break; } if (i < length) { int delim = delimiters? *delimiters : 0; char *buf; int ret; /*(utf8 conversion already does the control character quoting). */ buf = utf8_to_native (p, length, delim); if (bytes_written) *bytes_written = strlen (buf); ret = es_fputs (buf, stream); xfree (buf); return ret == EOF? ret : (int)i; } else return es_write_sanitized (stream, p, length, delimiters, bytes_written); } void print_utf8_buffer3 (estream_t stream, const void *p, size_t n, const char *delim) { do_print_utf8_buffer (stream, p, n, delim, NULL); } void print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim) { char tmp[2]; tmp[0] = delim; tmp[1] = 0; do_print_utf8_buffer (stream, p, n, tmp, NULL); } void print_utf8_buffer (estream_t stream, const void *p, size_t n) { do_print_utf8_buffer (stream, p, n, NULL, NULL); } void print_utf8_string (estream_t stream, const char *p) { if (!p) p = ""; do_print_utf8_buffer (stream, p, strlen (p), NULL, NULL); } /* Write LENGTH bytes of BUFFER to FP as a hex encoded string. RESERVED must be 0. */ void print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved) { #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) const unsigned char *s; (void)reserved; for (s = buffer; length; s++, length--) { putc ( tohex ((*s>>4)&15), fp); putc ( tohex (*s&15), fp); } #undef tohex } /* Create a string from the buffer P_ARG of length N which is suitable * for printing. Caller must release the created string using xfree. * On error ERRNO is set and NULL returned. Errors are only possible * due to malloc failure. */ char * try_make_printable_string (const void *p_arg, size_t n, int delim) { const unsigned char *p = p_arg; size_t save_n, buflen; const unsigned char *save_p; char *buffer, *d; /* First count length. */ for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) { if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { if ( *p=='\n' || *p=='\r' || *p=='\f' || *p=='\v' || *p=='\b' || !*p ) buflen += 2; else buflen += 5; } else buflen++; } p = save_p; n = save_n; /* And now make the string */ d = buffer = xtrymalloc (buflen); for ( ; n; n--, p++ ) { if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { *d++ = '\\'; if( *p == '\n' ) *d++ = 'n'; else if( *p == '\r' ) *d++ = 'r'; else if( *p == '\f' ) *d++ = 'f'; else if( *p == '\v' ) *d++ = 'v'; else if( *p == '\b' ) *d++ = 'b'; else if( !*p ) *d++ = '0'; else { sprintf(d, "x%02x", *p ); d += 3; } } else *d++ = *p; } *d = 0; return buffer; } /* Same as try_make_printable_string but terminates the process on * memory shortage. */ char * make_printable_string (const void *p, size_t n, int delim ) { char *string = try_make_printable_string (p, n, delim); if (!string) xoutofcore (); return string; } /* Decode the C formatted string SRC and return the result in a newly * allocated buffer. In error returns NULL and sets ERRNO. */ char * decode_c_string (const char *src) { char *buffer, *dst; int val; /* The converted string will never be larger than the original string. */ buffer = dst = xtrymalloc (strlen (src) + 1); if (!buffer) return NULL; while (*src) { if (*src != '\\') { *dst++ = *src++; continue; } #define DECODE_ONE(_m,_r) case _m: src += 2; *dst++ = _r; break; switch (src[1]) { DECODE_ONE ('n', '\n'); DECODE_ONE ('r', '\r'); DECODE_ONE ('f', '\f'); DECODE_ONE ('v', '\v'); DECODE_ONE ('b', '\b'); DECODE_ONE ('t', '\t'); DECODE_ONE ('\\', '\\'); DECODE_ONE ('\'', '\''); DECODE_ONE ('\"', '\"'); case 'x': val = hextobyte (src+2); if (val == -1) /* Bad coding, keep as is. */ { *dst++ = *src++; *dst++ = *src++; if (*src) *dst++ = *src++; if (*src) *dst++ = *src++; } else if (!val) { /* A binary zero is not representable in a C string thus * we keep the C-escaping. Note that this will also * never be larger than the source string. */ *dst++ = '\\'; *dst++ = '0'; src += 4; } else { *(unsigned char *)dst++ = val; src += 4; } break; default: /* Bad coding; keep as is.. */ *dst++ = *src++; *dst++ = *src++; break; } #undef DECODE_ONE } *dst++ = 0; return buffer; } /* Check whether (BUF,LEN) is valid header for an OpenPGP compressed * packet. LEN should be at least 6. */ static int -is_openpgp_compressed_packet (unsigned char *buf, size_t len) +is_openpgp_compressed_packet (const unsigned char *buf, size_t len) { int c, ctb, pkttype; int lenbytes; ctb = *buf++; len--; if (!(ctb & 0x80)) return 0; /* Invalid packet. */ if ((ctb & 0x40)) /* New style (OpenPGP) CTB. */ { pkttype = (ctb & 0x3f); if (!len) return 0; /* Expected first length octet missing. */ c = *buf++; len--; if (c < 192) ; else if (c < 224) { if (!len) return 0; /* Expected second length octet missing. */ } else if (c == 255) { if (len < 4) return 0; /* Expected length octets missing */ } } else /* Old style CTB. */ { pkttype = (ctb>>2)&0xf; lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); if (len < lenbytes) return 0; /* Not enough length bytes. */ } return (pkttype == 8); } /* - * Check if the file is compressed. + * Check if the file is compressed. You need to pass the first bytes + * of the file as (BUF,BUFLEN). Returns true if the buffer seems to + * be compressed. */ int -is_file_compressed (const char *s, int *ret_rc) +is_file_compressed (const byte *buf, unsigned int buflen) { - iobuf_t a; - byte buf[6]; - int i; - int rc = 0; - int overflow; - - struct magic_compress_s { - size_t len; - byte magic[4]; - } magic[] = { - { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */ - { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */ - { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */ - }; - - if ( iobuf_is_pipe_filename (s) || !ret_rc ) - return 0; /* We can't check stdin or no file was given */ - - a = iobuf_open( s ); - if ( a == NULL ) { - *ret_rc = gpg_error_from_syserror (); - return 0; - } - iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL); + int i; - if ( iobuf_get_filelength( a, &overflow ) < 6 && !overflow) { - *ret_rc = 0; - goto leave; - } + struct magic_compress_s + { + byte len; + byte magic[5]; + } magic[] = + { + { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */ + { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */ + { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */ + { 5, { '%', 'P', 'D', 'F', '-'} } /* PDF */ + }; - if ( iobuf_read( a, buf, 6 ) == -1 ) { - *ret_rc = a->error; - goto leave; + if ( buflen < 6 ) + { + return 0; /* Too short to check - assume uncompressed. */ } - for ( i = 0; i < DIM( magic ); i++ ) { - if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) { - *ret_rc = 0; - rc = 1; - goto leave; + for ( i = 0; i < DIM (magic); i++ ) + { + if ( !memcmp( buf, magic[i].magic, magic[i].len )) + { + return 1; /* Is compressed. */ } } - if (is_openpgp_compressed_packet (buf, 6)) - { - *ret_rc = 0; - rc = 1; - } + if (buflen >= 6 && is_openpgp_compressed_packet (buf, buflen)) + { + return 1; /* Already compressed. */ + } - leave: - iobuf_close( a ); - return rc; + return 0; /* Not detected as compressed. */ } /* Try match against each substring of multistr, delimited by | */ int match_multistr (const char *multistr,const char *match) { do { size_t seglen = strcspn (multistr,"|"); if (!seglen) break; /* Using the localized strncasecmp! */ if (strncasecmp(multistr,match,seglen)==0) return 1; multistr += seglen; if (*multistr == '|') multistr++; } while (*multistr); return 0; } /* Parse the first portion of the version number S and store it at NUMBER. On success, the function returns a pointer into S starting with the first character, which is not part of the initial number portion; on failure, NULL is returned. */ static const char* parse_version_number (const char *s, int *number) { int val = 0; if (*s == '0' && digitp (s+1)) return NULL; /* Leading zeros are not allowed. */ for (; digitp (s); s++ ) { val *= 10; val += *s - '0'; } *number = val; return val < 0? NULL : s; } /* Break up the complete string representation of the version number S, which is expected to have this format: ... The major, minor and micro number components will be stored at MAJOR, MINOR and MICRO. On success, a pointer to the last component, the patch level, will be returned; on failure, NULL will be returned. */ static const char * parse_version_string (const char *s, int *major, int *minor, int *micro) { s = parse_version_number (s, major); if (!s || *s != '.') return NULL; s++; s = parse_version_number (s, minor); if (!s || *s != '.') return NULL; s++; s = parse_version_number (s, micro); if (!s) return NULL; return s; /* Patchlevel. */ } /* Return true if version string is at least version B. */ int gnupg_compare_version (const char *a, const char *b) { int a_major, a_minor, a_micro; int b_major, b_minor, b_micro; const char *a_plvl, *b_plvl; if (!a || !b) return 0; /* Parse version A. */ a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro); if (!a_plvl ) return 0; /* Invalid version number. */ /* Parse version B. */ b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro); if (!b_plvl ) return 0; /* Invalid version number. */ /* Compare version numbers. */ return (a_major > b_major || (a_major == b_major && a_minor > b_minor) || (a_major == b_major && a_minor == b_minor && a_micro > b_micro) || (a_major == b_major && a_minor == b_minor && a_micro == b_micro && strcmp (a_plvl, b_plvl) >= 0)); } /* Parse an --debug style argument. We allow the use of number values * in the usual C notation or a string with comma separated keywords. * * Returns: 0 on success or -1 and ERRNO set on error. On success the * supplied variable is updated by the parsed flags. * * If STRING is NULL the enabled debug flags are printed. * * See doc/DETAILS for a summary of used debug options. */ int parse_debug_flag (const char *string, unsigned int *debugvar, const struct debug_flags_s *flags) { unsigned long result = 0; int i, j; if (!string) { if (debugvar) { log_info ("enabled debug flags:"); for (i=0; flags[i].name; i++) if ((*debugvar & flags[i].flag)) log_printf (" %s", flags[i].name); log_printf ("\n"); } return 0; } while (spacep (string)) string++; if (*string == '-') { errno = EINVAL; return -1; } if (!strcmp (string, "?") || !strcmp (string, "help")) { log_info ("available debug flags:\n"); for (i=0; flags[i].name; i++) log_info (" %5u %s\n", flags[i].flag, flags[i].name); if (flags[i].flag != 77) exit (0); } else if (digitp (string)) { errno = 0; result = strtoul (string, NULL, 0); if (result == ULONG_MAX && errno == ERANGE) return -1; } else { char **words; words = strtokenize (string, ","); if (!words) return -1; for (i=0; words[i]; i++) { if (*words[i]) { for (j=0; flags[j].name; j++) if (!strcmp (words[i], flags[j].name)) { result |= flags[j].flag; break; } if (!flags[j].name) { if (!strcmp (words[i], "none")) { *debugvar = 0; result = 0; } else if (!strcmp (words[i], "all")) result = ~0; else log_info (_("unknown debug flag '%s' ignored\n"), words[i]); } } } xfree (words); } *debugvar |= result; return 0; } /* Parse an --comaptibility_flags style argument consisting of comma * separated strings. * * Returns: 0 on success or -1 and ERRNO set on error. On success the * supplied variable is updated by the parsed flags. * * If STRING is NULL the enabled flags are printed. */ int parse_compatibility_flags (const char *string, unsigned int *flagvar, const struct compatibility_flags_s *flags) { unsigned long result = 0; int i, j; if (!string) { if (flagvar) { log_info ("enabled compatibility flags:"); for (i=0; flags[i].name; i++) if ((*flagvar & flags[i].flag)) log_printf (" %s", flags[i].name); log_printf ("\n"); } return 0; } while (spacep (string)) string++; if (!strcmp (string, "?") || !strcmp (string, "help")) { log_info ("available compatibility flags:\n"); for (i=0; flags[i].name; i++) log_info (" %s\n", flags[i].name); if (flags[i].flag != 77) exit (0); } else { char **words; words = strtokenize (string, ","); if (!words) return -1; for (i=0; words[i]; i++) { if (*words[i]) { for (j=0; flags[j].name; j++) if (!strcmp (words[i], flags[j].name)) { result |= flags[j].flag; break; } if (!flags[j].name) { if (!strcmp (words[i], "none")) { *flagvar = 0; result = 0; } else if (!strcmp (words[i], "all")) result = ~0; else log_info ("unknown compatibility flag '%s' ignored\n", words[i]); } } } xfree (words); } *flagvar |= result; return 0; } diff --git a/common/util.h b/common/util.h index 6978ab896..d80e4fb25 100644 --- a/common/util.h +++ b/common/util.h @@ -1,428 +1,428 @@ /* util.h - Utility functions for GnuPG * Copyright (C) 2001, 2002, 2003, 2004, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute and/or modify this * part of GnuPG under the terms of either * * - the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at * your option) any later version. * * or * * - the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at * your option) any later version. * * or both in parallel, as here. * * GnuPG is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copies of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, see . */ #ifndef GNUPG_COMMON_UTIL_H #define GNUPG_COMMON_UTIL_H #include /* We need this for the memory function protos. */ #include /* We need errno. */ #include /* We need gpg_error_t and estream. */ /* These error codes are used but not defined in the required * libgpg-error version. Define them here. * Example: (#if GPG_ERROR_VERSION_NUMBER < 0x011500 // 1.21) */ #ifndef EXTERN_UNLESS_MAIN_MODULE # if !defined (INCLUDED_BY_MAIN_MODULE) # define EXTERN_UNLESS_MAIN_MODULE extern # else # define EXTERN_UNLESS_MAIN_MODULE # endif #endif /* Hash function used with libksba. */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) /* The length of the keygrip. This is a SHA-1 hash of the key * parameters as generated by gcry_pk_get_keygrip. */ #define KEYGRIP_LEN 20 /* The length of the unique blob identifier as used by the keyboxd. * This is the possible truncated fingerprint of the primary key. */ #define UBID_LEN 20 /* Get all the stuff from jnlib. */ #include "../common/logging.h" #include "../common/stringhelp.h" #include "../common/mischelp.h" #include "../common/strlist.h" #include "../common/dotlock.h" #include "../common/utf8conv.h" #include "../common/dynload.h" #include "../common/fwddecl.h" #include "../common/utilproto.h" #include "gettime.h" /* Redefine asprintf by our estream version which uses our own memory allocator.. */ #define asprintf gpgrt_asprintf #define vasprintf gpgrt_vasprintf /* Due to a bug in mingw32's snprintf related to the 'l' modifier and for increased portability we use our snprintf on all systems. */ #undef snprintf #define snprintf gpgrt_snprintf /* Replacements for macros not available with libgpg-error < 1.20. */ /* We need this type even if we are not using libreadline and or we did not include libreadline in the current file. */ #ifndef GNUPG_LIBREADLINE_H_INCLUDED typedef char **rl_completion_func_t (const char *, int, int); #endif /*!GNUPG_LIBREADLINE_H_INCLUDED*/ /* Handy malloc macros - please use only them. */ #define xtrymalloc(a) gcry_malloc ((a)) #define xtrymalloc_secure(a) gcry_malloc_secure ((a)) #define xtrycalloc(a,b) gcry_calloc ((a),(b)) #define xtrycalloc_secure(a,b) gcry_calloc_secure ((a),(b)) #define xtryrealloc(a,b) gcry_realloc ((a),(b)) #define xtryreallocarray(a,b,c,d) gpgrt_reallocarray ((a),(b),(c),(d)) #define xtrystrdup(a) gcry_strdup ((a)) #define xfree(a) gcry_free ((a)) #define xfree_fnc gcry_free #define xmalloc(a) gcry_xmalloc ((a)) #define xmalloc_secure(a) gcry_xmalloc_secure ((a)) #define xcalloc(a,b) gcry_xcalloc ((a),(b)) #define xcalloc_secure(a,b) gcry_xcalloc_secure ((a),(b)) #define xrealloc(a,b) gcry_xrealloc ((a),(b)) #define xstrdup(a) gcry_xstrdup ((a)) /* See also the xreallocarray prototype below. */ /* For compatibility with gpg 1.4 we also define these: */ #define xmalloc_clear(a) gcry_xcalloc (1, (a)) #define xmalloc_secure_clear(a) gcry_xcalloc_secure (1, (a)) /* The default error source of the application. This is different from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the source file and thus is usable in code shared by applications. Defined by init.c. */ extern gpg_err_source_t default_errsource; /* Convenience function to return a gpg-error code for memory allocation failures. This function makes sure that an error will be returned even if accidentally ERRNO is not set. */ static inline gpg_error_t out_of_core (void) { return gpg_error_from_syserror (); } /*-- yesno.c --*/ int answer_is_yes (const char *s); int answer_is_yes_no_default (const char *s, int def_answer); int answer_is_yes_no_quit (const char *s); int answer_is_okay_cancel (const char *s, int def_answer); /*-- xreadline.c --*/ ssize_t read_line (FILE *fp, char **addr_of_buffer, size_t *length_of_buffer, size_t *max_length); /*-- b64enc.c and b64dec.c --*/ struct b64state { unsigned int flags; int idx; int quad_count; FILE *fp; estream_t stream; char *title; unsigned char radbuf[4]; u32 crc; int stop_seen:1; int invalid_encoding:1; gpg_error_t lasterr; }; gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title); gpg_error_t b64enc_start_es (struct b64state *state, estream_t fp, const char *title); gpg_error_t b64enc_write (struct b64state *state, const void *buffer, size_t nbytes); gpg_error_t b64enc_finish (struct b64state *state); gpg_error_t b64dec_start (struct b64state *state, const char *title); gpg_error_t b64dec_proc (struct b64state *state, void *buffer, size_t length, size_t *r_nbytes); gpg_error_t b64dec_finish (struct b64state *state); /*-- sexputil.c */ char *canon_sexp_to_string (const unsigned char *canon, size_t canonlen); void log_printcanon (const char *text, const unsigned char *sexp, size_t sexplen); void log_printsexp (const char *text, gcry_sexp_t sexp); gpg_error_t make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen); gpg_error_t make_canon_sexp_pad (gcry_sexp_t sexp, int secure, unsigned char **r_buffer, size_t *r_buflen); gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, unsigned char *grip); int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); int cmp_canon_sexp (const unsigned char *a, size_t alen, const unsigned char *b, size_t blen, int (*tcmp)(void *ctx, int depth, const unsigned char *aval, size_t avallen, const unsigned char *bval, size_t bvallen), void *tcmpctx); unsigned char *make_simple_sexp_from_hexstr (const char *line, size_t *nscanned); int hash_algo_from_sigval (const unsigned char *sigval); unsigned char *make_canon_sexp_from_rsa_pk (const void *m, size_t mlen, const void *e, size_t elen, size_t *r_len); gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen, unsigned char const **r_n, size_t *r_nlen, unsigned char const **r_e, size_t *r_elen); gpg_error_t get_ecc_q_from_canon_sexp (const unsigned char *keydata, size_t keydatalen, unsigned char const **r_q, size_t *r_qlen); gpg_error_t uncompress_ecc_q_in_canon_sexp (const unsigned char *keydata, size_t keydatalen, unsigned char **r_newkeydata, size_t *r_newkeydatalen); int get_pk_algo_from_key (gcry_sexp_t key); int get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen); char *pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid); const char *pubkey_algo_to_string (int algo); const char *hash_algo_to_string (int algo); const char *cipher_mode_to_string (int mode); /*-- convert.c --*/ int hex2bin (const char *string, void *buffer, size_t length); int hexcolon2bin (const char *string, void *buffer, size_t length); char *bin2hex (const void *buffer, size_t length, char *stringbuf); char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf); const char *hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen); char *hex2str_alloc (const char *hexstring, size_t *r_count); unsigned int hex2fixedbuf (const char *hexstr, void *buffer, size_t bufsize); /*-- percent.c --*/ char *percent_plus_escape (const char *string); char *percent_data_escape (int plus, const char *prefix, const void *data, size_t datalen); char *percent_plus_unescape (const char *string, int nulrepl); char *percent_unescape (const char *string, int nulrepl); size_t percent_plus_unescape_inplace (char *string, int nulrepl); size_t percent_unescape_inplace (char *string, int nulrepl); /*-- openpgp-oid.c --*/ gpg_error_t openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi); char *openpgp_oidbuf_to_str (const unsigned char *buf, size_t len); char *openpgp_oid_to_str (gcry_mpi_t a); int openpgp_oidbuf_is_ed25519 (const void *buf, size_t len); int openpgp_oid_is_ed25519 (gcry_mpi_t a); int openpgp_oidbuf_is_cv25519 (const void *buf, size_t len); int openpgp_oid_is_cv25519 (gcry_mpi_t a); int openpgp_oid_is_cv448 (gcry_mpi_t a); int openpgp_oid_is_ed448 (gcry_mpi_t a); const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo); const char *openpgp_oid_to_curve (const char *oid, int canon); const char *openpgp_oid_or_name_to_curve (const char *oidname, int canon); const char *openpgp_enum_curves (int *idxp); const char *openpgp_is_curve_supported (const char *name, int *r_algo, unsigned int *r_nbits); const char *get_keyalgo_string (enum gcry_pk_algos algo, unsigned int nbits, const char *curve); /*-- homedir.c --*/ const char *standard_homedir (void); void gnupg_set_homedir (const char *newdir); void gnupg_maybe_make_homedir (const char *fname, int quiet); const char *gnupg_homedir (void); int gnupg_default_homedir_p (void); const char *gnupg_daemon_rootdir (void); const char *gnupg_socketdir (void); const char *gnupg_sysconfdir (void); const char *gnupg_bindir (void); const char *gnupg_libexecdir (void); const char *gnupg_libdir (void); const char *gnupg_datadir (void); const char *gnupg_localedir (void); const char *gpg_agent_socket_name (void); const char *dirmngr_socket_name (void); const char *keyboxd_socket_name (void); char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info); /* All module names. We also include gpg and gpgsm for the sake for gpgconf. */ #define GNUPG_MODULE_NAME_AGENT 1 #define GNUPG_MODULE_NAME_PINENTRY 2 #define GNUPG_MODULE_NAME_SCDAEMON 3 #define GNUPG_MODULE_NAME_DIRMNGR 4 #define GNUPG_MODULE_NAME_PROTECT_TOOL 5 #define GNUPG_MODULE_NAME_CHECK_PATTERN 6 #define GNUPG_MODULE_NAME_GPGSM 7 #define GNUPG_MODULE_NAME_GPG 8 #define GNUPG_MODULE_NAME_CONNECT_AGENT 9 #define GNUPG_MODULE_NAME_GPGCONF 10 #define GNUPG_MODULE_NAME_DIRMNGR_LDAP 11 #define GNUPG_MODULE_NAME_GPGV 12 #define GNUPG_MODULE_NAME_KEYBOXD 13 #define GNUPG_MODULE_NAME_TPM2DAEMON 14 #define GNUPG_MODULE_NAME_CARD 15 const char *gnupg_module_name (int which); void gnupg_module_name_flush_some (void); void gnupg_set_builddir (const char *newdir); /* A list of constants to identify protocols. This is used by tools * which need to distinguish between the different protocols * implemented by GnuPG. May be used as bit flags. */ #define GNUPG_PROTOCOL_OPENPGP 1 /* The one and only (gpg). */ #define GNUPG_PROTOCOL_CMS 2 /* The core of S/MIME (gpgsm) */ #define GNUPG_PROTOCOL_SSH_AGENT 4 /* Out ssh-agent implementation */ /*-- gpgrlhelp.c --*/ void gnupg_rl_initialize (void); /*-- helpfile.c --*/ char *gnupg_get_help_string (const char *key, int only_current_locale); /*-- localename.c --*/ const char *gnupg_messages_locale_name (void); /*-- miscellaneous.c --*/ /* This function is called at startup to tell libgcrypt to use our own logging subsystem. */ void setup_libgcrypt_logging (void); /* Print an out of core message and die. */ void xoutofcore (void); /* Wrapper aroung gpgrt_reallocarray. Uses the gpgrt alloc function * which redirects to the Libgcrypt versions via * init_common_subsystems. Thus this can be used interchangeable with * the other alloc functions. */ void *xreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); /* Same as estream_asprintf but die on memory failure. */ char *xasprintf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); /* This is now an alias to estream_asprintf. */ char *xtryasprintf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); /* Replacement for gcry_cipher_algo_name. */ const char *gnupg_cipher_algo_name (int algo); void obsolete_option (const char *configname, unsigned int configlineno, const char *name); const char *print_fname_stdout (const char *s); const char *print_fname_stdin (const char *s); void print_utf8_buffer3 (estream_t fp, const void *p, size_t n, const char *delim); void print_utf8_buffer2 (estream_t fp, const void *p, size_t n, int delim); void print_utf8_buffer (estream_t fp, const void *p, size_t n); void print_utf8_string (estream_t stream, const char *p); void print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved); char *try_make_printable_string (const void *p, size_t n, int delim); char *make_printable_string (const void *p, size_t n, int delim); char *decode_c_string (const char *src); -int is_file_compressed (const char *s, int *ret_rc); +int is_file_compressed (const byte *buf, unsigned int buflen); int match_multistr (const char *multistr,const char *match); int gnupg_compare_version (const char *a, const char *b); struct debug_flags_s { unsigned int flag; const char *name; }; int parse_debug_flag (const char *string, unsigned int *debugvar, const struct debug_flags_s *flags); struct compatibility_flags_s { unsigned int flag; const char *name; const char *desc; }; int parse_compatibility_flags (const char *string, unsigned int *flagvar, const struct compatibility_flags_s *flags); /*-- Simple replacement functions. */ /* We use the gnupg_ttyname macro to be safe not to run into conflicts which an extisting but broken ttyname. */ #if !defined(HAVE_TTYNAME) || defined(HAVE_BROKEN_TTYNAME) # define gnupg_ttyname(n) _gnupg_ttyname ((n)) /* Systems without ttyname (W32) will merely return NULL. */ static inline char * _gnupg_ttyname (int fd) { (void)fd; return NULL; } #else /*HAVE_TTYNAME*/ # define gnupg_ttyname(n) ttyname ((n)) #endif /*HAVE_TTYNAME */ #define gnupg_isatty(a) isatty ((a)) /*-- Macros to replace ctype ones to avoid locale problems. --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') #define digitp(p) (*(p) >= '0' && *(p) <= '9') #define alphap(p) ((*(p) >= 'A' && *(p) <= 'Z') \ || (*(p) >= 'a' && *(p) <= 'z')) #define alnump(p) (alphap (p) || digitp (p)) #define hexdigitp(a) (digitp (a) \ || (*(a) >= 'A' && *(a) <= 'F') \ || (*(a) >= 'a' && *(a) <= 'f')) /* Note this isn't identical to a C locale isspace() without \f and \v, but works for the purposes used here. */ #define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') /* The atoi macros assume that the buffer has only valid digits. */ #define atoi_1(p) (*(p) - '0' ) #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2)) #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) #define xtoi_4(p) ((xtoi_2(p) * 256) + xtoi_2((p)+2)) #endif /*GNUPG_COMMON_UTIL_H*/ diff --git a/doc/gpg.texi b/doc/gpg.texi index 804ecf94a..457088eb3 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1,4634 +1,4646 @@ @c Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, @c 2008, 2009, 2010 Free Software Foundation, Inc. @c This is part of the GnuPG manual. @c For copying conditions, see the file gnupg.texi. @include defs.inc @node Invoking GPG @chapter Invoking GPG @cindex GPG command options @cindex command options @cindex options, GPG command @c Begin standard stuff @ifclear gpgtwohack @manpage gpg.1 @ifset manverb .B gpg \- OpenPGP encryption and signing tool @end ifset @mansect synopsis @ifset manverb .B gpg .RB [ \-\-homedir .IR dir ] .RB [ \-\-options .IR file ] .RI [ options ] .I command .RI [ args ] @end ifset @end ifclear @c End standard stuff @c Begin gpg2 hack stuff @ifset gpgtwohack @manpage gpg2.1 @ifset manverb .B gpg2 \- OpenPGP encryption and signing tool @end ifset @mansect synopsis @ifset manverb .B gpg2 .RB [ \-\-homedir .IR dir ] .RB [ \-\-options .IR file ] .RI [ options ] .I command .RI [ args ] @end ifset @end ifset @c End gpg2 hack stuff @mansect description @command{@gpgname} is the OpenPGP part of the GNU Privacy Guard (GnuPG). It is a tool to provide digital encryption and signing services using the OpenPGP standard. @command{@gpgname} features complete key management and all the bells and whistles you would expect from a full OpenPGP implementation. There are two main versions of GnuPG: GnuPG 1.x and GnuPG 2.x. GnuPG 2.x supports modern encryption algorithms and thus should be preferred over GnuPG 1.x. You only need to use GnuPG 1.x if your platform doesn't support GnuPG 2.x, or you need support for some features that GnuPG 2.x has deprecated, e.g., decrypting data created with PGP-2 keys. @ifclear gpgtwohack If you are looking for version 1 of GnuPG, you may find that version installed under the name @command{gpg1}. @end ifclear @ifset gpgtwohack In contrast to the standalone command @command{gpg} from GnuPG 1.x, the 2.x version is commonly installed under the name @command{@gpgname}. @end ifset @manpause @xref{Option Index}, for an index to @command{@gpgname}'s commands and options. @mancont @menu * GPG Commands:: List of all commands. * GPG Options:: List of all options. * GPG Configuration:: Configuration files. * GPG Examples:: Some usage examples. Developer information: * Unattended Usage of GPG:: Using @command{gpg} from other programs. @end menu @c * GPG Protocol:: The protocol the server mode uses. @c ******************************************* @c *************** **************** @c *************** COMMANDS **************** @c *************** **************** @c ******************************************* @mansect commands @node GPG Commands @section Commands Commands are not distinguished from options except for the fact that only one command is allowed. Generally speaking, irrelevant options are silently ignored, and may not be checked for correctness. @command{@gpgname} may be run with no commands. In this case it will print a warning perform a reasonable action depending on the type of file it is given as input (an encrypted message is decrypted, a signature is verified, a file containing keys is listed, etc.). If you run into any problems, please add the option @option{--verbose} to the invocation to see more diagnostics. @menu * General GPG Commands:: Commands not specific to the functionality. * Operational GPG Commands:: Commands to select the type of operation. * OpenPGP Key Management:: How to manage your keys. @end menu @c ******************************************* @c ********** GENERAL COMMANDS ************* @c ******************************************* @node General GPG Commands @subsection Commands not specific to the function @table @gnupgtabopt @item --version @opindex version Print the program version and licensing information. Note that you cannot abbreviate this command. @item --help @itemx -h @opindex help Print a usage message summarizing the most useful command-line options. Note that you cannot arbitrarily abbreviate this command (though you can use its short form @option{-h}). @item --warranty @opindex warranty Print warranty information. @item --dump-options @opindex dump-options Print a list of all available options and commands. Note that you cannot abbreviate this command. @end table @c ******************************************* @c ******** OPERATIONAL COMMANDS *********** @c ******************************************* @node Operational GPG Commands @subsection Commands to select the type of operation @table @gnupgtabopt @item --sign @itemx -s @opindex sign Sign a message. This command may be combined with @option{--encrypt} (to sign and encrypt a message), @option{--symmetric} (to sign and symmetrically encrypt a message), or both @option{--encrypt} and @option{--symmetric} (to sign and encrypt a message that can be decrypted using a secret key or a passphrase). The signing key is chosen by default or can be set explicitly using the @option{--local-user} and @option{--default-key} options. @item --clear-sign @opindex clear-sign @itemx --clearsign @opindex clearsign Make a cleartext signature. The content in a cleartext signature is readable without any special software. OpenPGP software is only needed to verify the signature. cleartext signatures may modify end-of-line whitespace for platform independence and are not intended to be reversible. The signing key is chosen by default or can be set explicitly using the @option{--local-user} and @option{--default-key} options. @item --detach-sign @itemx -b @opindex detach-sign Make a detached signature. @item --encrypt @itemx -e @opindex encrypt Encrypt data to one or more public keys. This command may be combined with @option{--sign} (to sign and encrypt a message), @option{--symmetric} (to encrypt a message that can be decrypted using a secret key or a passphrase), or @option{--sign} and @option{--symmetric} together (for a signed message that can be decrypted using a secret key or a passphrase). @option{--recipient} and related options specify which public keys to use for encryption. @item --symmetric @itemx -c @opindex symmetric Encrypt with a symmetric cipher using a passphrase. The default symmetric cipher used is @value{GPGSYMENCALGO}, but may be chosen with the @option{--cipher-algo} option. This command may be combined with @option{--sign} (for a signed and symmetrically encrypted message), @option{--encrypt} (for a message that may be decrypted via a secret key or a passphrase), or @option{--sign} and @option{--encrypt} together (for a signed message that may be decrypted via a secret key or a passphrase). @command{@gpgname} caches the passphrase used for symmetric encryption so that a decrypt operation may not require that the user needs to enter the passphrase. The option @option{--no-symkey-cache} can be used to disable this feature. @item --store @opindex store Store only (make a simple literal data packet). @item --decrypt @itemx -d @opindex decrypt Decrypt the file given on the command line (or STDIN if no file is specified) and write it to STDOUT (or the file specified with @option{--output}). If the decrypted file is signed, the signature is also verified. This command differs from the default operation, as it never writes to the filename which is included in the file and it rejects files that don't begin with an encrypted message. @item --verify @opindex verify Assume that the first argument is a signed file and verify it without generating any output. With no arguments, the signature packet is read from STDIN. If only one argument is given, the specified file is expected to include a complete signature. With more than one argument, the first argument should specify a file with a detached signature and the remaining files should contain the signed data. To read the signed data from STDIN, use @samp{-} as the second filename. For security reasons, a detached signature will not read the signed material from STDIN if not explicitly specified. Note: If the option @option{--batch} is not used, @command{@gpgname} may assume that a single argument is a file with a detached signature, and it will try to find a matching data file by stripping certain suffixes. Using this historical feature to verify a detached signature is strongly discouraged; you should always specify the data file explicitly. Note: When verifying a cleartext signature, @command{@gpgname} verifies only what makes up the cleartext signed data and not any extra data outside of the cleartext signature or the header lines directly following the dash marker line. The option @code{--output} may be used to write out the actual signed data, but there are other pitfalls with this format as well. It is suggested to avoid cleartext signatures in favor of detached signatures. Note: Sometimes the use of the @command{gpgv} tool is easier than using the full-fledged @command{gpg} with this option. @command{gpgv} is designed to compare signed data against a list of trusted keys and returns with success only for a good signature. It has its own manual page. @item --multifile @opindex multifile This modifies certain other commands to accept multiple files for processing on the command line or read from STDIN with each filename on a separate line. This allows for many files to be processed at once. @option{--multifile} may currently be used along with @option{--verify}, @option{--encrypt}, and @option{--decrypt}. Note that @option{--multifile --verify} may not be used with detached signatures. @item --verify-files @opindex verify-files Identical to @option{--multifile --verify}. @item --encrypt-files @opindex encrypt-files Identical to @option{--multifile --encrypt}. @item --decrypt-files @opindex decrypt-files Identical to @option{--multifile --decrypt}. @item --list-keys @itemx -k @itemx --list-public-keys @opindex list-keys List the specified keys. If no keys are specified, then all keys from the configured public keyrings are listed. Never use the output of this command in scripts or other programs. The output is intended only for humans and its format is likely to change. The @option{--with-colons} option emits the output in a stable, machine-parseable format, which is intended for use by scripts and other programs. @item --list-secret-keys @itemx -K @opindex list-secret-keys List the specified secret keys. If no keys are specified, then all known secret keys are listed. A @code{#} after the initial tags @code{sec} or @code{ssb} means that the secret key or subkey is currently not usable. We also say that this key has been taken offline (for example, a primary key can be taken offline by exporting the key using the command @option{--export-secret-subkeys}). A @code{>} after these tags indicate that the key is stored on a smartcard. See also @option{--list-keys}. @item --check-signatures @opindex check-signatures @itemx --check-sigs @opindex check-sigs Same as @option{--list-keys}, but the key signatures are verified and listed too. Note that for performance reasons the revocation status of a signing key is not shown. This command has the same effect as using @option{--list-keys} with @option{--with-sig-check}. The status of the verification is indicated by a flag directly following the "sig" tag (and thus before the flags described below. A "!" indicates that the signature has been successfully verified, a "-" denotes a bad signature and a "%" is used if an error occurred while checking the signature (e.g. a non supported algorithm). Signatures where the public key is not available are not listed; to see their keyids the command @option{--list-sigs} can be used. For each signature listed, there are several flags in between the signature status flag and keyid. These flags give additional information about each key signature. From left to right, they are the numbers 1-3 for certificate check level (see @option{--ask-cert-level}), "L" for a local or non-exportable signature (see @option{--lsign-key}), "R" for a nonRevocable signature (see the @option{--edit-key} command "nrsign"), "P" for a signature that contains a policy URL (see @option{--cert-policy-url}), "N" for a signature that contains a notation (see @option{--cert-notation}), "X" for an eXpired signature (see @option{--ask-cert-expire}), and the numbers 1-9 or "T" for 10 and above to indicate trust signature levels (see the @option{--edit-key} command "tsign"). @item --locate-keys @itemx --locate-external-keys @opindex locate-keys @opindex locate-external-keys Locate the keys given as arguments. This command basically uses the same algorithm as used when locating keys for encryption and may thus be used to see what keys @command{@gpgname} might use. In particular external methods as defined by @option{--auto-key-locate} are used to locate a key if the arguments comain valid mail addresses. Only public keys are listed. The variant @option{--locate-external-keys} does not consider a locally existing key and can thus be used to force the refresh of a key via the defined external methods. If a fingerprint is given and and the methods defined by --auto-key-locate define LDAP servers, the key is fetched from these resources; defined non-LDAP keyservers are skipped. @item --show-keys @opindex show-keys This commands takes OpenPGP keys as input and prints information about them in the same way the command @option{--list-keys} does for locally stored key. In addition the list options @code{show-unusable-uids}, @code{show-unusable-subkeys}, @code{show-notations} and @code{show-policy-urls} are also enabled. As usual for automated processing, this command should be combined with the option @option{--with-colons}. @item --fingerprint @opindex fingerprint List all keys (or the specified ones) along with their fingerprints. This is the same output as @option{--list-keys} but with the additional output of a line with the fingerprint. May also be combined with @option{--check-signatures}. If this command is given twice, the fingerprints of all secondary keys are listed too. This command also forces pretty printing of fingerprints if the keyid format has been set to "none". @item --list-packets @opindex list-packets List only the sequence of packets. This command is only useful for debugging. When used with option @option{--verbose} the actual MPI values are dumped and not only their lengths. Note that the output of this command may change with new releases. @item --edit-card @opindex edit-card @itemx --card-edit @opindex card-edit Present a menu to work with a smartcard. The subcommand "help" provides an overview on available commands. For a detailed description, please see the Card HOWTO at https://gnupg.org/documentation/howtos.html#GnuPG-cardHOWTO . @item --card-status @opindex card-status Show the content of the smart card. @item --change-pin @opindex change-pin Present a menu to allow changing the PIN of a smartcard. This functionality is also available as the subcommand "passwd" with the @option{--edit-card} command. @item --delete-keys @var{name} @opindex delete-keys Remove key from the public keyring. In batch mode either @option{--yes} is required or the key must be specified by fingerprint. This is a safeguard against accidental deletion of multiple keys. If the exclamation mark syntax is used with the fingerprint of a subkey only that subkey is deleted; if the exclamation mark is used with the fingerprint of the primary key the entire public key is deleted. @item --delete-secret-keys @var{name} @opindex delete-secret-keys Remove key from the secret keyring. In batch mode the key must be specified by fingerprint. The option @option{--yes} can be used to advise gpg-agent not to request a confirmation. This extra pre-caution is done because @command{@gpgname} can't be sure that the secret key (as controlled by gpg-agent) is only used for the given OpenPGP public key. If the exclamation mark syntax is used with the fingerprint of a subkey only the secret part of that subkey is deleted; if the exclamation mark is used with the fingerprint of the primary key only the secret part of the primary key is deleted. @item --delete-secret-and-public-key @var{name} @opindex delete-secret-and-public-key Same as @option{--delete-key}, but if a secret key exists, it will be removed first. In batch mode the key must be specified by fingerprint. The option @option{--yes} can be used to advise gpg-agent not to request a confirmation. @item --export @opindex export Either export all keys from all keyrings (default keyring and those registered via option @option{--keyring}), or if at least one name is given, those of the given name. The exported keys are written to STDOUT or to the file given with option @option{--output}. Use together with @option{--armor} to mail those keys. @item --send-keys @var{keyIDs} @opindex send-keys Similar to @option{--export} but sends the keys to a keyserver. Fingerprints may be used instead of key IDs. Don't send your complete keyring to a keyserver --- select only those keys which are new or changed by you. If no @var{keyIDs} are given, @command{@gpgname} does nothing. Take care: Keyservers are by design write only systems and thus it is not possible to ever delete keys once they have been send to a keyserver. @item --export-secret-keys @itemx --export-secret-subkeys @opindex export-secret-keys @opindex export-secret-subkeys Same as @option{--export}, but exports the secret keys instead. The exported keys are written to STDOUT or to the file given with option @option{--output}. This command is often used along with the option @option{--armor} to allow for easy printing of the key for paper backup; however the external tool @command{paperkey} does a better job of creating backups on paper. Note that exporting a secret key can be a security risk if the exported keys are sent over an insecure channel. The second form of the command has the special property to render the secret part of the primary key useless; this is a GNU extension to OpenPGP and other implementations can not be expected to successfully import such a key. Its intended use is in generating a full key with an additional signing subkey on a dedicated machine. This command then exports the key without the primary key to the main machine. GnuPG may ask you to enter the passphrase for the key. This is required, because the internal protection method of the secret key is different from the one specified by the OpenPGP protocol. @item --export-ssh-key @opindex export-ssh-key This command is used to export a key in the OpenSSH public key format. It requires the specification of one key by the usual means and exports the latest valid subkey which has an authentication capability to STDOUT or to the file given with option @option{--output}. That output can directly be added to ssh's @file{authorized_key} file. By specifying the key to export using a key ID or a fingerprint suffixed with an exclamation mark (!), a specific subkey or the primary key can be exported. This does not even require that the key has the authentication capability flag set. @item --import @itemx --fast-import @opindex import Import/merge keys. This adds the given keys to the keyring. The fast version is currently just a synonym. There are a few other options which control how this command works. Most notable here is the @option{--import-options merge-only} option which does not insert new keys but does only the merging of new signatures, user-IDs and subkeys. @item --receive-keys @var{keyIDs} @opindex receive-keys @itemx --recv-keys @var{keyIDs} @opindex recv-keys Import the keys with the given @var{keyIDs} from a keyserver. @item --refresh-keys @opindex refresh-keys Request updates from a keyserver for keys that already exist on the local keyring. This is useful for updating a key with the latest signatures, user IDs, etc. Calling this with no arguments will refresh the entire keyring. @item --search-keys @var{names} @opindex search-keys Search the keyserver for the given @var{names}. Multiple names given here will be joined together to create the search string for the keyserver. Note that keyservers search for @var{names} in a different and simpler way than gpg does. The best choice is to use a mail address. Due to data privacy reasons keyservers may even not even allow searching by user id or mail address and thus may only return results when being used with the @option{--recv-key} command to search by key fingerprint or keyid. @item --fetch-keys @var{URIs} @opindex fetch-keys Retrieve keys located at the specified @var{URIs}. Note that different installations of GnuPG may support different protocols (HTTP, FTP, LDAP, etc.). When using HTTPS the system provided root certificates are used by this command. @item --update-trustdb @opindex update-trustdb Do trust database maintenance. This command iterates over all keys and builds the Web of Trust. This is an interactive command because it may have to ask for the "ownertrust" values for keys. The user has to give an estimation of how far she trusts the owner of the displayed key to correctly certify (sign) other keys. GnuPG only asks for the ownertrust value if it has not yet been assigned to a key. Using the @option{--edit-key} menu, the assigned value can be changed at any time. @item --check-trustdb @opindex check-trustdb Do trust database maintenance without user interaction. From time to time the trust database must be updated so that expired keys or signatures and the resulting changes in the Web of Trust can be tracked. Normally, GnuPG will calculate when this is required and do it automatically unless @option{--no-auto-check-trustdb} is set. This command can be used to force a trust database check at any time. The processing is identical to that of @option{--update-trustdb} but it skips keys with a not yet defined "ownertrust". For use with cron jobs, this command can be used together with @option{--batch} in which case the trust database check is done only if a check is needed. To force a run even in batch mode add the option @option{--yes}. @anchor{option --export-ownertrust} @item --export-ownertrust @opindex export-ownertrust Send the ownertrust values to STDOUT. This is useful for backup purposes as these values are the only ones which can't be re-created from a corrupted trustdb. Example: @c man:.RS @example @gpgname{} --export-ownertrust > otrust.txt @end example @c man:.RE @item --import-ownertrust @opindex import-ownertrust Update the trustdb with the ownertrust values stored in @code{files} (or STDIN if not given); existing values will be overwritten. In case of a severely damaged trustdb and if you have a recent backup of the ownertrust values (e.g. in the file @file{otrust.txt}), you may re-create the trustdb using these commands: @c man:.RS @example cd ~/.gnupg rm trustdb.gpg @gpgname{} --import-ownertrust < otrust.txt @end example @c man:.RE @item --rebuild-keydb-caches @opindex rebuild-keydb-caches When updating from version 1.0.6 to 1.0.7 this command should be used to create signature caches in the keyring. It might be handy in other situations too. @item --print-md @var{algo} @itemx --print-mds @opindex print-md Print message digest of algorithm @var{algo} for all given files or STDIN. With the second form (or a deprecated "*" for @var{algo}) digests for all available algorithms are printed. @item --gen-random @var{0|1|2|16|30} @var{count} @opindex gen-random Emit @var{count} random bytes of the given quality level 0, 1 or 2. If @var{count} is not given or zero, an endless sequence of random bytes will be emitted. If used with @option{--armor} the output will be base64 encoded. The special level 16 uses a quality level of 1 and outputs an endless stream of hex-encoded octets. The special level 30 outputs random as 30 zBase-32 characters. @item --gen-prime @var{mode} @var{bits} @opindex gen-prime Use the source, Luke :-). The output format is subject to change with ant release. @item --enarmor @itemx --dearmor @opindex enarmor @opindex dearmor Pack or unpack an arbitrary input into/from an OpenPGP ASCII armor. This is a GnuPG extension to OpenPGP and in general not very useful. The @option{--dearmor} command can also be used to dearmor PEM armors. @item --unwrap @opindex unwrap -This command is similar to @option{--decrypt} with the change that the +This command is similar to @option{--decrypt} with the difference that the output is not the usual plaintext but the original message with the -decryption layer removed. Thus the output will be an OpenPGP data +encryption layer removed. Thus the output will be an OpenPGP data structure which often means a signed OpenPGP message. Note that this command may or may not remove a compression layer which is often found -beneath the encryption layer. +beneath the encryption layer. Without the option @option{--output} +the result is written to a file with the suffix stripped. @item --tofu-policy @{auto|good|unknown|bad|ask@} @var{keys} @opindex tofu-policy Set the TOFU policy for all the bindings associated with the specified @var{keys}. For more information about the meaning of the policies, @pxref{trust-model-tofu}. The @var{keys} may be specified either by their fingerprint (preferred) or their keyid. @c @item --server @c @opindex server @c Run gpg in server mode. This feature is not yet ready for use and @c thus not documented. @end table @c ******************************************** @c ******* KEY MANAGEMENT COMMANDS ********** @c ******************************************** @node OpenPGP Key Management @subsection How to manage your keys This section explains the main commands for key management. @table @gnupgtabopt @item --quick-generate-key @var{user-id} [@var{algo} [@var{usage} [@var{expire}]]] @itemx --quick-gen-key @opindex quick-generate-key @opindex quick-gen-key This is a simple command to generate a standard key with one user id. In contrast to @option{--generate-key} the key is generated directly without the need to answer a bunch of prompts. Unless the option @option{--yes} is given, the key creation will be canceled if the given user id already exists in the keyring. If invoked directly on the console without any special options an answer to a ``Continue?'' style confirmation prompt is required. In case the user id already exists in the keyring a second prompt to force the creation of the key will show up. If @var{algo} or @var{usage} are given, only the primary key is created and no prompts are shown. To specify an expiration date but still create a primary and subkey use ``default'' or ``future-default'' for @var{algo} and ``default'' for @var{usage}. For a description of these optional arguments see the command @code{--quick-add-key}. The @var{usage} accepts also the value ``cert'' which can be used to create a certification only primary key; the default is to a create certification and signing key. The @var{expire} argument can be used to specify an expiration date for the key. Several formats are supported; commonly the ISO formats ``YYYY-MM-DD'' or ``YYYYMMDDThhmmss'' are used. To make the key expire in N seconds, N days, N weeks, N months, or N years use ``seconds=N'', ``Nd'', ``Nw'', ``Nm'', or ``Ny'' respectively. Not specifying a value, or using ``-'' results in a key expiring in a reasonable default interval. The values ``never'', ``none'' can be used for no expiration date. If this command is used with @option{--batch}, @option{--pinentry-mode} has been set to @code{loopback}, and one of the passphrase options (@option{--passphrase}, @option{--passphrase-fd}, or @option{--passphrase-file}) is used, the supplied passphrase is used for the new key and the agent does not ask for it. To create a key without any protection @code{--passphrase ''} may be used. To create an OpenPGP key from the keys available on the currently inserted smartcard, the special string ``card'' can be used for @var{algo}. If the card features an encryption and a signing key, gpg will figure them out and creates an OpenPGP key consisting of the usual primary key and one subkey. This works only with certain smartcards. Note that the interactive @option{--full-gen-key} command allows to do the same but with greater flexibility in the selection of the smartcard keys. Note that it is possible to create a primary key and a subkey using non-default algorithms by using ``default'' and changing the default parameters using the option @option{--default-new-key-algo}. @item --quick-set-expire @var{fpr} @var{expire} [*|@var{subfprs}] @opindex quick-set-expire With two arguments given, directly set the expiration time of the primary key identified by @var{fpr} to @var{expire}. To remove the expiration time @code{0} can be used. With three arguments and the third given as an asterisk, the expiration time of all non-revoked and not yet expired subkeys are set to @var{expire}. With more than two arguments and a list of fingerprints given for @var{subfprs}, all non-revoked subkeys matching these fingerprints are set to @var{expire}. @item --quick-add-key @var{fpr} [@var{algo} [@var{usage} [@var{expire}]]] @opindex quick-add-key Directly add a subkey to the key identified by the fingerprint @var{fpr}. Without the optional arguments an encryption subkey is added. If any of the arguments are given a more specific subkey is added. @var{algo} may be any of the supported algorithms or curve names given in the format as used by key listings. To use the default algorithm the string ``default'' or ``-'' can be used. Supported algorithms are ``rsa'', ``dsa'', ``elg'', ``ed25519'', ``cv25519'', and other ECC curves. For example the string ``rsa'' adds an RSA key with the default key length; a string ``rsa4096'' requests that the key length is 4096 bits. The string ``future-default'' is an alias for the algorithm which will likely be used as default algorithm in future versions of gpg. To list the supported ECC curves the command @code{gpg --with-colons --list-config curve} can be used. Depending on the given @var{algo} the subkey may either be an encryption subkey or a signing subkey. If an algorithm is capable of signing and encryption and such a subkey is desired, a @var{usage} string must be given. This string is either ``default'' or ``-'' to keep the default or a comma delimited list (or space delimited list) of keywords: ``sign'' for a signing subkey, ``auth'' for an authentication subkey, and ``encr'' for an encryption subkey (``encrypt'' can be used as alias for ``encr''). The valid combinations depend on the algorithm. The @var{expire} argument can be used to specify an expiration date for the key. Several formats are supported; commonly the ISO formats ``YYYY-MM-DD'' or ``YYYYMMDDThhmmss'' are used. To make the key expire in N seconds, N days, N weeks, N months, or N years use ``seconds=N'', ``Nd'', ``Nw'', ``Nm'', or ``Ny'' respectively. Not specifying a value, or using ``-'' results in a key expiring in a reasonable default interval. The values ``never'', ``none'' can be used for no expiration date. @item --generate-key @opindex generate-key @itemx --gen-key @opindex gen-key Generate a new key pair using the current default parameters. This is the standard command to create a new key. In addition to the key a revocation certificate is created and stored in the @file{openpgp-revocs.d} directory below the GnuPG home directory. @item --full-generate-key @opindex full-generate-key @itemx --full-gen-key @opindex full-gen-key Generate a new key pair with dialogs for all options. This is an extended version of @option{--generate-key}. There is also a feature which allows you to create keys in batch mode. See the manual section ``Unattended key generation'' on how to use this. @item --generate-revocation @var{name} @opindex generate-revocation @itemx --gen-revoke @var{name} @opindex gen-revoke Generate a revocation certificate for the complete key. To only revoke a subkey or a key signature, use the @option{--edit} command. This command merely creates the revocation certificate so that it can be used to revoke the key if that is ever needed. To actually revoke a key the created revocation certificate needs to be merged with the key to revoke. This is done by importing the revocation certificate using the @option{--import} command. Then the revoked key needs to be published, which is best done by sending the key to a keyserver (command @option{--send-key}) and by exporting (@option{--export}) it to a file which is then send to frequent communication partners. @item --generate-designated-revocation @var{name} @opindex generate-designated-revocation @itemx --desig-revoke @var{name} @opindex desig-revoke Generate a designated revocation certificate for a key. This allows a user (with the permission of the keyholder) to revoke someone else's key. @item --edit-key @opindex edit-key Present a menu which enables you to do most of the key management related tasks. It expects the specification of a key on the command line. @c ******** Begin Edit-key Options ********** @table @asis @item uid @var{n} @opindex keyedit:uid Toggle selection of user ID or photographic user ID with index @var{n}. Use @code{*} to select all and @code{0} to deselect all. @item key @var{n} @opindex keyedit:key Toggle selection of subkey with index @var{n} or key ID @var{n}. Use @code{*} to select all and @code{0} to deselect all. @item sign @opindex keyedit:sign Make a signature on key of user @code{name}. If the key is not yet signed by the default user (or the users given with @option{-u}), the program displays the information of the key again, together with its fingerprint and asks whether it should be signed. This question is repeated for all users specified with @option{-u}. @item lsign @opindex keyedit:lsign Same as "sign" but the signature is marked as non-exportable and will therefore never be used by others. This may be used to make keys valid only in the local environment. @item nrsign @opindex keyedit:nrsign Same as "sign" but the signature is marked as non-revocable and can therefore never be revoked. @item tsign @opindex keyedit:tsign Make a trust signature. This is a signature that combines the notions of certification (like a regular signature), and trust (like the - "trust" command). It is generally only useful in distinct communities - or groups. For more information please read the sections - ``Trust Signature'' and ``Regular Expression'' in RFC-4880. + "trust" command). It is generally useful in distinct communities + or groups to implement the concept of a Trusted Introducer. For + more information please read the sections ``Trust Signature'' and + ``Regular Expression'' in RFC-4880. @end table @c man:.RS Note that "l" (for local / non-exportable), "nr" (for non-revocable, and "t" (for trust) may be freely mixed and prefixed to "sign" to create a signature of any type desired. @c man:.RE If the option @option{--only-sign-text-ids} is specified, then any non-text based user ids (e.g., photo IDs) will not be selected for signing. @table @asis @item delsig @opindex keyedit:delsig Delete a signature. Note that it is not possible to retract a signature, once it has been send to the public (i.e. to a keyserver). In that case you better use @code{revsig}. @item revsig @opindex keyedit:revsig Revoke a signature. For every signature which has been generated by one of the secret keys, GnuPG asks whether a revocation certificate should be generated. @item check @opindex keyedit:check Check the signatures on all selected user IDs. With the extra option @code{selfsig} only self-signatures are shown. @item adduid @opindex keyedit:adduid Create an additional user ID. @item addphoto @opindex keyedit:addphoto Create a photographic user ID. This will prompt for a JPEG file that will be embedded into the user ID. Note that a very large JPEG will make for a very large key. Also note that some programs will display your JPEG unchanged (GnuPG), and some programs will scale it to fit in a dialog box (PGP). @item showphoto @opindex keyedit:showphoto Display the selected photographic user ID. @item deluid @opindex keyedit:deluid Delete a user ID or photographic user ID. Note that it is not possible to retract a user id, once it has been send to the public (i.e. to a keyserver). In that case you better use @code{revuid}. @item revuid @opindex keyedit:revuid Revoke a user ID or photographic user ID. @item primary @opindex keyedit:primary Flag the current user id as the primary one, removes the primary user id flag from all other user ids and sets the timestamp of all affected self-signatures one second ahead. Note that setting a photo user ID as primary makes it primary over other photo user IDs, and setting a regular user ID as primary makes it primary over other regular user IDs. @item keyserver @opindex keyedit:keyserver Set a preferred keyserver for the specified user ID(s). This allows other users to know where you prefer they get your key from. See @option{--keyserver-options honor-keyserver-url} for more on how this works. Setting a value of "none" removes an existing preferred keyserver. @item notation @opindex keyedit:notation Set a name=value notation for the specified user ID(s). See @option{--cert-notation} for more on how this works. Setting a value of "none" removes all notations, setting a notation prefixed with a minus sign (-) removes that notation, and setting a notation name (without the =value) prefixed with a minus sign removes all notations with that name. @item pref @opindex keyedit:pref List preferences from the selected user ID. This shows the actual preferences, without including any implied preferences. @item showpref @opindex keyedit:showpref More verbose preferences listing for the selected user ID. This shows the preferences in effect by including the implied preferences of 3DES (cipher), SHA-1 (digest), and Uncompressed (compression) if they are not already included in the preference list. In addition, the preferred keyserver and signature notations (if any) are shown. @item setpref @var{string} @opindex keyedit:setpref Set the list of user ID preferences to @var{string} for all (or just the selected) user IDs. Calling setpref with no arguments sets the preference list to the default (either built-in or set via @option{--default-preference-list}), and calling setpref with "none" as the argument sets an empty preference list. Use @command{@gpgname --version} to get a list of available algorithms. Note that while you can change the preferences on an attribute user ID (aka "photo ID"), GnuPG does not select keys via attribute user IDs so these preferences will not be used by GnuPG. Note that an unattended version of this command is available as @option{--quick-update-pref}. When setting preferences, you should list the algorithms in the order which you'd like to see them used by someone else when encrypting a message to your key. If you don't include 3DES, it will be automatically added at the end. Note that there are many factors that go into choosing an algorithm (for example, your key may not be the only recipient), and so the remote OpenPGP application being used to send to you may or may not follow your exact chosen order for a given message. It will, however, only choose an algorithm that is present on the preference list of every recipient key. See also the INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS section below. @item addkey @opindex keyedit:addkey Add a subkey to this key. @item addcardkey @opindex keyedit:addcardkey Generate a subkey on a card and add it to this key. @item keytocard @opindex keyedit:keytocard Transfer the selected secret subkey (or the primary key if no subkey has been selected) to a smartcard. The secret key in the keyring will be replaced by a stub if the key could be stored successfully on the card and you use the save command later. Only certain key types may be transferred to the card. A sub menu allows you to select on what card to store the key. Note that it is not possible to get that key back from the card - if the card gets broken your secret key will be lost unless you have a backup somewhere. @item bkuptocard @var{file} @opindex keyedit:bkuptocard Restore the given @var{file} to a card. This command may be used to restore a backup key (as generated during card initialization) to a new card. In almost all cases this will be the encryption key. You should use this command only with the corresponding public key and make sure that the file given as argument is indeed the backup to restore. You should then select 2 to restore as encryption key. You will first be asked to enter the passphrase of the backup key and then for the Admin PIN of the card. @item keytotpm @opindex keyedit:keytotpm Transfer the selected secret subkey (or the primary key if no subkey has been selected) to TPM form. The secret key in the keyring will be replaced by the TPM representation of that key, which can only be read by the particular TPM that created it (so the keyfile now becomes locked to the laptop containing the TPM). Only certain key types may be transferred to the TPM (all TPM 2.0 systems are mandated to have the rsa2048 and nistp256 algorithms but newer TPMs may have more). Note that the key itself is not transferred into the TPM, merely encrypted by the TPM in-place, so if the keyfile is deleted, the key will be lost. Once transferred to TPM representation, the key file can never be converted back to non-TPM form and the key will die when the TPM does, so you should first have a backup on secure offline storage of the actual secret key file before conversion. It is essential to use the physical system TPM that you have rw permission on the TPM resource manager device (/dev/tpmrm0). Usually this means you must be a member of the tss group. @item delkey @opindex keyedit:delkey Remove a subkey (secondary key). Note that it is not possible to retract a subkey, once it has been send to the public (i.e. to a keyserver). In that case you better use @code{revkey}. Also note that this only deletes the public part of a key. @item revkey @opindex keyedit:revkey Revoke a subkey. @item expire @opindex keyedit:expire Change the key or subkey expiration time. If a subkey is selected, the expiration time of this subkey will be changed. With no selection, the key expiration of the primary key is changed. @item trust @opindex keyedit:trust Change the owner trust value for the key. This updates the trust-db immediately and no save is required. @item disable @itemx enable @opindex keyedit:disable @opindex keyedit:enable Disable or enable an entire key. A disabled key can not normally be used for encryption. @item addrevoker @opindex keyedit:addrevoker Add a designated revoker to the key. This takes one optional argument: "sensitive". If a designated revoker is marked as sensitive, it will not be exported by default (see export-options). @item passwd @opindex keyedit:passwd Change the passphrase of the secret key. @item toggle @opindex keyedit:toggle This is dummy command which exists only for backward compatibility. @item clean @opindex keyedit:clean Compact (by removing all signatures except the selfsig) any user ID that is no longer usable (e.g. revoked, or expired). Then, remove any signatures that are not usable by the trust calculations. Specifically, this removes any signature that does not validate, any signature that is superseded by a later signature, revoked signatures, and signatures issued by keys that are not present on the keyring. @item minimize @opindex keyedit:minimize Make the key as small as possible. This removes all signatures from each user ID except for the most recent self-signature. @item change-usage @opindex keyedit:change-usage Change the usage flags (capabilities) of the primary key or of subkeys. These usage flags (e.g. Certify, Sign, Authenticate, Encrypt) are set during key creation. Sometimes it is useful to have the opportunity to change them (for example to add Authenticate) after they have been created. Please take care when doing this; the allowed usage flags depend on the key algorithm. @item cross-certify @opindex keyedit:cross-certify Add cross-certification signatures to signing subkeys that may not currently have them. Cross-certification signatures protect against a subtle attack against signing subkeys. See @option{--require-cross-certification}. All new keys generated have this signature by default, so this command is only useful to bring older keys up to date. @item save @opindex keyedit:save Save all changes to the keyring and quit. @item quit @opindex keyedit:quit Quit the program without updating the keyring. @end table @c man:.RS The listing shows you the key with its secondary keys and all user IDs. The primary user ID is indicated by a dot, and selected keys or user IDs are indicated by an asterisk. The trust value is displayed with the primary key: "trust" is the assigned owner trust and "validity" is the calculated validity of the key. Validity values are also displayed for all user IDs. For possible values of trust, @pxref{trust-values}. @c man:.RE @c ******** End Edit-key Options ********** @item --sign-key @var{name} @opindex sign-key Signs a public key with your secret key. This is a shortcut version of the subcommand "sign" from @option{--edit-key}. @item --lsign-key @var{name} @opindex lsign-key Signs a public key with your secret key but marks it as non-exportable. This is a shortcut version of the subcommand "lsign" from @option{--edit-key}. @item --quick-sign-key @var{fpr} [@var{names}] @itemx --quick-lsign-key @var{fpr} [@var{names}] @opindex quick-sign-key @opindex quick-lsign-key Directly sign a key from the passphrase without any further user interaction. The @var{fpr} must be the verified primary fingerprint of a key in the local keyring. If no @var{names} are given, all useful user ids are signed; with given [@var{names}] only useful user ids matching one of these names are signed. By default, or if a name is prefixed with a '*', a case insensitive substring match is used. If a name is prefixed with a '=' a case sensitive exact match is done. The command @option{--quick-lsign-key} marks the signatures as non-exportable. If such a non-exportable signature already exists the @option{--quick-sign-key} turns it into a exportable signature. If you need to update an existing signature, for example to add or change notation data, you need to use the option @option{--force-sign-key}. This command uses reasonable defaults and thus does not provide the full flexibility of the "sign" subcommand from @option{--edit-key}. Its intended use is to help unattended key signing by utilizing a list of verified fingerprints. @item --quick-add-uid @var{user-id} @var{new-user-id} @opindex quick-add-uid This command adds a new user id to an existing key. In contrast to the interactive sub-command @code{adduid} of @option{--edit-key} the @var{new-user-id} is added verbatim with only leading and trailing white space removed, it is expected to be UTF-8 encoded, and no checks on its form are applied. @item --quick-revoke-uid @var{user-id} @var{user-id-to-revoke} @opindex quick-revoke-uid This command revokes a user ID on an existing key. It cannot be used to revoke the last user ID on key (some non-revoked user ID must remain), with revocation reason ``User ID is no longer valid''. If you want to specify a different revocation reason, or to supply supplementary revocation text, you should use the interactive sub-command @code{revuid} of @option{--edit-key}. @item --quick-revoke-sig @var{fpr} @var{signing-fpr} [@var{names}] @opindex quick-revoke-sig This command revokes the key signatures made by @var{signing-fpr} from the key specified by the fingerprint @var{fpr}. With @var{names} given only the signatures on user ids of the key matching any of the given names are affected (see @option{--quick-sign-key}). If a revocation already exists a notice is printed instead of creating a new revocation; no error is returned in this case. Note that key signature revocations may be superseded by a newer key signature and in turn again revoked. @item --quick-set-primary-uid @var{user-id} @var{primary-user-id} @opindex quick-set-primary-uid This command sets or updates the primary user ID flag on an existing key. @var{user-id} specifies the key and @var{primary-user-id} the user ID which shall be flagged as the primary user ID. The primary user ID flag is removed from all other user ids and the timestamp of all affected self-signatures is set one second ahead. @item --quick-update-pref @var{user-id} @opindex quick-update-pref This command updates the preference list of the key to the current default value (either built-in or set via @option{--default-preference-list}). This is the unattended version of of using "setpref" in the @option{--key-edit} menu without giving a list. Note that you can show the preferences in a key listing by using @option{--list-options show-pref} or @option{--list-options show-pref-verbose}. You should also re-distribute updated keys to your peers. @item --change-passphrase @var{user-id} @opindex change-passphrase @itemx --passwd @var{user-id} @opindex passwd Change the passphrase of the secret key belonging to the certificate specified as @var{user-id}. This is a shortcut for the sub-command @code{passwd} of the @option{--edit-key} menu. When using together with the option @option{--dry-run} this will not actually change the passphrase but check that the current passphrase is correct. @end table @c ******************************************* @c *************** **************** @c *************** OPTIONS **************** @c *************** **************** @c ******************************************* @mansect options @node GPG Options @section Option Summary @command{@gpgname} features a bunch of options to control the exact behaviour and to change the default configuration. @menu * GPG Configuration Options:: How to change the configuration. * GPG Key related Options:: Key related options. * GPG Input and Output:: Input and Output. * OpenPGP Options:: OpenPGP protocol specific options. * Compliance Options:: Compliance options. * GPG Esoteric Options:: Doing things one usually doesn't want to do. * Deprecated Options:: Deprecated options. @end menu Long options can be put in an options file (default "~/.gnupg/gpg.conf"). Short option names will not work - for example, "armor" is a valid option for the options file, while "a" is not. Do not write the 2 dashes, but simply the name of the option and any required arguments. Lines with a hash ('#') as the first non-white-space character are ignored. Commands may be put in this file too, but that is not generally useful as the command will execute automatically with every execution of gpg. Please remember that option parsing stops as soon as a non-option is encountered, you can explicitly stop parsing by using the special option @option{--}. @c ******************************************* @c ******** CONFIGURATION OPTIONS ********** @c ******************************************* @node GPG Configuration Options @subsection How to change the configuration These options are used to change the configuration and most of them are usually found in the option file. @table @gnupgtabopt @item --default-key @var{name} @opindex default-key Use @var{name} as the default key to sign with. If this option is not used, the default key is the first key found in the secret keyring. Note that @option{-u} or @option{--local-user} overrides this option. This option may be given multiple times. In this case, the last key for which a secret key is available is used. If there is no secret key available for any of the specified values, GnuPG will not emit an error message but continue as if this option wasn't given. @item --default-recipient @var{name} @opindex default-recipient Use @var{name} as default recipient if option @option{--recipient} is not used and don't ask if this is a valid one. @var{name} must be non-empty. @item --default-recipient-self @opindex default-recipient-self Use the default key as default recipient if option @option{--recipient} is not used and don't ask if this is a valid one. The default key is the first one from the secret keyring or the one set with @option{--default-key}. @item --no-default-recipient @opindex no-default-recipient Reset @option{--default-recipient} and @option{--default-recipient-self}. Should not be used in an option file. @item -v, --verbose @opindex verbose Give more information during processing. If used twice, the input data is listed in detail. @item --no-verbose @opindex no-verbose Reset verbose level to 0. Should not be used in an option file. @item -q, --quiet @opindex quiet Try to be as quiet as possible. Should not be used in an option file. @item --batch @itemx --no-batch @opindex batch @opindex no-batch Use batch mode. Never ask, do not allow interactive commands. @option{--no-batch} disables this option. Note that even with a filename given on the command line, gpg might still need to read from STDIN (in particular if gpg figures that the input is a detached signature and no data file has been specified). Thus if you do not want to feed data via STDIN, you should connect STDIN to @file{/dev/null}. It is highly recommended to use this option along with the options @option{--status-fd} and @option{--with-colons} for any unattended use of @command{gpg}. Should not be used in an option file. @item --no-tty @opindex no-tty Make sure that the TTY (terminal) is never used for any output. This option is needed in some cases because GnuPG sometimes prints warnings to the TTY even if @option{--batch} is used. @item --yes @opindex yes Assume "yes" on most questions. Should not be used in an option file. @item --no @opindex no Assume "no" on most questions. Should not be used in an option file. @item --list-filter @{select=@var{expr}@} @opindex list-filter A list filter can be used to output only certain keys during key listing commands. For the available property names, see the description of @option{--import-filter}. @item --list-options @var{parameters} @opindex list-options This is a space or comma delimited string that gives options used when listing keys and signatures (that is, @option{--list-keys}, @option{--check-signatures}, @option{--list-public-keys}, @option{--list-secret-keys}, and the @option{--edit-key} functions). Options can be prepended with a @option{no-} (after the two dashes) to give the opposite meaning. The options are: @table @asis @item show-photos @opindex list-options:show-photos Causes @option{--list-keys}, @option{--check-signatures}, @option{--list-public-keys}, and @option{--list-secret-keys} to display any photo IDs attached to the key. Defaults to no. See also @option{--photo-viewer}. Does not work with @option{--with-colons}: see @option{--attribute-fd} for the appropriate way to get photo data for scripts and other frontends. @item show-usage @opindex list-options:show-usage Show usage information for keys and subkeys in the standard key listing. This is a list of letters indicating the allowed usage for a key (@code{E}=encryption, @code{S}=signing, @code{C}=certification, @code{A}=authentication). Defaults to yes. @item show-policy-urls @opindex list-options:show-policy-urls Show policy URLs in the @option{--check-signatures} listings. Defaults to no. @item show-notations @itemx show-std-notations @itemx show-user-notations @opindex list-options:show-notations @opindex list-options:show-std-notations @opindex list-options:show-user-notations Show all, IETF standard, or user-defined signature notations in the @option{--check-signatures} listings. Defaults to no. @item show-keyserver-urls @opindex list-options:show-keyserver-urls Show any preferred keyserver URL in the @option{--check-signatures} listings. Defaults to no. @item show-uid-validity @opindex list-options:show-uid-validity Display the calculated validity of user IDs during key listings. Defaults to yes. @item show-unusable-uids @opindex list-options:show-unusable-uids Show revoked and expired user IDs in key listings. Defaults to no. @item show-unusable-subkeys @opindex list-options:show-unusable-subkeys Show revoked and expired subkeys in key listings. Defaults to no. @item show-keyring @opindex list-options:show-keyring Display the keyring name at the head of key listings to show which keyring a given key resides on. Defaults to no. @item show-sig-expire @opindex list-options:show-sig-expire Show signature expiration dates (if any) during @option{--check-signatures} listings. Defaults to no. @item show-sig-subpackets @opindex list-options:show-sig-subpackets Include signature subpackets in the key listing. This option can take an optional argument list of the subpackets to list. If no argument is passed, list all subpackets. Defaults to no. This option is only meaningful when using @option{--with-colons} along with @option{--check-signatures}. @item show-only-fpr-mbox @opindex list-options:show-only-fpr-mbox For each user-id which has a valid mail address print only the fingerprint followed by the mail address. @item sort-sigs @opindex list-options:sort-sigs With --list-sigs and --check-sigs sort the signatures by keyID and creation time to make it easier to view the history of these signatures. The self-signature is also listed before other signatures. Defaults to yes. @end table @item --verify-options @var{parameters} @opindex verify-options This is a space or comma delimited string that gives options used when verifying signatures. Options can be prepended with a `no-' to give the opposite meaning. The options are: @table @asis @item show-photos @opindex verify-options:show-photos Display any photo IDs present on the key that issued the signature. Defaults to no. See also @option{--photo-viewer}. @item show-policy-urls @opindex verify-options:show-policy-urls Show policy URLs in the signature being verified. Defaults to yes. @item show-notations @itemx show-std-notations @itemx show-user-notations @opindex verify-options:show-notations @opindex verify-options:show-std-notations @opindex verify-options:show-user-notations Show all, IETF standard, or user-defined signature notations in the signature being verified. Defaults to IETF standard. @item show-keyserver-urls @opindex verify-options:show-keyserver-urls Show any preferred keyserver URL in the signature being verified. Defaults to yes. @item show-uid-validity @opindex verify-options:show-uid-validity Display the calculated validity of the user IDs on the key that issued the signature. Defaults to yes. @item show-unusable-uids @opindex verify-options:show-unusable-uids Show revoked and expired user IDs during signature verification. Defaults to no. @item show-primary-uid-only @opindex verify-options:show-primary-uid-only Show only the primary user ID during signature verification. That is all the AKA lines as well as photo Ids are not shown with the signature verification status. @end table @item --enable-large-rsa @itemx --disable-large-rsa @opindex enable-large-rsa @opindex disable-large-rsa With --generate-key and --batch, enable the creation of RSA secret keys as large as 8192 bit. Note: 8192 bit is more than is generally recommended. These large keys don't significantly improve security, but they are more expensive to use, and their signatures and certifications are larger. This option is only available if the binary was build with large-secmem support. @item --enable-dsa2 @itemx --disable-dsa2 @opindex enable-dsa2 @opindex disable-dsa2 Enable hash truncation for all DSA keys even for old DSA Keys up to 1024 bit. This is also the default with @option{--openpgp}. Note that older versions of GnuPG also required this flag to allow the generation of DSA larger than 1024 bit. @item --photo-viewer @var{string} @opindex photo-viewer This is the command line that should be run to view a photo ID. "%i" will be expanded to a filename containing the photo. "%I" does the same, except the file will not be deleted once the viewer exits. Other flags are "%k" for the key ID, "%K" for the long key ID, "%f" for the key fingerprint, "%t" for the extension of the image type (e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"), "%v" for the single-character calculated validity of the image being viewed (e.g. "f"), "%V" for the calculated validity as a string (e.g. "full"), "%U" for a base32 encoded hash of the user ID, and "%%" for an actual percent sign. If neither %i or %I are present, then the photo will be supplied to the viewer on standard input. On Unix the default viewer is @code{xloadimage -fork -quiet -title 'KeyID 0x%k' STDIN} with a fallback to @code{display -title 'KeyID 0x%k' %i} and finally to @code{xdg-open %i}. On Windows @code{!ShellExecute 400 %i} is used; here the command is a meta command to use that API call followed by a wait time in milliseconds which is used to give the viewer time to read the temporary image file before gpg deletes it again. Note that if your image viewer program is not secure, then executing it from gpg does not make it secure. @item --exec-path @var{string} @opindex exec-path @efindex PATH Sets a list of directories to search for photo viewers If not provided photo viewers use the @code{PATH} environment variable. @item --keyring @var{file} @opindex keyring Add @var{file} to the current list of keyrings. If @var{file} begins with a tilde and a slash, these are replaced by the $HOME directory. If the filename does not contain a slash, it is assumed to be in the GnuPG home directory ("~/.gnupg" unless @option{--homedir} or $GNUPGHOME is used). Note that this adds a keyring to the current list. If the intent is to use the specified keyring alone, use @option{--keyring} along with @option{--no-default-keyring}. If the option @option{--no-keyring} has been used no keyrings will be used at all. Note that if the option @option{use-keyboxd} is enabled in @file{common.conf}, no keyrings are used at all and keys are all maintained by the keyboxd process in its own database. @item --primary-keyring @var{file} @opindex primary-keyring This is a varian of @option{--keyring} and designates @var{file} as the primary public keyring. This means that newly imported keys (via @option{--import} or keyserver @option{--recv-from}) will go to this keyring. @item --secret-keyring @var{file} @opindex secret-keyring This is an obsolete option and ignored. All secret keys are stored in the @file{private-keys-v1.d} directory below the GnuPG home directory. @item --trustdb-name @var{file} @opindex trustdb-name Use @var{file} instead of the default trustdb. If @var{file} begins with a tilde and a slash, these are replaced by the $HOME directory. If the filename does not contain a slash, it is assumed to be in the GnuPG home directory (@file{~/.gnupg} if @option{--homedir} or $GNUPGHOME is not used). @include opt-homedir.texi @item --display-charset @var{name} @opindex display-charset Set the name of the native character set. This is used to convert some informational strings like user IDs to the proper UTF-8 encoding. Note that this has nothing to do with the character set of data to be encrypted or signed; GnuPG does not recode user-supplied data. If this option is not used, the default character set is determined from the current locale. A verbosity level of 3 shows the chosen set. This option should not be used on Windows. Valid values for @var{name} are: @table @asis @item iso-8859-1 @opindex display-charset:iso-8859-1 This is the Latin 1 set. @item iso-8859-2 @opindex display-charset:iso-8859-2 The Latin 2 set. @item iso-8859-15 @opindex display-charset:iso-8859-15 This is currently an alias for the Latin 1 set. @item koi8-r @opindex display-charset:koi8-r The usual Russian set (RFC-1489). @item utf-8 @opindex display-charset:utf-8 Bypass all translations and assume that the OS uses native UTF-8 encoding. @end table @item --utf8-strings @itemx --no-utf8-strings @opindex utf8-strings Assume that command line arguments are given as UTF-8 strings. The default (@option{--no-utf8-strings}) is to assume that arguments are encoded in the character set as specified by @option{--display-charset}. These options affect all following arguments. Both options may be used multiple times. This option should not be used in an option file. This option has no effect on Windows. There the internal used UTF-8 encoding is translated for console input and output. The command line arguments are expected as Unicode and translated to UTF-8. Thus when calling this program from another, make sure to use the Unicode version of CreateProcess. @anchor{gpg-option --options} @item --options @var{file} @opindex options Read options from @var{file} and do not try to read them from the default options file in the homedir (see @option{--homedir}). This option is ignored if used in an options file. @item --no-options @opindex no-options Shortcut for @option{--options /dev/null}. This option is detected before an attempt to open an option file. Using this option will also prevent the creation of a @file{~/.gnupg} homedir. @item -z @var{n} @itemx --compress-level @var{n} @itemx --bzip2-compress-level @var{n} @opindex compress-level @opindex bzip2-compress-level Set compression level to @var{n} for the ZIP and ZLIB compression algorithms. The default is to use the default compression level of zlib (normally 6). @option{--bzip2-compress-level} sets the compression level for the BZIP2 compression algorithm (defaulting to 6 as well). This is a different option from @option{--compress-level} since BZIP2 uses a significant amount of memory for each additional compression level. @option{-z} sets both. A value of 0 for @var{n} disables compression. +A value of -1 forces compression using the default level. + +Except for the @option{--store} command compression is always used +unless @command{gpg} detects that the input is already compressed. To +inhibit the use of compression use @option{-z0}; to force compression +use @option{-z-1} or option @option{z} with another compression level +than the default as indicated by -1. Note that this overriding of the +default deection works only with @option{z} and not with the long +variant of this option. + @item --bzip2-decompress-lowmem @opindex bzip2-decompress-lowmem Use a different decompression method for BZIP2 compressed files. This alternate method uses a bit more than half the memory, but also runs at half the speed. This is useful under extreme low memory circumstances when the file was originally compressed at a high @option{--bzip2-compress-level}. @item --mangle-dos-filenames @itemx --no-mangle-dos-filenames @opindex mangle-dos-filenames @opindex no-mangle-dos-filenames Older version of Windows cannot handle filenames with more than one dot. @option{--mangle-dos-filenames} causes GnuPG to replace (rather than add to) the extension of an output filename to avoid this problem. This option is off by default and has no effect on non-Windows platforms. @item --ask-cert-level @itemx --no-ask-cert-level @opindex ask-cert-level When making a key signature, prompt for a certification level. If this option is not specified, the certification level used is set via @option{--default-cert-level}. See @option{--default-cert-level} for information on the specific levels and how they are used. @option{--no-ask-cert-level} disables this option. This option defaults to no. @item --default-cert-level @var{n} @opindex default-cert-level The default to use for the check level when signing a key. 0 means you make no particular claim as to how carefully you verified the key. 1 means you believe the key is owned by the person who claims to own it but you could not, or did not verify the key at all. This is useful for a "persona" verification, where you sign the key of a pseudonymous user. 2 means you did casual verification of the key. For example, this could mean that you verified the key fingerprint and checked the user ID on the key against a photo ID. 3 means you did extensive verification of the key. For example, this could mean that you verified the key fingerprint with the owner of the key in person, and that you checked, by means of a hard to forge document with a photo ID (such as a passport) that the name of the key owner matches the name in the user ID on the key, and finally that you verified (by exchange of email) that the email address on the key belongs to the key owner. Note that the examples given above for levels 2 and 3 are just that: examples. In the end, it is up to you to decide just what "casual" and "extensive" mean to you. This option defaults to 0 (no particular claim). @item --min-cert-level @opindex min-cert-level When building the trust database, treat any signatures with a certification level below this as invalid. Defaults to 2, which disregards level 1 signatures. Note that level 0 "no particular claim" signatures are always accepted. @item --trusted-key @var{long key ID or fingerprint} @opindex trusted-key Assume that the specified key (which should be given as fingerprint) is as trustworthy as one of your own secret keys. This option is useful if you don't want to keep your secret keys (or one of them) online but still want to be able to check the validity of a given recipient's or signator's key. If the given key is not locally available but an LDAP keyserver is configured the missing key is imported from that server. @item --trust-model @{pgp|classic|tofu|tofu+pgp|direct|always|auto@} @opindex trust-model Set what trust model GnuPG should follow. The models are: @table @asis @item pgp @opindex trust-model:pgp This is the Web of Trust combined with trust signatures as used in PGP 5.x and later. This is the default trust model when creating a new trust database. @item classic @opindex trust-model:classic This is the standard Web of Trust as introduced by PGP 2. @item tofu @opindex trust-model:tofu @anchor{trust-model-tofu} TOFU stands for Trust On First Use. In this experimental trust model, the first time a key is seen, it is memorized. If later another key with a user id with the same email address is seen, both keys are marked as suspect. In that case, the next time either is used, a warning is displayed describing the conflict, why it might have occurred (either the user generated a new key and failed to cross sign the old and new keys, the key is forgery, or a man-in-the-middle attack is being attempted), and the user is prompted to manually confirm the validity of the key in question. Because a potential attacker is able to control the email address and thereby circumvent the conflict detection algorithm by using an email address that is similar in appearance to a trusted email address, whenever a message is verified, statistics about the number of messages signed with the key are shown. In this way, a user can easily identify attacks using fake keys for regular correspondents. When compared with the Web of Trust, TOFU offers significantly weaker security guarantees. In particular, TOFU only helps ensure consistency (that is, that the binding between a key and email address doesn't change). A major advantage of TOFU is that it requires little maintenance to use correctly. To use the web of trust properly, you need to actively sign keys and mark users as trusted introducers. This is a time-consuming process and anecdotal evidence suggests that even security-conscious users rarely take the time to do this thoroughly and instead rely on an ad-hoc TOFU process. In the TOFU model, policies are associated with bindings between keys and email addresses (which are extracted from user ids and normalized). There are five policies, which can be set manually using the @option{--tofu-policy} option. The default policy can be set using the @option{--tofu-default-policy} option. The TOFU policies are: @code{auto}, @code{good}, @code{unknown}, @code{bad} and @code{ask}. The @code{auto} policy is used by default (unless overridden by @option{--tofu-default-policy}) and marks a binding as marginally trusted. The @code{good}, @code{unknown} and @code{bad} policies mark a binding as fully trusted, as having unknown trust or as having trust never, respectively. The @code{unknown} policy is useful for just using TOFU to detect conflicts, but to never assign positive trust to a binding. The final policy, @code{ask} prompts the user to indicate the binding's trust. If batch mode is enabled (or input is inappropriate in the context), then the user is not prompted and the @code{undefined} trust level is returned. @item tofu+pgp @opindex trust-model:tofu+pgp This experimental trust model combines TOFU with the Web of Trust. This is done by computing the trust level for each model and then taking the maximum trust level where the trust levels are ordered as follows: @code{unknown < undefined < marginal < fully < ultimate < expired < never}. By setting @option{--tofu-default-policy=unknown}, this model can be used to implement the web of trust with TOFU's conflict detection algorithm, but without its assignment of positive trust values, which some security-conscious users don't like. @item direct @opindex trust-model:direct Key validity is set directly by the user and not calculated via the Web of Trust. This model is solely based on the key and does not distinguish user IDs. Note that when changing to another trust model the trust values assigned to a key are transformed into ownertrust values, which also indicate how you trust the owner of the key to sign other keys. @item always @opindex trust-model:always Skip key validation and assume that used keys are always fully valid. You generally won't use this unless you are using some external validation scheme. This option also suppresses the "[uncertain]" tag printed with signature checks when there is no evidence that the user ID is bound to the key. Note that this trust model still does not allow the use of expired, revoked, or disabled keys. @item auto @opindex trust-model:auto Select the trust model depending on whatever the internal trust database says. This is the default model if such a database already exists. Note that a tofu trust model is not considered here and must be enabled explicitly. @end table @item --auto-key-locate @var{mechanisms} @itemx --no-auto-key-locate @opindex auto-key-locate GnuPG can automatically locate and retrieve keys as needed using this option. This happens when encrypting to an email address (in the "user@@example.com" form), and there are no "user@@example.com" keys on the local keyring. This option takes any number of the mechanisms listed below, in the order they are to be tried. Instead of listing the mechanisms as comma delimited arguments, the option may also be given several times to add more mechanism. The option @option{--no-auto-key-locate} or the mechanism "clear" resets the list. The default is "local,wkd". @table @asis @item cert Locate a key using DNS CERT, as specified in RFC-4398. @item dane Locate a key using DANE, as specified in draft-ietf-dane-openpgpkey-05.txt. @item wkd Locate a key using the Web Key Directory protocol. @item ldap Using DNS Service Discovery, check the domain in question for any LDAP keyservers to use. If this fails, attempt to locate the key using the PGP Universal method of checking @samp{ldap://keys.(thedomain)}. @item ntds Locate the key using the Active Directory (Windows only). This method also allows to search by fingerprint using the command @option{--locate-external-key}. Note that this mechanism is actually a shortcut for the mechanism @samp{keyserver} but using "ldap:///" as the keyserver. @item keyserver Locate a key using a keyserver. This method also allows to search by fingerprint using the command @option{--locate-external-key} if any of the configured keyservers is an LDAP server. @item keyserver-URL In addition, a keyserver URL as used in the @command{dirmngr} configuration may be used here to query that particular keyserver. This method also allows to search by fingerprint using the command @option{--locate-external-key} if the URL specifies an LDAP server. @item local Locate the key using the local keyrings. This mechanism allows the user to select the order a local key lookup is done. Thus using @samp{--auto-key-locate local} is identical to @option{--no-auto-key-locate}. @item nodefault This flag disables the standard local key lookup, done before any of the mechanisms defined by the @option{--auto-key-locate} are tried. The position of this mechanism in the list does not matter. It is not required if @code{local} is also used. @item clear Clear all defined mechanisms. This is useful to override mechanisms given in a config file. Note that a @code{nodefault} in @var{mechanisms} will also be cleared unless it is given after the @code{clear}. @end table @item --auto-key-import @itemx --no-auto-key-import @opindex auto-key-import @opindex no-auto-key-import This is an offline mechanism to get a missing key for signature verification and for later encryption to this key. If this option is enabled and a signature includes an embedded key, that key is used to verify the signature and on verification success the key is imported. The default is @option{--no-auto-key-import}. On the sender (signing) site the option @option{--include-key-block} needs to be used to put the public part of the signing key as “Key Block subpacket” into the signature. @item --auto-key-retrieve @itemx --no-auto-key-retrieve @opindex auto-key-retrieve @opindex no-auto-key-retrieve These options enable or disable the automatic retrieving of keys from a keyserver when verifying signatures made by keys that are not on the local keyring. The default is @option{--no-auto-key-retrieve}. The order of methods tried to lookup the key is: 1. If the option @option{--auto-key-import} is set and the signatures includes an embedded key, that key is used to verify the signature and on verification success that key is imported. 2. If a preferred keyserver is specified in the signature and the option @option{honor-keyserver-url} is active (which is not the default), that keyserver is tried. Note that the creator of the signature uses the option @option{--sig-keyserver-url} to specify the preferred keyserver for data signatures. 3. If the signature has the Signer's UID set (e.g. using @option{--sender} while creating the signature) a Web Key Directory (WKD) lookup is done. This is the default configuration but can be disabled by removing WKD from the auto-key-locate list or by using the option @option{--disable-signer-uid}. 4. If any keyserver is configured and the Issuer Fingerprint is part of the signature (since GnuPG 2.1.16), the configured keyservers are tried. Note that this option makes a "web bug" like behavior possible. Keyserver or Web Key Directory operators can see which keys you request, so by sending you a message signed by a brand new key (which you naturally will not have on your local keyring), the operator can tell both your IP address and the time when you verified the signature. @item --keyid-format @{none|short|0xshort|long|0xlong@} @opindex keyid-format Select how to display key IDs. "none" does not show the key ID at all but shows the fingerprint in a separate line. "short" is the traditional 8-character key ID. "long" is the more accurate (but less convenient) 16-character key ID. Add an "0x" to either to include an "0x" at the beginning of the key ID, as in 0x99242560. Note that this option is ignored if the option @option{--with-colons} is used. @item --keyserver @var{name} @opindex keyserver This option is deprecated - please use the @option{--keyserver} in @file{dirmngr.conf} instead. Use @var{name} as your keyserver. This is the server that @option{--receive-keys}, @option{--send-keys}, and @option{--search-keys} will communicate with to receive keys from, send keys to, and search for keys on. The format of the @var{name} is a URI: `scheme:[//]keyservername[:port]' The scheme is the type of keyserver: "hkp"/"hkps" for the HTTP (or compatible) keyservers or "ldap"/"ldaps" for the LDAP keyservers. Note that your particular installation of GnuPG may have other keyserver types available as well. Keyserver schemes are case-insensitive. Most keyservers synchronize with each other, so there is generally no need to send keys to more than one server. The keyserver @code{hkp://keys.gnupg.net} uses round robin DNS to give a different keyserver each time you use it. @item --keyserver-options @{@var{name}=@var{value}@} @opindex keyserver-options This is a space or comma delimited string that gives options for the keyserver. Options can be prefixed with a `no-' to give the opposite meaning. Valid import-options or export-options may be used here as well to apply to importing (@option{--recv-key}) or exporting (@option{--send-key}) a key from a keyserver. While not all options are available for all keyserver types, some common options are: @table @asis @item include-revoked When searching for a key with @option{--search-keys}, include keys that are marked on the keyserver as revoked. Note that not all keyservers differentiate between revoked and unrevoked keys, and for such keyservers this option is meaningless. Note also that most keyservers do not have cryptographic verification of key revocations, and so turning this option off may result in skipping keys that are incorrectly marked as revoked. @item include-disabled When searching for a key with @option{--search-keys}, include keys that are marked on the keyserver as disabled. Note that this option is not used with HKP keyservers. @item auto-key-retrieve This is an obsolete alias for the option @option{auto-key-retrieve}. Please do not use it; it will be removed in future versions.. @item honor-keyserver-url When using @option{--refresh-keys}, if the key in question has a preferred keyserver URL, then use that preferred keyserver to refresh the key from. In addition, if auto-key-retrieve is set, and the signature being verified has a preferred keyserver URL, then use that preferred keyserver to fetch the key from. Note that this option introduces a "web bug": The creator of the key can see when the keys is refreshed. Thus this option is not enabled by default. @item include-subkeys When receiving a key, include subkeys as potential targets. Note that this option is not used with HKP keyservers, as they do not support retrieving keys by subkey id. @item timeout @itemx http-proxy=@var{value} @itemx verbose @itemx debug @itemx check-cert @item ca-cert-file These options have no more function since GnuPG 2.1. Use the @code{dirmngr} configuration options instead. @end table The default list of options is: "self-sigs-only, import-clean, repair-keys, repair-pks-subkey-bug, export-attributes". However, if the actual used source is an LDAP server "no-self-sigs-only" is assumed unless "self-sigs-only" has been explicitly configured. @item --completes-needed @var{n} @opindex compliant-needed Number of completely trusted users to introduce a new key signer (defaults to 1). @item --marginals-needed @var{n} @opindex marginals-needed Number of marginally trusted users to introduce a new key signer (defaults to 3) @item --tofu-default-policy @{auto|good|unknown|bad|ask@} @opindex tofu-default-policy The default TOFU policy (defaults to @code{auto}). For more information about the meaning of this option, @pxref{trust-model-tofu}. @item --max-cert-depth @var{n} @opindex max-cert-depth Maximum depth of a certification chain (default is 5). @item --no-sig-cache @opindex no-sig-cache Do not cache the verification status of key signatures. Caching gives a much better performance in key listings. However, if you suspect that your public keyring is not safe against write modifications, you can use this option to disable the caching. It probably does not make sense to disable it because all kind of damage can be done if someone else has write access to your public keyring. @item --auto-check-trustdb @itemx --no-auto-check-trustdb @opindex auto-check-trustdb If GnuPG feels that its information about the Web of Trust has to be updated, it automatically runs the @option{--check-trustdb} command internally. This may be a time consuming process. @option{--no-auto-check-trustdb} disables this option. @item --use-agent @itemx --no-use-agent @opindex use-agent This is dummy option. @command{@gpgname} always requires the agent. @item --gpg-agent-info @opindex gpg-agent-info This is dummy option. It has no effect when used with @command{@gpgname}. @item --agent-program @var{file} @opindex agent-program Specify an agent program to be used for secret key operations. The default value is determined by running @command{gpgconf} with the option @option{--list-dirs}. Note that the pipe symbol (@code{|}) is used for a regression test suite hack and may thus not be used in the file name. @item --dirmngr-program @var{file} @opindex dirmngr-program Specify a dirmngr program to be used for keyserver access. The default value is @file{@value{BINDIR}/dirmngr}. @item --disable-dirmngr Entirely disable the use of the Dirmngr. @item --no-autostart @opindex no-autostart Do not start the gpg-agent or the dirmngr if it has not yet been started and its service is required. This option is mostly useful on machines where the connection to gpg-agent has been redirected to another machines. If dirmngr is required on the remote machine, it may be started manually using @command{gpgconf --launch dirmngr}. @item --lock-once @opindex lock-once Lock the databases the first time a lock is requested and do not release the lock until the process terminates. @item --lock-multiple @opindex lock-multiple Release the locks every time a lock is no longer needed. Use this to override a previous @option{--lock-once} from a config file. @item --lock-never @opindex lock-never Disable locking entirely. This option should be used only in very special environments, where it can be assured that only one process is accessing those files. A bootable floppy with a stand-alone encryption system will probably use this. Improper usage of this option may lead to data and key corruption. @item --exit-on-status-write-error @opindex exit-on-status-write-error This option will cause write errors on the status FD to immediately terminate the process. That should in fact be the default but it never worked this way and thus we need an option to enable this, so that the change won't break applications which close their end of a status fd connected pipe too early. Using this option along with @option{--enable-progress-filter} may be used to cleanly cancel long running gpg operations. @item --limit-card-insert-tries @var{n} @opindex limit-card-insert-tries With @var{n} greater than 0 the number of prompts asking to insert a smartcard gets limited to N-1. Thus with a value of 1 gpg won't at all ask to insert a card if none has been inserted at startup. This option is useful in the configuration file in case an application does not know about the smartcard support and waits ad infinitum for an inserted card. @item --no-random-seed-file @opindex no-random-seed-file GnuPG uses a file to store its internal random pool over invocations. This makes random generation faster; however sometimes write operations are not desired. This option can be used to achieve that with the cost of slower random generation. @item --no-greeting @opindex no-greeting Suppress the initial copyright message. @item --no-secmem-warning @opindex no-secmem-warning Suppress the warning about "using insecure memory". @item --no-permission-warning @opindex permission-warning Suppress the warning about unsafe file and home directory (@option{--homedir}) permissions. Note that the permission checks that GnuPG performs are not intended to be authoritative, but rather they simply warn about certain common permission problems. Do not assume that the lack of a warning means that your system is secure. Note that the warning for unsafe @option{--homedir} permissions cannot be suppressed in the gpg.conf file, as this would allow an attacker to place an unsafe gpg.conf file in place, and use this file to suppress warnings about itself. The @option{--homedir} permissions warning may only be suppressed on the command line. @item --require-secmem @itemx --no-require-secmem @opindex require-secmem Refuse to run if GnuPG cannot get secure memory. Defaults to no (i.e. run, but give a warning). @item --require-cross-certification @itemx --no-require-cross-certification @opindex require-cross-certification When verifying a signature made from a subkey, ensure that the cross certification "back signature" on the subkey is present and valid. This protects against a subtle attack against subkeys that can sign. Defaults to @option{--require-cross-certification} for @command{@gpgname}. @item --expert @itemx --no-expert @opindex expert Allow the user to do certain nonsensical or "silly" things like signing an expired or revoked key, or certain potentially incompatible things like generating unusual key types. This also disables certain warning messages about potentially incompatible actions. As the name implies, this option is for experts only. If you don't fully understand the implications of what it allows you to do, leave this off. @option{--no-expert} disables this option. @end table @c ******************************************* @c ******** KEY RELATED OPTIONS ************ @c ******************************************* @node GPG Key related Options @subsection Key related options @table @gnupgtabopt @item --recipient @var{name} @itemx -r @opindex recipient Encrypt for user id @var{name}. If this option or @option{--hidden-recipient} is not specified, GnuPG asks for the user-id unless @option{--default-recipient} is given. @item --hidden-recipient @var{name} @itemx -R @opindex hidden-recipient Encrypt for user ID @var{name}, but hide the key ID of this user's key. This option helps to hide the receiver of the message and is a limited countermeasure against traffic analysis. If this option or @option{--recipient} is not specified, GnuPG asks for the user ID unless @option{--default-recipient} is given. @item --recipient-file @var{file} @itemx -f @opindex recipient-file This option is similar to @option{--recipient} except that it encrypts to a key stored in the given file. @var{file} must be the name of a file containing exactly one key. @command{@gpgname} assumes that the key in this file is fully valid. @item --hidden-recipient-file @var{file} @itemx -F @opindex hidden-recipient-file This option is similar to @option{--hidden-recipient} except that it encrypts to a key stored in the given file. @var{file} must be the name of a file containing exactly one key. @command{@gpgname} assumes that the key in this file is fully valid. @item --encrypt-to @var{name} @opindex encrypt-to Same as @option{--recipient} but this one is intended for use in the options file and may be used with your own user-id as an "encrypt-to-self". These keys are only used when there are other recipients given either by use of @option{--recipient} or by the asked user id. No trust checking is performed for these user ids and even disabled keys can be used. @item --hidden-encrypt-to @var{name} @opindex hidden-encrypt-to Same as @option{--hidden-recipient} but this one is intended for use in the options file and may be used with your own user-id as a hidden "encrypt-to-self". These keys are only used when there are other recipients given either by use of @option{--recipient} or by the asked user id. No trust checking is performed for these user ids and even disabled keys can be used. @item --no-encrypt-to @opindex no-encrypt-to Disable the use of all @option{--encrypt-to} and @option{--hidden-encrypt-to} keys. @item --group @{@var{name}=@var{value}@} @opindex group Sets up a named group, which is similar to aliases in email programs. Any time the group name is a recipient (@option{-r} or @option{--recipient}), it will be expanded to the values specified. Multiple groups with the same name are automatically merged into a single group. The values are @code{key IDs} or fingerprints, but any key description is accepted. Note that a value with spaces in it will be treated as two different values. Note also there is only one level of expansion --- you cannot make an group that points to another group. When used from the command line, it may be necessary to quote the argument to this option to prevent the shell from treating it as multiple arguments. @item --ungroup @var{name} @opindex ungroup Remove a given entry from the @option{--group} list. @item --no-groups @opindex no-groups Remove all entries from the @option{--group} list. @item --local-user @var{name} @itemx -u @opindex local-user Use @var{name} as the key to sign with. Note that this option overrides @option{--default-key}. @item --sender @var{mbox} @opindex sender This option has two purposes. @var{mbox} must either be a complete user ID containing a proper mail address or just a plain mail address. The option can be given multiple times. When creating a signature this option tells gpg the signing key's user id used to make the signature and embeds that user ID into the created signature (using OpenPGP's ``Signer's User ID'' subpacket). If the option is given multiple times a suitable user ID is picked. However, if the signing key was specified directly by using a mail address (i.e. not by using a fingerprint or key ID) this option is used and the mail address is embedded in the created signature. When verifying a signature @var{mbox} is used to restrict the information printed by the TOFU code to matching user IDs. If the option is used and the signature contains a ``Signer's User ID'' subpacket that information is is also used to restrict the printed information. Note that GnuPG considers only the mail address part of a User ID. If this option or the said subpacket is available the TRUST lines as printed by option @option{status-fd} correspond to the corresponding User ID; if no User ID is known the TRUST lines are computed directly on the key and do not give any information about the User ID. In the latter case it his highly recommended to scripts and other frontends to evaluate the VALIDSIG line, retrieve the key and print all User IDs along with their validity (trust) information. @item --try-secret-key @var{name} @opindex try-secret-key For hidden recipients GPG needs to know the keys to use for trial decryption. The key set with @option{--default-key} is always tried first, but this is often not sufficient. This option allows setting more keys to be used for trial decryption. Although any valid user-id specification may be used for @var{name} it makes sense to use at least the long keyid to avoid ambiguities. Note that gpg-agent might pop up a pinentry for a lot keys to do the trial decryption. If you want to stop all further trial decryption you may use close-window button instead of the cancel button. @item --try-all-secrets @opindex try-all-secrets Don't look at the key ID as stored in the message but try all secret keys in turn to find the right decryption key. This option forces the behaviour as used by anonymous recipients (created by using @option{--throw-keyids} or @option{--hidden-recipient}) and might come handy in case where an encrypted message contains a bogus key ID. @item --skip-hidden-recipients @itemx --no-skip-hidden-recipients @opindex skip-hidden-recipients @opindex no-skip-hidden-recipients During decryption skip all anonymous recipients. This option helps in the case that people use the hidden recipients feature to hide their own encrypt-to key from others. If one has many secret keys this may lead to a major annoyance because all keys are tried in turn to decrypt something which was not really intended for it. The drawback of this option is that it is currently not possible to decrypt a message which includes real anonymous recipients. @end table @c ******************************************* @c ******** INPUT AND OUTPUT *************** @c ******************************************* @node GPG Input and Output @subsection Input and Output @table @gnupgtabopt @item --armor @itemx -a @opindex armor Create ASCII armored output. The default is to create the binary OpenPGP format. @item --no-armor @opindex no-armor Assume the input data is not in ASCII armored format. @item --output @var{file} @itemx -o @var{file} @opindex output Write output to @var{file}. To write to stdout use @code{-} as the filename. @item --max-output @var{n} @opindex max-output This option sets a limit on the number of bytes that will be generated when processing a file. Since OpenPGP supports various levels of compression, it is possible that the plaintext of a given message may be significantly larger than the original OpenPGP message. While GnuPG works properly with such messages, there is often a desire to set a maximum file size that will be generated before processing is forced to stop by the OS limits. Defaults to 0, which means "no limit". @item --chunk-size @var{n} @opindex chunk-size The AEAD encryption mode encrypts the data in chunks so that a receiving side can check for transmission errors or tampering at the end of each chunk and does not need to delay this until all data has been received. The used chunk size is 2^@var{n} byte. The lowest allowed value for @var{n} is 6 (64 byte) and the largest is the default of 22 which creates chunks not larger than 4 MiB. @item --input-size-hint @var{n} @opindex input-size-hint This option can be used to tell GPG the size of the input data in bytes. @var{n} must be a positive base-10 number. This option is only useful if the input is not taken from a file. GPG may use this hint to optimize its buffer allocation strategy. It is also used by the @option{--status-fd} line ``PROGRESS'' to provide a value for ``total'' if that is not available by other means. @item --key-origin @var{string}[,@var{url}] @opindex key-origin gpg can track the origin of a key. Certain origins are implicitly known (e.g. keyserver, web key directory) and set. For a standard import the origin of the keys imported can be set with this option. To list the possible values use "help" for @var{string}. Some origins can store an optional @var{url} argument. That URL can appended to @var{string} after a comma. @item --import-options @var{parameters} @opindex import-options This is a space or comma delimited string that gives options for importing keys. Options can be prepended with a `no-' to give the opposite meaning. The options are: @table @asis @item import-local-sigs Allow importing key signatures marked as "local". This is not generally useful unless a shared keyring scheme is being used. Defaults to no. @item keep-ownertrust Normally possible still existing ownertrust values of a key are cleared if a key is imported. This is in general desirable so that a formerly deleted key does not automatically gain an ownertrust values merely due to import. On the other hand it is sometimes necessary to re-import a trusted set of keys again but keeping already assigned ownertrust values. This can be achieved by using this option. @item repair-pks-subkey-bug During import, attempt to repair the damage caused by the PKS keyserver bug (pre version 0.9.6) that mangles keys with multiple subkeys. Note that this cannot completely repair the damaged key as some crucial data is removed by the keyserver, but it does at least give you back one subkey. Defaults to no for regular @option{--import} and to yes for keyserver @option{--receive-keys}. @item import-show @itemx show-only Show a listing of the key as imported right before it is stored. This can be combined with the option @option{--dry-run} to only look at keys; the option @option{show-only} is a shortcut for this combination. The command @option{--show-keys} is another shortcut for this. Note that suffixes like '#' for "sec" and "sbb" lines may or may not be printed. @item import-export Run the entire import code but instead of storing the key to the local keyring write it to the output. The export option @option{export-dane} affect the output. This option can for example be used to remove all invalid parts from a key without the need to store it. @item merge-only During import, allow key updates to existing keys, but do not allow any new keys to be imported. Defaults to no. @item import-clean After import, compact (remove all signatures except the self-signature) any user IDs from the new key that are not usable. Then, remove any signatures from the new key that are not usable. This includes signatures that were issued by keys that are not present on the keyring. This option is the same as running the @option{--edit-key} command "clean" after import. Defaults to no. @item self-sigs-only Accept only self-signatures while importing a key. All other key signatures are skipped at an early import stage. This option can be used with @code{keyserver-options} to mitigate attempts to flood a key with bogus signatures from a keyserver. The drawback is that all other valid key signatures, as required by the Web of Trust are also not imported. Note that when using this option along with import-clean it suppresses the final clean step after merging the imported key into the existing key. @item repair-keys After import, fix various problems with the keys. For example, this reorders signatures, and strips duplicate signatures. Defaults to yes. @item bulk-import When used the keyboxd (option @option{use-keyboxd} in @file{common.conf}) does the import within a single transaction. @item import-minimal Import the smallest key possible. This removes all signatures except the most recent self-signature on each user ID. This option is the same as running the @option{--edit-key} command "minimize" after import. Defaults to no. @item restore @itemx import-restore Import in key restore mode. This imports all data which is usually skipped during import; including all GnuPG specific data. All other contradicting options are overridden. @end table @item --import-filter @{@var{name}=@var{expr}@} @itemx --export-filter @{@var{name}=@var{expr}@} @opindex import-filter @opindex export-filter These options define an import/export filter which are applied to the imported/exported keyblock right before it will be stored/written. @var{name} defines the type of filter to use, @var{expr} the expression to evaluate. The option can be used several times which then appends more expression to the same @var{name}. @noindent The available filter types are: @table @asis @item keep-uid This filter will keep a user id packet and its dependent packets in the keyblock if the expression evaluates to true. @item drop-subkey This filter drops the selected subkeys. Currently only implemented for --export-filter. @item drop-sig This filter drops the selected key signatures on user ids. Self-signatures are not considered. Currently only implemented for --import-filter. @item select This filter is only implemented by @option{--list-filter}. All property names may be used. @end table For the syntax of the expression see the chapter "FILTER EXPRESSIONS". The property names for the expressions depend on the actual filter type and are indicated in the following table. Note that all property names may also be used by @option{--list-filter}. Property names may be prefix with a scope delimited by a slash. Valid scopes are "pub" for public and secret primary keys, "sub" for public and secret subkeys, "uid" for for user-ID packets, and "sig" for signature packets. Invalid scopes are currently ignored. The available properties are: @table @asis @item uid A string with the user id. (keep-uid) @item mbox The addr-spec part of a user id with mailbox or the empty string. (keep-uid) @item algostr A string with the key algorithm description. For example "rsa3072" or "ed25519". @item key_algo A number with the public key algorithm of a key or subkey packet. (drop-subkey) @item key_size A number with the effective key size of a key or subkey packet. (drop-subkey) @item key_created @itemx key_created_d The first is the timestamp a public key or subkey packet was created. The second is the same but given as an ISO string, e.g. "2016-08-17". (drop-subkey) @item fpr The hexified fingerprint of the current subkey or primary key. (drop-subkey) @item primary Boolean indicating whether the user id is the primary one. (keep-uid) @item expired Boolean indicating whether a user id (keep-uid), a key (drop-subkey), or a signature (drop-sig) expired. @item revoked Boolean indicating whether a user id (keep-uid) or a key (drop-subkey) has been revoked. @item disabled Boolean indicating whether a primary key is disabled. @item secret Boolean indicating whether a key or subkey is a secret one. (drop-subkey) @item usage A string indicating the usage flags for the subkey, from the sequence ``ecsa?''. For example, a subkey capable of just signing and authentication would be an exact match for ``sa''. (drop-subkey) @item sig_created @itemx sig_created_d The first is the timestamp a signature packet was created. The second is the same but given as an ISO date string, e.g. "2016-08-17". (drop-sig) @item sig_algo A number with the public key algorithm of a signature packet. (drop-sig) @item sig_digest_algo A number with the digest algorithm of a signature packet. (drop-sig) @item origin A string with the key origin or a question mark. For example the string ``wkd'' is used if a key originated from a Web Key Directory lookup. @item lastupd The timestamp the key was last updated from a keyserver or the Web Key Directory. @item url A string with the the URL associated wit the last key lookup. @end table @item --export-options @var{parameters} @opindex export-options This is a space or comma delimited string that gives options for exporting keys. Options can be prepended with a `no-' to give the opposite meaning. The options are: @table @asis @item export-local-sigs Allow exporting key signatures marked as "local". This is not generally useful unless a shared keyring scheme is being used. Defaults to no. @item export-attributes Include attribute user IDs (photo IDs) while exporting. Not including attribute user IDs is useful to export keys that are going to be used by an OpenPGP program that does not accept attribute user IDs. Defaults to yes. @item export-sensitive-revkeys Include designated revoker information that was marked as "sensitive". Defaults to no. @c Since GnuPG 2.1 gpg-agent manages the secret key and thus the @c export-reset-subkey-passwd hack is not anymore justified. Such use @c cases may be implemented using a specialized secret key export @c tool. @c @item export-reset-subkey-passwd @c When using the @option{--export-secret-subkeys} command, this option resets @c the passphrases for all exported subkeys to empty. This is useful @c when the exported subkey is to be used on an unattended machine where @c a passphrase doesn't necessarily make sense. Defaults to no. @item backup @itemx export-backup Export for use as a backup. The exported data includes all data which is needed to restore the key or keys later with GnuPG. The format is basically the OpenPGP format but enhanced with GnuPG specific data. All other contradicting options are overridden. @item export-clean Compact (remove all signatures from) user IDs on the key being exported if the user IDs are not usable. Also, do not export any signatures that are not usable. This includes signatures that were issued by keys that are not present on the keyring. This option is the same as running the @option{--edit-key} command "clean" before export except that the local copy of the key is not modified. Defaults to no. @item export-minimal Export the smallest key possible. This removes all signatures except the most recent self-signature on each user ID. This option is the same as running the @option{--edit-key} command "minimize" before export except that the local copy of the key is not modified. Defaults to no. @item export-revocs Export only standalone revocation certificates of the key. This option does not export revocations of 3rd party certificate revocations. @item export-dane Instead of outputting the key material output OpenPGP DANE records suitable to put into DNS zone files. An ORIGIN line is printed before each record to allow diverting the records to the corresponding zone file. @item mode1003 Enable the use of a new secret key export format. This format avoids the re-encryption as required with the current OpenPGP format and also improves the security of the secret key if it has been protected with a passphrase. Note that an unprotected key is exported as-is and thus not secure; the general rule to convey secret keys in an OpenPGP encrypted file still applies with this mode. Versions of GnuPG before 2.4.0 are not able to import such a secret file. @end table @item --with-colons @opindex with-colons Print key listings delimited by colons. Note that the output will be encoded in UTF-8 regardless of any @option{--display-charset} setting. This format is useful when GnuPG is called from scripts and other programs as it is easily machine parsed. The details of this format are documented in the file @file{doc/DETAILS}, which is included in the GnuPG source distribution. @item --fixed-list-mode @opindex fixed-list-mode Do not merge primary user ID and primary key in @option{--with-colon} listing mode and print all timestamps as seconds since 1970-01-01. Since GnuPG 2.0.10, this mode is always used and thus this option is obsolete; it does not harm to use it though. @item --legacy-list-mode @opindex legacy-list-mode Revert to the pre-2.1 public key list mode. This only affects the human readable output and not the machine interface (i.e. @code{--with-colons}). Note that the legacy format does not convey suitable information for elliptic curves. @item --with-fingerprint @opindex with-fingerprint Same as the command @option{--fingerprint} but changes only the format of the output and may be used together with another command. @item --with-subkey-fingerprint @opindex with-subkey-fingerprint If a fingerprint is printed for the primary key, this option forces printing of the fingerprint for all subkeys. This could also be achieved by using the @option{--with-fingerprint} twice but by using this option along with keyid-format "none" a compact fingerprint is printed. @item --with-icao-spelling @opindex with-icao-spelling Print the ICAO spelling of the fingerprint in addition to the hex digits. @item --with-keygrip @opindex with-keygrip Include the keygrip in the key listings. In @code{--with-colons} mode this is implicitly enable for secret keys. @item --with-key-origin @opindex with-key-origin Include the locally held information on the origin and last update of a key in a key listing. In @code{--with-colons} mode this is always printed. This data is currently experimental and shall not be considered part of the stable API. @item --with-wkd-hash @opindex with-wkd-hash Print a Web Key Directory identifier along with each user ID in key listings. This is an experimental feature and semantics may change. @item --with-secret @opindex with-secret Include info about the presence of a secret key in public key listings done with @code{--with-colons}. @end table @c ******************************************* @c ******** OPENPGP OPTIONS **************** @c ******************************************* @node OpenPGP Options @subsection OpenPGP protocol specific options @table @gnupgtabopt @item -t, --textmode @itemx --no-textmode @opindex textmode Treat input files as text and store them in the OpenPGP canonical text form with standard "CRLF" line endings. This also sets the necessary flags to inform the recipient that the encrypted or signed data is text and may need its line endings converted back to whatever the local system uses. This option is useful when communicating between two platforms that have different line ending conventions (UNIX-like to Mac, Mac to Windows, etc). @option{--no-textmode} disables this option, and is the default. @item --force-v3-sigs @itemx --no-force-v3-sigs @item --force-v4-certs @itemx --no-force-v4-certs These options are obsolete and have no effect since GnuPG 2.1. @item --force-ocb @itemx --force-aead @opindex force-ocb @opindex force-aead Force the use of AEAD encryption over MDC encryption. AEAD is a modern and faster way to do authenticated encryption than the old MDC method. @option{--force-aead} is an alias and deprecated. See also option @option{--chunk-size}. @item --force-mdc @itemx --disable-mdc @opindex force-mdc @opindex disable-mdc These options are obsolete and have no effect since GnuPG 2.2.8. The MDC is always used unless the keys indicate that an AEAD algorithm can be used in which case AEAD is used. But note: If the creation of a legacy non-MDC message is exceptionally required, the option @option{--rfc2440} allows for this. @item --disable-signer-uid @opindex disable-signer-uid By default the user ID of the signing key is embedded in the data signature. As of now this is only done if the signing key has been specified with @option{local-user} using a mail address, or with @option{sender}. This information can be helpful for verifier to locate the key; see option @option{--auto-key-retrieve}. @item --include-key-block @itemx --no-include-key-block @opindex include-key-block @opindex no-include-key-block This option is used to embed the actual signing key into a data signature. The embedded key is stripped down to a single user id and includes only the signing subkey used to create the signature as well as as valid encryption subkeys. All other info is removed from the key to keep it and thus the signature small. This option is the OpenPGP counterpart to the @command{gpgsm} option @option{--include-certs} and allows the recipient of a signed message to reply encrypted to the sender without using any online directories to lookup the key. The default is @option{--no-include-key-block}. See also the option @option{--auto-key-import}. @item --personal-cipher-preferences @var{string} @opindex personal-cipher-preferences Set the list of personal cipher preferences to @var{string}. Use @command{@gpgname --version} to get a list of available algorithms, and use @code{none} to set no preference at all. This allows the user to safely override the algorithm chosen by the recipient key preferences, as GPG will only select an algorithm that is usable by all recipients. The most highly ranked cipher in this list is also used for the @option{--symmetric} encryption command. @item --personal-digest-preferences @var{string} @opindex personal-digest-preferences Set the list of personal digest preferences to @var{string}. Use @command{@gpgname --version} to get a list of available algorithms, and use @code{none} to set no preference at all. This allows the user to safely override the algorithm chosen by the recipient key preferences, as GPG will only select an algorithm that is usable by all recipients. The most highly ranked digest algorithm in this list is also used when signing without encryption (e.g. @option{--clear-sign} or @option{--sign}). @item --personal-compress-preferences @var{string} @opindex personal-compress-preferences Set the list of personal compression preferences to @var{string}. Use @command{@gpgname --version} to get a list of available algorithms, and use @code{none} to set no preference at all. This allows the user to safely override the algorithm chosen by the recipient key preferences, as GPG will only select an algorithm that is usable by all recipients. The most highly ranked compression algorithm in this list is also used when there are no recipient keys to consider (e.g. @option{--symmetric}). @item --s2k-cipher-algo @var{name} @opindex s2k-cipher-algo Use @var{name} as the cipher algorithm for symmetric encryption with a passphrase if @option{--personal-cipher-preferences} and @option{--cipher-algo} are not given. The default is @value{GPGSYMENCALGO}. @item --s2k-digest-algo @var{name} @opindex s2k-digest-algo Use @var{name} as the digest algorithm used to mangle the passphrases for symmetric encryption. The default is SHA-1. @item --s2k-mode @var{n} @opindex s2k-mode Selects how passphrases for symmetric encryption are mangled. If @var{n} is 0 a plain passphrase (which is in general not recommended) will be used, a 1 adds a salt (which should not be used) to the passphrase and a 3 (the default) iterates the whole process a number of times (see @option{--s2k-count}). @item --s2k-count @var{n} @opindex s2k-count Specify how many times the passphrases mangling for symmetric encryption is repeated. This value may range between 1024 and 65011712 inclusive. The default is inquired from gpg-agent. Note that not all values in the 1024-65011712 range are legal and if an illegal value is selected, GnuPG will round up to the nearest legal value. This option is only meaningful if @option{--s2k-mode} is set to the default of 3. @end table @c *************************** @c ******* Compliance ******** @c *************************** @node Compliance Options @subsection Compliance options These options control what GnuPG is compliant to. Only one of these options may be active at a time. Note that the default setting of this is nearly always the correct one. See the INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS section below before using one of these options. @table @gnupgtabopt @item --gnupg @opindex gnupg Use standard GnuPG behavior. This is essentially OpenPGP behavior (see @option{--openpgp}), but with extension from the proposed update to OpenPGP and with some additional workarounds for common compatibility problems in different versions of PGP. This is the default option, so it is not generally needed, but it may be useful to override a different compliance option in the gpg.conf file. @item --openpgp @opindex openpgp Reset all packet, cipher and digest options to strict OpenPGP behavior. This option implies @option{--allow-old-cipher-algos}. Use this option to reset all previous options like @option{--s2k-*}, @option{--cipher-algo}, @option{--digest-algo} and @option{--compress-algo} to OpenPGP compliant values. All PGP workarounds are disabled. @item --rfc4880 @opindex rfc4880 Reset all packet, cipher and digest options to strict RFC-4880 behavior. This option implies @option{--allow-old-cipher-algos}. Note that this is currently the same thing as @option{--openpgp}. @item --rfc4880bis @opindex rfc4880bis Reset all packet, cipher and digest options to strict according to the proposed updates of RFC-4880. @item --rfc2440 @opindex rfc2440 Reset all packet, cipher and digest options to strict RFC-2440 behavior. Note that by using this option encryption packets are created in a legacy mode without MDC protection. This is dangerous and should thus only be used for experiments. This option implies @option{--allow-old-cipher-algos}. See also option @option{--ignore-mdc-error}. @item --pgp6 @opindex pgp6 This option is obsolete; it is handled as an alias for @option{--pgp7} @item --pgp7 @opindex pgp7 Set up all options to be as PGP 7 compliant as possible. This allowed the ciphers IDEA, 3DES, CAST5,AES128, AES192, AES256, and TWOFISH., the hashes MD5, SHA1 and RIPEMD160, and the compression algorithms none and ZIP. This option implies @option{--escape-from-lines} and disables @option{--throw-keyids}, @item --pgp8 @opindex pgp8 Set up all options to be as PGP 8 compliant as possible. PGP 8 is a lot closer to the OpenPGP standard than previous versions of PGP, so all this does is disable @option{--throw-keyids} and set @option{--escape-from-lines}. All algorithms are allowed except for the SHA224, SHA384, and SHA512 digests. @item --compliance @var{string} @opindex compliance This option can be used instead of one of the options above. Valid values for @var{string} are the above option names (without the double dash) and possibly others as shown when using "help" for @var{string}. @item --min-rsa-length @var{n} @opindex min-rsa-length This option adjusts the compliance mode "de-vs" for stricter key size requirements. For example, a value of 3000 turns rsa2048 and dsa2048 keys into non-VS-NfD compliant keys. @item --require-compliance @opindex require-compliance To check that data has been encrypted according to the rules of the current compliance mode, a gpg user needs to evaluate the status lines. This is allows frontends to handle compliance check in a more flexible way. However, for scripted use the required evaluation of the status-line requires quite some effort; this option can be used instead to make sure that the gpg process exits with a failure if the compliance rules are not fulfilled. Note that this option has currently an effect only in "de-vs" mode. @end table @c ******************************************* @c ******** ESOTERIC OPTIONS *************** @c ******************************************* @node GPG Esoteric Options @subsection Doing things one usually doesn't want to do @table @gnupgtabopt @item -n @itemx --dry-run @opindex dry-run Don't make any changes (this is not completely implemented). @item --list-only @opindex list-only Changes the behaviour of some commands. This is like @option{--dry-run} but different in some cases. The semantic of this option may be extended in the future. Currently it only skips the actual decryption pass and therefore enables a fast listing of the encryption keys. @item -i @itemx --interactive @opindex interactive Prompt before overwriting any files. @item --compatibility-flags @var{flags} @opindex compatibility-flags Set compatibility flags to work around problems due to non-compliant keys or data. The @var{flags} are given as a comma separated list of flag names and are OR-ed together. The special flag "none" clears the list and allows to start over with an empty list. To get a list of available flags the sole word "help" can be used. @item --debug-level @var{level} @opindex debug-level Select the debug level for investigating problems. @var{level} may be a numeric value or by a keyword: @table @code @item none No debugging at all. A value of less than 1 may be used instead of the keyword. @item basic Some basic debug messages. A value between 1 and 2 may be used instead of the keyword. @item advanced More verbose debug messages. A value between 3 and 5 may be used instead of the keyword. @item expert Even more detailed messages. A value between 6 and 8 may be used instead of the keyword. @item guru All of the debug messages you can get. A value greater than 8 may be used instead of the keyword. The creation of hash tracing files is only enabled if the keyword is used. @end table How these messages are mapped to the actual debugging flags is not specified and may change with newer releases of this program. They are however carefully selected to best aid in debugging. @item --debug @var{flags} @opindex debug Set debug flags. All flags are or-ed and @var{flags} may be given in C syntax (e.g. 0x0042) or as a comma separated list of flag names. To get a list of all supported flags the single word "help" can be used. This option is only useful for debugging and the behavior may change at any time without notice. @item --debug-all @opindex debug-all Set all useful debugging flags. @item --debug-iolbf @opindex debug-iolbf Set stdout into line buffered mode. This option is only honored when given on the command line. @item --debug-set-iobuf-size @var{n} @opindex debug-iolbf Change the buffer size of the IOBUFs to @var{n} kilobyte. Using 0 prints the current size. Note well: This is a maintainer only option and may thus be changed or removed at any time without notice. @item --debug-allow-large-chunks @opindex debug-allow-large-chunks To facilitate software tests and experiments this option allows to specify a limit of up to 4 EiB (@code{--chunk-size 62}). @item --faked-system-time @var{epoch} @opindex faked-system-time This option is only useful for testing; it sets the system time back or forth to @var{epoch} which is the number of seconds elapsed since the year 1970. Alternatively @var{epoch} may be given as a full ISO time string (e.g. "20070924T154812"). If you suffix @var{epoch} with an exclamation mark (!), the system time will appear to be frozen at the specified time. @item --full-timestrings @opindex full-timestrings Change the format of printed creation and expiration times from just the date to the date and time. This is in general not useful and the same information is anyway available in @option{--with-colons} mode. These longer strings are also not well aligned with other printed data. @item --enable-progress-filter @opindex enable-progress-filter Enable certain PROGRESS status outputs. This option allows frontends to display a progress indicator while gpg is processing larger files. There is a slight performance overhead using it. @item --status-fd @var{n} @opindex status-fd Write special status strings to the file descriptor @var{n}. See the file DETAILS in the documentation for a listing of them. @item --status-file @var{file} @opindex status-file Same as @option{--status-fd}, except the status data is written to file @var{file}. @item --logger-fd @var{n} @opindex logger-fd Write log output to file descriptor @var{n} and not to STDERR. @item --log-file @var{file} @itemx --logger-file @var{file} @opindex log-file Same as @option{--logger-fd}, except the logger data is written to file @var{file}. Use @file{socket://} to log to s socket. @item --attribute-fd @var{n} @opindex attribute-fd Write attribute subpackets to the file descriptor @var{n}. This is most useful for use with @option{--status-fd}, since the status messages are needed to separate out the various subpackets from the stream delivered to the file descriptor. @item --attribute-file @var{file} @opindex attribute-file Same as @option{--attribute-fd}, except the attribute data is written to file @var{file}. @item --comment @var{string} @itemx --no-comments @opindex comment Use @var{string} as a comment string in cleartext signatures and ASCII armored messages or keys (see @option{--armor}). The default behavior is not to use a comment string. @option{--comment} may be repeated multiple times to get multiple comment strings. @option{--no-comments} removes all comments. It is a good idea to keep the length of a single comment below 60 characters to avoid problems with mail programs wrapping such lines. Note that comment lines, like all other header lines, are not protected by the signature. @item --emit-version @itemx --no-emit-version @opindex emit-version Force inclusion of the version string in ASCII armored output. If given once only the name of the program and the major number is emitted, given twice the minor is also emitted, given thrice the micro is added, and given four times an operating system identification is also emitted. @option{--no-emit-version} (default) disables the version line. @item --sig-notation @{@var{name}=@var{value}@} @itemx --cert-notation @{@var{name}=@var{value}@} @itemx -N, --set-notation @{@var{name}=@var{value}@} @opindex sig-notation @opindex cert-notation @opindex set-notation Put the name value pair into the signature as notation data. @var{name} must consist only of printable characters or spaces, and must contain a '@@' character in the form keyname@@domain.example.com (substituting the appropriate keyname and domain name, of course). This is to help prevent pollution of the IETF reserved notation namespace. The @option{--expert} flag overrides the '@@' check. @var{value} may be any printable string; it will be encoded in UTF-8, so you should check that your @option{--display-charset} is set correctly. If you prefix @var{name} with an exclamation mark (!), the notation data will be flagged as critical (rfc4880:5.2.3.16). @option{--sig-notation} sets a notation for data signatures. @option{--cert-notation} sets a notation for key signatures (certifications). @option{--set-notation} sets both. There are special codes that may be used in notation names. "%k" will be expanded into the key ID of the key being signed, "%K" into the long key ID of the key being signed, "%f" into the fingerprint of the key being signed, "%s" into the key ID of the key making the signature, "%S" into the long key ID of the key making the signature, "%g" into the fingerprint of the key making the signature (which might be a subkey), "%p" into the fingerprint of the primary key of the key making the signature, "%c" into the signature count from the OpenPGP smartcard, and "%%" results in a single "%". %k, %K, and %f are only meaningful when making a key signature (certification), and %c is only meaningful when using the OpenPGP smartcard. @item --known-notation @var{name} @opindex known-notation Adds @var{name} to a list of known critical signature notations. The effect of this is that gpg will not mark a signature with a critical signature notation of that name as bad. Note that gpg already knows by default about a few critical signatures notation names. @item --sig-policy-url @var{string} @itemx --cert-policy-url @var{string} @itemx --set-policy-url @var{string} @opindex sig-policy-url @opindex cert-policy-url @opindex set-policy-url Use @var{string} as a Policy URL for signatures (rfc4880:5.2.3.20). If you prefix it with an exclamation mark (!), the policy URL packet will be flagged as critical. @option{--sig-policy-url} sets a policy url for data signatures. @option{--cert-policy-url} sets a policy url for key signatures (certifications). @option{--set-policy-url} sets both. The same %-expandos used for notation data are available here as well. @item --sig-keyserver-url @var{string} @opindex sig-keyserver-url Use @var{string} as a preferred keyserver URL for data signatures. If you prefix it with an exclamation mark (!), the keyserver URL packet will be flagged as critical. The same %-expandos used for notation data are available here as well. @item --set-filename @var{string} @opindex set-filename Use @var{string} as the filename which is stored inside messages. This overrides the default, which is to use the actual filename of the file being encrypted. Using the empty string for @var{string} effectively removes the filename from the output. @item --for-your-eyes-only @itemx --no-for-your-eyes-only @opindex for-your-eyes-only Set the `for your eyes only' flag in the message. This causes GnuPG to refuse to save the file unless the @option{--output} option is given, and PGP to use a "secure viewer" with a claimed Tempest-resistant font to display the message. This option overrides @option{--set-filename}. @option{--no-for-your-eyes-only} disables this option. @item --use-embedded-filename @itemx --no-use-embedded-filename @opindex use-embedded-filename Try to create a file with a name as embedded in the data. This can be a dangerous option as it enables overwriting files. Defaults to no. Note that the option @option{--output} overrides this option. @item --cipher-algo @var{name} @opindex cipher-algo Use @var{name} as cipher algorithm. Running the program with the command @option{--version} yields a list of supported algorithms. If this is not used the cipher algorithm is selected from the preferences stored with the key. In general, you do not want to use this option as it allows you to violate the OpenPGP standard. The option @option{--personal-cipher-preferences} is the safe way to accomplish the same thing. @item --digest-algo @var{name} @opindex digest-algo Use @var{name} as the message digest algorithm. Running the program with the command @option{--version} yields a list of supported algorithms. In general, you do not want to use this option as it allows you to violate the OpenPGP standard. The option @option{--personal-digest-preferences} is the safe way to accomplish the same thing. @item --compress-algo @var{name} @opindex compress-algo Use compression algorithm @var{name}. "zlib" is RFC-1950 ZLIB compression. "zip" is RFC-1951 ZIP compression which is used by PGP. "bzip2" is a more modern compression scheme that can compress some things better than zip or zlib, but at the cost of more memory used during compression and decompression. "uncompressed" or "none" disables compression. If this option is not used, the default behavior is to examine the recipient key preferences to see which algorithms the recipient supports. If all else fails, ZIP is used for maximum compatibility. ZLIB may give better compression results than ZIP, as the compression window size is not limited to 8k. BZIP2 may give even better compression results than that, but will use a significantly larger amount of memory while compressing and decompressing. This may be significant in low memory situations. Note, however, that PGP (all versions) only supports ZIP compression. Using any algorithm other than ZIP or "none" will make the message unreadable with PGP. In general, you do not want to use this option as it allows you to violate the OpenPGP standard. The option @option{--personal-compress-preferences} is the safe way to accomplish the same thing. @item --cert-digest-algo @var{name} @opindex cert-digest-algo Use @var{name} as the message digest algorithm used when signing a key. Running the program with the command @option{--version} yields a list of supported algorithms. Be aware that if you choose an algorithm that GnuPG supports but other OpenPGP implementations do not, then some users will not be able to use the key signatures you make, or quite possibly your entire key. Note also that a public key algorithm must be compatible with the specified digest algorithm; thus selecting an arbitrary digest algorithm may result in error messages from lower crypto layers or lead to security flaws. @item --disable-cipher-algo @var{name} @opindex disable-cipher-algo Never allow the use of @var{name} as cipher algorithm. The given name will not be checked so that a later loaded algorithm will still get disabled. @item --disable-pubkey-algo @var{name} @opindex disable-pubkey-algo Never allow the use of @var{name} as public key algorithm. The given name will not be checked so that a later loaded algorithm will still get disabled. @item --throw-keyids @itemx --no-throw-keyids @opindex throw-keyids Do not put the recipient key IDs into encrypted messages. This helps to hide the receivers of the message and is a limited countermeasure against traffic analysis.@footnote{Using a little social engineering anyone who is able to decrypt the message can check whether one of the other recipients is the one he suspects.} On the receiving side, it may slow down the decryption process because all available secret keys must be tried. @option{--no-throw-keyids} disables this option. This option is essentially the same as using @option{--hidden-recipient} for all recipients. @item --not-dash-escaped @opindex not-dash-escaped This option changes the behavior of cleartext signatures so that they can be used for patch files. You should not send such an armored file via email because all spaces and line endings are hashed too. You can not use this option for data which has 5 dashes at the beginning of a line, patch files don't have this. A special armor header line tells GnuPG about this cleartext signature option. @item --escape-from-lines @itemx --no-escape-from-lines @opindex escape-from-lines Because some mailers change lines starting with "From " to ">From " it is good to handle such lines in a special way when creating cleartext signatures to prevent the mail system from breaking the signature. Note that all other PGP versions do it this way too. Enabled by default. @option{--no-escape-from-lines} disables this option. @item --passphrase-repeat @var{n} @opindex passphrase-repeat Specify how many times @command{@gpgname} will request a new passphrase be repeated. This is useful for helping memorize a passphrase. Defaults to 1 repetition; can be set to 0 to disable any passphrase repetition. Note that a @var{n} greater than 1 will pop up the pinentry window @var{n}+1 times even if a modern pinentry with two entry fields is used. @item --passphrase-fd @var{n} @opindex passphrase-fd Read the passphrase from file descriptor @var{n}. Only the first line will be read from file descriptor @var{n}. If you use 0 for @var{n}, the passphrase will be read from STDIN. This can only be used if only one passphrase is supplied. Note that since Version 2.0 this passphrase is only used if the option @option{--batch} has also been given. Since Version 2.1 the @option{--pinentry-mode} also needs to be set to @code{loopback}. @item --passphrase-file @var{file} @opindex passphrase-file Read the passphrase from file @var{file}. Only the first line will be read from file @var{file}. This can only be used if only one passphrase is supplied. Obviously, a passphrase stored in a file is of questionable security if other users can read this file. Don't use this option if you can avoid it. Note that since Version 2.0 this passphrase is only used if the option @option{--batch} has also been given. Since Version 2.1 the @option{--pinentry-mode} also needs to be set to @code{loopback}. @item --passphrase @var{string} @opindex passphrase Use @var{string} as the passphrase. This can only be used if only one passphrase is supplied. Obviously, this is of very questionable security on a multi-user system. Don't use this option if you can avoid it. Note that since Version 2.0 this passphrase is only used if the option @option{--batch} has also been given. Since Version 2.1 the @option{--pinentry-mode} also needs to be set to @code{loopback}. @item --pinentry-mode @var{mode} @opindex pinentry-mode Set the pinentry mode to @var{mode}. Allowed values for @var{mode} are: @table @asis @item default Use the default of the agent, which is @code{ask}. @item ask Force the use of the Pinentry. @item cancel Emulate use of Pinentry's cancel button. @item error Return a Pinentry error (``No Pinentry''). @item loopback Redirect Pinentry queries to the caller. Note that in contrast to Pinentry the user is not prompted again if he enters a bad password. @end table @item --no-symkey-cache @opindex no-symkey-cache Disable the passphrase cache used for symmetrical en- and decryption. This cache is based on the message specific salt value (cf. @option{--s2k-mode}). @item --request-origin @var{origin} @opindex request-origin Tell gpg to assume that the operation ultimately originated at @var{origin}. Depending on the origin certain restrictions are applied and the Pinentry may include an extra note on the origin. Supported values for @var{origin} are: @code{local} which is the default, @code{remote} to indicate a remote origin or @code{browser} for an operation requested by a web browser. @item --command-fd @var{n} @opindex command-fd This is a replacement for the deprecated shared-memory IPC mode. If this option is enabled, user input on questions is not expected from the TTY but from the given file descriptor. It should be used together with @option{--status-fd}. See the file doc/DETAILS in the source distribution for details on how to use it. @item --command-file @var{file} @opindex command-file Same as @option{--command-fd}, except the commands are read out of file @var{file} @item --allow-non-selfsigned-uid @itemx --no-allow-non-selfsigned-uid @opindex allow-non-selfsigned-uid Allow the import and use of keys with user IDs which are not self-signed. This is not recommended, as a non self-signed user ID is trivial to forge. @option{--no-allow-non-selfsigned-uid} disables. @item --allow-freeform-uid @opindex allow-freeform-uid Disable all checks on the form of the user ID while generating a new one. This option should only be used in very special environments as it does not ensure the de-facto standard format of user IDs. @item --ignore-time-conflict @opindex ignore-time-conflict GnuPG normally checks that the timestamps associated with keys and signatures have plausible values. However, sometimes a signature seems to be older than the key due to clock problems. This option makes these checks just a warning. See also @option{--ignore-valid-from} for timestamp issues on subkeys. @item --ignore-valid-from @opindex ignore-valid-from GnuPG normally does not select and use subkeys created in the future. This option allows the use of such keys and thus exhibits the pre-1.0.7 behaviour. You should not use this option unless there is some clock problem. See also @option{--ignore-time-conflict} for timestamp issues with signatures. @item --ignore-crc-error @opindex ignore-crc-error The ASCII armor used by OpenPGP is protected by a CRC checksum against transmission errors. Occasionally the CRC gets mangled somewhere on the transmission channel but the actual content (which is protected by the OpenPGP protocol anyway) is still okay. This option allows GnuPG to ignore CRC errors. @item --ignore-mdc-error @opindex ignore-mdc-error This option changes a MDC integrity protection failure into a warning. It is required to decrypt old messages which did not use an MDC. It may also be useful if a message is partially garbled, but it is necessary to get as much data as possible out of that garbled message. Be aware that a missing or failed MDC can be an indication of an attack. Use with great caution; see also option @option{--rfc2440}. @item --allow-old-cipher-algos @opindex allow-old-cipher-algos Old cipher algorithms like 3DES, IDEA, or CAST5 encrypt data using blocks of 64 bits; modern algorithms use blocks of 128 bit instead. To avoid certain attack on these old algorithms it is suggested not to encrypt more than 150 MiByte using the same key. For this reason gpg does not allow the use of 64 bit block size algorithms for encryption unless this option is specified. @item --allow-weak-digest-algos @opindex allow-weak-digest-algos Signatures made with known-weak digest algorithms are normally rejected with an ``invalid digest algorithm'' message. This option allows the verification of signatures made with such weak algorithms. MD5 is the only digest algorithm considered weak by default. See also @option{--weak-digest} to reject other digest algorithms. @item --weak-digest @var{name} @opindex weak-digest Treat the specified digest algorithm as weak. Signatures made over weak digests algorithms are normally rejected. This option can be supplied multiple times if multiple algorithms should be considered weak. See also @option{--allow-weak-digest-algos} to disable rejection of weak digests. MD5 is always considered weak, and does not need to be listed explicitly. @item --allow-weak-key-signatures @opindex allow-weak-key-signatures To avoid a minor risk of collision attacks on third-party key signatures made using SHA-1, those key signatures are considered invalid. This options allows to override this restriction. @item --override-compliance-check @opindex --override-compliance-check The signature verification only allows the use of keys suitable in the current compliance mode. If the compliance mode has been forced by a global option, there might be no way to check certain signature. This option allows to override this and prints an extra warning in such a case. This option is ignored in --batch mode so that no accidental unattended verification may happen. @item --no-default-keyring @opindex no-default-keyring Do not add the default keyring to the list of keyrings. Note that GnuPG needs for almost all operations a keyring. Thus if you use this option and do not provide alternate keyrings via @option{--keyring}, then GnuPG will still use the default keyring. Note that if the option @option{use-keyboxd} is enabled in @file{common.conf}, no keyrings are used at all and keys are all maintained by the keyboxd process in its own database. @item --no-keyring @opindex no-keyring Do not use any keyring at all. This overrides the default and all options which specify keyrings. @item --skip-verify @opindex skip-verify Skip the signature verification step. This may be used to make the decryption faster if the signature verification is not needed. @item --with-key-data @opindex with-key-data Print key listings delimited by colons (like @option{--with-colons}) and print the public key data. @item --list-signatures @opindex list-signatures @itemx --list-sigs @opindex list-sigs Same as @option{--list-keys}, but the signatures are listed too. This command has the same effect as using @option{--list-keys} with @option{--with-sig-list}. Note that in contrast to @option{--check-signatures} the key signatures are not verified. This command can be used to create a list of signing keys missing in the local keyring; for example: @example gpg --list-sigs --with-colons USERID | \ awk -F: '$1=="sig" && $2=="?" @{if($13)@{print $13@}else@{print $5@}@}' @end example @item --fast-list-mode @opindex fast-list-mode Changes the output of the list commands to work faster; this is achieved by leaving some parts empty. Some applications don't need the user ID and the trust information given in the listings. By using this options they can get a faster listing. The exact behaviour of this option may change in future versions. If you are missing some information, don't use this option. @item --no-literal @opindex no-literal This is not for normal use. Use the source to see for what it might be useful. @item --set-filesize @opindex set-filesize This is not for normal use. Use the source to see for what it might be useful. @item --show-session-key @opindex show-session-key Display the session key used for one message. See @option{--override-session-key} for the counterpart of this option. We think that Key Escrow is a Bad Thing; however the user should have the freedom to decide whether to go to prison or to reveal the content of one specific message without compromising all messages ever encrypted for one secret key. You can also use this option if you receive an encrypted message which is abusive or offensive, to prove to the administrators of the messaging system that the ciphertext transmitted corresponds to an inappropriate plaintext so they can take action against the offending user. @item --override-session-key @var{string} @itemx --override-session-key-fd @var{fd} @opindex override-session-key Don't use the public key but the session key @var{string} respective the session key taken from the first line read from file descriptor @var{fd}. The format of this string is the same as the one printed by @option{--show-session-key}. This option is normally not used but comes handy in case someone forces you to reveal the content of an encrypted message; using this option you can do this without handing out the secret key. Note that using @option{--override-session-key} may reveal the session key to all local users via the global process table. Often it is useful to combine this option with @option{--no-keyring}. @item --ask-sig-expire @itemx --no-ask-sig-expire @opindex ask-sig-expire When making a data signature, prompt for an expiration time. If this option is not specified, the expiration time set via @option{--default-sig-expire} is used. @option{--no-ask-sig-expire} disables this option. @item --default-sig-expire @opindex default-sig-expire The default expiration time to use for signature expiration. Valid values are "0" for no expiration, a number followed by the letter d (for days), w (for weeks), m (for months), or y (for years) (for example "2m" for two months, or "5y" for five years), or an absolute date in the form YYYY-MM-DD. Defaults to "0". @item --ask-cert-expire @itemx --no-ask-cert-expire @opindex ask-cert-expire When making a key signature, prompt for an expiration time. If this option is not specified, the expiration time set via @option{--default-cert-expire} is used. @option{--no-ask-cert-expire} disables this option. @item --default-cert-expire @opindex default-cert-expire The default expiration time to use for key signature expiration. Valid values are "0" for no expiration, a number followed by the letter d (for days), w (for weeks), m (for months), or y (for years) (for example "2m" for two months, or "5y" for five years), or an absolute date in the form YYYY-MM-DD. Defaults to "0". @item --default-new-key-algo @var{string} @opindex default-new-key-algo @var{string} This option can be used to change the default algorithms for key generation. The @var{string} is similar to the arguments required for the command @option{--quick-add-key} but slightly different. For example the current default of @code{"rsa2048/cert,sign+rsa2048/encr"} (or @code{"rsa3072"}) can be changed to the value of what we currently call future default, which is @code{"ed25519/cert,sign+cv25519/encr"}. You need to consult the source code to learn the details. Note that the advanced key generation commands can always be used to specify a key algorithm directly. @item --no-auto-trust-new-key @opindex no-auto-trust-new-key When creating a new key the ownertrust of the new key is set to ultimate. This option disables this and the user needs to manually assign an ownertrust value. @item --force-sign-key @opindex force-sign-key This option modifies the behaviour of the commands @option{--quick-sign-key}, @option{--quick-lsign-key}, and the "sign" sub-commands of @option{--edit-key} by forcing the creation of a key signature, even if one already exists. @item --forbid-gen-key @opindex forbid-gen-key This option is intended for use in the global config file to disallow the use of generate key commands. Those commands will then fail with the error code for Not Enabled. @item --allow-secret-key-import @opindex allow-secret-key-import This is an obsolete option and is not used anywhere. @item --allow-multiple-messages @item --no-allow-multiple-messages These are obsolete options; they have no more effect since GnuPG 2.2.8. @item --enable-special-filenames @opindex enable-special-filenames This option enables a mode in which filenames of the form @file{-&n}, where n is a non-negative decimal number, refer to the file descriptor n and not to a file with that name. @item --no-expensive-trust-checks @opindex no-expensive-trust-checks Experimental use only. @item --preserve-permissions @opindex preserve-permissions Don't change the permissions of a secret keyring back to user read/write only. Use this option only if you really know what you are doing. @item --default-preference-list @var{string} @opindex default-preference-list Set the list of default preferences to @var{string}. This preference list is used for new keys and becomes the default for "setpref" in the @option{--edit-key} menu. @item --default-keyserver-url @var{name} @opindex default-keyserver-url Set the default keyserver URL to @var{name}. This keyserver will be used as the keyserver URL when writing a new self-signature on a key, which includes key generation and changing preferences. @item --list-config @opindex list-config Display various internal configuration parameters of GnuPG. This option is intended for external programs that call GnuPG to perform tasks, and is thus not generally useful. See the file @file{doc/DETAILS} in the source distribution for the details of which configuration items may be listed. @option{--list-config} is only usable with @option{--with-colons} set. @item --list-gcrypt-config @opindex list-gcrypt-config Display various internal configuration parameters of Libgcrypt. @item --gpgconf-list @opindex gpgconf-list This command is similar to @option{--list-config} but in general only internally used by the @command{gpgconf} tool. @item --gpgconf-test @opindex gpgconf-test This is more or less dummy action. However it parses the configuration file and returns with failure if the configuration file would prevent @command{@gpgname} from startup. Thus it may be used to run a syntax check on the configuration file. @c @item --use-only-openpgp-card @c @opindex use-only-openpgp-card @c Only access OpenPGP card's and no other cards. This is a hidden @c option which could be used in case an old use case required the @c OpenPGP card while several cards are available. This option might be @c removed if it turns out that nobody requires it. @item --chuid @var{uid} @opindex chuid Change the current user to @var{uid} which may either be a number or a name. This can be used from the root account to run gpg for another user. If @var{uid} is not the current UID a standard PATH is set and the envvar GNUPGHOME is unset. To override the latter the option @option{--homedir} can be used. This option has only an effect when used on the command line. This option has currently no effect at all on Windows. @end table @c ******************************* @c ******* Deprecated ************ @c ******************************* @node Deprecated Options @subsection Deprecated options @table @gnupgtabopt @item --show-photos @itemx --no-show-photos @opindex show-photos Causes @option{--list-keys}, @option{--list-signatures}, @option{--list-public-keys}, @option{--list-secret-keys}, and verifying a signature to also display the photo ID attached to the key, if any. See also @option{--photo-viewer}. These options are deprecated. Use @option{--list-options [no-]show-photos} and/or @option{--verify-options [no-]show-photos} instead. @item --show-keyring @opindex show-keyring Display the keyring name at the head of key listings to show which keyring a given key resides on. This option is deprecated: use @option{--list-options [no-]show-keyring} instead. @item --always-trust @opindex always-trust Identical to @option{--trust-model always}. This option is deprecated. @item --show-notation @itemx --no-show-notation @opindex show-notation Show signature notations in the @option{--list-signatures} or @option{--check-signatures} listings as well as when verifying a signature with a notation in it. These options are deprecated. Use @option{--list-options [no-]show-notation} and/or @option{--verify-options [no-]show-notation} instead. @item --show-policy-url @itemx --no-show-policy-url @opindex show-policy-url Show policy URLs in the @option{--list-signatures} or @option{--check-signatures} listings as well as when verifying a signature with a policy URL in it. These options are deprecated. Use @option{--list-options [no-]show-policy-url} and/or @option{--verify-options [no-]show-policy-url} instead. @item --personal-aead-preferences @var{string} @opindex personal-aead-preferences This option is deprecated and has no more effect since version 2.3.9. @item --aead-algo @var{name} This option is deprecated and has no more effect since version 2.3.9. @end table @c ******************************************* @c *************** **************** @c *************** FILES **************** @c *************** **************** @c ******************************************* @mansect files @node GPG Configuration @section Configuration files There are a few configuration files to control certain aspects of @command{@gpgname}'s operation. Unless noted, they are expected in the current home directory (@pxref{option --homedir}). @table @file @item gpg.conf @efindex gpg.conf This is the standard configuration file read by @command{@gpgname} on startup. It may contain any valid long option; the leading two dashes may not be entered and the option may not be abbreviated. This default name may be changed on the command line (@pxref{gpg-option --options}). You should backup this file. @item common.conf @efindex common.conf This is an optional configuration file read by @command{@gpgname} on startup. It may contain options pertaining to all components of GnuPG. Its current main use is for the "use-keyboxd" option. @end table Note that on larger installations, it is useful to put predefined files into the directory @file{@value{SYSCONFSKELDIR}} so that newly created users start up with a working configuration. For existing users a small helper script is provided to create these files (@pxref{addgnupghome}). For internal purposes @command{@gpgname} creates and maintains a few other files; They all live in the current home directory (@pxref{option --homedir}). Only the @command{@gpgname} program may modify these files. @table @file @item ~/.gnupg @efindex ~/.gnupg This is the default home directory which is used if neither the environment variable @code{GNUPGHOME} nor the option @option{--homedir} is given. @item ~/.gnupg/pubring.gpg @efindex pubring.gpg The public keyring using a legacy format. You should backup this file. If this file is not available, @command{gpg} defaults to the new keybox format and creates a file @file{pubring.kbx} unless that file already exists in which case that file will also be used for OpenPGP keys. Note that in the case that both files, @file{pubring.gpg} and @file{pubring.kbx} exists but the latter has no OpenPGP keys, the legacy file @file{pubring.gpg} will be used. Take care: GnuPG versions before 2.1 will always use the file @file{pubring.gpg} because they do not know about the new keybox format. In the case that you have to use GnuPG 1.4 to decrypt archived data you should keep this file. @item ~/.gnupg/pubring.gpg.lock The lock file for the public keyring. @item ~/.gnupg/pubring.kbx @efindex pubring.kbx The public keyring using the new keybox format. This file is shared with @command{gpgsm}. You should backup this file. See above for the relation between this file and it predecessor. To convert an existing @file{pubring.gpg} file to the keybox format, you first backup the ownertrust values, then rename @file{pubring.gpg} to @file{publickeys.backup}, so it won’t be recognized by any GnuPG version, run import, and finally restore the ownertrust values: @example $ cd ~/.gnupg $ gpg --export-ownertrust >otrust.lst $ mv pubring.gpg publickeys.backup $ gpg --import-options restore --import publickeys.backup $ gpg --import-ownertrust otrust.lst @end example @item ~/.gnupg/pubring.kbx.lock The lock file for @file{pubring.kbx}. @item ~/.gnupg/secring.gpg @efindex secring.gpg The legacy secret keyring as used by GnuPG versions before 2.1. It is not used by GnuPG 2.1 and later. You may want to keep it in case you have to use GnuPG 1.4 to decrypt archived data. @item ~/.gnupg/secring.gpg.lock The lock file for the legacy secret keyring. @item ~/.gnupg/.gpg-v21-migrated @efindex .gpg-v21-migrated File indicating that a migration to GnuPG 2.1 has been done. @item ~/.gnupg/trustdb.gpg @efindex trustdb.gpg The trust database. There is no need to backup this file; it is better to backup the ownertrust values (@pxref{option --export-ownertrust}). @item ~/.gnupg/trustdb.gpg.lock The lock file for the trust database. @item ~/.gnupg/random_seed @efindex random_seed A file used to preserve the state of the internal random pool. @item ~/.gnupg/openpgp-revocs.d/ @efindex openpgp-revocs.d This is the directory where gpg stores pre-generated revocation certificates. The file name corresponds to the OpenPGP fingerprint of the respective key. It is suggested to backup those certificates and if the primary private key is not stored on the disk to move them to an external storage device. Anyone who can access these files is able to revoke the corresponding key. You may want to print them out. You should backup all files in this directory and take care to keep this backup closed away. @end table Operation is further controlled by a few environment variables: @table @asis @item HOME @efindex HOME Used to locate the default home directory. @item GNUPGHOME @efindex GNUPGHOME If set directory used instead of "~/.gnupg". @item GPG_AGENT_INFO This variable is obsolete; it was used by GnuPG versions before 2.1. @item PINENTRY_USER_DATA @efindex PINENTRY_USER_DATA This value is passed via gpg-agent to pinentry. It is useful to convey extra information to a custom pinentry. @item COLUMNS @itemx LINES @efindex COLUMNS @efindex LINES Used to size some displays to the full size of the screen. @item LANGUAGE @efindex LANGUAGE Apart from its use by GNU, it is used in the W32 version to override the language selection done through the Registry. If used and set to a valid and available language name (@var{langid}), the file with the translation is loaded from @code{@var{gpgdir}/gnupg.nls/@var{langid}.mo}. Here @var{gpgdir} is the directory out of which the gpg binary has been loaded. If it can't be loaded the Registry is tried and as last resort the native Windows locale system is used. @item GNUPG_BUILD_ROOT @efindex GNUPG_BUILD_ROOT This variable is only used by the regression test suite as a helper under operating systems without proper support to figure out the name of a process' text file. @item GNUPG_EXEC_DEBUG_FLAGS @efindex GNUPG_EXEC_DEBUG_FLAGS This variable allows to enable diagnostics for process management. A numeric decimal value is expected. Bit 0 enables general diagnostics, bit 1 enables certain warnings on Windows. @end table When calling the gpg-agent component @command{@gpgname} sends a set of environment variables to gpg-agent. The names of these variables can be listed using the command: @example gpg-connect-agent 'getinfo std_env_names' /bye | awk '$1=="D" @{print $2@}' @end example @c ******************************************* @c *************** **************** @c *************** EXAMPLES **************** @c *************** **************** @c ******************************************* @mansect examples @node GPG Examples @section Examples @table @asis @item gpg -se -r @code{Bob} @code{file} sign and encrypt for user Bob @item gpg --clear-sign @code{file} make a cleartext signature @item gpg -sb @code{file} make a detached signature @item gpg -u 0x12345678 -sb @code{file} make a detached signature with the key 0x12345678 @item gpg --list-keys @code{user_ID} show keys @item gpg --fingerprint @code{user_ID} show fingerprint @item gpg --verify @code{pgpfile} @itemx gpg --verify @code{sigfile} [@code{datafile}] Verify the signature of the file but do not output the data unless requested. The second form is used for detached signatures, where @code{sigfile} is the detached signature (either ASCII armored or binary) and @code{datafile} are the signed data; if this is not given, the name of the file holding the signed data is constructed by cutting off the extension (".asc" or ".sig") of @code{sigfile} or by asking the user for the filename. If the option @option{--output} is also used the signed data is written to the file specified by that option; use @code{-} to write the signed data to stdout. @end table @c ******************************************* @c *************** **************** @c *************** USER ID **************** @c *************** **************** @c ******************************************* @mansect how to specify a user id @ifset isman @include specify-user-id.texi @end ifset @mansect filter expressions @chapheading FILTER EXPRESSIONS The options @option{--import-filter} and @option{--export-filter} use expressions with this syntax (square brackets indicate an optional part and curly braces a repetition, white space between the elements are allowed): @c man:.RS @example [lc] @{[@{flag@}] PROPNAME op VALUE [lc]@} @end example @c man:.RE The name of a property (@var{PROPNAME}) may only consist of letters, digits and underscores. The description for the filter type describes which properties are defined. If an undefined property is used it evaluates to the empty string. Unless otherwise noted, the @var{VALUE} must always be given and may not be the empty string. No quoting is defined for the value, thus the value may not contain the strings @code{&&} or @code{||}, which are used as logical connection operators. The flag @code{--} can be used to remove this restriction. Numerical values are computed as long int; standard C notation applies. @var{lc} is the logical connection operator; either @code{&&} for a conjunction or @code{||} for a disjunction. A conjunction is assumed at the begin of an expression. Conjunctions have higher precedence than disjunctions. If @var{VALUE} starts with one of the characters used in any @var{op} a space after the @var{op} is required. @noindent The supported operators (@var{op}) are: @table @asis @item =~ Substring must match. @item !~ Substring must not match. @item = The full string must match. @item <> The full string must not match. @item == The numerical value must match. @item != The numerical value must not match. @item <= The numerical value of the field must be LE than the value. @item < The numerical value of the field must be LT than the value. @item > The numerical value of the field must be GT than the value. @item >= The numerical value of the field must be GE than the value. @item -le The string value of the field must be less or equal than the value. @item -lt The string value of the field must be less than the value. @item -gt The string value of the field must be greater than the value. @item -ge The string value of the field must be greater or equal than the value. @item -n True if value is not empty (no value allowed). @item -z True if value is empty (no value allowed). @item -t Alias for "PROPNAME != 0" (no value allowed). @item -f Alias for "PROPNAME == 0" (no value allowed). @end table @noindent Values for @var{flag} must be space separated. The supported flags are: @table @asis @item -- @var{VALUE} spans to the end of the expression. @item -c The string match in this part is done case-sensitive. @item -t Leading and trailing spaces are not removed from @var{VALUE}. The optional single space after @var{op} is here required. @end table The filter options concatenate several specifications for a filter of the same type. For example the four options in this example: @c man:.RS @example --import-filter keep-uid="uid =~ Alfa" --import-filter keep-uid="&& uid !~ Test" --import-filter keep-uid="|| uid =~ Alpha" --import-filter keep-uid="uid !~ Test" @end example @c man:.RE @noindent which is equivalent to @c man:.RS @example --import-filter \ keep-uid="uid =~ Alfa" && uid !~ Test" || uid =~ Alpha" && "uid !~ Test" @end example @c man:.RE imports only the user ids of a key containing the strings "Alfa" or "Alpha" but not the string "test". @mansect trust values @ifset isman @include trust-values.texi @end ifset @mansect return value @chapheading RETURN VALUE The program returns 0 if there are no severe errors, 1 if at least a signature was bad, and other error codes for fatal errors. Note that signature verification requires exact knowledge of what has been signed and by whom it has been signed. Using only the return code is thus not an appropriate way to verify a signature by a script. Either make proper use or the status codes or use the @command{gpgv} tool which has been designed to make signature verification easy for scripts. @mansect warnings @chapheading WARNINGS Use a good password for your user account and make sure that all security issues are always fixed on your machine. Also employ diligent physical protection to your machine. Consider to use a good passphrase as a last resort protection to your secret key in the case your machine gets stolen. It is important that your secret key is never leaked. Using an easy to carry around token or smartcard with the secret key is often a advisable. If you are going to verify detached signatures, make sure that the program knows about it; either give both filenames on the command line or use @samp{-} to specify STDIN. For scripted or other unattended use of @command{gpg} make sure to use the machine-parseable interface and not the default interface which is intended for direct use by humans. The machine-parseable interface provides a stable and well documented API independent of the locale or future changes of @command{gpg}. To enable this interface use the options @option{--with-colons} and @option{--status-fd}. For certain operations the option @option{--command-fd} may come handy too. See this man page and the file @file{DETAILS} for the specification of the interface. Note that the GnuPG ``info'' pages as well as the PDF version of the GnuPG manual features a chapter on unattended use of GnuPG. As an alternative the library @command{GPGME} can be used as a high-level abstraction on top of that interface. @mansect interoperability @chapheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS GnuPG tries to be a very flexible implementation of the OpenPGP standard. In particular, GnuPG implements many of the optional parts of the standard, such as the SHA-512 hash, and the ZLIB and BZIP2 compression algorithms. It is important to be aware that not all OpenPGP programs implement these optional algorithms and that by forcing their use via the @option{--cipher-algo}, @option{--digest-algo}, @option{--cert-digest-algo}, or @option{--compress-algo} options in GnuPG, it is possible to create a perfectly valid OpenPGP message, but one that cannot be read by the intended recipient. There are dozens of variations of OpenPGP programs available, and each supports a slightly different subset of these optional algorithms. For example, until recently, no (unhacked) version of PGP supported the BLOWFISH cipher algorithm. A message using BLOWFISH simply could not be read by a PGP user. By default, GnuPG uses the standard OpenPGP preferences system that will always do the right thing and create messages that are usable by all recipients, regardless of which OpenPGP program they use. Only override this safe default if you really know what you are doing. If you absolutely must override the safe default, or if the preferences on a given key are invalid for some reason, you are far better off using the @option{--pgp6}, @option{--pgp7}, or @option{--pgp8} options. These options are safe as they do not force any particular algorithms in violation of OpenPGP, but rather reduce the available algorithms to a "PGP-safe" list. @mansect bugs @chapheading BUGS On older systems this program should be installed as setuid(root). This is necessary to lock memory pages. Locking memory pages prevents the operating system from writing memory pages (which may contain passphrases or other sensitive material) to disk. If you get no warning message about insecure memory your operating system supports locking without being root. The program drops root privileges as soon as locked memory is allocated. Note also that some systems (especially laptops) have the ability to ``suspend to disk'' (also known as ``safe sleep'' or ``hibernate''). This writes all memory to disk before going into a low power or even powered off mode. Unless measures are taken in the operating system to protect the saved memory, passphrases or other sensitive material may be recoverable from it later. Before you report a bug you should first search the mailing list archives for similar problems and second check whether such a bug has already been reported to our bug tracker at @url{https://bugs.gnupg.org}. @c ******************************************* @c *************** ************** @c *************** UNATTENDED ************** @c *************** ************** @c ******************************************* @manpause @node Unattended Usage of GPG @section Unattended Usage @command{@gpgname} is often used as a backend engine by other software. To help with this a machine interface has been defined to have an unambiguous way to do this. The options @option{--status-fd} and @option{--batch} are almost always required for this. @menu * Programmatic use of GnuPG:: Programmatic use of GnuPG * Ephemeral home directories:: Ephemeral home directories * The quick key manipulation interface:: The quick key manipulation interface * Unattended GPG key generation:: Unattended key generation @end menu @node Programmatic use of GnuPG @subsection Programmatic use of GnuPG Please consider using GPGME instead of calling @command{@gpgname} directly. GPGME offers a stable, backend-independent interface for many cryptographic operations. It supports OpenPGP and S/MIME, and also allows interaction with various GnuPG components. GPGME provides a C-API, and comes with bindings for C++, Qt, and Python. Bindings for other languages are available. @node Ephemeral home directories @subsection Ephemeral home directories Sometimes you want to contain effects of some operation, for example you want to import a key to inspect it, but you do not want this key to be added to your keyring. In earlier versions of GnuPG, it was possible to specify alternate keyring files for both public and secret keys. In modern GnuPG versions, however, we changed how secret keys are stored in order to better protect secret key material, and it was not possible to preserve this interface. The preferred way to do this is to use ephemeral home directories. This technique works across all versions of GnuPG. Create a temporary directory, create (or copy) a configuration that meets your needs, make @command{@gpgname} use this directory either using the environment variable @var{GNUPGHOME}, or the option @option{--homedir}. GPGME supports this too on a per-context basis, by modifying the engine info of contexts. Now execute whatever operation you like, import and export key material as necessary. Once finished, you can delete the directory. All GnuPG backend services that were started will detect this and shut down. @node The quick key manipulation interface @subsection The quick key manipulation interface Recent versions of GnuPG have an interface to manipulate keys without using the interactive command @option{--edit-key}. This interface was added mainly for the benefit of GPGME (please consider using GPGME, see the manual subsection ``Programmatic use of GnuPG''). This interface is described in the subsection ``How to manage your keys''. @node Unattended GPG key generation @subsection Unattended key generation The command @option{--generate-key} may be used along with the option @option{--batch} for unattended key generation. This is the most flexible way of generating keys, but it is also the most complex one. Consider using the quick key manipulation interface described in the previous subsection ``The quick key manipulation interface''. The parameters for the key are either read from stdin or given as a file on the command line. The format of the parameter file is as follows: @itemize @bullet @item Text only, line length is limited to about 1000 characters. @item UTF-8 encoding must be used to specify non-ASCII characters. @item Empty lines are ignored. @item Leading and trailing white space is ignored. @item A hash sign as the first non white space character indicates a comment line. @item Control statements are indicated by a leading percent sign, the arguments are separated by white space from the keyword. @item Parameters are specified by a keyword, followed by a colon. Arguments are separated by white space. @item The first parameter must be @samp{Key-Type}; control statements may be placed anywhere. @item The order of the parameters does not matter except for @samp{Key-Type} which must be the first parameter. The parameters are only used for the generated keyblock (primary and subkeys); parameters from previous sets are not used. Some syntactically checks may be performed. @item Key generation takes place when either the end of the parameter file is reached, the next @samp{Key-Type} parameter is encountered or at the control statement @samp{%commit} is encountered. @end itemize @noindent Control statements: @table @asis @item %echo @var{text} Print @var{text} as diagnostic. @item %dry-run Suppress actual key generation (useful for syntax checking). @item %commit Perform the key generation. Note that an implicit commit is done at the next @asis{Key-Type} parameter. @item %pubring @var{filename} Do not write the key to the default or commandline given keyring but to @var{filename}. This must be given before the first commit to take place, duplicate specification of the same filename is ignored, the last filename before a commit is used. The filename is used until a new filename is used (at commit points) and all keys are written to that file. If a new filename is given, this file is created (and overwrites an existing one). See the previous subsection ``Ephemeral home directories'' for a more robust way to contain side-effects. @item %secring @var{filename} This option is a no-op for GnuPG 2.1 and later. See the previous subsection ``Ephemeral home directories''. @item %ask-passphrase @itemx %no-ask-passphrase This option is a no-op for GnuPG 2.1 and later. @item %no-protection Using this option allows the creation of keys without any passphrase protection. This option is mainly intended for regression tests. @item %transient-key If given the keys are created using a faster and a somewhat less secure random number generator. This option may be used for keys which are only used for a short time and do not require full cryptographic strength. It takes only effect if used together with the control statement @samp{%no-protection}. @end table @noindent General Parameters: @table @asis @item Key-Type: @var{algo} Starts a new parameter block by giving the type of the primary key. The algorithm must be capable of signing. This is a required parameter. @var{algo} may either be an OpenPGP algorithm number or a string with the algorithm name. The special value @samp{default} may be used for @var{algo} to create the default key type; in this case a @samp{Key-Usage} shall not be given and @samp{default} also be used for @samp{Subkey-Type}. @item Key-Length: @var{nbits} The requested length of the generated key in bits. The default is returned by running the command @samp{@gpgname --gpgconf-list}. For ECC keys this parameter is ignored. @item Key-Curve: @var{curve} The requested elliptic curve of the generated key. This is a required parameter for ECC keys. It is ignored for non-ECC keys. @item Key-Grip: @var{hexstring} This is optional and used to generate a CSR or certificate for an already existing key. Key-Length will be ignored when given. @item Key-Usage: @var{usage-list} Space or comma delimited list of key usages. Allowed values are @samp{encrypt}, @samp{sign}, and @samp{auth}. This is used to generate the key flags. Please make sure that the algorithm is capable of this usage. Note that OpenPGP requires that all primary keys are capable of certification, so no matter what usage is given here, the @samp{cert} flag will be on. If no @samp{Key-Usage} is specified and the @samp{Key-Type} is not @samp{default}, all allowed usages for that particular algorithm are used; if it is not given but @samp{default} is used the usage will be @samp{sign}. @item Subkey-Type: @var{algo} This generates a secondary key (subkey). Currently only one subkey can be handled. See also @samp{Key-Type} above. @item Subkey-Length: @var{nbits} Length of the secondary key (subkey) in bits. The default is returned by running the command @samp{@gpgname --gpgconf-list}. @item Subkey-Curve: @var{curve} Key curve for a subkey; similar to @samp{Key-Curve}. @item Subkey-Usage: @var{usage-list} Key usage lists for a subkey; similar to @samp{Key-Usage}. @item Passphrase: @var{string} If you want to specify a passphrase for the secret key, enter it here. Default is to use the Pinentry dialog to ask for a passphrase. @item Name-Real: @var{name} @itemx Name-Comment: @var{comment} @itemx Name-Email: @var{email} The three parts of a user name. Remember to use UTF-8 encoding here. If you don't give any of them, no user ID is created. @item Expire-Date: @var{iso-date}|(@var{number}[d|w|m|y]) Set the expiration date for the key (and the subkey). It may either be entered in ISO date format (e.g. "20000815T145012") or as number of days, weeks, month or years after the creation date. The special notation "seconds=N" is also allowed to specify a number of seconds since creation. Without a letter days are assumed. Note that there is no check done on the overflow of the type used by OpenPGP for timestamps. Thus you better make sure that the given value make sense. Although OpenPGP works with time intervals, GnuPG uses an absolute value internally and thus the last year we can represent is 2105. @item Creation-Date: @var{iso-date} Set the creation date of the key as stored in the key information and which is also part of the fingerprint calculation. Either a date like "1986-04-26" or a full timestamp like "19860426T042640" may be used. The time is considered to be UTC. The special notation "seconds=N" may be used to directly specify a the number of seconds since Epoch (Unix time). If it is not given the current time is used. @item Preferences: @var{string} Set the cipher, hash, and compression preference values for this key. This expects the same type of string as the sub-command @samp{setpref} in the @option{--edit-key} menu. @item Revoker: @var{algo}:@var{fpr} [sensitive] Add a designated revoker to the generated key. Algo is the public key algorithm of the designated revoker (i.e. RSA=1, DSA=17, etc.) @var{fpr} is the fingerprint of the designated revoker. The optional @samp{sensitive} flag marks the designated revoker as sensitive information. Only v4 keys may be designated revokers. @item Keyserver: @var{string} This is an optional parameter that specifies the preferred keyserver URL for the key. @item Handle: @var{string} This is an optional parameter only used with the status lines KEY_CREATED and KEY_NOT_CREATED. @var{string} may be up to 100 characters and should not contain spaces. It is useful for batch key generation to associate a key parameter block with a status line. @end table @noindent Here is an example on how to create a key in an ephemeral home directory: @smallexample $ export GNUPGHOME="$(mktemp -d)" $ cat >foo < ssb elg1024 2016-12-16 [E] @end smallexample @noindent If you want to create a key with the default algorithms you would use these parameters: @smallexample %echo Generating a default key Key-Type: default Subkey-Type: default Name-Real: Joe Tester Name-Comment: with stupid passphrase Name-Email: joe@@foo.bar Expire-Date: 0 Passphrase: abc # Do a commit here, so that we can later print "done" :-) %commit %echo done @end smallexample @mansect see also @ifset isman @command{gpgv}(1), @command{gpgsm}(1), @command{gpg-agent}(1) @end ifset @include see-also-note.texi diff --git a/g10/encrypt.c b/g10/encrypt.c index d0e142714..687b4344e 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -1,1243 +1,1266 @@ /* encrypt.c - Main encryption driver * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2009 Free Software Foundation, Inc. - * Copyright (C) 2016 g10 Code GmbH + * Copyright (C) 2016, 2023 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . + * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include #include #include #include "gpg.h" #include "options.h" #include "packet.h" #include "../common/status.h" #include "../common/iobuf.h" #include "keydb.h" #include "../common/util.h" #include "main.h" #include "filter.h" #include "trustdb.h" #include "../common/i18n.h" #include "../common/status.h" #include "pkglue.h" #include "../common/compliance.h" static int encrypt_simple( const char *filename, int mode, int use_seskey ); static int write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out); /**************** * Encrypt FILENAME with only the symmetric cipher. Take input from * stdin if FILENAME is NULL. If --force-aead is used we use an SKESK. */ int encrypt_symmetric (const char *filename) { return encrypt_simple( filename, 1, opt.force_aead); } /**************** * Encrypt FILENAME as a literal data packet only. Take input from * stdin if FILENAME is NULL. */ int encrypt_store (const char *filename) { return encrypt_simple( filename, 0, 0 ); } /* Create and setup a DEK structure and print approriate warnings. * PK_LIST gives the list of public keys. Always returns a DEK. The * actual session needs to be added later. */ static DEK * create_dek_with_warnings (pk_list_t pk_list) { DEK *dek; dek = xmalloc_secure_clear (sizeof *dek); if (!opt.def_cipher_algo) { /* Try to get it from the prefs. */ dek->algo = select_algo_from_prefs (pk_list, PREFTYPE_SYM, -1, NULL); if (dek->algo == -1) { /* If does not make sense to fallback to the rfc4880 * required 3DES if we will reject that algo later. Thus we * fallback to AES anticipating RFC4880bis rules. */ if (opt.flags.allow_old_cipher_algos) dek->algo = CIPHER_ALGO_3DES; else dek->algo = CIPHER_ALGO_AES; } /* In case 3DES has been selected, print a warning if any key * does not have a preference for AES. This should help to * indentify why encrypting to several recipients falls back to * 3DES. */ if (opt.verbose && dek->algo == CIPHER_ALGO_3DES) warn_missing_aes_from_pklist (pk_list); } else { if (!opt.expert && (select_algo_from_prefs (pk_list, PREFTYPE_SYM, opt.def_cipher_algo, NULL) != opt.def_cipher_algo)) { log_info(_("WARNING: forcing symmetric cipher %s (%d)" " violates recipient preferences\n"), openpgp_cipher_algo_name (opt.def_cipher_algo), opt.def_cipher_algo); } dek->algo = opt.def_cipher_algo; } return dek; } /* Check whether all encryption keys are compliant with the current * mode and issue respective status lines. DEK has the info about the * session key and PK_LIST the list of public keys. */ static gpg_error_t check_encryption_compliance (DEK *dek, pk_list_t pk_list) { gpg_error_t err = 0; pk_list_t pkr; int compliant; /* First check whether we should use the algo at all. */ if (openpgp_cipher_blocklen (dek->algo) < 16 && !opt.flags.allow_old_cipher_algos) { log_error (_("cipher algorithm '%s' may not be used for encryption\n"), openpgp_cipher_algo_name (dek->algo)); if (!opt.quiet) log_info (_("(use option \"%s\" to override)\n"), "--allow-old-cipher-algos"); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } /* Now check the compliance. */ if (! gnupg_cipher_is_allowed (opt.compliance, 1, dek->algo, GCRY_CIPHER_MODE_CFB)) { log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (dek->algo), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } if (!gnupg_rng_is_compliant (opt.compliance)) { err = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", err); goto leave; } /* From here on we only test for CO_DE_VS - if we ever want to * return other compliance mode values we need to change this to * loop over all those values. */ compliant = gnupg_gcrypt_is_compliant (CO_DE_VS); if (!gnupg_cipher_is_compliant (CO_DE_VS, dek->algo, GCRY_CIPHER_MODE_CFB)) compliant = 0; for (pkr = pk_list; pkr; pkr = pkr->next) { PKT_public_key *pk = pkr->pk; unsigned int nbits = nbits_from_pk (pk); if (!gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0, pk->pkey, nbits, NULL)) log_info (_("WARNING: key %s is not suitable for encryption" " in %s mode\n"), keystr_from_pk (pk), gnupg_compliance_option_string (opt.compliance)); if (compliant && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey, nbits, NULL)) compliant = 0; /* Not compliant - reset flag. */ } /* If we are compliant print the status for de-vs compliance. */ if (compliant) write_status_strings (STATUS_ENCRYPTION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS), NULL); /* Check whether we should fail the operation. */ if (opt.flags.require_compliance && opt.compliance == CO_DE_VS && !compliant) { compliance_failure (); err = gpg_error (GPG_ERR_FORBIDDEN); goto leave; } leave: return err; } /* Encrypt a session key using DEK and store a pointer to the result * at R_ENCKEY and its length at R_ENCKEYLEN. * * R_SESKEY points to the unencrypted session key (.KEY, .KEYLEN) and * the algorithm that will be used to encrypt the contents of the * SKESK packet (.ALGO). If R_SESKEY points to NULL, then a random * session key that is appropriate for DEK->ALGO is generated and * stored at R_SESKEY. If AEAD_ALGO is not 0 the given AEAD algorithm * is used for encryption. */ static gpg_error_t encrypt_seskey (DEK *dek, aead_algo_t aead_algo, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) { gpg_error_t err; gcry_cipher_hd_t hd = NULL; byte *buf = NULL; DEK *seskey; *r_enckey = NULL; *r_enckeylen = 0; if (*r_seskey) seskey = *r_seskey; else { seskey = xtrycalloc (1, sizeof(DEK)); if (!seskey) { err = gpg_error_from_syserror (); goto leave; } seskey->algo = dek->algo; make_session_key (seskey); /*log_hexdump( "thekey", c->key, c->keylen );*/ } if (aead_algo) { unsigned int noncelen; enum gcry_cipher_modes ciphermode; byte ad[4]; err = openpgp_aead_algo_info (aead_algo, &ciphermode, &noncelen); if (err) goto leave; /* Allocate space for the nonce, the key, and the authentication * tag (16). */ buf = xtrymalloc_secure (noncelen + seskey->keylen + 16); if (!buf) { err = gpg_error_from_syserror (); goto leave; } gcry_randomize (buf, noncelen, GCRY_STRONG_RANDOM); err = openpgp_cipher_open (&hd, dek->algo, ciphermode, GCRY_CIPHER_SECURE); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, buf, noncelen); if (err) goto leave; ad[0] = (0xc0 | PKT_SYMKEY_ENC); ad[1] = 5; ad[2] = dek->algo; ad[3] = aead_algo; err = gcry_cipher_authenticate (hd, ad, 4); if (err) goto leave; memcpy (buf + noncelen, seskey->key, seskey->keylen); gcry_cipher_final (hd); err = gcry_cipher_encrypt (hd, buf + noncelen, seskey->keylen, NULL,0); if (err) goto leave; err = gcry_cipher_gettag (hd, buf + noncelen + seskey->keylen, 16); if (err) goto leave; *r_enckeylen = noncelen + seskey->keylen + 16; *r_enckey = buf; buf = NULL; } else { /* In the old version 4 SKESK the encrypted session key is * prefixed with a one-octet algorithm id. */ buf = xtrymalloc_secure (1 + seskey->keylen); if (!buf) { err = gpg_error_from_syserror (); goto leave; } buf[0] = seskey->algo; memcpy (buf + 1, seskey->key, seskey->keylen); err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, NULL, 0); if (!err) err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0); if (err) goto leave; *r_enckeylen = seskey->keylen + 1; *r_enckey = buf; buf = NULL; } /* Return the session key in case we allocated it. */ *r_seskey = seskey; seskey = NULL; leave: gcry_cipher_close (hd); if (seskey != *r_seskey) xfree (seskey); xfree (buf); return err; } /* Return the AEAD algo if we shall use AEAD mode. Returns 0 if AEAD * shall not be used. */ aead_algo_t use_aead (pk_list_t pk_list, int algo) { int can_use; can_use = openpgp_cipher_get_algo_blklen (algo) == 16; /* With --force-aead we want AEAD. */ if (opt.force_aead) { if (!can_use) { log_info ("Warning: request to use OCB ignored for cipher '%s'\n", openpgp_cipher_algo_name (algo)); return 0; } return AEAD_ALGO_OCB; } /* AEAD does only work with 128 bit cipher blocklength. */ if (!can_use) return 0; /* Note the user which keys have no AEAD feature flag set. */ if (opt.verbose) warn_missing_aead_from_pklist (pk_list); /* If all keys support AEAD we can use it. */ return select_aead_from_pklist (pk_list); } /* Shall we use the MDC? Yes - unless rfc-2440 compatibility is * requested. */ int use_mdc (pk_list_t pk_list,int algo) { (void)pk_list; (void)algo; /* RFC-2440 don't has MDC - this is the only way to create a legacy * non-MDC encryption packet. */ if (RFC2440) return 0; return 1; /* In all other cases we use the MDC */ } /* We don't want to use use_seskey yet because older gnupg versions can't handle it, and there isn't really any point unless we're making a message that can be decrypted by a public key or passphrase. */ static int encrypt_simple (const char *filename, int mode, int use_seskey) { iobuf_t inp, out; PACKET pkt; PKT_plaintext *pt = NULL; STRING2KEY *s2k = NULL; void *enckey = NULL; size_t enckeylen = 0; int rc = 0; u32 filesize; cipher_filter_context_t cfx; armor_filter_context_t *afx = NULL; compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t *pfx; int do_compress = !!default_compress_algo(); + char peekbuf[32]; + int peekbuflen; if (!gnupg_rng_is_compliant (opt.compliance)) { rc = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", rc); return rc; } pfx = new_progress_context (); memset( &cfx, 0, sizeof cfx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet(&pkt); /* Prepare iobufs. */ inp = iobuf_open(filename); if (inp) iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error(_("can't open '%s': %s\n"), filename? filename: "[stdin]", strerror(errno) ); release_progress_context (pfx); return rc; } + peekbuflen = iobuf_ioctl (inp, IOBUF_IOCTL_PEEK, sizeof peekbuf, peekbuf); + if (peekbuflen < 0) + { + peekbuflen = 0; + if (DBG_FILTER) + log_debug ("peeking at input failed\n"); + } + handle_progress (pfx, inp, filename); if (opt.textmode) iobuf_push_filter( inp, text_filter, &tfx ); cfx.dek = NULL; if ( mode ) { aead_algo_t aead_algo; rc = setup_symkey (&s2k, &cfx.dek); if (rc) { iobuf_close (inp); if (gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO || gpg_err_code (rc) == GPG_ERR_DIGEST_ALGO) ; /* Error has already been printed. */ else log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc)); release_progress_context (pfx); return rc; } if (use_seskey && s2k->mode != 1 && s2k->mode != 3) { use_seskey = 0; log_info (_("can't use a SKESK packet due to the S2K mode\n")); } /* See whether we want to use AEAD. */ aead_algo = use_aead (NULL, cfx.dek->algo); if ( use_seskey ) { DEK *dek = NULL; rc = encrypt_seskey (cfx.dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) { xfree (cfx.dek); xfree (s2k); iobuf_close (inp); release_progress_context (pfx); return rc; } /* Replace key in DEK. */ xfree (cfx.dek); cfx.dek = dek; } if (aead_algo) cfx.dek->use_aead = aead_algo; else cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); if (opt.verbose) log_info(_("using cipher %s.%s\n"), openpgp_cipher_algo_name (cfx.dek->algo), cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead) /**/ : "CFB"); } if (do_compress && cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead) - && is_file_compressed(filename, &rc)) + && !opt.explicit_compress_option + && is_file_compressed (peekbuf, peekbuflen)) { if (opt.verbose) - log_info(_("'%s' already compressed\n"), filename); + log_info(_("'%s' already compressed\n"), filename? filename: "[stdin]"); do_compress = 0; } if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, 0, &out ))) { iobuf_cancel (inp); xfree (cfx.dek); xfree (s2k); release_progress_context (pfx); return rc; } if ( opt.armor ) { afx = new_armor_context (); push_armor_filter (afx, out); } if ( s2k ) { /* Fixme: This is quite similar to write_symkey_enc. */ PKT_symkey_enc *enc = xmalloc_clear (sizeof *enc + enckeylen); enc->version = cfx.dek->use_aead ? 5 : 4; enc->cipher_algo = cfx.dek->algo; enc->aead_algo = cfx.dek->use_aead; enc->s2k = *s2k; if (enckeylen) { enc->seskeylen = enckeylen; memcpy (enc->seskey, enckey, enckeylen); } pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if ((rc = build_packet( out, &pkt ))) log_error("build symkey packet failed: %s\n", gpg_strerror (rc) ); xfree (enc); xfree (enckey); enckey = NULL; } if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); /* Note that PGP 5 has problems decrypting symmetrically encrypted data if the file length is in the inner packet. It works when only partial length headers are use. In the past, we always used partial body length here, but since PGP 2, PGP 6, and PGP 7 need the file length, and nobody should be using PGP 5 nowadays anyway, this is now set to the file length. Note also that this only applies to the RFC-1991 style symmetric messages, and not the RFC-2440 style. PGP 6 and 7 work with either partial length or fixed length with the new style messages. */ if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) { off_t tmpsize; int overflow; if ( !(tmpsize = iobuf_get_filelength(inp, &overflow)) && !overflow && opt.verbose) log_info(_("WARNING: '%s' is an empty file\n"), filename ); /* We can't encode the length of very large files because OpenPGP uses only 32 bit for file sizes. So if the size of a file is larger than 2^32 minus some bytes for packet headers, we switch to partial length encoding. */ if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; } else filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { /* Note that PT has been initialized above in !no_literal mode. */ pt->timestamp = make_timestamp(); pt->mode = opt.mimemode? 'm' : opt.textmode? 't' : 'b'; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0; } else { cfx.datalen = filesize && !do_compress ? filesize : 0; pkt.pkttype = 0; pkt.pkt.generic = NULL; } /* Register the cipher filter. */ if (mode) iobuf_push_filter (out, cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &cfx ); /* Register the compress filter. */ if ( do_compress ) { if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead)) zfx.new_ctb = 1; push_compress_filter (out, &zfx, default_compress_algo()); } /* Do the work. */ if (!opt.no_literal) { if ( (rc = build_packet( out, &pkt )) ) log_error("build_packet failed: %s\n", gpg_strerror (rc) ); } else { /* User requested not to create a literal packet, so we copy the plain data. */ rc = iobuf_copy (out, inp); if (rc) log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); } /* Finish the stuff. */ iobuf_close (inp); if (rc) iobuf_cancel(out); else { iobuf_close (out); /* fixme: check returncode */ if (mode) write_status ( STATUS_END_ENCRYPTION ); } if (pt) pt->buf = NULL; free_packet (&pkt, NULL); xfree (enckey); xfree (cfx.dek); xfree (s2k); release_armor_context (afx); release_progress_context (pfx); return rc; } gpg_error_t setup_symkey (STRING2KEY **symkey_s2k, DEK **symkey_dek) { int canceled; int defcipher; int s2kdigest; defcipher = default_cipher_algo (); if (openpgp_cipher_blocklen (defcipher) < 16 && !opt.flags.allow_old_cipher_algos) { log_error (_("cipher algorithm '%s' may not be used for encryption\n"), openpgp_cipher_algo_name (defcipher)); if (!opt.quiet) log_info (_("(use option \"%s\" to override)\n"), "--allow-old-cipher-algos"); return gpg_error (GPG_ERR_CIPHER_ALGO); } if (!gnupg_cipher_is_allowed (opt.compliance, 1, defcipher, GCRY_CIPHER_MODE_CFB)) { log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (defcipher), gnupg_compliance_option_string (opt.compliance)); return gpg_error (GPG_ERR_CIPHER_ALGO); } s2kdigest = S2K_DIGEST_ALGO; if (!gnupg_digest_is_allowed (opt.compliance, 1, s2kdigest)) { log_error (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (s2kdigest), gnupg_compliance_option_string (opt.compliance)); return gpg_error (GPG_ERR_DIGEST_ALGO); } *symkey_s2k = xmalloc_clear (sizeof **symkey_s2k); (*symkey_s2k)->mode = opt.s2k_mode; (*symkey_s2k)->hash_algo = s2kdigest; *symkey_dek = passphrase_to_dek (defcipher, *symkey_s2k, 1, 0, NULL, 0, &canceled); if (!*symkey_dek || !(*symkey_dek)->keylen) { xfree(*symkey_dek); xfree(*symkey_s2k); return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE); } return 0; } static int write_symkey_enc (STRING2KEY *symkey_s2k, aead_algo_t aead_algo, DEK *symkey_dek, DEK *dek, iobuf_t out) { int rc; void *enckey; size_t enckeylen; PKT_symkey_enc *enc; PACKET pkt; rc = encrypt_seskey (symkey_dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) return rc; enc = xtrycalloc (1, sizeof (PKT_symkey_enc) + enckeylen); if (!enc) { rc = gpg_error_from_syserror (); xfree (enckey); return rc; } enc->version = aead_algo? 5 : 4; enc->cipher_algo = opt.s2k_cipher_algo; enc->aead_algo = aead_algo; enc->s2k = *symkey_s2k; enc->seskeylen = enckeylen; memcpy (enc->seskey, enckey, enckeylen); xfree (enckey); pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if ((rc=build_packet(out,&pkt))) log_error("build symkey_enc packet failed: %s\n",gpg_strerror (rc)); xfree (enc); return rc; } /* * Encrypt the file with the given userids (or ask if none is * supplied). Either FILENAME or FILEFD must be given, but not both. * The caller may provide a checked list of public keys in * PROVIDED_PKS; if not the function builds a list of keys on its own. * * Note that FILEFD is currently only used by cmd_encrypt in the * not yet finished server.c. */ int encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, strlist_t remusr, int use_symkey, pk_list_t provided_keys, int outputfd) { iobuf_t inp = NULL; iobuf_t out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; DEK *symkey_dek = NULL; STRING2KEY *symkey_s2k = NULL; int rc = 0, rc2 = 0; u32 filesize; cipher_filter_context_t cfx; armor_filter_context_t *afx = NULL; compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t *pfx; PK_LIST pk_list; int do_compress; + char peekbuf[32]; + int peekbuflen; if (filefd != -1 && filename) return gpg_error (GPG_ERR_INV_ARG); /* Both given. */ do_compress = !!opt.compress_algo; pfx = new_progress_context (); memset( &cfx, 0, sizeof cfx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet(&pkt); if (use_symkey && (rc=setup_symkey(&symkey_s2k,&symkey_dek))) { release_progress_context (pfx); return rc; } if (provided_keys) pk_list = provided_keys; else { if ((rc = build_pk_list (ctrl, remusr, &pk_list))) { release_progress_context (pfx); return rc; } } /* Prepare iobufs. */ #ifdef HAVE_W32_SYSTEM if (filefd == -1) inp = iobuf_open (filename); else { inp = NULL; gpg_err_set_errno (ENOSYS); } #else if (filefd == -1) inp = iobuf_open (filename); else inp = iobuf_fdopen_nc (filefd, "rb"); #endif if (inp) iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { char xname[64]; rc = gpg_error_from_syserror (); if (filefd != -1) snprintf (xname, sizeof xname, "[fd %d]", filefd); else if (!filename) strcpy (xname, "[stdin]"); else *xname = 0; log_error (_("can't open '%s': %s\n"), *xname? xname : filename, gpg_strerror (rc) ); goto leave; } if (opt.verbose) log_info (_("reading from '%s'\n"), iobuf_get_fname_nonnull (inp)); + peekbuflen = iobuf_ioctl (inp, IOBUF_IOCTL_PEEK, sizeof peekbuf, peekbuf); + if (peekbuflen < 0) + { + peekbuflen = 0; + if (DBG_FILTER) + log_debug ("peeking at input failed\n"); + } + handle_progress (pfx, inp, filename); if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); rc = open_outfile (outputfd, filename, opt.armor? 1:0, 0, &out); if (rc) goto leave; if (opt.armor) { afx = new_armor_context (); push_armor_filter (afx, out); } /* Create a session key. */ cfx.dek = create_dek_with_warnings (pk_list); rc = check_encryption_compliance (cfx.dek, pk_list); if (rc) goto leave; cfx.dek->use_aead = use_aead (pk_list, cfx.dek->algo); if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo); /* Only do the is-file-already-compressed check if we are using a * MDC or AEAD. This forces compressed files to be re-compressed if * we do not have a MDC to give some protection against chosen * ciphertext attacks. */ if (do_compress && (cfx.dek->use_mdc || cfx.dek->use_aead) - && is_file_compressed (filename, &rc2)) + && !opt.explicit_compress_option + && is_file_compressed (peekbuf, peekbuflen)) { if (opt.verbose) - log_info(_("'%s' already compressed\n"), filename); + log_info(_("'%s' already compressed\n"), filename? filename: "[stdin]"); do_compress = 0; } if (rc2) { rc = rc2; goto leave; } make_session_key (cfx.dek); if (DBG_CRYPTO) log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: "); rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out); if (rc) goto leave; /* We put the passphrase (if any) after any public keys as this * seems to be the most useful on the recipient side - there is no * point in prompting a user for a passphrase if they have the * secret key needed to decrypt. */ if (use_symkey && (rc = write_symkey_enc (symkey_s2k, cfx.dek->use_aead, symkey_dek, cfx.dek, out))) goto leave; if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); /* Get the size of the file if possible, i.e., if it is a real file. */ if (filename && *filename && !iobuf_is_pipe_filename (filename) && !opt.textmode ) { off_t tmpsize; int overflow; if ( !(tmpsize = iobuf_get_filelength(inp, &overflow)) && !overflow && opt.verbose) log_info(_("WARNING: '%s' is an empty file\n"), filename ); /* We can't encode the length of very large files because OpenPGP uses only 32 bit for file sizes. So if the size of a file is larger than 2^32 minus some bytes for packet headers, we switch to partial length encoding. */ if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; } else filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { pt->timestamp = make_timestamp(); pt->mode = opt.mimemode? 'm' : opt.textmode ? 't' : 'b'; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0; } else cfx.datalen = filesize && !do_compress ? filesize : 0; /* Register the cipher filter. */ iobuf_push_filter (out, cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &cfx); /* Register the compress filter. */ if (do_compress) { int compr_algo = opt.compress_algo; if (compr_algo == -1) { compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL); if (compr_algo == -1) compr_algo = DEFAULT_COMPRESS_ALGO; /* Theoretically impossible to get here since uncompressed is implicit. */ } else if (!opt.expert && select_algo_from_prefs(pk_list, PREFTYPE_ZIP, compr_algo, NULL) != compr_algo) { log_info (_("WARNING: forcing compression algorithm %s (%d)" " violates recipient preferences\n"), compress_algo_to_string(compr_algo), compr_algo); } /* Algo 0 means no compression. */ if (compr_algo) { if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead)) zfx.new_ctb = 1; push_compress_filter (out,&zfx,compr_algo); } } /* Do the work. */ if (!opt.no_literal) { if ((rc = build_packet( out, &pkt ))) log_error ("build_packet failed: %s\n", gpg_strerror (rc)); } else { /* User requested not to create a literal packet, so we copy the plain data. */ byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1) { rc = iobuf_write (out, copy_buffer, bytes_copied); if (rc) { log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); break; } } wipememory (copy_buffer, 4096); /* Burn the buffer. */ } /* Finish the stuff. */ leave: iobuf_close (inp); if (rc) iobuf_cancel (out); else { iobuf_close (out); /* fixme: check returncode */ write_status (STATUS_END_ENCRYPTION); } if (pt) pt->buf = NULL; free_packet (&pkt, NULL); xfree (cfx.dek); xfree (symkey_dek); xfree (symkey_s2k); if (!provided_keys) release_pk_list (pk_list); release_armor_context (afx); release_progress_context (pfx); return rc; } /* * Filter to do a complete public key encryption. */ int encrypt_filter (void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; encrypt_filter_context_t *efx = opaque; int rc = 0; if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */ { BUG(); /* not used */ } else if ( control == IOBUFCTRL_FLUSH ) /* encrypt */ { if ( !efx->header_okay ) { efx->header_okay = 1; efx->cfx.dek = create_dek_with_warnings (efx->pk_list); rc = check_encryption_compliance (efx->cfx.dek, efx->pk_list); if (rc) return rc; efx->cfx.dek->use_aead = use_aead (efx->pk_list, efx->cfx.dek->algo); if (!efx->cfx.dek->use_aead) efx->cfx.dek->use_mdc = !!use_mdc (efx->pk_list,efx->cfx.dek->algo); make_session_key ( efx->cfx.dek ); if (DBG_CRYPTO) log_printhex (efx->cfx.dek->key, efx->cfx.dek->keylen, "DEK is: "); rc = write_pubkey_enc_from_list (efx->ctrl, efx->pk_list, efx->cfx.dek, a); if (rc) return rc; if(efx->symkey_s2k && efx->symkey_dek) { rc = write_symkey_enc (efx->symkey_s2k, efx->cfx.dek->use_aead, efx->symkey_dek, efx->cfx.dek, a); if (rc) return rc; } iobuf_push_filter (a, efx->cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &efx->cfx); } rc = iobuf_write (a, buf, size); } else if (control == IOBUFCTRL_FREE) { xfree (efx->symkey_dek); xfree (efx->symkey_s2k); } else if ( control == IOBUFCTRL_DESC ) { mem2str (buf, "encrypt_filter", *ret_len); } return rc; } /* * Write a pubkey-enc packet for the public key PK to OUT. */ int write_pubkey_enc (ctrl_t ctrl, PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out) { PACKET pkt; PKT_pubkey_enc *enc; int rc; gcry_mpi_t frame; print_pubkey_algo_note ( pk->pubkey_algo ); enc = xmalloc_clear ( sizeof *enc ); enc->pubkey_algo = pk->pubkey_algo; keyid_from_pk( pk, enc->keyid ); enc->throw_keyid = throw_keyid; /* Okay, what's going on: We have the session key somewhere in * the structure DEK and want to encode this session key in an * integer value of n bits. pubkey_nbits gives us the number of * bits we have to use. We then encode the session key in some * way and we get it back in the big intger value FRAME. Then * we use FRAME, the public key PK->PKEY and the algorithm * number PK->PUBKEY_ALGO and pass it to pubkey_encrypt which * returns the encrypted value in the array ENC->DATA. This * array has a size which depends on the used algorithm (e.g. 2 * for Elgamal). We don't need frame anymore because we have * everything now in enc->data which is the passed to * build_packet(). */ frame = encode_session_key (pk->pubkey_algo, dek, pubkey_nbits (pk->pubkey_algo, pk->pkey)); rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk, pk->pkey); gcry_mpi_release (frame); if (rc) log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) ); else { if ( opt.verbose ) { char *ustr = get_user_id_string_native (ctrl, enc->keyid); log_info (_("%s/%s.%s encrypted for: \"%s\"\n"), openpgp_pk_algo_name (enc->pubkey_algo), openpgp_cipher_algo_name (dek->algo), dek->use_aead? openpgp_aead_algo_name (dek->use_aead) /**/ : "CFB", ustr ); xfree (ustr); } /* And write it. */ init_packet (&pkt); pkt.pkttype = PKT_PUBKEY_ENC; pkt.pkt.pubkey_enc = enc; rc = build_packet (out, &pkt); if (rc) log_error ("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc)); } free_pubkey_enc(enc); return rc; } /* * Write pubkey-enc packets from the list of PKs to OUT. */ static int write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out) { if (opt.throw_keyids && (PGP7 || PGP8)) { log_info(_("option '%s' may not be used in %s mode\n"), "--throw-keyids", gnupg_compliance_option_string (opt.compliance)); compliance_failure(); } for ( ; pk_list; pk_list = pk_list->next ) { PKT_public_key *pk = pk_list->pk; int throw_keyid = (opt.throw_keyids || (pk_list->flags&1)); int rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out); if (rc) return rc; } return 0; } void encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr) { int rc = 0; if (opt.outfile) { log_error(_("--output doesn't work for this command\n")); return; } if (!nfiles) { char line[2048]; unsigned int lno = 0; while ( fgets(line, DIM(line), stdin) ) { lno++; if (!*line || line[strlen(line)-1] != '\n') { log_error("input line %u too long or missing LF\n", lno); return; } line[strlen(line)-1] = '\0'; print_file_status(STATUS_FILE_START, line, 2); rc = encrypt_crypt (ctrl, -1, line, remusr, 0, NULL, -1); if (rc) log_error ("encryption of '%s' failed: %s\n", print_fname_stdin(line), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); } } else { while (nfiles--) { print_file_status(STATUS_FILE_START, *files, 2); if ( (rc = encrypt_crypt (ctrl, -1, *files, remusr, 0, NULL, -1)) ) log_error("encryption of '%s' failed: %s\n", print_fname_stdin(*files), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); files++; } } } diff --git a/g10/gpg.c b/g10/gpg.c index 68c0454ee..de40d3828 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1,5759 +1,5760 @@ /* gpg.c - The GnuPG OpenPGP tool * Copyright (C) 1998-2020 Free Software Foundation, Inc. * Copyright (C) 1997-2019 Werner Koch * Copyright (C) 2015-2022 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include #include #include #include #include #ifdef HAVE_STAT #include /* for stat() */ #endif #include #ifdef HAVE_W32_SYSTEM # ifdef HAVE_WINSOCK2_H # include # endif # include #endif #include #define INCLUDED_BY_MAIN_MODULE 1 #include "gpg.h" #include #include "../common/iobuf.h" #include "../common/util.h" #include "packet.h" #include "../common/membuf.h" #include "main.h" #include "options.h" #include "keydb.h" #include "trustdb.h" #include "filter.h" #include "../common/ttyio.h" #include "../common/i18n.h" #include "../common/sysutils.h" #include "../common/status.h" #include "keyserver-internal.h" #include "exec.h" #include "../common/gc-opt-flags.h" #include "../common/asshelp.h" #include "call-dirmngr.h" #include "tofu.h" #include "objcache.h" #include "../common/init.h" #include "../common/mbox-util.h" #include "../common/zb32.h" #include "../common/shareddefs.h" #include "../common/compliance.h" #include "../common/comopt.h" #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) #define MY_O_BINARY O_BINARY #ifndef S_IRGRP # define S_IRGRP 0 # define S_IWGRP 0 #endif #else #define MY_O_BINARY 0 #endif enum cmd_and_opt_values { aNull = 0, oArmor = 'a', aDetachedSign = 'b', aSym = 'c', aDecrypt = 'd', aEncr = 'e', oRecipientFile = 'f', oHiddenRecipientFile = 'F', oInteractive = 'i', aListKeys = 'k', oDryRun = 'n', oOutput = 'o', oQuiet = 'q', oRecipient = 'r', oHiddenRecipient = 'R', aSign = 's', oTextmodeShort= 't', oLocalUser = 'u', oVerbose = 'v', oCompress = 'z', oSetNotation = 'N', aListSecretKeys = 'K', oBatch = 500, oMaxOutput, oInputSizeHint, oChunkSize, oSigNotation, oCertNotation, oShowNotation, oNoShowNotation, oKnownNotation, aEncrFiles, aEncrSym, aDecryptFiles, aClearsign, aStore, aQuickKeygen, aFullKeygen, aKeygen, aSignEncr, aSignEncrSym, aSignSym, aSignKey, aLSignKey, aQuickSignKey, aQuickLSignKey, aQuickRevSig, aQuickAddUid, aQuickAddKey, aQuickRevUid, aQuickSetExpire, aQuickSetPrimaryUid, aQuickUpdatePref, aListConfig, aListGcryptConfig, aGPGConfList, aGPGConfTest, aListPackets, aEditKey, aDeleteKeys, aDeleteSecretKeys, aDeleteSecretAndPublicKeys, aImport, aFastImport, aVerify, aVerifyFiles, aListSigs, aSendKeys, aRecvKeys, aLocateKeys, aLocateExtKeys, aSearchKeys, aRefreshKeys, aFetchKeys, aShowKeys, aExport, aExportSecret, aExportSecretSub, aExportSshKey, aExportSecretSshKey, aCheckKeys, aGenRevoke, aDesigRevoke, aPrimegen, aPrintMD, aPrintMDs, aCheckTrustDB, aUpdateTrustDB, aFixTrustDB, aListTrustDB, aListTrustPath, aExportOwnerTrust, aImportOwnerTrust, aDeArmor, aEnArmor, aGenRandom, aRebuildKeydbCaches, aCardStatus, aCardEdit, aChangePIN, aPasswd, aServer, aTOFUPolicy, oMimemode, oTextmode, oNoTextmode, oExpert, oNoExpert, oDefSigExpire, oAskSigExpire, oNoAskSigExpire, oDefCertExpire, oAskCertExpire, oNoAskCertExpire, oDefCertLevel, oMinCertLevel, oAskCertLevel, oNoAskCertLevel, oFingerprint, oWithFingerprint, oWithSubkeyFingerprint, oWithICAOSpelling, oWithKeygrip, oWithKeyScreening, oWithSecret, oWithWKDHash, oWithColons, oWithKeyData, oWithKeyOrigin, oWithTofuInfo, oWithSigList, oWithSigCheck, oAnswerYes, oAnswerNo, oKeyring, oPrimaryKeyring, oSecretKeyring, oShowKeyring, oDefaultKey, oDefRecipient, oDefRecipientSelf, oNoDefRecipient, oTrySecretKey, oOptions, oDebug, oDebugLevel, oDebugAll, oDebugIOLBF, oDebugSetIobufSize, oDebugAllowLargeChunks, oStatusFD, oStatusFile, oAttributeFD, oAttributeFile, oEmitVersion, oNoEmitVersion, oCompletesNeeded, oMarginalsNeeded, oMaxCertDepth, oLoadExtension, oCompliance, oGnuPG, oRFC2440, oRFC4880, oOpenPGP, oPGP7, oPGP8, oDE_VS, oMinRSALength, oRFC2440Text, oNoRFC2440Text, oCipherAlgo, oDigestAlgo, oCertDigestAlgo, oCompressAlgo, oCompressLevel, oBZ2CompressLevel, oBZ2DecompressLowmem, oPassphrase, oPassphraseFD, oPassphraseFile, oPassphraseRepeat, oPinentryMode, oCommandFD, oCommandFile, oQuickRandom, oNoVerbose, oTrustDBName, oNoSecmemWarn, oRequireSecmem, oNoRequireSecmem, oNoPermissionWarn, oNoArmor, oNoDefKeyring, oNoKeyring, oNoGreeting, oNoTTY, oNoOptions, oNoBatch, oHomedir, oSkipVerify, oSkipHiddenRecipients, oNoSkipHiddenRecipients, oAlwaysTrust, oTrustModel, oForceOwnertrust, oNoAutoTrustNewKey, oSetFilename, oForYourEyesOnly, oNoForYourEyesOnly, oSetPolicyURL, oSigPolicyURL, oCertPolicyURL, oShowPolicyURL, oNoShowPolicyURL, oSigKeyserverURL, oUseEmbeddedFilename, oNoUseEmbeddedFilename, oComment, oDefaultComment, oNoComments, oThrowKeyids, oNoThrowKeyids, oShowPhotos, oNoShowPhotos, oPhotoViewer, oForceAEAD, oS2KMode, oS2KDigest, oS2KCipher, oS2KCount, oDisplayCharset, oNotDashEscaped, oEscapeFrom, oNoEscapeFrom, oLockOnce, oLockMultiple, oLockNever, oKeyServer, oKeyServerOptions, oImportOptions, oImportFilter, oExportOptions, oExportFilter, oListOptions, oListFilter, oVerifyOptions, oTempDir, oExecPath, oEncryptTo, oHiddenEncryptTo, oNoEncryptTo, oEncryptToDefaultKey, oLoggerFD, oLoggerFile, oUtf8Strings, oNoUtf8Strings, oDisableCipherAlgo, oDisablePubkeyAlgo, oAllowNonSelfsignedUID, oNoAllowNonSelfsignedUID, oAllowFreeformUID, oNoAllowFreeformUID, oAllowSecretKeyImport, oAllowOldCipherAlgos, oEnableSpecialFilenames, oNoLiteral, oSetFilesize, oHonorHttpProxy, oFastListMode, oListOnly, oIgnoreTimeConflict, oIgnoreValidFrom, oIgnoreCrcError, oIgnoreMDCError, oShowSessionKey, oOverrideSessionKey, oOverrideSessionKeyFD, oOverrideComplianceCheck, oNoRandomSeedFile, oAutoKeyRetrieve, oNoAutoKeyRetrieve, oAutoKeyImport, oNoAutoKeyImport, oUseAgent, oNoUseAgent, oGpgAgentInfo, oUseKeyboxd, oMergeOnly, oTryAllSecrets, oTrustedKey, oNoExpensiveTrustChecks, oFixedListMode, oLegacyListMode, oNoSigCache, oAutoCheckTrustDB, oNoAutoCheckTrustDB, oPreservePermissions, oDefaultPreferenceList, oDefaultKeyserverURL, oPersonalCipherPreferences, oPersonalDigestPreferences, oPersonalCompressPreferences, oAgentProgram, oKeyboxdProgram, oDirmngrProgram, oDisableDirmngr, oDisplay, oTTYname, oTTYtype, oLCctype, oLCmessages, oXauthority, oGroup, oUnGroup, oNoGroups, oStrict, oNoStrict, oMangleDosFilenames, oNoMangleDosFilenames, oEnableProgressFilter, oMultifile, oKeyidFormat, oExitOnStatusWriteError, oLimitCardInsertTries, oReaderPort, octapiDriver, opcscDriver, oDisableCCID, oRequireCrossCert, oNoRequireCrossCert, oAutoKeyLocate, oNoAutoKeyLocate, oEnableLargeRSA, oDisableLargeRSA, oEnableDSA2, oDisableDSA2, oAllowWeakDigestAlgos, oAllowWeakKeySignatures, oFakedSystemTime, oNoAutostart, oPrintDANERecords, oTOFUDefaultPolicy, oTOFUDBFormat, oDefaultNewKeyAlgo, oWeakDigest, oUnwrap, oOnlySignTextIDs, oDisableSignerUID, oSender, oKeyOrigin, oRequestOrigin, oNoSymkeyCache, oUseOnlyOpenPGPCard, oFullTimestrings, oIncludeKeyBlock, oNoIncludeKeyBlock, oChUid, oForceSignKey, oForbidGenKey, oRequireCompliance, oCompatibilityFlags, oNoop }; static gpgrt_opt_t opts[] = { ARGPARSE_group (300, N_("@Commands:\n ")), ARGPARSE_c (aSign, "sign", N_("make a signature")), ARGPARSE_c (aClearsign, "clear-sign", N_("make a clear text signature")), ARGPARSE_c (aClearsign, "clearsign", "@"), ARGPARSE_c (aDetachedSign, "detach-sign", N_("make a detached signature")), ARGPARSE_c (aEncr, "encrypt", N_("encrypt data")), ARGPARSE_c (aEncrFiles, "encrypt-files", "@"), ARGPARSE_c (aSym, "symmetric", N_("encryption only with symmetric cipher")), ARGPARSE_c (aStore, "store", "@"), ARGPARSE_c (aDecrypt, "decrypt", N_("decrypt data (default)")), ARGPARSE_c (aDecryptFiles, "decrypt-files", "@"), ARGPARSE_c (aVerify, "verify" , N_("verify a signature")), ARGPARSE_c (aVerifyFiles, "verify-files" , "@" ), ARGPARSE_c (aListKeys, "list-keys", N_("list keys")), ARGPARSE_c (aListKeys, "list-public-keys", "@" ), ARGPARSE_c (aListSigs, "list-signatures", N_("list keys and signatures")), ARGPARSE_c (aListSigs, "list-sigs", "@"), ARGPARSE_c (aCheckKeys, "check-signatures", N_("list and check key signatures")), ARGPARSE_c (aCheckKeys, "check-sigs", "@"), ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")), ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")), ARGPARSE_c (aKeygen, "generate-key", N_("generate a new key pair")), ARGPARSE_c (aKeygen, "gen-key", "@"), ARGPARSE_c (aQuickKeygen, "quick-generate-key" , N_("quickly generate a new key pair")), ARGPARSE_c (aQuickKeygen, "quick-gen-key", "@"), ARGPARSE_c (aQuickAddUid, "quick-add-uid", N_("quickly add a new user-id")), ARGPARSE_c (aQuickAddUid, "quick-adduid", "@"), ARGPARSE_c (aQuickAddKey, "quick-add-key", "@"), ARGPARSE_c (aQuickAddKey, "quick-addkey", "@"), ARGPARSE_c (aQuickRevUid, "quick-revoke-uid", N_("quickly revoke a user-id")), ARGPARSE_c (aQuickRevUid, "quick-revuid", "@"), ARGPARSE_c (aQuickSetExpire, "quick-set-expire", N_("quickly set a new expiration date")), ARGPARSE_c (aQuickSetPrimaryUid, "quick-set-primary-uid", "@"), ARGPARSE_c (aQuickUpdatePref, "quick-update-pref", "@"), ARGPARSE_c (aFullKeygen, "full-generate-key" , N_("full featured key pair generation")), ARGPARSE_c (aFullKeygen, "full-gen-key", "@"), ARGPARSE_c (aGenRevoke, "generate-revocation", N_("generate a revocation certificate")), ARGPARSE_c (aGenRevoke, "gen-revoke", "@"), ARGPARSE_c (aDeleteKeys,"delete-keys", N_("remove keys from the public keyring")), ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys", N_("remove keys from the secret keyring")), ARGPARSE_c (aQuickSignKey, "quick-sign-key" , N_("quickly sign a key")), ARGPARSE_c (aQuickLSignKey, "quick-lsign-key", N_("quickly sign a key locally")), ARGPARSE_c (aQuickRevSig, "quick-revoke-sig" , N_("quickly revoke a key signature")), ARGPARSE_c (aSignKey, "sign-key" ,N_("sign a key")), ARGPARSE_c (aLSignKey, "lsign-key" ,N_("sign a key locally")), ARGPARSE_c (aEditKey, "edit-key" ,N_("sign or edit a key")), ARGPARSE_c (aEditKey, "key-edit" ,"@"), ARGPARSE_c (aPasswd, "change-passphrase", N_("change a passphrase")), ARGPARSE_c (aPasswd, "passwd", "@"), ARGPARSE_c (aDesigRevoke, "generate-designated-revocation", "@"), ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ), ARGPARSE_c (aExport, "export" , N_("export keys") ), ARGPARSE_c (aSendKeys, "send-keys" , N_("export keys to a keyserver") ), ARGPARSE_c (aRecvKeys, "receive-keys" , N_("import keys from a keyserver") ), ARGPARSE_c (aRecvKeys, "recv-keys" , "@"), ARGPARSE_c (aSearchKeys, "search-keys" , N_("search for keys on a keyserver") ), ARGPARSE_c (aRefreshKeys, "refresh-keys", N_("update all keys from a keyserver")), ARGPARSE_c (aLocateKeys, "locate-keys", "@"), ARGPARSE_c (aLocateExtKeys, "locate-external-keys", "@"), ARGPARSE_c (aFetchKeys, "fetch-keys" , "@" ), ARGPARSE_c (aShowKeys, "show-keys" , "@" ), ARGPARSE_c (aExportSecret, "export-secret-keys" , "@" ), ARGPARSE_c (aExportSecretSub, "export-secret-subkeys" , "@" ), ARGPARSE_c (aExportSshKey, "export-ssh-key", "@" ), ARGPARSE_c (aExportSecretSshKey, "export-secret-ssh-key", "@" ), ARGPARSE_c (aImport, "import", N_("import/merge keys")), ARGPARSE_c (aFastImport, "fast-import", "@"), #ifdef ENABLE_CARD_SUPPORT ARGPARSE_c (aCardStatus, "card-status", N_("print the card status")), ARGPARSE_c (aCardEdit, "edit-card", N_("change data on a card")), ARGPARSE_c (aCardEdit, "card-edit", "@"), ARGPARSE_c (aChangePIN, "change-pin", N_("change a card's PIN")), #endif ARGPARSE_c (aListConfig, "list-config", "@"), ARGPARSE_c (aListGcryptConfig, "list-gcrypt-config", "@"), ARGPARSE_c (aGPGConfList, "gpgconf-list", "@" ), ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@" ), ARGPARSE_c (aListPackets, "list-packets","@"), #ifndef NO_TRUST_MODELS ARGPARSE_c (aExportOwnerTrust, "export-ownertrust", "@"), ARGPARSE_c (aImportOwnerTrust, "import-ownertrust", "@"), ARGPARSE_c (aUpdateTrustDB,"update-trustdb", N_("update the trust database")), ARGPARSE_c (aCheckTrustDB, "check-trustdb", "@"), ARGPARSE_c (aFixTrustDB, "fix-trustdb", "@"), ARGPARSE_c (aListTrustDB, "list-trustdb", "@"), #endif ARGPARSE_c (aDeArmor, "dearmor", "@"), ARGPARSE_c (aDeArmor, "dearmour", "@"), ARGPARSE_c (aEnArmor, "enarmor", "@"), ARGPARSE_c (aEnArmor, "enarmour", "@"), ARGPARSE_c (aPrintMD, "print-md", N_("print message digests")), ARGPARSE_c (aPrintMDs, "print-mds", "@"), /* old */ ARGPARSE_c (aPrimegen, "gen-prime", "@" ), ARGPARSE_c (aGenRandom,"gen-random", "@" ), ARGPARSE_c (aServer, "server", N_("run in server mode")), ARGPARSE_c (aTOFUPolicy, "tofu-policy", N_("|VALUE|set the TOFU policy for a key")), /* Not yet used: ARGPARSE_c (aListTrustPath, "list-trust-path", "@"), */ ARGPARSE_c (aDeleteSecretAndPublicKeys, "delete-secret-and-public-keys", "@"), ARGPARSE_c (aRebuildKeydbCaches, "rebuild-keydb-caches", "@"), ARGPARSE_c (aListKeys, "list-key", "@"), /* alias */ ARGPARSE_c (aListSigs, "list-sig", "@"), /* alias */ ARGPARSE_c (aCheckKeys, "check-sig", "@"), /* alias */ ARGPARSE_c (aShowKeys, "show-key", "@"), /* alias */ ARGPARSE_header ("Monitor", N_("Options controlling the diagnostic output")), ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")), ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"), ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")), ARGPARSE_s_n (oNoTTY, "no-tty", "@"), ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"), ARGPARSE_s_s (oDebug, "debug", "@"), ARGPARSE_s_s (oDebugLevel, "debug-level", "@"), ARGPARSE_s_n (oDebugAll, "debug-all", "@"), ARGPARSE_s_n (oDebugIOLBF, "debug-iolbf", "@"), ARGPARSE_s_u (oDebugSetIobufSize, "debug-set-iobuf-size", "@"), ARGPARSE_s_u (oDebugAllowLargeChunks, "debug-allow-large-chunks", "@"), ARGPARSE_s_s (oDisplayCharset, "display-charset", "@"), ARGPARSE_s_s (oDisplayCharset, "charset", "@"), ARGPARSE_conffile (oOptions, "options", N_("|FILE|read options from FILE")), ARGPARSE_noconffile (oNoOptions, "no-options", "@"), ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"), ARGPARSE_s_s (oLoggerFile, "log-file", N_("|FILE|write server mode logs to FILE")), ARGPARSE_s_s (oLoggerFile, "logger-file", "@"), /* 1.4 compatibility. */ ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"), ARGPARSE_header ("Configuration", N_("Options controlling the configuration")), ARGPARSE_s_s (oHomedir, "homedir", "@"), ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"), ARGPARSE_s_s (oDefaultKey, "default-key", N_("|NAME|use NAME as default secret key")), ARGPARSE_s_s (oEncryptTo, "encrypt-to", N_("|NAME|encrypt to user ID NAME as well")), ARGPARSE_s_n (oNoEncryptTo, "no-encrypt-to", "@"), ARGPARSE_s_s (oHiddenEncryptTo, "hidden-encrypt-to", "@"), ARGPARSE_s_n (oEncryptToDefaultKey, "encrypt-to-default-key", "@"), ARGPARSE_s_s (oDefRecipient, "default-recipient", "@"), ARGPARSE_s_n (oDefRecipientSelf, "default-recipient-self", "@"), ARGPARSE_s_n (oNoDefRecipient, "no-default-recipient", "@"), ARGPARSE_s_s (oGroup, "group", N_("|SPEC|set up email aliases")), ARGPARSE_s_s (oUnGroup, "ungroup", "@"), ARGPARSE_s_n (oNoGroups, "no-groups", "@"), ARGPARSE_s_s (oCompliance, "compliance", "@"), ARGPARSE_s_n (oGnuPG, "gnupg", "@"), ARGPARSE_s_n (oGnuPG, "no-pgp2", "@"), ARGPARSE_s_n (oGnuPG, "no-pgp6", "@"), ARGPARSE_s_n (oGnuPG, "no-pgp7", "@"), ARGPARSE_s_n (oGnuPG, "no-pgp8", "@"), ARGPARSE_s_n (oRFC2440, "rfc2440", "@"), ARGPARSE_s_n (oRFC4880, "rfc4880", "@"), ARGPARSE_s_n (oOpenPGP, "openpgp", N_("use strict OpenPGP behavior")), ARGPARSE_s_n (oPGP7, "pgp6", "@"), ARGPARSE_s_n (oPGP7, "pgp7", "@"), ARGPARSE_s_n (oPGP8, "pgp8", "@"), ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"), ARGPARSE_p_u (oMinRSALength, "min-rsa-length", "@"), #ifndef NO_TRUST_MODELS ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"), #endif ARGPARSE_s_s (oTrustModel, "trust-model", "@"), ARGPARSE_s_s (oPhotoViewer, "photo-viewer", "@"), ARGPARSE_s_s (oKnownNotation, "known-notation", "@"), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), ARGPARSE_s_s (oKeyboxdProgram, "keyboxd-program", "@"), ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"), ARGPARSE_s_n (oExitOnStatusWriteError, "exit-on-status-write-error", "@"), ARGPARSE_s_i (oLimitCardInsertTries, "limit-card-insert-tries", "@"), ARGPARSE_s_n (oEnableProgressFilter, "enable-progress-filter", "@"), ARGPARSE_s_s (oTempDir, "temp-directory", "@"), ARGPARSE_s_s (oExecPath, "exec-path", "@"), ARGPARSE_s_n (oExpert, "expert", "@"), ARGPARSE_s_n (oNoExpert, "no-expert", "@"), ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"), ARGPARSE_s_n (oRequireSecmem, "require-secmem", "@"), ARGPARSE_s_n (oNoRequireSecmem, "no-require-secmem", "@"), ARGPARSE_s_n (oNoPermissionWarn, "no-permission-warning", "@"), ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")), ARGPARSE_s_n (oInteractive, "interactive", N_("prompt before overwriting")), ARGPARSE_s_s (oDefSigExpire, "default-sig-expire", "@"), ARGPARSE_s_n (oAskSigExpire, "ask-sig-expire", "@"), ARGPARSE_s_n (oNoAskSigExpire, "no-ask-sig-expire", "@"), ARGPARSE_s_s (oDefCertExpire, "default-cert-expire", "@"), ARGPARSE_s_n (oAskCertExpire, "ask-cert-expire", "@"), ARGPARSE_s_n (oNoAskCertExpire, "no-ask-cert-expire", "@"), ARGPARSE_s_i (oDefCertLevel, "default-cert-level", "@"), ARGPARSE_s_i (oMinCertLevel, "min-cert-level", "@"), ARGPARSE_s_n (oAskCertLevel, "ask-cert-level", "@"), ARGPARSE_s_n (oNoAskCertLevel, "no-ask-cert-level", "@"), ARGPARSE_s_n (oOnlySignTextIDs, "only-sign-text-ids", "@"), ARGPARSE_s_n (oEnableLargeRSA, "enable-large-rsa", "@"), ARGPARSE_s_n (oDisableLargeRSA, "disable-large-rsa", "@"), ARGPARSE_s_n (oEnableDSA2, "enable-dsa2", "@"), ARGPARSE_s_n (oDisableDSA2, "disable-dsa2", "@"), ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-preferences","@"), ARGPARSE_s_s (oPersonalDigestPreferences, "personal-digest-preferences","@"), ARGPARSE_s_s (oPersonalCompressPreferences, "personal-compress-preferences", "@"), ARGPARSE_s_s (oDefaultPreferenceList, "default-preference-list", "@"), ARGPARSE_s_s (oDefaultKeyserverURL, "default-keyserver-url", "@"), ARGPARSE_s_n (oNoExpensiveTrustChecks, "no-expensive-trust-checks", "@"), ARGPARSE_s_n (oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", "@"), ARGPARSE_s_n (oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", "@"), ARGPARSE_s_n (oAllowFreeformUID, "allow-freeform-uid", "@"), ARGPARSE_s_n (oNoAllowFreeformUID, "no-allow-freeform-uid", "@"), ARGPARSE_s_n (oPreservePermissions, "preserve-permissions", "@"), ARGPARSE_s_i (oDefCertLevel, "default-cert-check-level", "@"), /* old */ ARGPARSE_s_s (oTOFUDefaultPolicy, "tofu-default-policy", "@"), ARGPARSE_s_n (oLockOnce, "lock-once", "@"), ARGPARSE_s_n (oLockMultiple, "lock-multiple", "@"), ARGPARSE_s_n (oLockNever, "lock-never", "@"), ARGPARSE_s_s (oCompressAlgo,"compress-algo", "@"), ARGPARSE_s_s (oCompressAlgo, "compression-algo", "@"), /* Alias */ ARGPARSE_s_n (oBZ2DecompressLowmem, "bzip2-decompress-lowmem", "@"), ARGPARSE_s_i (oCompletesNeeded, "completes-needed", "@"), ARGPARSE_s_i (oMarginalsNeeded, "marginals-needed", "@"), ARGPARSE_s_i (oMaxCertDepth, "max-cert-depth", "@" ), #ifndef NO_TRUST_MODELS ARGPARSE_s_s (oTrustDBName, "trustdb-name", "@"), ARGPARSE_s_n (oAutoCheckTrustDB, "auto-check-trustdb", "@"), ARGPARSE_s_n (oNoAutoCheckTrustDB, "no-auto-check-trustdb", "@"), ARGPARSE_s_s (oForceOwnertrust, "force-ownertrust", "@"), ARGPARSE_s_n (oNoAutoTrustNewKey, "no-auto-trust-new-key", "@"), #endif ARGPARSE_header ("Input", N_("Options controlling the input")), ARGPARSE_s_n (oMultifile, "multifile", "@"), ARGPARSE_s_s (oInputSizeHint, "input-size-hint", "@"), ARGPARSE_s_n (oUtf8Strings, "utf8-strings", "@"), ARGPARSE_s_n (oNoUtf8Strings, "no-utf8-strings", "@"), ARGPARSE_p_u (oSetFilesize, "set-filesize", "@"), ARGPARSE_s_n (oNoLiteral, "no-literal", "@"), ARGPARSE_s_s (oSetNotation, "set-notation", "@"), ARGPARSE_s_s (oSigNotation, "sig-notation", "@"), ARGPARSE_s_s (oCertNotation, "cert-notation", "@"), ARGPARSE_s_s (oSetPolicyURL, "set-policy-url", "@"), ARGPARSE_s_s (oSigPolicyURL, "sig-policy-url", "@"), ARGPARSE_s_s (oCertPolicyURL, "cert-policy-url", "@"), ARGPARSE_s_s (oSigKeyserverURL, "sig-keyserver-url", "@"), ARGPARSE_header ("Output", N_("Options controlling the output")), ARGPARSE_s_n (oArmor, "armor", N_("create ascii armored output")), ARGPARSE_s_n (oArmor, "armour", "@"), ARGPARSE_s_n (oNoArmor, "no-armor", "@"), ARGPARSE_s_n (oNoArmor, "no-armour", "@"), ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")), ARGPARSE_p_u (oMaxOutput, "max-output", "@"), ARGPARSE_s_s (oComment, "comment", "@"), ARGPARSE_s_n (oDefaultComment, "default-comment", "@"), ARGPARSE_s_n (oNoComments, "no-comments", "@"), ARGPARSE_s_n (oEmitVersion, "emit-version", "@"), ARGPARSE_s_n (oNoEmitVersion, "no-emit-version", "@"), ARGPARSE_s_n (oNoEmitVersion, "no-version", "@"), /* alias */ ARGPARSE_s_n (oNotDashEscaped, "not-dash-escaped", "@"), ARGPARSE_s_n (oEscapeFrom, "escape-from-lines", "@"), ARGPARSE_s_n (oNoEscapeFrom, "no-escape-from-lines", "@"), ARGPARSE_s_n (oMimemode, "mimemode", "@"), ARGPARSE_s_n (oTextmodeShort, NULL, "@"), ARGPARSE_s_n (oTextmode, "textmode", N_("use canonical text mode")), ARGPARSE_s_n (oNoTextmode, "no-textmode", "@"), ARGPARSE_s_s (oSetFilename, "set-filename", "@"), ARGPARSE_s_n (oForYourEyesOnly, "for-your-eyes-only", "@"), ARGPARSE_s_n (oNoForYourEyesOnly, "no-for-your-eyes-only", "@"), ARGPARSE_s_n (oShowNotation, "show-notation", "@"), ARGPARSE_s_n (oNoShowNotation, "no-show-notation", "@"), ARGPARSE_s_n (oShowSessionKey, "show-session-key", "@"), ARGPARSE_s_n (oUseEmbeddedFilename, "use-embedded-filename", "@"), ARGPARSE_s_n (oNoUseEmbeddedFilename, "no-use-embedded-filename", "@"), ARGPARSE_s_n (oUnwrap, "unwrap", "@"), ARGPARSE_s_n (oMangleDosFilenames, "mangle-dos-filenames", "@"), ARGPARSE_s_n (oNoMangleDosFilenames, "no-mangle-dos-filenames", "@"), ARGPARSE_s_i (oChunkSize, "chunk-size", "@"), ARGPARSE_s_n (oNoSymkeyCache, "no-symkey-cache", "@"), ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"), ARGPARSE_s_n (oListOnly, "list-only", "@"), ARGPARSE_s_i (oCompress, NULL, N_("|N|set compress level to N (0 disables)")), ARGPARSE_s_i (oCompressLevel, "compress-level", "@"), ARGPARSE_s_i (oBZ2CompressLevel, "bzip2-compress-level", "@"), ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"), ARGPARSE_header ("ImportExport", N_("Options controlling key import and export")), ARGPARSE_s_s (oAutoKeyLocate, "auto-key-locate", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address")), ARGPARSE_s_n (oNoAutoKeyLocate, "no-auto-key-locate", "@"), ARGPARSE_s_n (oAutoKeyImport, "auto-key-import", N_("import missing key from a signature")), ARGPARSE_s_n (oNoAutoKeyImport, "no-auto-key-import", "@"), ARGPARSE_s_n (oAutoKeyRetrieve, "auto-key-retrieve", "@"), ARGPARSE_s_n (oNoAutoKeyRetrieve, "no-auto-key-retrieve", "@"), ARGPARSE_s_n (oIncludeKeyBlock, "include-key-block", N_("include the public key in signatures")), ARGPARSE_s_n (oNoIncludeKeyBlock, "no-include-key-block", "@"), ARGPARSE_s_n (oDisableDirmngr, "disable-dirmngr", N_("disable all access to the dirmngr")), ARGPARSE_s_s (oKeyServer, "keyserver", "@"), /* Deprecated. */ ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"), ARGPARSE_s_s (oKeyOrigin, "key-origin", "@"), ARGPARSE_s_s (oImportOptions, "import-options", "@"), ARGPARSE_s_s (oImportFilter, "import-filter", "@"), ARGPARSE_s_s (oExportOptions, "export-options", "@"), ARGPARSE_s_s (oExportFilter, "export-filter", "@"), ARGPARSE_s_n (oMergeOnly, "merge-only", "@" ), ARGPARSE_s_n (oAllowSecretKeyImport, "allow-secret-key-import", "@"), ARGPARSE_header ("Keylist", N_("Options controlling key listings")), ARGPARSE_s_s (oListOptions, "list-options", "@"), ARGPARSE_s_s (oListFilter, "list-filter", "@"), ARGPARSE_s_n (oFullTimestrings, "full-timestrings", "@"), ARGPARSE_s_n (oShowPhotos, "show-photos", "@"), ARGPARSE_s_n (oNoShowPhotos, "no-show-photos", "@"), ARGPARSE_s_n (oShowPolicyURL, "show-policy-url", "@"), ARGPARSE_s_n (oNoShowPolicyURL, "no-show-policy-url", "@"), ARGPARSE_s_n (oWithColons, "with-colons", "@"), ARGPARSE_s_n (oWithTofuInfo,"with-tofu-info", "@"), ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"), ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"), ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"), ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"), ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprint", "@"), ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"), ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"), ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"), ARGPARSE_s_n (oWithKeyScreening,"with-key-screening", "@"), ARGPARSE_s_n (oWithSecret, "with-secret", "@"), ARGPARSE_s_n (oWithWKDHash, "with-wkd-hash", "@"), ARGPARSE_s_n (oWithKeyOrigin, "with-key-origin", "@"), ARGPARSE_s_n (oFastListMode, "fast-list-mode", "@"), ARGPARSE_s_n (oFixedListMode, "fixed-list-mode", "@"), ARGPARSE_s_n (oLegacyListMode, "legacy-list-mode", "@"), ARGPARSE_s_n (oPrintDANERecords, "print-dane-records", "@"), ARGPARSE_s_s (oKeyidFormat, "keyid-format", "@"), ARGPARSE_s_n (oShowKeyring, "show-keyring", "@"), ARGPARSE_header (NULL, N_("Options to specify keys")), ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")), ARGPARSE_s_s (oHiddenRecipient, "hidden-recipient", "@"), ARGPARSE_s_s (oRecipientFile, "recipient-file", "@"), ARGPARSE_s_s (oHiddenRecipientFile, "hidden-recipient-file", "@"), ARGPARSE_s_s (oRecipient, "remote-user", "@"), /* (old option name) */ ARGPARSE_s_n (oThrowKeyids, "throw-keyids", "@"), ARGPARSE_s_n (oNoThrowKeyids, "no-throw-keyids", "@"), ARGPARSE_s_s (oLocalUser, "local-user", N_("|USER-ID|use USER-ID to sign or decrypt")), ARGPARSE_s_s (oTrustedKey, "trusted-key", "@"), ARGPARSE_s_s (oSender, "sender", "@"), ARGPARSE_s_s (oTrySecretKey, "try-secret-key", "@"), ARGPARSE_s_n (oTryAllSecrets, "try-all-secrets", "@"), ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"), ARGPARSE_s_n (oNoKeyring, "no-keyring", "@"), ARGPARSE_s_s (oKeyring, "keyring", "@"), ARGPARSE_s_s (oPrimaryKeyring, "primary-keyring", "@"), ARGPARSE_s_s (oSecretKeyring, "secret-keyring", "@"), ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"), ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"), ARGPARSE_s_s (oOverrideSessionKey, "override-session-key", "@"), ARGPARSE_s_i (oOverrideSessionKeyFD, "override-session-key-fd", "@"), ARGPARSE_header ("Security", N_("Options controlling the security")), ARGPARSE_s_i (oS2KMode, "s2k-mode", "@"), ARGPARSE_s_s (oS2KDigest, "s2k-digest-algo", "@"), ARGPARSE_s_s (oS2KCipher, "s2k-cipher-algo", "@"), ARGPARSE_s_i (oS2KCount, "s2k-count", "@"), ARGPARSE_s_n (oForceAEAD, "force-ocb", "@"), ARGPARSE_s_n (oForceAEAD, "force-aead", "@"), /*(old name)*/ ARGPARSE_s_n (oRequireCrossCert, "require-backsigs", "@"), ARGPARSE_s_n (oRequireCrossCert, "require-cross-certification", "@"), ARGPARSE_s_n (oNoRequireCrossCert, "no-require-backsigs", "@"), ARGPARSE_s_n (oNoRequireCrossCert, "no-require-cross-certification", "@"), /* Options to override new security defaults. */ ARGPARSE_s_n (oAllowWeakKeySignatures, "allow-weak-key-signatures", "@"), ARGPARSE_s_n (oAllowWeakDigestAlgos, "allow-weak-digest-algos", "@"), ARGPARSE_s_n (oAllowOldCipherAlgos, "allow-old-cipher-algos", "@"), ARGPARSE_s_s (oWeakDigest, "weak-digest","@"), ARGPARSE_s_s (oVerifyOptions, "verify-options", "@"), ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"), ARGPARSE_s_n (oNoRandomSeedFile, "no-random-seed-file", "@"), ARGPARSE_s_n (oNoSigCache, "no-sig-cache", "@"), ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"), ARGPARSE_s_n (oIgnoreValidFrom, "ignore-valid-from", "@"), ARGPARSE_s_n (oIgnoreCrcError, "ignore-crc-error", "@"), ARGPARSE_s_n (oIgnoreMDCError, "ignore-mdc-error", "@"), ARGPARSE_s_s (oDisableCipherAlgo, "disable-cipher-algo", "@"), ARGPARSE_s_s (oDisablePubkeyAlgo, "disable-pubkey-algo", "@"), ARGPARSE_s_s (oCipherAlgo, "cipher-algo", "@"), ARGPARSE_s_s (oDigestAlgo, "digest-algo", "@"), ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"), ARGPARSE_s_n (oOverrideComplianceCheck, "override-compliance-check", "@"), ARGPARSE_header (NULL, N_("Options for unattended use")), ARGPARSE_s_n (oBatch, "batch", "@"), ARGPARSE_s_n (oNoBatch, "no-batch", "@"), ARGPARSE_s_n (oAnswerYes, "yes", "@"), ARGPARSE_s_n (oAnswerNo, "no", "@"), ARGPARSE_s_i (oStatusFD, "status-fd", "@"), ARGPARSE_s_s (oStatusFile, "status-file", "@"), ARGPARSE_s_i (oAttributeFD, "attribute-fd", "@"), ARGPARSE_s_s (oAttributeFile, "attribute-file", "@"), ARGPARSE_s_i (oCommandFD, "command-fd", "@"), ARGPARSE_s_s (oCommandFile, "command-file", "@"), ARGPARSE_o_s (oPassphrase, "passphrase", "@"), ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"), ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"), ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"), ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"), ARGPARSE_s_n (oForceSignKey, "force-sign-key", "@"), ARGPARSE_header (NULL, N_("Other options")), ARGPARSE_s_s (oRequestOrigin, "request-origin", "@"), ARGPARSE_s_s (oDisplay, "display", "@"), ARGPARSE_s_s (oTTYname, "ttyname", "@"), ARGPARSE_s_s (oTTYtype, "ttytype", "@"), ARGPARSE_s_s (oLCctype, "lc-ctype", "@"), ARGPARSE_s_s (oLCmessages, "lc-messages","@"), ARGPARSE_s_s (oXauthority, "xauthority", "@"), ARGPARSE_s_s (oChUid, "chuid", "@"), ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"), ARGPARSE_s_n (oUseKeyboxd, "use-keyboxd", "@"), ARGPARSE_s_n (oForbidGenKey, "forbid-gen-key", "@"), ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"), ARGPARSE_s_s (oCompatibilityFlags, "compatibility-flags", "@"), /* Options which can be used in special circumstances. They are not * published and we hope they are never required. */ ARGPARSE_s_n (oUseOnlyOpenPGPCard, "use-only-openpgp-card", "@"), /* Esoteric compatibility options. */ ARGPARSE_s_n (oRFC2440Text, "rfc2440-text", "@"), ARGPARSE_s_n (oNoRFC2440Text, "no-rfc2440-text", "@"), ARGPARSE_header (NULL, ""), /* Stop the header group. */ /* Aliases. I constantly mistype these, and assume other people do as well. */ ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-prefs", "@"), ARGPARSE_s_s (oPersonalCompressPreferences, "personal-compress-prefs", "@"), /* These two are aliases to help users of the PGP command line product use gpg with minimal pain. Many commands are common already as they seem to have borrowed commands from us. Now I'm returning the favor. */ ARGPARSE_s_s (oLocalUser, "sign-with", "@"), ARGPARSE_s_s (oRecipient, "user", "@"), /* Dummy options with warnings. */ ARGPARSE_s_n (oUseAgent, "use-agent", "@"), ARGPARSE_s_n (oNoUseAgent, "no-use-agent", "@"), ARGPARSE_s_s (oGpgAgentInfo, "gpg-agent-info", "@"), ARGPARSE_s_s (oReaderPort, "reader-port", "@"), ARGPARSE_s_s (octapiDriver, "ctapi-driver", "@"), ARGPARSE_s_s (opcscDriver, "pcsc-driver", "@"), ARGPARSE_s_n (oDisableCCID, "disable-ccid", "@"), ARGPARSE_s_n (oHonorHttpProxy, "honor-http-proxy", "@"), ARGPARSE_s_s (oTOFUDBFormat, "tofu-db-format", "@"), /* Dummy options. */ ARGPARSE_ignore (oStrict, "strict"), ARGPARSE_ignore (oNoStrict, "no-strict"), ARGPARSE_ignore (oLoadExtension, "load-extension"), /* from 1.4. */ ARGPARSE_s_n (oNoop, "sk-comments", "@"), ARGPARSE_s_n (oNoop, "no-sk-comments", "@"), ARGPARSE_s_n (oNoop, "compress-keys", "@"), ARGPARSE_s_n (oNoop, "compress-sigs", "@"), ARGPARSE_s_n (oNoop, "force-v3-sigs", "@"), ARGPARSE_s_n (oNoop, "no-force-v3-sigs", "@"), ARGPARSE_s_n (oNoop, "force-v4-certs", "@"), ARGPARSE_s_n (oNoop, "no-force-v4-certs", "@"), ARGPARSE_s_n (oNoop, "no-mdc-warning", "@"), ARGPARSE_s_n (oNoop, "force-mdc", "@"), ARGPARSE_s_n (oNoop, "no-force-mdc", "@"), ARGPARSE_s_n (oNoop, "disable-mdc", "@"), ARGPARSE_s_n (oNoop, "no-disable-mdc", "@"), ARGPARSE_s_n (oNoop, "allow-multisig-verification", "@"), ARGPARSE_s_n (oNoop, "allow-multiple-messages", "@"), ARGPARSE_s_n (oNoop, "no-allow-multiple-messages", "@"), ARGPARSE_s_s (oNoop, "aead-algo", "@"), ARGPARSE_s_s (oNoop, "personal-aead-preferences","@"), ARGPARSE_s_n (oNoop, "rfc4880bis", "@"), ARGPARSE_group (302, N_( "@\n(See the man page for a complete listing of all commands and options)\n" )), ARGPARSE_group (303, N_("@\nExamples:\n\n" " -se -r Bob [file] sign and encrypt for user Bob\n" " --clear-sign [file] make a clear text signature\n" " --detach-sign [file] make a detached signature\n" " --list-keys [names] show keys\n" " --fingerprint [names] show fingerprints\n")), ARGPARSE_end () }; /* The list of supported debug flags. */ static struct debug_flags_s debug_flags [] = { { DBG_PACKET_VALUE , "packet" }, { DBG_MPI_VALUE , "mpi" }, { DBG_CRYPTO_VALUE , "crypto" }, { DBG_FILTER_VALUE , "filter" }, { DBG_IOBUF_VALUE , "iobuf" }, { DBG_MEMORY_VALUE , "memory" }, { DBG_CACHE_VALUE , "cache" }, { DBG_MEMSTAT_VALUE, "memstat" }, { DBG_TRUST_VALUE , "trust" }, { DBG_HASHING_VALUE, "hashing" }, { DBG_IPC_VALUE , "ipc" }, { DBG_CLOCK_VALUE , "clock" }, { DBG_LOOKUP_VALUE , "lookup" }, { DBG_EXTPROG_VALUE, "extprog" }, { 0, NULL } }; /* The list of compatibility flags. */ static struct compatibility_flags_s compatibility_flags [] = { { 0, NULL } }; #ifdef ENABLE_SELINUX_HACKS #define ALWAYS_ADD_KEYRINGS 1 #else #define ALWAYS_ADD_KEYRINGS 0 #endif /* The list of the default AKL methods. */ #define DEFAULT_AKL_LIST "local,wkd" int g10_errors_seen = 0; static int utf8_strings = #ifdef HAVE_W32_SYSTEM 1 #else 0 #endif ; static int maybe_setuid = 1; static unsigned int opt_set_iobuf_size; static unsigned int opt_set_iobuf_size_used; /* Collection of options used only in this module. */ static struct { unsigned int forbid_gen_key; } mopt; static char *build_list( const char *text, char letter, const char *(*mapf)(int), int (*chkf)(int) ); static void set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ); static void print_mds( const char *fname, int algo ); static void add_notation_data( const char *string, int which ); static void add_policy_url( const char *string, int which ); static void add_keyserver_url( const char *string, int which ); static void emergency_cleanup (void); static void read_sessionkey_from_fd (int fd); /* NPth wrapper function definitions. */ ASSUAN_SYSTEM_NPTH_IMPL; static char * make_libversion (const char *libname, const char *(*getfnc)(const char*)) { const char *s; char *result; if (maybe_setuid) { gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ maybe_setuid = 0; } s = getfnc (NULL); result = xmalloc (strlen (libname) + 1 + strlen (s) + 1); strcpy (stpcpy (stpcpy (result, libname), " "), s); return result; } static int build_list_pk_test_algo (int algo) { /* Show only one "RSA" string. If RSA_E or RSA_S is available RSA is also available. */ if (algo == PUBKEY_ALGO_RSA_E || algo == PUBKEY_ALGO_RSA_S) return GPG_ERR_DIGEST_ALGO; return openpgp_pk_test_algo (algo); } static const char * build_list_pk_algo_name (int algo) { return openpgp_pk_algo_name (algo); } static int build_list_cipher_test_algo (int algo) { return openpgp_cipher_test_algo (algo); } static const char * build_list_cipher_algo_name (int algo) { return openpgp_cipher_algo_name (algo); } static int build_list_md_test_algo (int algo) { /* By default we do not accept MD5 based signatures. To avoid confusion we do not announce support for it either. */ if (algo == DIGEST_ALGO_MD5) return GPG_ERR_DIGEST_ALGO; return openpgp_md_test_algo (algo); } static const char * build_list_md_algo_name (int algo) { return openpgp_md_algo_name (algo); } static const char * my_strusage( int level ) { static char *digests, *pubkeys, *ciphers, *zips, *ver_gcry; const char *p; switch( level ) { case 9: p = "GPL-3.0-or-later"; break; case 11: p = "@GPG@ (@GNUPG@)"; break; case 13: p = VERSION; break; case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break; case 20: if (!ver_gcry) ver_gcry = make_libversion ("libgcrypt", gcry_check_version); p = ver_gcry; break; #ifdef IS_DEVELOPMENT_VERSION case 25: p="NOTE: THIS IS A DEVELOPMENT VERSION!"; break; case 26: p="It is only intended for test purposes and should NOT be"; break; case 27: p="used in a production environment or with production keys!"; break; #endif case 1: case 40: p = _("Usage: @GPG@ [options] [files] (-h for help)"); break; case 41: p = _("Syntax: @GPG@ [options] [files]\n" "Sign, check, encrypt or decrypt\n" "Default operation depends on the input data\n"); break; case 31: p = "\nHome: "; break; #ifndef __riscos__ case 32: p = gnupg_homedir (); break; #else /* __riscos__ */ case 32: p = make_filename(gnupg_homedir (), NULL); break; #endif /* __riscos__ */ case 33: p = _("\nSupported algorithms:\n"); break; case 34: if (!pubkeys) pubkeys = build_list (_("Pubkey: "), 1, build_list_pk_algo_name, build_list_pk_test_algo ); p = pubkeys; break; case 35: if( !ciphers ) ciphers = build_list(_("Cipher: "), 'S', build_list_cipher_algo_name, build_list_cipher_test_algo ); p = ciphers; break; case 37: if( !digests ) digests = build_list(_("Hash: "), 'H', build_list_md_algo_name, build_list_md_test_algo ); p = digests; break; case 38: if( !zips ) zips = build_list(_("Compression: "),'Z', compress_algo_to_string, check_compress_algo); p = zips; break; case 95: p = "1"; /* <-- Enable globbing under Windows (see init.c) */ break; default: p = NULL; } return p; } static char * build_list (const char *text, char letter, const char * (*mapf)(int), int (*chkf)(int)) { membuf_t mb; int indent; int i, j, len; int limit; const char *s; char *string; if (maybe_setuid) gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ indent = utf8_charcount (text, -1); len = 0; init_membuf (&mb, 512); limit = (letter == 'A')? 4 : 110; for (i=0; i <= limit; i++ ) { if (!chkf (i) && (s = mapf (i))) { if (mb.len - len > 60) { put_membuf_str (&mb, ",\n"); len = mb.len; for (j=0; j < indent; j++) put_membuf_str (&mb, " "); } else if (mb.len) put_membuf_str (&mb, ", "); else put_membuf_str (&mb, text); put_membuf_str (&mb, s); if (opt.verbose && letter) { char num[20]; if (letter == 1) snprintf (num, sizeof num, " (%d)", i); else snprintf (num, sizeof num, " (%c%d)", letter, i); put_membuf_str (&mb, num); } } } if (mb.len) put_membuf_str (&mb, "\n"); put_membuf (&mb, "", 1); string = get_membuf (&mb, NULL); return xrealloc (string, strlen (string)+1); } static void wrong_args( const char *text) { es_fprintf (es_stderr, _("usage: %s [options] %s\n"), GPG_NAME, text); log_inc_errorcount (); g10_exit(2); } static char * make_username( const char *string ) { char *p; if( utf8_strings ) p = xstrdup(string); else p = native_to_utf8( string ); return p; } static void set_opt_session_env (const char *name, const char *value) { gpg_error_t err; err = session_env_setenv (opt.session_env, name, value); if (err) log_fatal ("error setting session environment: %s\n", gpg_strerror (err)); } /* Setup the debugging. With a LEVEL of NULL only the active debug flags are propagated to the subsystems. With LEVEL set, a specific set of debug flags is set; thus overriding all flags already set. */ static void set_debug (const char *level) { int numok = (level && digitp (level)); int numlvl = numok? atoi (level) : 0; if (!level) ; else if (!strcmp (level, "none") || (numok && numlvl < 1)) opt.debug = 0; else if (!strcmp (level, "basic") || (numok && numlvl <= 2)) opt.debug = DBG_MEMSTAT_VALUE; else if (!strcmp (level, "advanced") || (numok && numlvl <= 5)) opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE; else if (!strcmp (level, "expert") || (numok && numlvl <= 8)) opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE |DBG_CACHE_VALUE|DBG_LOOKUP|DBG_FILTER_VALUE|DBG_PACKET_VALUE); else if (!strcmp (level, "guru") || numok) { opt.debug = ~0; /* Unless the "guru" string has been used we don't want to allow hashing debugging. The rationale is that people tend to select the highest debug value and would then clutter their disk with debug files which may reveal confidential data. */ if (numok) opt.debug &= ~(DBG_HASHING_VALUE); } else { log_error (_("invalid debug-level '%s' given\n"), level); g10_exit (2); } if ((opt.debug & DBG_MEMORY_VALUE)) memory_debug_mode = 1; if ((opt.debug & DBG_MEMSTAT_VALUE)) memory_stat_debug_mode = 1; if (DBG_MPI) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); if (DBG_CRYPTO) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); if ((opt.debug & DBG_IOBUF_VALUE)) iobuf_debug_mode = 1; gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); if (opt.debug) parse_debug_flag (NULL, &opt.debug, debug_flags); /* Make sure that we are --verbose in debug mode. */ if (opt.debug && !opt.verbose) opt.verbose = 1; if (opt.debug && opt.quiet) opt.quiet = 0; if (opt_set_iobuf_size || opt_set_iobuf_size_used) log_debug ("iobuf buffer size is %uk\n", iobuf_set_buffer_size (opt_set_iobuf_size)); } /* We set the screen dimensions for UI purposes. Do not allow screens smaller than 80x24 for the sake of simplicity. */ static void set_screen_dimensions(void) { #ifndef HAVE_W32_SYSTEM char *str; str=getenv("COLUMNS"); if(str) opt.screen_columns=atoi(str); str=getenv("LINES"); if(str) opt.screen_lines=atoi(str); #endif if(opt.screen_columns<80 || opt.screen_columns>255) opt.screen_columns=80; if(opt.screen_lines<24 || opt.screen_lines>255) opt.screen_lines=24; } /* Helper to open a file FNAME either for reading or writing to be used with --status-file etc functions. Not generally useful but it avoids the riscos specific functions and well some Windows people might like it too. Prints an error message and returns -1 on error. On success the file descriptor is returned. */ static int open_info_file (const char *fname, int for_write, int binary) { #ifdef __riscos__ return riscos_fdopenfile (fname, for_write); #elif defined (ENABLE_SELINUX_HACKS) /* We can't allow these even when testing for a secured filename because files to be secured might not yet been secured. This is similar to the option file but in that case it is unlikely that sensitive information may be retrieved by means of error messages. */ (void)fname; (void)for_write; (void)binary; return -1; #else int fd; if (binary) binary = MY_O_BINARY; /* if (is_secured_filename (fname)) */ /* { */ /* fd = -1; */ /* gpg_err_set_errno (EPERM); */ /* } */ /* else */ /* { */ do { if (for_write) fd = gnupg_open (fname, O_CREAT | O_TRUNC | O_WRONLY | binary, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); else fd = gnupg_open (fname, O_RDONLY | binary, 0); } while (fd == -1 && errno == EINTR); /* } */ if ( fd == -1) log_error ( for_write? _("can't create '%s': %s\n") : _("can't open '%s': %s\n"), fname, strerror(errno)); return fd; #endif } static void set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) { enum cmd_and_opt_values cmd = *ret_cmd; if( !cmd || cmd == new_cmd ) cmd = new_cmd; else if( cmd == aSign && new_cmd == aEncr ) cmd = aSignEncr; else if( cmd == aEncr && new_cmd == aSign ) cmd = aSignEncr; else if( cmd == aSign && new_cmd == aSym ) cmd = aSignSym; else if( cmd == aSym && new_cmd == aSign ) cmd = aSignSym; else if( cmd == aSym && new_cmd == aEncr ) cmd = aEncrSym; else if( cmd == aEncr && new_cmd == aSym ) cmd = aEncrSym; else if (cmd == aSignEncr && new_cmd == aSym) cmd = aSignEncrSym; else if (cmd == aSignSym && new_cmd == aEncr) cmd = aSignEncrSym; else if (cmd == aEncrSym && new_cmd == aSign) cmd = aSignEncrSym; else if( ( cmd == aSign && new_cmd == aClearsign ) || ( cmd == aClearsign && new_cmd == aSign ) ) cmd = aClearsign; else { log_error(_("conflicting commands\n")); g10_exit(2); } *ret_cmd = cmd; } static void add_group(char *string) { char *name,*value; struct groupitem *item; /* Break off the group name */ name=strsep(&string,"="); if(string==NULL) { log_error(_("no = sign found in group definition '%s'\n"),name); return; } trim_trailing_ws(name,strlen(name)); /* Does this group already exist? */ for(item=opt.grouplist;item;item=item->next) if(strcasecmp(item->name,name)==0) break; if(!item) { item=xmalloc(sizeof(struct groupitem)); item->name=name; item->next=opt.grouplist; item->values=NULL; opt.grouplist=item; } /* Break apart the values */ while ((value= strsep(&string," \t"))) { if (*value) add_to_strlist2(&item->values,value,utf8_strings); } } static void rm_group(char *name) { struct groupitem *item,*last=NULL; trim_trailing_ws(name,strlen(name)); for(item=opt.grouplist;item;last=item,item=item->next) { if(strcasecmp(item->name,name)==0) { if(last) last->next=item->next; else opt.grouplist=item->next; free_strlist(item->values); xfree(item); break; } } } /* We need to check three things. 0) The homedir. It must be x00, a directory, and owned by the user. 1) The options/gpg.conf file. Okay unless it or its containing directory is group or other writable or not owned by us. Disable exec in this case. 2) Extensions. Same as #1. Returns true if the item is unsafe. */ static int check_permissions (const char *path, int item) { #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM) static int homedir_cache=-1; char *tmppath,*dir; struct stat statbuf,dirbuf; int homedir=0,ret=0,checkonly=0; int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0; if(opt.no_perm_warn) return 0; log_assert(item==0 || item==1 || item==2); /* extensions may attach a path */ if(item==2 && path[0]!=DIRSEP_C) { if(strchr(path,DIRSEP_C)) tmppath=make_filename(path,NULL); else tmppath=make_filename(gnupg_libdir (),path,NULL); } else tmppath=xstrdup(path); /* If the item is located in the homedir, but isn't the homedir, don't continue if we already checked the homedir itself. This is to avoid user confusion with an extra options file warning which could be rectified if the homedir itself had proper permissions. */ if(item!=0 && homedir_cache>-1 && !ascii_strncasecmp (gnupg_homedir (), tmppath, strlen (gnupg_homedir ()))) { ret=homedir_cache; goto end; } /* It's okay if the file or directory doesn't exist */ if (gnupg_stat (tmppath,&statbuf)) { ret=0; goto end; } /* Now check the enclosing directory. Theoretically, we could walk this test up to the root directory /, but for the sake of sanity, I'm stopping at one level down. */ dir=make_dirname(tmppath); if (gnupg_stat (dir,&dirbuf) || !S_ISDIR (dirbuf.st_mode)) { /* Weird error */ xfree(dir); ret=1; goto end; } xfree(dir); /* Assume failure */ ret=1; if(item==0) { /* The homedir must be x00, a directory, and owned by the user. */ if(S_ISDIR(statbuf.st_mode)) { if(statbuf.st_uid==getuid()) { if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0) ret=0; else perm=1; } else own=1; homedir_cache=ret; } } else if(item==1 || item==2) { /* The options or extension file. Okay unless it or its containing directory is group or other writable or not owned by us or root. */ if(S_ISREG(statbuf.st_mode)) { if(statbuf.st_uid==getuid() || statbuf.st_uid==0) { if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0) { /* it's not writable, so make sure the enclosing directory is also not writable */ if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) { if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0) ret=0; else enc_dir_perm=1; } else enc_dir_own=1; } else { /* it's writable, so the enclosing directory had better not let people get to it. */ if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) { if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0) ret=0; else perm=enc_dir_perm=1; /* unclear which one to fix! */ } else enc_dir_own=1; } } else own=1; } } else BUG(); if(!checkonly) { if(own) { if(item==0) log_info(_("WARNING: unsafe ownership on" " homedir '%s'\n"),tmppath); else if(item==1) log_info(_("WARNING: unsafe ownership on" " configuration file '%s'\n"),tmppath); else log_info(_("WARNING: unsafe ownership on" " extension '%s'\n"),tmppath); } if(perm) { if(item==0) log_info(_("WARNING: unsafe permissions on" " homedir '%s'\n"),tmppath); else if(item==1) log_info(_("WARNING: unsafe permissions on" " configuration file '%s'\n"),tmppath); else log_info(_("WARNING: unsafe permissions on" " extension '%s'\n"),tmppath); } if(enc_dir_own) { if(item==0) log_info(_("WARNING: unsafe enclosing directory ownership on" " homedir '%s'\n"),tmppath); else if(item==1) log_info(_("WARNING: unsafe enclosing directory ownership on" " configuration file '%s'\n"),tmppath); else log_info(_("WARNING: unsafe enclosing directory ownership on" " extension '%s'\n"),tmppath); } if(enc_dir_perm) { if(item==0) log_info(_("WARNING: unsafe enclosing directory permissions on" " homedir '%s'\n"),tmppath); else if(item==1) log_info(_("WARNING: unsafe enclosing directory permissions on" " configuration file '%s'\n"),tmppath); else log_info(_("WARNING: unsafe enclosing directory permissions on" " extension '%s'\n"),tmppath); } } end: xfree(tmppath); if(homedir) homedir_cache=ret; return ret; #else /*!(HAVE_STAT && !HAVE_DOSISH_SYSTEM)*/ (void)path; (void)item; return 0; #endif /*!(HAVE_STAT && !HAVE_DOSISH_SYSTEM)*/ } /* Print the OpenPGP defined algo numbers. */ static void print_algo_numbers(int (*checker)(int)) { int i,first=1; for(i=0;i<=110;i++) { if(!checker(i)) { if(first) first=0; else es_printf (";"); es_printf ("%d",i); } } } static void print_algo_names(int (*checker)(int),const char *(*mapper)(int)) { int i,first=1; for(i=0;i<=110;i++) { if(!checker(i)) { if(first) first=0; else es_printf (";"); es_printf ("%s",mapper(i)); } } } /* In the future, we can do all sorts of interesting configuration output here. For now, just give "group" as the Enigmail folks need it, and pubkey, cipher, hash, and compress as they may be useful for frontends. */ static void list_config(char *items) { int show_all = !items; char *name = NULL; const char *s; struct groupitem *giter; int first, iter; if(!opt.with_colons) return; while(show_all || (name=strsep(&items," "))) { int any=0; if(show_all || ascii_strcasecmp(name,"group")==0) { for (giter = opt.grouplist; giter; giter = giter->next) { strlist_t sl; es_fprintf (es_stdout, "cfg:group:"); es_write_sanitized (es_stdout, giter->name, strlen(giter->name), ":", NULL); es_putc (':', es_stdout); for(sl=giter->values; sl; sl=sl->next) { es_write_sanitized (es_stdout, sl->d, strlen (sl->d), ":;", NULL); if(sl->next) es_printf(";"); } es_printf("\n"); } any=1; } if(show_all || ascii_strcasecmp(name,"version")==0) { es_printf("cfg:version:"); es_write_sanitized (es_stdout, VERSION, strlen(VERSION), ":", NULL); es_printf ("\n"); any=1; } if(show_all || ascii_strcasecmp(name,"pubkey")==0) { es_printf ("cfg:pubkey:"); print_algo_numbers (build_list_pk_test_algo); es_printf ("\n"); any=1; } if(show_all || ascii_strcasecmp(name,"pubkeyname")==0) { es_printf ("cfg:pubkeyname:"); print_algo_names (build_list_pk_test_algo, build_list_pk_algo_name); es_printf ("\n"); any=1; } if(show_all || ascii_strcasecmp(name,"cipher")==0) { es_printf ("cfg:cipher:"); print_algo_numbers (build_list_cipher_test_algo); es_printf ("\n"); any=1; } if (show_all || !ascii_strcasecmp (name,"ciphername")) { es_printf ("cfg:ciphername:"); print_algo_names (build_list_cipher_test_algo, build_list_cipher_algo_name); es_printf ("\n"); any = 1; } if(show_all || ascii_strcasecmp(name,"digest")==0 || ascii_strcasecmp(name,"hash")==0) { es_printf ("cfg:digest:"); print_algo_numbers (build_list_md_test_algo); es_printf ("\n"); any=1; } if (show_all || !ascii_strcasecmp(name,"digestname") || !ascii_strcasecmp(name,"hashname")) { es_printf ("cfg:digestname:"); print_algo_names (build_list_md_test_algo, build_list_md_algo_name); es_printf ("\n"); any=1; } if(show_all || ascii_strcasecmp(name,"compress")==0) { es_printf ("cfg:compress:"); print_algo_numbers(check_compress_algo); es_printf ("\n"); any=1; } if(show_all || ascii_strcasecmp (name, "compressname") == 0) { es_printf ("cfg:compressname:"); print_algo_names (check_compress_algo, compress_algo_to_string); es_printf ("\n"); any=1; } if (show_all || !ascii_strcasecmp(name,"ccid-reader-id")) { /* We ignore this for GnuPG 1.4 backward compatibility. */ any=1; } if (show_all || !ascii_strcasecmp (name,"curve")) { es_printf ("cfg:curve:"); for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first=0) es_printf ("%s%s", first?"":";", s); es_printf ("\n"); any=1; } /* Curve OIDs are rarely useful and thus only printed if requested. */ if (name && !ascii_strcasecmp (name,"curveoid")) { es_printf ("cfg:curveoid:"); for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first = 0) { s = openpgp_curve_to_oid (s, NULL, NULL); es_printf ("%s%s", first?"":";", s? s:"[?]"); } es_printf ("\n"); any=1; } if(show_all) break; if(!any) log_error(_("unknown configuration item '%s'\n"),name); } } /* List default values for use by gpgconf. */ static void gpgconf_list (void) { es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT); es_printf ("compliance:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, "gnupg"); /* The next one is an info only item and should match the macros at the top of keygen.c */ es_printf ("default_pubkey_algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, get_default_pubkey_algo ()); /* This info only mode tells whether the we are running in de-vs * compliance mode. This does not test all parameters but the basic * conditions like a proper RNG and Libgcrypt. AS of now we always * return 0 because this version of gnupg has not yet received an * appoval. */ es_printf ("compliance_de_vs:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, 0 /*gnupg_rng_is_compliant (CO_DE_VS)*/); es_printf ("use_keyboxd:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, opt.use_keyboxd); } static int parse_subpacket_list(char *list) { char *tok; byte subpackets[128],i; int count=0; if(!list) { /* No arguments means all subpackets */ memset(subpackets+1,1,sizeof(subpackets)-1); count=127; } else { memset(subpackets,0,sizeof(subpackets)); /* Merge with earlier copy */ if(opt.show_subpackets) { byte *in; for(in=opt.show_subpackets;*in;in++) { if(*in>127 || *in<1) BUG(); if(!subpackets[*in]) count++; subpackets[*in]=1; } } while((tok=strsep(&list," ,"))) { if(!*tok) continue; i=atoi(tok); if(i>127 || i<1) return 0; if(!subpackets[i]) count++; subpackets[i]=1; } } xfree(opt.show_subpackets); opt.show_subpackets=xmalloc(count+1); opt.show_subpackets[count--]=0; for(i=1;i<128 && count>=0;i++) if(subpackets[i]) opt.show_subpackets[count--]=i; return 1; } static int parse_list_options(char *str) { char *subpackets=""; /* something that isn't NULL */ struct parse_options lopts[]= { {"show-photos",LIST_SHOW_PHOTOS,NULL, N_("display photo IDs during key listings")}, {"show-usage",LIST_SHOW_USAGE,NULL, N_("show key usage information during key listings")}, {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL, N_("show policy URLs during signature listings")}, {"show-notations",LIST_SHOW_NOTATIONS,NULL, N_("show all notations during signature listings")}, {"show-std-notations",LIST_SHOW_STD_NOTATIONS,NULL, N_("show IETF standard notations during signature listings")}, {"show-standard-notations",LIST_SHOW_STD_NOTATIONS,NULL, NULL}, {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL, N_("show user-supplied notations during signature listings")}, {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL, N_("show preferred keyserver URLs during signature listings")}, {"show-uid-validity",LIST_SHOW_UID_VALIDITY,NULL, N_("show user ID validity during key listings")}, {"show-unusable-uids",LIST_SHOW_UNUSABLE_UIDS,NULL, N_("show revoked and expired user IDs in key listings")}, {"show-unusable-subkeys",LIST_SHOW_UNUSABLE_SUBKEYS,NULL, N_("show revoked and expired subkeys in key listings")}, {"show-keyring",LIST_SHOW_KEYRING,NULL, N_("show the keyring name in key listings")}, {"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL, N_("show expiration dates during signature listings")}, {"show-pref", LIST_SHOW_PREF, NULL, N_("show preferences")}, {"show-pref-verbose", LIST_SHOW_PREF_VERBOSE, NULL, N_("show preferences")}, {"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL, NULL}, {"show-only-fpr-mbox",LIST_SHOW_ONLY_FPR_MBOX, NULL, NULL}, {"sort-sigs", LIST_SORT_SIGS, NULL, NULL}, {NULL,0,NULL,NULL} }; /* C99 allows for non-constant initializers, but we'd like to compile everywhere, so fill in the show-sig-subpackets argument here. Note that if the parse_options array changes, we'll have to change the subscript here. */ lopts[13].value=&subpackets; if(parse_options(str,&opt.list_options,lopts,1)) { if(opt.list_options&LIST_SHOW_SIG_SUBPACKETS) { /* Unset so users can pass multiple lists in. */ opt.list_options&=~LIST_SHOW_SIG_SUBPACKETS; if(!parse_subpacket_list(subpackets)) return 0; } else if(subpackets==NULL && opt.show_subpackets) { /* User did 'no-show-subpackets' */ xfree(opt.show_subpackets); opt.show_subpackets=NULL; } return 1; } else return 0; } /* Collapses argc/argv into a single string that must be freed */ static char * collapse_args(int argc,char *argv[]) { char *str=NULL; int i,first=1,len=0; for(i=0;imagic = SERVER_CONTROL_MAGIC; } /* This function is called to deinitialize a control object. It is not deallocated. */ static void gpg_deinit_default_ctrl (ctrl_t ctrl) { #ifdef USE_TOFU tofu_closedbs (ctrl); #endif gpg_dirmngr_deinit_session_data (ctrl); keydb_release (ctrl->cached_getkey_kdb); gpg_keyboxd_deinit_session_data (ctrl); xfree (ctrl->secret_keygrips); ctrl->secret_keygrips = NULL; } int main (int argc, char **argv) { gpgrt_argparse_t pargs; IOBUF a; int rc=0; int orig_argc; char **orig_argv; const char *fname; char *username; int may_coredump; strlist_t sl; strlist_t remusr = NULL; strlist_t locusr = NULL; strlist_t nrings = NULL; armor_filter_context_t *afx = NULL; int detached_sig = 0; char *last_configname = NULL; const char *configname = NULL; /* NULL or points to last_configname. * NULL also indicates that we are * processing options from the cmdline. */ int debug_argparser = 0; int default_keyring = 1; int greeting = 0; int nogreeting = 0; char *logfile = NULL; int use_random_seed = 1; enum cmd_and_opt_values cmd = 0; const char *debug_level = NULL; #ifndef NO_TRUST_MODELS const char *trustdb_name = NULL; #endif /*!NO_TRUST_MODELS*/ char *def_cipher_string = NULL; char *def_digest_string = NULL; char *compress_algo_string = NULL; char *cert_digest_string = NULL; char *s2k_cipher_string = NULL; char *s2k_digest_string = NULL; char *pers_cipher_list = NULL; char *pers_digest_list = NULL; char *pers_compress_list = NULL; int eyes_only=0; int multifile=0; int pwfd = -1; int ovrseskeyfd = -1; int fpr_maybe_cmd = 0; /* --fingerprint maybe a command. */ int any_explicit_recipient = 0; int default_akl = 1; int require_secmem = 0; int got_secmem = 0; struct assuan_malloc_hooks malloc_hooks; ctrl_t ctrl; static int print_dane_records; static int allow_large_chunks; static const char *homedirvalue; static const char *changeuser; #ifdef __riscos__ opt.lock_once = 1; #endif /* __riscos__ */ /* Please note that we may running SUID(ROOT), so be very CAREFUL when adding any stuff between here and the call to secmem_init() somewhere after the option parsing. */ early_system_init (); gnupg_reopen_std (GPG_NAME); trap_unaligned (); gnupg_rl_initialize (); gpgrt_set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); log_set_prefix (GPG_NAME, GPGRT_LOG_WITH_PREFIX|GPGRT_LOG_NO_REGISTRY); /* Make sure that our subsystems are ready. */ i18n_init(); init_common_subsystems (&argc, &argv); /* Use our own logging handler for Libcgrypt. */ setup_libgcrypt_logging (); /* Put random number into secure memory */ gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); may_coredump = disable_core_dumps(); gnupg_init_signals (0, emergency_cleanup); dotlock_create (NULL, 0); /* Register lock file cleanup. */ /* Tell the compliance module who we are. */ gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG); opt.autostart = 1; opt.session_env = session_env_new (); if (!opt.session_env) log_fatal ("error allocating session environment block: %s\n", strerror (errno)); opt.command_fd = -1; /* no command fd */ opt.compress_level = -1; /* defaults to standard compress level */ opt.bz2_compress_level = -1; /* defaults to standard compress level */ /* note: if you change these lines, look at oOpenPGP */ opt.def_cipher_algo = 0; opt.def_digest_algo = 0; opt.cert_digest_algo = 0; opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */ opt.s2k_mode = 3; /* iterated+salted */ opt.s2k_count = 0; /* Auto-calibrate when needed. */ opt.s2k_cipher_algo = DEFAULT_CIPHER_ALGO; opt.completes_needed = 1; opt.marginals_needed = 3; opt.max_cert_depth = 5; opt.escape_from = 1; opt.flags.require_cross_cert = 1; opt.import_options = (IMPORT_REPAIR_KEYS | IMPORT_COLLAPSE_UIDS | IMPORT_COLLAPSE_SUBKEYS); opt.export_options = EXPORT_ATTRIBUTES; opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS | IMPORT_REPAIR_PKS_SUBKEY_BUG | IMPORT_SELF_SIGS_ONLY | IMPORT_COLLAPSE_UIDS | IMPORT_COLLAPSE_SUBKEYS | IMPORT_CLEAN); opt.keyserver_options.export_options = EXPORT_ATTRIBUTES; opt.keyserver_options.options = 0; opt.verify_options = (LIST_SHOW_UID_VALIDITY | VERIFY_SHOW_POLICY_URLS | VERIFY_SHOW_STD_NOTATIONS | VERIFY_SHOW_KEYSERVER_URLS); opt.list_options = (LIST_SHOW_UID_VALIDITY | LIST_SORT_SIGS | LIST_SHOW_USAGE); #ifdef NO_TRUST_MODELS opt.trust_model = TM_ALWAYS; #else opt.trust_model = TM_AUTO; #endif opt.tofu_default_policy = TOFU_POLICY_AUTO; opt.mangle_dos_filenames = 0; opt.min_cert_level = 2; set_screen_dimensions (); opt.keyid_format = KF_NONE; opt.def_sig_expire = "0"; opt.def_cert_expire = "0"; opt.passphrase_repeat = 1; opt.emit_version = 0; opt.weak_digests = NULL; opt.compliance = CO_GNUPG; /* Check special options given on the command line. */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; pargs.argv = &argv; pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION); while (gpgrt_argparse (NULL, &pargs, opts)) { switch (pargs.r_opt) { case oDebug: case oDebugAll: debug_argparser++; break; case oDebugIOLBF: es_setvbuf (es_stdout, NULL, _IOLBF, 0); break; case oNoOptions: /* Set here here because the homedir would otherwise be * created before main option parsing starts. */ opt.no_homedir_creation = 1; break; case oHomedir: homedirvalue = pargs.r.ret_str; break; case oChUid: changeuser = pargs.r.ret_str; break; case oNoPermissionWarn: opt.no_perm_warn = 1; break; } } /* Reset the flags. */ pargs.flags &= ~(ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION); #ifdef HAVE_DOSISH_SYSTEM /* FIXME: Do we still need this? No: gnupg_homedir calls * make_filename which changes the slashed anyway. IsDBCSLeadByte still * needed? See bug #561. */ if ( strchr (gnupg_homedir (), '\\') ) { char *d, *buf = xmalloc (strlen (gnupg_homedir ())+1); const char *s; for (d=buf, s = gnupg_homedir (); *s; s++) { *d++ = *s == '\\'? '/': *s; #ifdef HAVE_W32_SYSTEM if (s[1] && IsDBCSLeadByte (*s)) *d++ = *++s; #endif } *d = 0; gnupg_set_homedir (buf); } #endif /* Initialize the secure memory. */ if (!gcry_control (GCRYCTL_INIT_SECMEM, SECMEM_BUFFER_SIZE, 0)) got_secmem = 1; #if defined(HAVE_GETUID) && defined(HAVE_GETEUID) /* There should be no way to get to this spot while still carrying setuid privs. Just in case, bomb out if we are. */ if ( getuid () != geteuid () ) BUG (); #endif maybe_setuid = 0; /* Okay, we are now working under our real uid */ /* malloc hooks go here ... */ malloc_hooks.malloc = gcry_malloc; malloc_hooks.realloc = gcry_realloc; malloc_hooks.free = gcry_free; assuan_set_malloc_hooks (&malloc_hooks); assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT); setup_libassuan_logging (&opt.debug, NULL); /* Change UID and then set the homedir. */ if (changeuser && gnupg_chuid (changeuser, 0)) log_inc_errorcount (); /* Force later termination. */ gnupg_set_homedir (homedirvalue); /* Set default options which require that malloc stuff is ready. */ additional_weak_digest ("MD5"); parse_auto_key_locate (DEFAULT_AKL_LIST); argc = orig_argc; argv = orig_argv; pargs.argc = &argc; pargs.argv = &argv; /* We are re-using the struct, thus the reset flag. We OR the * flags so that the internal intialized flag won't be cleared. */ pargs.flags |= (ARGPARSE_FLAG_RESET | ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_SYS | ARGPARSE_FLAG_USER | ARGPARSE_FLAG_USERVERS); /* By this point we have a homedir, and cannot change it. */ check_permissions (gnupg_homedir (), 0); /* The configuraton directories for use by gpgrt_argparser. */ gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ()); gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ()); while (gpgrt_argparser (&pargs, opts, GPG_NAME EXTSEP_S "conf" )) { switch (pargs.r_opt) { case ARGPARSE_CONFFILE: if (debug_argparser) log_info (_("reading options from '%s'\n"), pargs.r_type? pargs.r.ret_str: "[cmdline]"); if (pargs.r_type) { xfree (last_configname); last_configname = xstrdup (pargs.r.ret_str); configname = last_configname; if (is_secured_filename (configname)) { pargs.r_opt = ARGPARSE_PERMISSION_ERROR; pargs.err = ARGPARSE_PRINT_ERROR; } else if (strncmp (configname, gnupg_sysconfdir (), strlen (gnupg_sysconfdir ()))) { /* This is not the global config file and thus we * need to check the permissions: If the file is * unsafe, then disable any external programs for * keyserver calls or photo IDs. Since the * external program to call is set in the options * file, a unsafe options file can lead to an * arbitrary program being run. */ if (check_permissions (configname, 1)) opt.exec_disable=1; } } else configname = NULL; break; /* case oOptions: */ /* case oNoOptions: */ /* We will never see these options here because * gpgrt_argparse handles them for us. */ /* break */ case aListConfig: case aListGcryptConfig: case aGPGConfList: case aGPGConfTest: set_cmd (&cmd, pargs.r_opt); /* Do not register a keyring for these commands. */ default_keyring = -1; break; case aCheckKeys: case aListPackets: case aImport: case aFastImport: case aSendKeys: case aRecvKeys: case aSearchKeys: case aRefreshKeys: case aFetchKeys: case aExport: #ifdef ENABLE_CARD_SUPPORT case aCardStatus: case aCardEdit: case aChangePIN: #endif /* ENABLE_CARD_SUPPORT*/ case aListKeys: case aLocateKeys: case aLocateExtKeys: case aListSigs: case aExportSecret: case aExportSecretSub: case aExportSshKey: case aExportSecretSshKey: case aSym: case aClearsign: case aGenRevoke: case aDesigRevoke: case aPrimegen: case aGenRandom: case aPrintMD: case aPrintMDs: case aListTrustDB: case aCheckTrustDB: case aUpdateTrustDB: case aFixTrustDB: case aListTrustPath: case aDeArmor: case aEnArmor: case aSign: case aQuickSignKey: case aQuickLSignKey: case aQuickRevSig: case aSignKey: case aLSignKey: case aStore: case aQuickKeygen: case aQuickAddUid: case aQuickAddKey: case aQuickRevUid: case aQuickSetExpire: case aQuickSetPrimaryUid: case aQuickUpdatePref: case aExportOwnerTrust: case aImportOwnerTrust: case aRebuildKeydbCaches: set_cmd (&cmd, pargs.r_opt); break; case aKeygen: case aFullKeygen: case aEditKey: case aDeleteSecretKeys: case aDeleteSecretAndPublicKeys: case aDeleteKeys: case aPasswd: set_cmd (&cmd, pargs.r_opt); greeting=1; break; case aShowKeys: set_cmd (&cmd, pargs.r_opt); opt.import_options |= IMPORT_SHOW; opt.import_options |= IMPORT_DRY_RUN; opt.import_options &= ~IMPORT_REPAIR_KEYS; opt.list_options |= LIST_SHOW_UNUSABLE_UIDS; opt.list_options |= LIST_SHOW_UNUSABLE_SUBKEYS; opt.list_options |= LIST_SHOW_NOTATIONS; opt.list_options |= LIST_SHOW_POLICY_URLS; break; case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; case aDecryptFiles: multifile=1; /* fall through */ case aDecrypt: set_cmd( &cmd, aDecrypt); break; case aEncrFiles: multifile=1; /* fall through */ case aEncr: set_cmd( &cmd, aEncr); break; case aVerifyFiles: multifile=1; /* fall through */ case aVerify: set_cmd( &cmd, aVerify); break; case aServer: set_cmd (&cmd, pargs.r_opt); opt.batch = 1; break; case aTOFUPolicy: set_cmd (&cmd, pargs.r_opt); break; case oArmor: opt.armor = 1; opt.no_armor=0; break; case oOutput: opt.outfile = pargs.r.ret_str; break; case oMaxOutput: opt.max_output = pargs.r.ret_ulong; break; case oInputSizeHint: opt.input_size_hint = string_to_u64 (pargs.r.ret_str); break; case oChunkSize: opt.chunk_size = pargs.r.ret_int; break; case oQuiet: opt.quiet = 1; break; case oNoTTY: tty_no_terminal(1); break; case oDryRun: opt.dry_run = 1; break; case oInteractive: opt.interactive = 1; break; case oVerbose: opt.verbose++; gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); opt.list_options|=LIST_SHOW_UNUSABLE_UIDS; opt.list_options|=LIST_SHOW_UNUSABLE_SUBKEYS; break; case oBatch: opt.batch = 1; nogreeting = 1; break; case oUseAgent: /* Dummy. */ break; case oNoUseAgent: obsolete_option (configname, pargs.lineno, "no-use-agent"); break; case oGpgAgentInfo: obsolete_option (configname, pargs.lineno, "gpg-agent-info"); break; case oUseKeyboxd: opt.use_keyboxd = 1; break; case oReaderPort: obsolete_scdaemon_option (configname, pargs.lineno, "reader-port"); break; case octapiDriver: obsolete_scdaemon_option (configname, pargs.lineno, "ctapi-driver"); break; case opcscDriver: obsolete_scdaemon_option (configname, pargs.lineno, "pcsc-driver"); break; case oDisableCCID: obsolete_scdaemon_option (configname, pargs.lineno, "disable-ccid"); break; case oHonorHttpProxy: obsolete_option (configname, pargs.lineno, "honor-http-proxy"); break; case oAnswerYes: opt.answer_yes = 1; break; case oAnswerNo: opt.answer_no = 1; break; case oForceSignKey: opt.flags.force_sign_key = 1; break; case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; case oPrimaryKeyring: sl = append_to_strlist (&nrings, pargs.r.ret_str); sl->flags = KEYDB_RESOURCE_FLAG_PRIMARY; break; case oShowKeyring: deprecated_warning(configname,pargs.lineno,"--show-keyring", "--list-options ","show-keyring"); opt.list_options|=LIST_SHOW_KEYRING; break; case oDebug: if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags)) { pargs.r_opt = ARGPARSE_INVALID_ARG; pargs.err = ARGPARSE_PRINT_ERROR; } break; case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugIOLBF: break; /* Already set in pre-parse step. */ case oDebugSetIobufSize: opt_set_iobuf_size = pargs.r.ret_ulong; opt_set_iobuf_size_used = 1; break; case oDebugAllowLargeChunks: allow_large_chunks = 1; break; case oCompatibilityFlags: if (parse_compatibility_flags (pargs.r.ret_str, &opt.compat_flags, compatibility_flags)) { pargs.r_opt = ARGPARSE_INVALID_ARG; pargs.err = ARGPARSE_PRINT_ERROR; } break; case oStatusFD: set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) ); break; case oStatusFile: set_status_fd ( open_info_file (pargs.r.ret_str, 1, 0) ); break; case oAttributeFD: set_attrib_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) ); break; case oAttributeFile: set_attrib_fd ( open_info_file (pargs.r.ret_str, 1, 1) ); break; case oLoggerFD: log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1)); break; case oLoggerFile: logfile = pargs.r.ret_str; break; case oWithFingerprint: opt.with_fingerprint = 1; opt.fingerprint++; break; case oWithSubkeyFingerprint: opt.with_subkey_fingerprint = 1; break; case oWithICAOSpelling: opt.with_icao_spelling = 1; break; case oFingerprint: opt.fingerprint++; fpr_maybe_cmd = 1; break; case oWithKeygrip: opt.with_keygrip = 1; break; case oWithKeyScreening: opt.with_key_screening = 1; break; case oWithSecret: opt.with_secret = 1; break; case oWithWKDHash: opt.with_wkd_hash = 1; break; case oWithKeyOrigin: opt.with_key_origin = 1; break; case oSecretKeyring: obsolete_option (configname, pargs.lineno, "secret-keyring"); break; case oNoArmor: opt.no_armor=1; opt.armor=0; break; case oNoDefKeyring: if (default_keyring > 0) default_keyring = 0; break; case oNoKeyring: default_keyring = -1; break; case oNoGreeting: nogreeting = 1; break; case oNoVerbose: opt.verbose = 0; gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); opt.list_sigs=0; break; case oQuickRandom: gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); break; case oEmitVersion: opt.emit_version++; break; case oNoEmitVersion: opt.emit_version=0; break; case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; #ifndef NO_TRUST_MODELS case oTrustDBName: trustdb_name = pargs.r.ret_str; break; #endif /*!NO_TRUST_MODELS*/ case oDefaultKey: sl = add_to_strlist (&opt.def_secret_key, pargs.r.ret_str); sl->flags = (pargs.r_opt << PK_LIST_SHIFT); if (configname) sl->flags |= PK_LIST_CONFIG; break; case oDefRecipient: if( *pargs.r.ret_str ) { xfree (opt.def_recipient); opt.def_recipient = make_username(pargs.r.ret_str); } break; case oDefRecipientSelf: xfree(opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 1; break; case oNoDefRecipient: xfree(opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 0; break; case oHomedir: break; case oChUid: break; /* Command line only (see above). */ case oNoBatch: opt.batch = 0; break; case oWithTofuInfo: opt.with_tofu_info = 1; break; case oWithKeyData: opt.with_key_data=1; /*FALLTHRU*/ case oWithColons: opt.with_colons=':'; break; case oWithSigCheck: opt.check_sigs = 1; /*FALLTHRU*/ case oWithSigList: opt.list_sigs = 1; break; case oSkipVerify: opt.skip_verify=1; break; case oSkipHiddenRecipients: opt.skip_hidden_recipients = 1; break; case oNoSkipHiddenRecipients: opt.skip_hidden_recipients = 0; break; case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; #ifndef NO_TRUST_MODELS /* There are many programs (like mutt) that call gpg with --always-trust so keep this option around for a long time. */ case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break; case oTrustModel: parse_trust_model(pargs.r.ret_str); break; #endif /*!NO_TRUST_MODELS*/ case oTOFUDefaultPolicy: opt.tofu_default_policy = parse_tofu_policy (pargs.r.ret_str); break; case oTOFUDBFormat: obsolete_option (configname, pargs.lineno, "tofu-db-format"); break; case oForceOwnertrust: log_info(_("Note: %s is not for normal use!\n"), "--force-ownertrust"); opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str); if(opt.force_ownertrust==-1) { log_error("invalid ownertrust '%s'\n",pargs.r.ret_str); opt.force_ownertrust=0; } break; case oNoAutoTrustNewKey: opt.flags.no_auto_trust_new_key = 1; break; case oCompliance: { int compliance = gnupg_parse_compliance_option (pargs.r.ret_str, compliance_options, DIM (compliance_options), opt.quiet); if (compliance < 0) g10_exit (1); set_compliance_option (compliance); } break; case oOpenPGP: case oRFC2440: case oRFC4880: case oPGP7: case oPGP8: case oGnuPG: set_compliance_option (pargs.r_opt); break; case oMinRSALength: opt.min_rsa_length = pargs.r.ret_ulong; break; case oRFC2440Text: opt.rfc2440_text=1; break; case oNoRFC2440Text: opt.rfc2440_text=0; break; case oSetFilename: if(utf8_strings) opt.set_filename = pargs.r.ret_str; else opt.set_filename = native_to_utf8(pargs.r.ret_str); break; case oForYourEyesOnly: eyes_only = 1; break; case oNoForYourEyesOnly: eyes_only = 0; break; case oSetPolicyURL: add_policy_url(pargs.r.ret_str,0); add_policy_url(pargs.r.ret_str,1); break; case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; case oShowPolicyURL: deprecated_warning(configname,pargs.lineno,"--show-policy-url", "--list-options ","show-policy-urls"); deprecated_warning(configname,pargs.lineno,"--show-policy-url", "--verify-options ","show-policy-urls"); opt.list_options|=LIST_SHOW_POLICY_URLS; opt.verify_options|=VERIFY_SHOW_POLICY_URLS; break; case oNoShowPolicyURL: deprecated_warning(configname,pargs.lineno,"--no-show-policy-url", "--list-options ","no-show-policy-urls"); deprecated_warning(configname,pargs.lineno,"--no-show-policy-url", "--verify-options ","no-show-policy-urls"); opt.list_options&=~LIST_SHOW_POLICY_URLS; opt.verify_options&=~VERIFY_SHOW_POLICY_URLS; break; case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; case oUseEmbeddedFilename: opt.flags.use_embedded_filename=1; break; case oNoUseEmbeddedFilename: opt.flags.use_embedded_filename=0; break; case oComment: if(pargs.r.ret_str[0]) append_to_strlist(&opt.comments,pargs.r.ret_str); break; case oDefaultComment: deprecated_warning(configname,pargs.lineno, "--default-comment","--no-comments",""); /* fall through */ case oNoComments: free_strlist(opt.comments); opt.comments=NULL; break; case oThrowKeyids: opt.throw_keyids = 1; break; case oNoThrowKeyids: opt.throw_keyids = 0; break; case oShowPhotos: deprecated_warning(configname,pargs.lineno,"--show-photos", "--list-options ","show-photos"); deprecated_warning(configname,pargs.lineno,"--show-photos", "--verify-options ","show-photos"); opt.list_options|=LIST_SHOW_PHOTOS; opt.verify_options|=VERIFY_SHOW_PHOTOS; break; case oNoShowPhotos: deprecated_warning(configname,pargs.lineno,"--no-show-photos", "--list-options ","no-show-photos"); deprecated_warning(configname,pargs.lineno,"--no-show-photos", "--verify-options ","no-show-photos"); opt.list_options&=~LIST_SHOW_PHOTOS; opt.verify_options&=~VERIFY_SHOW_PHOTOS; break; case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; case oForceAEAD: opt.force_aead = 1; break; case oDisableSignerUID: opt.flags.disable_signer_uid = 1; break; case oIncludeKeyBlock: opt.flags.include_key_block = 1; break; case oNoIncludeKeyBlock: opt.flags.include_key_block = 0; break; case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; case oS2KDigest: s2k_digest_string = xstrdup(pargs.r.ret_str); break; case oS2KCipher: s2k_cipher_string = xstrdup(pargs.r.ret_str); break; case oS2KCount: if (pargs.r.ret_int) opt.s2k_count = encode_s2k_iterations (pargs.r.ret_int); else opt.s2k_count = 0; /* Auto-calibrate when needed. */ break; case oRecipient: case oHiddenRecipient: case oRecipientFile: case oHiddenRecipientFile: /* Store the recipient. Note that we also store the * option as private data in the flags. This is achieved * by shifting the option value to the left so to keep * enough space for the flags. */ sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); sl->flags = (pargs.r_opt << PK_LIST_SHIFT); if (configname) sl->flags |= PK_LIST_CONFIG; if (pargs.r_opt == oHiddenRecipient || pargs.r_opt == oHiddenRecipientFile) sl->flags |= PK_LIST_HIDDEN; if (pargs.r_opt == oRecipientFile || pargs.r_opt == oHiddenRecipientFile) sl->flags |= PK_LIST_FROM_FILE; any_explicit_recipient = 1; break; case oEncryptTo: case oHiddenEncryptTo: /* Store an additional recipient. */ sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO); if (configname) sl->flags |= PK_LIST_CONFIG; if (pargs.r_opt == oHiddenEncryptTo) sl->flags |= PK_LIST_HIDDEN; break; case oNoEncryptTo: opt.no_encrypt_to = 1; break; case oEncryptToDefaultKey: opt.encrypt_to_default_key = configname ? 2 : 1; break; case oTrySecretKey: add_to_strlist2 (&opt.secret_keys_to_try, pargs.r.ret_str, utf8_strings); break; case oMimemode: opt.mimemode = opt.textmode = 1; break; case oTextmodeShort: opt.textmode = 2; break; case oTextmode: opt.textmode=1; break; case oNoTextmode: opt.textmode=opt.mimemode=0; break; case oExpert: opt.expert = 1; break; case oNoExpert: opt.expert = 0; break; case oDefSigExpire: if(*pargs.r.ret_str!='\0') { if(parse_expire_string(pargs.r.ret_str)==(u32)-1) log_error(_("'%s' is not a valid signature expiration\n"), pargs.r.ret_str); else opt.def_sig_expire=pargs.r.ret_str; } break; case oAskSigExpire: opt.ask_sig_expire = 1; break; case oNoAskSigExpire: opt.ask_sig_expire = 0; break; case oDefCertExpire: if(*pargs.r.ret_str!='\0') { if(parse_expire_string(pargs.r.ret_str)==(u32)-1) log_error(_("'%s' is not a valid signature expiration\n"), pargs.r.ret_str); else opt.def_cert_expire=pargs.r.ret_str; } break; case oAskCertExpire: opt.ask_cert_expire = 1; break; case oNoAskCertExpire: opt.ask_cert_expire = 0; break; case oDefCertLevel: opt.def_cert_level=pargs.r.ret_int; break; case oMinCertLevel: opt.min_cert_level=pargs.r.ret_int; break; case oAskCertLevel: opt.ask_cert_level = 1; break; case oNoAskCertLevel: opt.ask_cert_level = 0; break; case oLocalUser: /* store the local users */ sl = add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); sl->flags = (pargs.r_opt << PK_LIST_SHIFT); if (configname) sl->flags |= PK_LIST_CONFIG; break; case oSender: { char *mbox = mailbox_from_userid (pargs.r.ret_str, 0); if (!mbox) log_error (_("\"%s\" is not a proper mail address\n"), pargs.r.ret_str); else { add_to_strlist (&opt.sender_list, mbox); xfree (mbox); } } break; case oCompress: /* this is the -z command line option */ opt.compress_level = opt.bz2_compress_level = pargs.r.ret_int; + opt.explicit_compress_option = 1; break; case oCompressLevel: opt.compress_level = pargs.r.ret_int; break; case oBZ2CompressLevel: opt.bz2_compress_level = pargs.r.ret_int; break; case oBZ2DecompressLowmem: opt.bz2_decompress_lowmem=1; break; case oPassphrase: set_passphrase_from_string (pargs.r_type ? pargs.r.ret_str : ""); break; case oPassphraseFD: pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); break; case oPassphraseFile: pwfd = open_info_file (pargs.r.ret_str, 0, 1); break; case oPassphraseRepeat: opt.passphrase_repeat = pargs.r.ret_int; 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; case oRequestOrigin: opt.request_origin = parse_request_origin (pargs.r.ret_str); if (opt.request_origin == -1) log_error (_("invalid request origin '%s'\n"), pargs.r.ret_str); break; case oCommandFD: opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); if (! gnupg_fd_valid (opt.command_fd)) log_error ("command-fd is invalid: %s\n", strerror (errno)); break; case oCommandFile: opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1); break; case oCipherAlgo: def_cipher_string = xstrdup(pargs.r.ret_str); break; case oDigestAlgo: def_digest_string = xstrdup(pargs.r.ret_str); break; case oCompressAlgo: /* If it is all digits, stick a Z in front of it for later. This is for backwards compatibility with versions that took the compress algorithm number. */ { char *pt=pargs.r.ret_str; while(*pt) { if (!isascii (*pt) || !isdigit (*pt)) break; pt++; } if(*pt=='\0') { compress_algo_string=xmalloc(strlen(pargs.r.ret_str)+2); strcpy(compress_algo_string,"Z"); strcat(compress_algo_string,pargs.r.ret_str); } else compress_algo_string = xstrdup(pargs.r.ret_str); } break; case oCertDigestAlgo: cert_digest_string = xstrdup(pargs.r.ret_str); break; case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break; case oRequireSecmem: require_secmem=1; break; case oNoRequireSecmem: require_secmem=0; break; case oNoPermissionWarn: opt.no_perm_warn=1; break; case oDisplayCharset: if( set_native_charset( pargs.r.ret_str ) ) log_error(_("'%s' is not a valid character set\n"), pargs.r.ret_str); break; case oNotDashEscaped: opt.not_dash_escaped = 1; break; case oEscapeFrom: opt.escape_from = 1; break; case oNoEscapeFrom: opt.escape_from = 0; break; case oLockOnce: opt.lock_once = 1; break; case oLockNever: dotlock_disable (); break; case oLockMultiple: #ifndef __riscos__ opt.lock_once = 0; #else /* __riscos__ */ riscos_not_implemented("lock-multiple"); #endif /* __riscos__ */ break; case oKeyServer: { keyserver_spec_t keyserver; keyserver = parse_keyserver_uri (pargs.r.ret_str, 0); if (!keyserver) log_error (_("could not parse keyserver URL\n")); else { /* We only support a single keyserver. Later ones override earlier ones. (Since we parse the config file first and then the command line arguments, the command line takes precedence.) */ if (opt.keyserver) free_keyserver_spec (opt.keyserver); opt.keyserver = keyserver; } } break; case oKeyServerOptions: if(!parse_keyserver_options(pargs.r.ret_str)) { if(configname) log_error(_("%s:%d: invalid keyserver options\n"), configname,pargs.lineno); else log_error(_("invalid keyserver options\n")); } break; case oImportOptions: if(!parse_import_options(pargs.r.ret_str,&opt.import_options,1)) { if(configname) log_error(_("%s:%d: invalid import options\n"), configname,pargs.lineno); else log_error(_("invalid import options\n")); } break; case oImportFilter: rc = parse_and_set_import_filter (pargs.r.ret_str); if (rc) log_error (_("invalid filter option: %s\n"), gpg_strerror (rc)); break; case oExportOptions: if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1)) { if(configname) log_error(_("%s:%d: invalid export options\n"), configname,pargs.lineno); else log_error(_("invalid export options\n")); } break; case oExportFilter: rc = parse_and_set_export_filter (pargs.r.ret_str); if (rc) log_error (_("invalid filter option: %s\n"), gpg_strerror (rc)); break; case oListFilter: rc = parse_and_set_list_filter (pargs.r.ret_str); if (rc) log_error (_("invalid filter option: %s\n"), gpg_strerror (rc)); break; case oListOptions: if(!parse_list_options(pargs.r.ret_str)) { if(configname) log_error(_("%s:%d: invalid list options\n"), configname,pargs.lineno); else log_error(_("invalid list options\n")); } break; case oVerifyOptions: { struct parse_options vopts[]= { {"show-photos",VERIFY_SHOW_PHOTOS,NULL, N_("display photo IDs during signature verification")}, {"show-policy-urls",VERIFY_SHOW_POLICY_URLS,NULL, N_("show policy URLs during signature verification")}, {"show-notations",VERIFY_SHOW_NOTATIONS,NULL, N_("show all notations during signature verification")}, {"show-std-notations",VERIFY_SHOW_STD_NOTATIONS,NULL, N_("show IETF standard notations during signature verification")}, {"show-standard-notations",VERIFY_SHOW_STD_NOTATIONS,NULL, NULL}, {"show-user-notations",VERIFY_SHOW_USER_NOTATIONS,NULL, N_("show user-supplied notations during signature verification")}, {"show-keyserver-urls",VERIFY_SHOW_KEYSERVER_URLS,NULL, N_("show preferred keyserver URLs during signature verification")}, {"show-uid-validity",VERIFY_SHOW_UID_VALIDITY,NULL, N_("show user ID validity during signature verification")}, {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL, N_("show revoked and expired user IDs in signature verification")}, {"show-primary-uid-only",VERIFY_SHOW_PRIMARY_UID_ONLY,NULL, N_("show only the primary user ID in signature verification")}, {NULL,0,NULL,NULL} }; if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts,1)) { if(configname) log_error(_("%s:%d: invalid verify options\n"), configname,pargs.lineno); else log_error(_("invalid verify options\n")); } } break; case oTempDir: opt.temp_dir=pargs.r.ret_str; break; case oExecPath: if(set_exec_path(pargs.r.ret_str)) log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); else opt.exec_path_set=1; break; case oSetNotation: add_notation_data( pargs.r.ret_str, 0 ); add_notation_data( pargs.r.ret_str, 1 ); break; case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; case oKnownNotation: register_known_notation (pargs.r.ret_str); break; case oShowNotation: deprecated_warning(configname,pargs.lineno,"--show-notation", "--list-options ","show-notations"); deprecated_warning(configname,pargs.lineno,"--show-notation", "--verify-options ","show-notations"); opt.list_options|=LIST_SHOW_NOTATIONS; opt.verify_options|=VERIFY_SHOW_NOTATIONS; break; case oNoShowNotation: deprecated_warning(configname,pargs.lineno,"--no-show-notation", "--list-options ","no-show-notations"); deprecated_warning(configname,pargs.lineno,"--no-show-notation", "--verify-options ","no-show-notations"); opt.list_options&=~LIST_SHOW_NOTATIONS; opt.verify_options&=~VERIFY_SHOW_NOTATIONS; break; case oUtf8Strings: utf8_strings = 1; break; case oNoUtf8Strings: #ifdef HAVE_W32_SYSTEM utf8_strings = 0; #endif break; case oDisableCipherAlgo: { int algo = string_to_cipher_algo (pargs.r.ret_str); gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); } break; case oDisablePubkeyAlgo: { int algo = gcry_pk_map_name (pargs.r.ret_str); gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); } break; case oNoSigCache: opt.no_sig_cache = 1; break; case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; case oNoLiteral: opt.no_literal = 1; break; case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oFastListMode: opt.fast_list_mode = 1; break; case oFixedListMode: /* Dummy */ break; case oLegacyListMode: opt.legacy_list_mode = 1; break; case oPrintDANERecords: print_dane_records = 1; break; case oListOnly: opt.list_only=1; break; case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; case oIgnoreCrcError: opt.ignore_crc_error = 1; break; case oIgnoreMDCError: opt.ignore_mdc_error = 1; break; case oNoRandomSeedFile: use_random_seed = 0; break; case oAutoKeyImport: opt.flags.auto_key_import = 1; break; case oNoAutoKeyImport: opt.flags.auto_key_import = 0; break; case oAutoKeyRetrieve: opt.keyserver_options.options |= KEYSERVER_AUTO_KEY_RETRIEVE; break; case oNoAutoKeyRetrieve: opt.keyserver_options.options &= ~KEYSERVER_AUTO_KEY_RETRIEVE; break; case oShowSessionKey: opt.show_session_key = 1; break; case oOverrideSessionKey: opt.override_session_key = pargs.r.ret_str; break; case oOverrideSessionKeyFD: ovrseskeyfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); break; case oMergeOnly: deprecated_warning(configname,pargs.lineno,"--merge-only", "--import-options ","merge-only"); opt.import_options|=IMPORT_MERGE_ONLY; break; case oAllowSecretKeyImport: /* obsolete */ break; case oTryAllSecrets: opt.try_all_secrets = 1; break; case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; case oEnableSpecialFilenames: enable_special_filenames (); break; case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break; case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break; case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break; case oPreservePermissions: opt.preserve_permissions=1; break; case oDefaultPreferenceList: opt.def_preference_list = pargs.r.ret_str; break; case oDefaultKeyserverURL: { keyserver_spec_t keyserver; keyserver = parse_keyserver_uri (pargs.r.ret_str,1 ); if (!keyserver) log_error (_("could not parse keyserver URL\n")); else free_keyserver_spec (keyserver); opt.def_keyserver_url = pargs.r.ret_str; } break; case oPersonalCipherPreferences: pers_cipher_list=pargs.r.ret_str; break; case oPersonalDigestPreferences: pers_digest_list=pargs.r.ret_str; break; case oPersonalCompressPreferences: pers_compress_list=pargs.r.ret_str; break; case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break; case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; case oDisableDirmngr: opt.disable_dirmngr = 1; break; case oWeakDigest: additional_weak_digest(pargs.r.ret_str); break; case oUnwrap: opt.unwrap_encryption = 1; break; case oOnlySignTextIDs: opt.only_sign_text_ids = 1; break; case oDisplay: set_opt_session_env ("DISPLAY", pargs.r.ret_str); break; case oTTYname: set_opt_session_env ("GPG_TTY", pargs.r.ret_str); break; case oTTYtype: set_opt_session_env ("TERM", pargs.r.ret_str); break; case oXauthority: set_opt_session_env ("XAUTHORITY", pargs.r.ret_str); break; case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; case oGroup: add_group(pargs.r.ret_str); break; case oUnGroup: rm_group(pargs.r.ret_str); break; case oNoGroups: while(opt.grouplist) { struct groupitem *iter=opt.grouplist; free_strlist(iter->values); opt.grouplist=opt.grouplist->next; xfree(iter); } break; case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; case oEnableProgressFilter: opt.enable_progress_filter = 1; break; case oMultifile: multifile=1; break; case oKeyidFormat: if(ascii_strcasecmp(pargs.r.ret_str,"short")==0) opt.keyid_format=KF_SHORT; else if(ascii_strcasecmp(pargs.r.ret_str,"long")==0) opt.keyid_format=KF_LONG; else if(ascii_strcasecmp(pargs.r.ret_str,"0xshort")==0) opt.keyid_format=KF_0xSHORT; else if(ascii_strcasecmp(pargs.r.ret_str,"0xlong")==0) opt.keyid_format=KF_0xLONG; else if(ascii_strcasecmp(pargs.r.ret_str,"none")==0) opt.keyid_format = KF_NONE; else log_error("unknown keyid-format '%s'\n",pargs.r.ret_str); break; case oExitOnStatusWriteError: opt.exit_on_status_write_error = 1; break; case oLimitCardInsertTries: opt.limit_card_insert_tries = pargs.r.ret_int; break; case oRequireCrossCert: opt.flags.require_cross_cert=1; break; case oNoRequireCrossCert: opt.flags.require_cross_cert=0; break; case oAutoKeyLocate: if (default_akl) { /* This is the first time --auto-key-locate is seen. * We need to reset the default akl. */ default_akl = 0; release_akl(); } if(!parse_auto_key_locate(pargs.r.ret_str)) { if(configname) log_error(_("%s:%d: invalid auto-key-locate list\n"), configname,pargs.lineno); else log_error(_("invalid auto-key-locate list\n")); } break; case oNoAutoKeyLocate: release_akl(); break; case oKeyOrigin: if(!parse_key_origin (pargs.r.ret_str)) log_error (_("invalid argument for option \"%.50s\"\n"), "--key-origin"); break; case oEnableLargeRSA: #if SECMEM_BUFFER_SIZE >= 65536 opt.flags.large_rsa=1; #else if (configname) log_info("%s:%d: WARNING: gpg not built with large secure " "memory buffer. Ignoring enable-large-rsa\n", configname,pargs.lineno); else log_info("WARNING: gpg not built with large secure " "memory buffer. Ignoring --enable-large-rsa\n"); #endif /* SECMEM_BUFFER_SIZE >= 65536 */ break; case oDisableLargeRSA: opt.flags.large_rsa=0; break; case oEnableDSA2: opt.flags.dsa2=1; break; case oDisableDSA2: opt.flags.dsa2=0; break; case oAllowWeakDigestAlgos: opt.flags.allow_weak_digest_algos = 1; break; case oAllowWeakKeySignatures: opt.flags.allow_weak_key_signatures = 1; break; case oAllowOldCipherAlgos: opt.flags.allow_old_cipher_algos = 1; break; case oOverrideComplianceCheck: opt.flags.override_compliance_check = 1; break; case oFakedSystemTime: { size_t len = strlen (pargs.r.ret_str); int freeze = 0; time_t faked_time; if (len > 0 && pargs.r.ret_str[len-1] == '!') { freeze = 1; pargs.r.ret_str[len-1] = '\0'; } faked_time = isotime2epoch (pargs.r.ret_str); if (faked_time == (time_t)(-1)) faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10); gnupg_set_time (faked_time, freeze); } break; case oNoAutostart: opt.autostart = 0; break; case oNoSymkeyCache: opt.no_symkey_cache = 1; break; case oDefaultNewKeyAlgo: opt.def_new_key_algo = pargs.r.ret_str; break; case oUseOnlyOpenPGPCard: opt.flags.use_only_openpgp_card = 1; break; case oFullTimestrings: opt.flags.full_timestrings = 1; break; case oForbidGenKey: mopt.forbid_gen_key = 1; break; case oRequireCompliance: opt.flags.require_compliance = 1; break; case oNoop: break; default: if (configname) pargs.err = ARGPARSE_PRINT_WARNING; else { pargs.err = ARGPARSE_PRINT_ERROR; /* The argparse function calls a plain exit and thus * we need to print a status here. */ write_status_failure ("option-parser", gpg_error(GPG_ERR_GENERAL)); } break; } } gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */ if (log_get_errorcount (0)) { write_status_failure ("option-parser", gpg_error(GPG_ERR_GENERAL)); g10_exit(2); } /* Process common component options. */ if (parse_comopt (GNUPG_MODULE_NAME_GPG, debug_argparser)) { write_status_failure ("option-parser", gpg_error(GPG_ERR_GENERAL)); g10_exit(2); } if (opt.use_keyboxd) log_info ("Note: Please move option \"%s\" to \"common.conf\"\n", "use-keyboxd"); opt.use_keyboxd = comopt.use_keyboxd; /* Override. */ if (opt.keyboxd_program) log_info ("Note: Please move option \"%s\" to \"common.conf\"\n", "keyboxd-program"); if (!opt.keyboxd_program && comopt.keyboxd_program) { opt.keyboxd_program = comopt.keyboxd_program; comopt.keyboxd_program = NULL; } if (comopt.no_autostart) opt.autostart = 0; /* The command --gpgconf-list is pretty simple and may be called directly after the option parsing. */ if (cmd == aGPGConfList) { gpgconf_list (); g10_exit (0); } xfree (last_configname); if (print_dane_records) log_error ("invalid option \"%s\"; use \"%s\" instead\n", "--print-dane-records", "--export-options export-dane"); if (log_get_errorcount (0)) { write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); g10_exit(2); } if( nogreeting ) greeting = 0; if( greeting ) { es_fprintf (es_stderr, "%s %s; %s\n", gpgrt_strusage(11), gpgrt_strusage(13), gpgrt_strusage(14)); es_fprintf (es_stderr, "%s\n", gpgrt_strusage(15) ); } #ifdef IS_DEVELOPMENT_VERSION if (!opt.batch) { const char *s; if((s=gpgrt_strusage(25))) log_info("%s\n",s); if((s=gpgrt_strusage(26))) log_info("%s\n",s); if((s=gpgrt_strusage(27))) log_info("%s\n",s); } #endif /* Init threading which is used by some helper functions. */ npth_init (); assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH); gpgrt_set_syscall_clamp (npth_unprotect, npth_protect); if (logfile) { log_set_file (logfile); log_set_prefix (NULL, (GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID )); } if (opt.verbose > 2) log_info ("using character set '%s'\n", get_native_charset ()); if( may_coredump && !opt.quiet ) log_info(_("WARNING: program may create a core file!\n")); if (eyes_only) { if (opt.set_filename) log_info(_("WARNING: %s overrides %s\n"), "--for-your-eyes-only","--set-filename"); opt.set_filename="_CONSOLE"; } if (opt.no_literal) { log_info(_("Note: %s is not for normal use!\n"), "--no-literal"); if (opt.textmode) log_error(_("%s not allowed with %s!\n"), "--textmode", "--no-literal" ); if (opt.set_filename) log_error(_("%s makes no sense with %s!\n"), eyes_only?"--for-your-eyes-only":"--set-filename", "--no-literal" ); } if (opt.set_filesize) log_info(_("Note: %s is not for normal use!\n"), "--set-filesize"); if( opt.batch ) tty_batchmode( 1 ); if (gnupg_faked_time_p ()) { gnupg_isotime_t tbuf; log_info (_("WARNING: running with faked system time: ")); gnupg_get_isotime (tbuf); dump_isotime (tbuf); log_printf ("\n"); } /* Print a warning if an argument looks like an option. */ if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN)) { int i; 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]); } gcry_control (GCRYCTL_RESUME_SECMEM_WARN); if(require_secmem && !got_secmem) { log_info(_("will not run with insecure memory due to %s\n"), "--require-secmem"); write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); g10_exit(2); } /* We allow overriding the compliance check only in non-batch mode * so that the user has a chance to see the message. */ if (opt.flags.override_compliance_check && opt.batch) { opt.flags.override_compliance_check = 0; log_info ("Note: '%s' ignored due to batch mode\n", "--override-compliance-check"); } set_debug (debug_level); if (opt.verbose) /* Print the compatibility flags. */ parse_compatibility_flags (NULL, &opt.compat_flags, compatibility_flags); gnupg_set_compliance_extra_info (opt.min_rsa_length); if (DBG_CLOCK) log_clock ("start"); /* Do these after the switch(), so they can override settings. */ if (PGP7) { /* That does not anymore work because we have no more support for v3 signatures. */ opt.escape_from=1; opt.ask_sig_expire=0; } else if(PGP8) { opt.escape_from=1; } if( def_cipher_string ) { opt.def_cipher_algo = string_to_cipher_algo (def_cipher_string); xfree(def_cipher_string); def_cipher_string = NULL; if ( openpgp_cipher_test_algo (opt.def_cipher_algo) ) log_error(_("selected cipher algorithm is invalid\n")); } if( def_digest_string ) { opt.def_digest_algo = string_to_digest_algo (def_digest_string); xfree(def_digest_string); def_digest_string = NULL; if ( openpgp_md_test_algo (opt.def_digest_algo) ) log_error(_("selected digest algorithm is invalid\n")); } if( compress_algo_string ) { opt.compress_algo = string_to_compress_algo(compress_algo_string); xfree(compress_algo_string); compress_algo_string = NULL; if( check_compress_algo(opt.compress_algo) ) log_error(_("selected compression algorithm is invalid\n")); } if( cert_digest_string ) { opt.cert_digest_algo = string_to_digest_algo (cert_digest_string); xfree(cert_digest_string); cert_digest_string = NULL; if (openpgp_md_test_algo(opt.cert_digest_algo)) log_error(_("selected certification digest algorithm is invalid\n")); } if( s2k_cipher_string ) { opt.s2k_cipher_algo = string_to_cipher_algo (s2k_cipher_string); xfree(s2k_cipher_string); s2k_cipher_string = NULL; if (openpgp_cipher_test_algo (opt.s2k_cipher_algo)) log_error(_("selected cipher algorithm is invalid\n")); } if( s2k_digest_string ) { opt.s2k_digest_algo = string_to_digest_algo (s2k_digest_string); xfree(s2k_digest_string); s2k_digest_string = NULL; if (openpgp_md_test_algo(opt.s2k_digest_algo)) log_error(_("selected digest algorithm is invalid\n")); } if( opt.completes_needed < 1 ) log_error(_("completes-needed must be greater than 0\n")); if( opt.marginals_needed < 2 ) log_error(_("marginals-needed must be greater than 1\n")); if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) log_error(_("max-cert-depth must be in the range from 1 to 255\n")); if(opt.def_cert_level<0 || opt.def_cert_level>3) log_error(_("invalid default-cert-level; must be 0, 1, 2, or 3\n")); if( opt.min_cert_level < 1 || opt.min_cert_level > 3 ) log_error(_("invalid min-cert-level; must be 1, 2, or 3\n")); switch( opt.s2k_mode ) { case 0: if (!opt.quiet) log_info(_("Note: simple S2K mode (0) is strongly discouraged\n")); break; case 1: case 3: break; default: log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); } /* This isn't actually needed, but does serve to error out if the string is invalid. */ if(opt.def_preference_list && keygen_set_std_prefs(opt.def_preference_list,0)) log_error(_("invalid default preferences\n")); if(pers_cipher_list && keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM)) log_error(_("invalid personal cipher preferences\n")); if(pers_digest_list && keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH)) log_error(_("invalid personal digest preferences\n")); if(pers_compress_list && keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) log_error(_("invalid personal compress preferences\n")); /* Check chunk size. Please fix also the man page if you change * the default. The limits are given by the specs. */ if (!opt.chunk_size) opt.chunk_size = 22; /* Default to the suggested max of 4 MiB. */ else if (opt.chunk_size < 6) { opt.chunk_size = 6; log_info (_("chunk size invalid - using %d\n"), opt.chunk_size); } else if (opt.chunk_size > (allow_large_chunks? 62 : 22)) { opt.chunk_size = (allow_large_chunks? 62 : 22); log_info (_("chunk size invalid - using %d\n"), opt.chunk_size); } /* We don't support all possible commands with multifile yet */ if(multifile) { char *cmdname; switch(cmd) { case aSign: cmdname="--sign"; break; case aSignEncr: cmdname="--sign --encrypt"; break; case aClearsign: cmdname="--clear-sign"; break; case aDetachedSign: cmdname="--detach-sign"; break; case aSym: cmdname="--symmetric"; break; case aEncrSym: cmdname="--symmetric --encrypt"; break; case aStore: cmdname="--store"; break; default: cmdname=NULL; break; } if(cmdname) log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile"); } if( log_get_errorcount(0) ) { write_status_failure ("option-postprocessing", gpg_error(GPG_ERR_GENERAL)); g10_exit (2); } if(opt.compress_level==0) opt.compress_algo=COMPRESS_ALGO_NONE; /* Check our chosen algorithms against the list of legal algorithms. */ if(!GNUPG) { const char *badalg=NULL; preftype_t badtype=PREFTYPE_NONE; if(opt.def_cipher_algo && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) { badalg = openpgp_cipher_algo_name (opt.def_cipher_algo); badtype = PREFTYPE_SYM; } else if(opt.def_digest_algo && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL)) { badalg = gcry_md_algo_name (opt.def_digest_algo); badtype = PREFTYPE_HASH; } else if(opt.cert_digest_algo && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL)) { badalg = gcry_md_algo_name (opt.cert_digest_algo); badtype = PREFTYPE_HASH; } else if(opt.compress_algo!=-1 && !algo_available(PREFTYPE_ZIP,opt.compress_algo,NULL)) { badalg = compress_algo_to_string(opt.compress_algo); badtype = PREFTYPE_ZIP; } if(badalg) { switch(badtype) { case PREFTYPE_SYM: log_info (_("cipher algorithm '%s'" " may not be used in %s mode\n"), badalg, gnupg_compliance_option_string (opt.compliance)); break; case PREFTYPE_HASH: log_info (_("digest algorithm '%s'" " may not be used in %s mode\n"), badalg, gnupg_compliance_option_string (opt.compliance)); break; case PREFTYPE_ZIP: log_info (_("compression algorithm '%s'" " may not be used in %s mode\n"), badalg, gnupg_compliance_option_string (opt.compliance)); break; default: BUG(); } compliance_failure(); } } /* Check our chosen algorithms against the list of allowed * algorithms in the current compliance mode, and fail hard if it * is not. This is us being nice to the user informing her early * that the chosen algorithms are not available. We also check * and enforce this right before the actual operation. */ if (opt.def_cipher_algo && ! gnupg_cipher_is_allowed (opt.compliance, cmd == aEncr || cmd == aSignEncr || cmd == aEncrSym || cmd == aSym || cmd == aSignSym || cmd == aSignEncrSym, opt.def_cipher_algo, GCRY_CIPHER_MODE_NONE)) log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (opt.def_cipher_algo), gnupg_compliance_option_string (opt.compliance)); if (opt.def_digest_algo && ! gnupg_digest_is_allowed (opt.compliance, cmd == aSign || cmd == aSignEncr || cmd == aSignEncrSym || cmd == aSignSym || cmd == aClearsign, opt.def_digest_algo)) log_error (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (opt.def_digest_algo), gnupg_compliance_option_string (opt.compliance)); /* Fail hard. */ if (log_get_errorcount (0)) { write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); g10_exit (2); } /* Set the random seed file. */ if (use_random_seed) { char *p = make_filename (gnupg_homedir (), "random_seed", NULL ); gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); if (!gnupg_access (p, F_OK)) register_secured_file (p); xfree(p); } /* If there is no command but the --fingerprint is given, default to the --list-keys command. */ if (!cmd && fpr_maybe_cmd) { set_cmd (&cmd, aListKeys); } if( opt.verbose > 1 ) set_packet_list_mode(1); /* Add the keyrings, but not for some special commands. We always * need to add the keyrings if we are running under SELinux, this * is so that the rings are added to the list of secured files. * We do not add any keyring if --no-keyring or --use-keyboxd has * been used. */ if (!opt.use_keyboxd && default_keyring >= 0 && (ALWAYS_ADD_KEYRINGS || (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest))) { if (!nrings || default_keyring > 0) /* Add default ring. */ keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT); for (sl = nrings; sl; sl = sl->next ) keydb_add_resource (sl->d, sl->flags); } FREE_STRLIST(nrings); /* In loopback mode, never ask for the password multiple times. */ if (opt.pinentry_mode == PINENTRY_MODE_LOOPBACK) { opt.passphrase_repeat = 0; } /* If no pinentry is expected shunt * gnupg_allow_set_foregound_window to avoid useless error * messages on Windows. */ if (opt.pinentry_mode != PINENTRY_MODE_ASK) { gnupg_inhibit_set_foregound_window (1); } if (cmd == aGPGConfTest) g10_exit(0); if (pwfd != -1) /* Read the passphrase now. */ read_passphrase_from_fd (pwfd); if (ovrseskeyfd != -1 ) /* Read the sessionkey now. */ read_sessionkey_from_fd (ovrseskeyfd); fname = argc? *argv : NULL; if(fname && utf8_strings) opt.flags.utf8_filename=1; ctrl = xcalloc (1, sizeof *ctrl); gpg_init_default_ctrl (ctrl); #ifndef NO_TRUST_MODELS switch (cmd) { case aPrimegen: case aPrintMD: case aPrintMDs: case aGenRandom: case aDeArmor: case aEnArmor: case aListConfig: case aListGcryptConfig: break; case aFixTrustDB: case aExportOwnerTrust: rc = setup_trustdb (0, trustdb_name); break; case aListTrustDB: rc = setup_trustdb (argc? 1:0, trustdb_name); break; case aKeygen: case aFullKeygen: case aQuickKeygen: rc = setup_trustdb (1, trustdb_name); break; default: /* If we are using TM_ALWAYS, we do not need to create the trustdb. */ rc = setup_trustdb (opt.trust_model != TM_ALWAYS, trustdb_name); break; } if (rc) log_error (_("failed to initialize the TrustDB: %s\n"), gpg_strerror (rc)); #endif /*!NO_TRUST_MODELS*/ switch (cmd) { case aStore: case aSym: case aSign: case aSignSym: case aClearsign: if (!opt.quiet && any_explicit_recipient) log_info (_("WARNING: recipients (-r) given " "without using public key encryption\n")); break; default: break; } /* Check for certain command whether we need to migrate a secring.gpg to the gpg-agent. */ switch (cmd) { case aListSecretKeys: case aSign: case aSignEncr: case aSignEncrSym: case aSignSym: case aClearsign: case aDecrypt: case aSignKey: case aLSignKey: case aEditKey: case aPasswd: case aDeleteSecretKeys: case aDeleteSecretAndPublicKeys: case aQuickKeygen: case aQuickAddUid: case aQuickAddKey: case aQuickRevUid: case aQuickSetPrimaryUid: case aQuickUpdatePref: case aFullKeygen: case aKeygen: case aImport: case aExportSecret: case aExportSecretSub: case aGenRevoke: case aDesigRevoke: case aCardEdit: case aChangePIN: migrate_secring (ctrl); break; case aListKeys: if (opt.with_secret) migrate_secring (ctrl); break; default: break; } /* The command dispatcher. */ switch( cmd ) { case aServer: gpg_server (ctrl); break; case aStore: /* only store the file */ if( argc > 1 ) wrong_args("--store [filename]"); if( (rc = encrypt_store(fname)) ) { write_status_failure ("store", rc); log_error ("storing '%s' failed: %s\n", print_fname_stdin(fname),gpg_strerror (rc) ); } break; case aSym: /* encrypt the given file only with the symmetric cipher */ if( argc > 1 ) wrong_args("--symmetric [filename]"); if( (rc = encrypt_symmetric(fname)) ) { write_status_failure ("symencrypt", rc); log_error (_("symmetric encryption of '%s' failed: %s\n"), print_fname_stdin(fname),gpg_strerror (rc) ); } break; case aEncr: /* encrypt the given file */ if(multifile) encrypt_crypt_files (ctrl, argc, argv, remusr); else { if( argc > 1 ) wrong_args("--encrypt [filename]"); if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 0, NULL, -1)) ) { write_status_failure ("encrypt", rc); log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } } break; case aEncrSym: /* This works with PGP 8 in the sense that it acts just like a symmetric message. It doesn't work at all with 2 or 6. It might work with 7, but alas, I don't have a copy to test with right now. */ if( argc > 1 ) wrong_args("--symmetric --encrypt [filename]"); else if(opt.s2k_mode==0) log_error(_("you cannot use --symmetric --encrypt" " with --s2k-mode 0\n")); else if (PGP7) log_error(_("you cannot use --symmetric --encrypt" " in %s mode\n"), gnupg_compliance_option_string (opt.compliance)); else { if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 1, NULL, -1)) ) { write_status_failure ("encrypt", rc); log_error ("%s: encryption failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } } break; case aSign: /* sign the given file */ sl = NULL; if( detached_sig ) { /* sign all files */ for( ; argc; argc--, argv++ ) add_to_strlist( &sl, *argv ); } else { if( argc > 1 ) wrong_args("--sign [filename]"); if( argc ) { sl = xmalloc_clear( sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } } if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 0, NULL, NULL))) { write_status_failure ("sign", rc); log_error ("signing failed: %s\n", gpg_strerror (rc) ); } free_strlist(sl); break; case aSignEncr: /* sign and encrypt the given file */ if( argc > 1 ) wrong_args("--sign --encrypt [filename]"); if( argc ) { sl = xmalloc_clear( sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } else sl = NULL; if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 1, remusr, NULL))) { write_status_failure ("sign-encrypt", rc); log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } free_strlist(sl); break; case aSignEncrSym: /* sign and encrypt the given file */ if( argc > 1 ) wrong_args("--symmetric --sign --encrypt [filename]"); else if(opt.s2k_mode==0) log_error(_("you cannot use --symmetric --sign --encrypt" " with --s2k-mode 0\n")); else if (PGP7) log_error(_("you cannot use --symmetric --sign --encrypt" " in %s mode\n"), gnupg_compliance_option_string (opt.compliance)); else { if( argc ) { sl = xmalloc_clear( sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } else sl = NULL; if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 2, remusr, NULL))) { write_status_failure ("sign-encrypt", rc); log_error("%s: symmetric+sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } free_strlist(sl); } break; case aSignSym: /* sign and conventionally encrypt the given file */ if (argc > 1) wrong_args("--sign --symmetric [filename]"); rc = sign_symencrypt_file (ctrl, fname, locusr); if (rc) { write_status_failure ("sign-symencrypt", rc); log_error("%s: sign+symmetric failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } break; case aClearsign: /* make a clearsig */ if( argc > 1 ) wrong_args("--clear-sign [filename]"); if( (rc = clearsign_file (ctrl, fname, locusr, NULL)) ) { write_status_failure ("sign", rc); log_error("%s: clear-sign failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); } break; case aVerify: if (multifile) { if ((rc = verify_files (ctrl, argc, argv))) log_error("verify files failed: %s\n", gpg_strerror (rc) ); } else { if ((rc = verify_signatures (ctrl, argc, argv))) log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); } if (rc) write_status_failure ("verify", rc); break; case aDecrypt: if (multifile) decrypt_messages (ctrl, argc, argv); else { if( argc > 1 ) wrong_args("--decrypt [filename]"); if( (rc = decrypt_message (ctrl, fname) )) { write_status_failure ("decrypt", rc); log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); } } break; case aQuickSignKey: case aQuickLSignKey: { const char *fpr; if (argc < 1) wrong_args ("--quick-[l]sign-key fingerprint [userids]"); fpr = *argv++; argc--; sl = NULL; for( ; argc; argc--, argv++) append_to_strlist2 (&sl, *argv, utf8_strings); keyedit_quick_sign (ctrl, fpr, sl, locusr, (cmd == aQuickLSignKey)); free_strlist (sl); } break; case aQuickRevSig: { const char *userid, *siguserid; if (argc < 2) wrong_args ("--quick-revoke-sig USER-ID SIG-USER-ID [userids]"); userid = *argv++; argc--; siguserid = *argv++; argc--; sl = NULL; for( ; argc; argc--, argv++) append_to_strlist2 (&sl, *argv, utf8_strings); keyedit_quick_revsig (ctrl, userid, siguserid, sl); free_strlist (sl); } break; case aSignKey: if( argc != 1 ) wrong_args("--sign-key user-id"); /* fall through */ case aLSignKey: if( argc != 1 ) wrong_args("--lsign-key user-id"); /* fall through */ sl=NULL; if(cmd==aSignKey) append_to_strlist(&sl,"sign"); else if(cmd==aLSignKey) append_to_strlist(&sl,"lsign"); else BUG(); append_to_strlist( &sl, "save" ); username = make_username( fname ); keyedit_menu (ctrl, username, locusr, sl, 0, 0 ); xfree(username); free_strlist(sl); break; case aEditKey: /* Edit a key signature */ if( !argc ) wrong_args("--edit-key user-id [commands]"); username = make_username( fname ); if( argc > 1 ) { sl = NULL; for( argc--, argv++ ; argc; argc--, argv++ ) append_to_strlist( &sl, *argv ); keyedit_menu (ctrl, username, locusr, sl, 0, 1 ); free_strlist(sl); } else keyedit_menu (ctrl, username, locusr, NULL, 0, 1 ); xfree(username); break; case aPasswd: if (argc != 1) wrong_args("--change-passphrase "); else { username = make_username (fname); keyedit_passwd (ctrl, username); xfree (username); } break; case aDeleteKeys: case aDeleteSecretKeys: case aDeleteSecretAndPublicKeys: sl = NULL; /* Print a note if the user did not specify any key. */ if (!argc && !opt.quiet) log_info (_("Note: %s\n"), gpg_strerror (GPG_ERR_NO_KEY)); /* I'm adding these in reverse order as add_to_strlist2 reverses them again, and it's easier to understand in the proper order :) */ for( ; argc; argc-- ) add_to_strlist2( &sl, argv[argc-1], utf8_strings ); delete_keys (ctrl, sl, cmd==aDeleteSecretKeys, cmd==aDeleteSecretAndPublicKeys); free_strlist(sl); break; case aCheckKeys: opt.check_sigs = 1; /* fall through */ case aListSigs: opt.list_sigs = 1; /* fall through */ case aListKeys: sl = NULL; for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); public_key_list (ctrl, sl, 0, 0); free_strlist(sl); break; case aListSecretKeys: sl = NULL; for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); secret_key_list (ctrl, sl); free_strlist(sl); break; case aLocateKeys: case aLocateExtKeys: sl = NULL; for (; argc; argc--, argv++) add_to_strlist2( &sl, *argv, utf8_strings ); if (cmd == aLocateExtKeys && akl_empty_or_only_local ()) { /* This is a kludge to let --locate-external-keys even * work if the config file has --no-auto-key-locate. This * better matches the expectations of the user. */ release_akl (); parse_auto_key_locate (DEFAULT_AKL_LIST); } public_key_list (ctrl, sl, 1, cmd == aLocateExtKeys); free_strlist (sl); break; case aQuickKeygen: { const char *x_algo, *x_usage, *x_expire; if (argc < 1 || argc > 4) wrong_args("--quick-generate-key USER-ID [ALGO [USAGE [EXPIRE]]]"); username = make_username (fname); argv++, argc--; x_algo = ""; x_usage = ""; x_expire = ""; if (argc) { x_algo = *argv++; argc--; if (argc) { x_usage = *argv++; argc--; if (argc) { x_expire = *argv++; argc--; } } } if (mopt.forbid_gen_key) gen_key_forbidden (); else quick_generate_keypair (ctrl, username, x_algo, x_usage, x_expire); xfree (username); } break; case aKeygen: /* generate a key */ if (mopt.forbid_gen_key) gen_key_forbidden (); else if( opt.batch ) { if( argc > 1 ) wrong_args("--generate-key [parameterfile]"); generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0); } else { if (opt.command_fd != -1 && argc) { if( argc > 1 ) wrong_args("--generate-key [parameterfile]"); opt.batch = 1; generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0); } else if (argc) wrong_args ("--generate-key"); else generate_keypair (ctrl, 0, NULL, NULL, 0); } break; case aFullKeygen: /* Generate a key with all options. */ if (mopt.forbid_gen_key) gen_key_forbidden (); else if (opt.batch) { if (argc > 1) wrong_args ("--full-generate-key [parameterfile]"); generate_keypair (ctrl, 1, argc? *argv : NULL, NULL, 0); } else { if (argc) wrong_args("--full-generate-key"); generate_keypair (ctrl, 1, NULL, NULL, 0); } break; case aQuickAddUid: { const char *uid, *newuid; if (argc != 2) wrong_args ("--quick-add-uid USER-ID NEW-USER-ID"); uid = *argv++; argc--; newuid = *argv++; argc--; keyedit_quick_adduid (ctrl, uid, newuid); } break; case aQuickAddKey: { const char *x_fpr, *x_algo, *x_usage, *x_expire; if (argc < 1 || argc > 4) wrong_args ("--quick-add-key FINGERPRINT [ALGO [USAGE [EXPIRE]]]"); x_fpr = *argv++; argc--; x_algo = ""; x_usage = ""; x_expire = ""; if (argc) { x_algo = *argv++; argc--; if (argc) { x_usage = *argv++; argc--; if (argc) { x_expire = *argv++; argc--; } } } if (mopt.forbid_gen_key) gen_key_forbidden (); else keyedit_quick_addkey (ctrl, x_fpr, x_algo, x_usage, x_expire); } break; case aQuickRevUid: { const char *uid, *uidtorev; if (argc != 2) wrong_args ("--quick-revoke-uid USER-ID USER-ID-TO-REVOKE"); uid = *argv++; argc--; uidtorev = *argv++; argc--; keyedit_quick_revuid (ctrl, uid, uidtorev); } break; case aQuickSetExpire: { const char *x_fpr, *x_expire; if (argc < 2) wrong_args ("--quick-set-exipre FINGERPRINT EXPIRE [SUBKEY-FPRS]"); x_fpr = *argv++; argc--; x_expire = *argv++; argc--; keyedit_quick_set_expire (ctrl, x_fpr, x_expire, argv); } break; case aQuickSetPrimaryUid: { const char *uid, *primaryuid; if (argc != 2) wrong_args ("--quick-set-primary-uid USER-ID PRIMARY-USER-ID"); uid = *argv++; argc--; primaryuid = *argv++; argc--; keyedit_quick_set_primary (ctrl, uid, primaryuid); } break; case aQuickUpdatePref: { if (argc != 1) wrong_args ("--quick-update-pref USER-ID"); keyedit_quick_update_pref (ctrl, *argv); } break; case aFastImport: opt.import_options |= IMPORT_FAST; /* fall through */ case aImport: case aShowKeys: import_keys (ctrl, argc? argv:NULL, argc, NULL, opt.import_options, opt.key_origin, opt.key_origin_url); break; /* TODO: There are a number of command that use this same "make strlist, call function, report error, free strlist" pattern. Join them together here and avoid all that duplicated code. */ case aExport: case aSendKeys: case aRecvKeys: sl = NULL; for( ; argc; argc--, argv++ ) append_to_strlist2( &sl, *argv, utf8_strings ); if( cmd == aSendKeys ) rc = keyserver_export (ctrl, sl ); else if( cmd == aRecvKeys ) rc = keyserver_import (ctrl, sl ); else { export_stats_t stats = export_new_stats (); rc = export_pubkeys (ctrl, sl, opt.export_options, stats); export_print_stats (stats); export_release_stats (stats); } if(rc) { if(cmd==aSendKeys) { write_status_failure ("send-keys", rc); log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc)); } else if(cmd==aRecvKeys) { write_status_failure ("recv-keys", rc); log_error (_("keyserver receive failed: %s\n"), gpg_strerror (rc)); } else { write_status_failure ("export", rc); log_error (_("key export failed: %s\n"), gpg_strerror (rc)); } } free_strlist(sl); break; case aExportSshKey: if (argc != 1) wrong_args ("--export-ssh-key "); rc = export_ssh_key (ctrl, argv[0]); if (rc) { write_status_failure ("export-ssh-key", rc); log_error (_("export as ssh key failed: %s\n"), gpg_strerror (rc)); } break; case aExportSecretSshKey: if (argc != 1) wrong_args ("--export-secret-ssh-key "); rc = export_secret_ssh_key (ctrl, argv[0]); if (rc) { write_status_failure ("export-ssh-key", rc); log_error (_("export as ssh key failed: %s\n"), gpg_strerror (rc)); } break; case aSearchKeys: sl = NULL; for (; argc; argc--, argv++) append_to_strlist2 (&sl, *argv, utf8_strings); rc = keyserver_search (ctrl, sl); if (rc) { write_status_failure ("search-keys", rc); log_error (_("keyserver search failed: %s\n"), gpg_strerror (rc)); } free_strlist (sl); break; case aRefreshKeys: sl = NULL; for( ; argc; argc--, argv++ ) append_to_strlist2( &sl, *argv, utf8_strings ); rc = keyserver_refresh (ctrl, sl); if(rc) { write_status_failure ("refresh-keys", rc); log_error (_("keyserver refresh failed: %s\n"),gpg_strerror (rc)); } free_strlist(sl); break; case aFetchKeys: sl = NULL; for( ; argc; argc--, argv++ ) append_to_strlist2( &sl, *argv, utf8_strings ); rc = keyserver_fetch (ctrl, sl, opt.key_origin); free_strlist (sl); if(rc) { write_status_failure ("fetch-keys", rc); log_error ("key fetch failed: %s\n",gpg_strerror (rc)); if (gpg_err_code (rc) == GPG_ERR_NO_DATA) g10_exit (1); /* In this case return 1 and not 2. */ } break; case aExportSecret: sl = NULL; for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); { export_stats_t stats = export_new_stats (); export_seckeys (ctrl, sl, opt.export_options, stats); export_print_stats (stats); export_release_stats (stats); } free_strlist(sl); break; case aExportSecretSub: sl = NULL; for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); { export_stats_t stats = export_new_stats (); export_secsubkeys (ctrl, sl, opt.export_options, stats); export_print_stats (stats); export_release_stats (stats); } free_strlist(sl); break; case aGenRevoke: if( argc != 1 ) wrong_args("--generate-revocation user-id"); username = make_username(*argv); gen_revoke (ctrl, username ); xfree( username ); break; case aDesigRevoke: if (argc != 1) wrong_args ("--generate-designated-revocation user-id"); username = make_username (*argv); gen_desig_revoke (ctrl, username, locusr); xfree (username); break; case aDeArmor: if( argc > 1 ) wrong_args("--dearmor [file]"); rc = dearmor_file( argc? *argv: NULL ); if( rc ) { write_status_failure ("dearmor", rc); log_error (_("dearmoring failed: %s\n"), gpg_strerror (rc)); } break; case aEnArmor: if( argc > 1 ) wrong_args("--enarmor [file]"); rc = enarmor_file( argc? *argv: NULL ); if( rc ) { write_status_failure ("enarmor", rc); log_error (_("enarmoring failed: %s\n"), gpg_strerror (rc)); } break; case aPrimegen: #if 0 /*FIXME*/ { int mode = argc < 2 ? 0 : atoi(*argv); if( mode == 1 && argc == 2 ) { mpi_print (es_stdout, generate_public_prime( atoi(argv[1]) ), 1); } else if( mode == 2 && argc == 3 ) { mpi_print (es_stdout, generate_elg_prime( 0, atoi(argv[1]), atoi(argv[2]), NULL,NULL ), 1); } else if( mode == 3 && argc == 3 ) { MPI *factors; mpi_print (es_stdout, generate_elg_prime( 1, atoi(argv[1]), atoi(argv[2]), NULL,&factors ), 1); es_putc ('\n', es_stdout); mpi_print (es_stdout, factors[0], 1 ); /* print q */ } else if( mode == 4 && argc == 3 ) { MPI g = mpi_alloc(1); mpi_print (es_stdout, generate_elg_prime( 0, atoi(argv[1]), atoi(argv[2]), g, NULL ), 1); es_putc ('\n', es_stdout); mpi_print (es_stdout, g, 1 ); mpi_free (g); } else wrong_args("--gen-prime mode bits [qbits] "); es_putc ('\n', es_stdout); } #endif wrong_args("--gen-prime not yet supported "); break; case aGenRandom: { int level = argc ? atoi(*argv):0; int count = argc > 1 ? atoi(argv[1]): 0; int endless = !count; int hexhack = (level == 16); if (hexhack) level = 1; /* Level 30 uses the same algorithm as our magic wand in * pinentry/gpg-agent. */ if (level == 30) { unsigned int nbits = 150; size_t nbytes = (nbits + 7) / 8; void *rand; char *generated; rand = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM); if (!rand) log_fatal ("failed to generate random password\n"); generated = zb32_encode (rand, nbits); gcry_free (rand); es_fputs (generated, es_stdout); es_putc ('\n', es_stdout); xfree (generated); break; } if (argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0) wrong_args ("--gen-random 0|1|2|16|30 [count]"); while (endless || count) { byte *p; /* We need a multiple of 3, so that in case of armored * output we get a correct string. No linefolding is * done, as it is best to leave this to other tools */ size_t n = !endless && count < 99? count : 99; size_t nn; p = gcry_random_bytes (n, level); #ifdef HAVE_DOSISH_SYSTEM setmode ( fileno(stdout), O_BINARY ); #endif if (hexhack) { for (nn = 0; nn < n; nn++) es_fprintf (es_stdout, "%02x", p[nn]); } else if (opt.armor) { char *tmp = make_radix64_string (p, n); es_fputs (tmp, es_stdout); xfree (tmp); if (n%3 == 1) es_putc ('=', es_stdout); if (n%3) es_putc ('=', es_stdout); } else { es_fwrite( p, n, 1, es_stdout ); } xfree(p); if (!endless) count -= n; } if (opt.armor || hexhack) es_putc ('\n', es_stdout); } break; case aPrintMD: if( argc < 1) wrong_args("--print-md algo [files]"); { int all_algos = (**argv=='*' && !(*argv)[1]); int algo = all_algos? 0 : gcry_md_map_name (*argv); if( !algo && !all_algos ) log_error(_("invalid hash algorithm '%s'\n"), *argv ); else { argc--; argv++; if( !argc ) print_mds(NULL, algo); else { for(; argc; argc--, argv++ ) print_mds(*argv, algo); } } } break; case aPrintMDs: /* old option */ if( !argc ) print_mds(NULL,0); else { for(; argc; argc--, argv++ ) print_mds(*argv,0); } break; #ifndef NO_TRUST_MODELS case aListTrustDB: if( !argc ) list_trustdb (ctrl, es_stdout, NULL); else { for( ; argc; argc--, argv++ ) list_trustdb (ctrl, es_stdout, *argv ); } break; case aUpdateTrustDB: if( argc ) wrong_args("--update-trustdb"); update_trustdb (ctrl); break; case aCheckTrustDB: /* Old versions allowed for arguments - ignore them */ check_trustdb (ctrl); break; case aFixTrustDB: how_to_fix_the_trustdb (); break; case aListTrustPath: if( !argc ) wrong_args("--list-trust-path "); for( ; argc; argc--, argv++ ) { username = make_username( *argv ); list_trust_path( username ); xfree(username); } break; case aExportOwnerTrust: if( argc ) wrong_args("--export-ownertrust"); export_ownertrust (ctrl); break; case aImportOwnerTrust: if( argc > 1 ) wrong_args("--import-ownertrust [file]"); import_ownertrust (ctrl, argc? *argv:NULL ); break; #endif /*!NO_TRUST_MODELS*/ case aRebuildKeydbCaches: if (argc) wrong_args ("--rebuild-keydb-caches"); keydb_rebuild_caches (ctrl, 1); break; #ifdef ENABLE_CARD_SUPPORT case aCardStatus: if (argc == 0) card_status (ctrl, es_stdout, NULL); else if (argc == 1) card_status (ctrl, es_stdout, *argv); else wrong_args ("--card-status [serialno]"); break; case aCardEdit: if (argc) { sl = NULL; for (argc--, argv++ ; argc; argc--, argv++) append_to_strlist (&sl, *argv); card_edit (ctrl, sl); free_strlist (sl); } else card_edit (ctrl, NULL); break; case aChangePIN: if (!argc) change_pin (0,1); else if (argc == 1) change_pin (atoi (*argv),1); else wrong_args ("--change-pin [no]"); break; #endif /* ENABLE_CARD_SUPPORT*/ case aListConfig: { char *str=collapse_args(argc,argv); list_config(str); xfree(str); } break; case aListGcryptConfig: /* Fixme: It would be nice to integrate that with --list-config but unfortunately there is no way yet to have libgcrypt print it to an estream for further parsing. */ gcry_control (GCRYCTL_PRINT_CONFIG, stdout); break; case aTOFUPolicy: #ifdef USE_TOFU { int policy; int i; KEYDB_HANDLE hd; if (argc < 2) wrong_args ("--tofu-policy POLICY KEYID [KEYID...]"); policy = parse_tofu_policy (argv[0]); hd = keydb_new (ctrl); if (! hd) { write_status_failure ("tofu-driver", gpg_error(GPG_ERR_GENERAL)); g10_exit (1); } tofu_begin_batch_update (ctrl); for (i = 1; i < argc; i ++) { KEYDB_SEARCH_DESC desc; kbnode_t kb; rc = classify_user_id (argv[i], &desc, 0); if (rc) { log_error (_("error parsing key specification '%s': %s\n"), argv[i], gpg_strerror (rc)); write_status_failure ("tofu-driver", rc); g10_exit (1); } if (! (desc.mode == KEYDB_SEARCH_MODE_SHORT_KID || desc.mode == KEYDB_SEARCH_MODE_LONG_KID || desc.mode == KEYDB_SEARCH_MODE_FPR || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP)) { log_error (_("'%s' does not appear to be a valid" " key ID, fingerprint or keygrip\n"), argv[i]); write_status_failure ("tofu-driver", gpg_error(GPG_ERR_GENERAL)); g10_exit (1); } rc = keydb_search_reset (hd); if (rc) { /* This should not happen, thus no need to tranalate the string. */ log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); write_status_failure ("tofu-driver", rc); g10_exit (1); } rc = keydb_search (hd, &desc, 1, NULL); if (rc) { log_error (_("key \"%s\" not found: %s\n"), argv[i], gpg_strerror (rc)); write_status_failure ("tofu-driver", rc); g10_exit (1); } rc = keydb_get_keyblock (hd, &kb); if (rc) { log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc)); write_status_failure ("tofu-driver", rc); g10_exit (1); } merge_keys_and_selfsig (ctrl, kb); if (tofu_set_policy (ctrl, kb, policy)) { write_status_failure ("tofu-driver", rc); g10_exit (1); } release_kbnode (kb); } tofu_end_batch_update (ctrl); keydb_release (hd); } #endif /*USE_TOFU*/ break; default: if (!opt.quiet) log_info (_("WARNING: no command supplied." " Trying to guess what you mean ...\n")); /*FALLTHRU*/ case aListPackets: if( argc > 1 ) wrong_args("[filename]"); /* Issue some output for the unix newbie */ if (!fname && !opt.outfile && gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)) && gnupg_isatty (fileno (stderr))) log_info(_("Go ahead and type your message ...\n")); a = iobuf_open(fname); if (a && is_secured_file (iobuf_get_fd (a))) { iobuf_close (a); a = NULL; gpg_err_set_errno (EPERM); } if( !a ) log_error(_("can't open '%s'\n"), print_fname_stdin(fname)); else { if( !opt.no_armor ) { if( use_armor_filter( a ) ) { afx = new_armor_context (); push_armor_filter (afx, a); } } if( cmd == aListPackets ) { opt.list_packets=1; set_packet_list_mode(1); } rc = proc_packets (ctrl, NULL, a ); if( rc ) { write_status_failure ("-", rc); log_error ("processing message failed: %s\n", gpg_strerror (rc)); } iobuf_close(a); } break; } /* cleanup */ gpg_deinit_default_ctrl (ctrl); xfree (ctrl); release_armor_context (afx); FREE_STRLIST(remusr); FREE_STRLIST(locusr); g10_exit(0); return 8; /*NEVER REACHED*/ } /* Note: This function is used by signal handlers!. */ static void emergency_cleanup (void) { gcry_control (GCRYCTL_TERM_SECMEM ); } void g10_exit( int rc ) { /* If we had an error but not printed an error message, do it now. * Note that write_status_failure will never print a second failure * status line. */ if (rc) write_status_failure ("gpg-exit", gpg_error (GPG_ERR_GENERAL)); gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); if (DBG_CLOCK) log_clock ("stop"); if ( (opt.debug & DBG_MEMSTAT_VALUE) ) { keydb_dump_stats (); sig_check_dump_stats (); objcache_dump_stats (); gcry_control (GCRYCTL_DUMP_MEMORY_STATS); gcry_control (GCRYCTL_DUMP_RANDOM_STATS); } if (opt.debug) gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); gnupg_block_all_signals (); emergency_cleanup (); rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0; exit (rc); } /* Pretty-print hex hashes. This assumes at least an 80-character display, but there are a few other similar assumptions in the display code. */ static void print_hex (gcry_md_hd_t md, int algo, const char *fname) { int i,n,count,indent=0; const byte *p; if (fname) indent = es_printf("%s: ",fname); if (indent>40) { es_printf ("\n"); indent=0; } if (algo==DIGEST_ALGO_RMD160) indent += es_printf("RMD160 = "); else if (algo>0) indent += es_printf("%6s = ", gcry_md_algo_name (algo)); else algo = abs(algo); count = indent; p = gcry_md_read (md, algo); n = gcry_md_get_algo_dlen (algo); count += es_printf ("%02X",*p++); for(i=1;i79) { es_printf ("\n%*s",indent,indent?" ":""); count = indent; } else count += es_printf(" "); if (!(i%8)) count += es_printf(" "); } else if (n==20) { if(!(i%2)) { if(count+4>79) { es_printf ("\n%*s",indent,indent?" ":""); count=indent; } else count += es_printf(" "); } if (!(i%10)) count += es_printf(" "); } else { if(!(i%4)) { if (count+8>=79) { es_printf ("\n%*s",indent, indent?" ":""); count=indent; } else count += es_printf(" "); } } count += es_printf("%02X",*p); } es_printf ("\n"); } static void print_hashline( gcry_md_hd_t md, int algo, const char *fname ) { int i, n; const byte *p; if ( fname ) { for (p = fname; *p; p++ ) { if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) es_printf ("%%%02X", *p ); else es_putc (*p, es_stdout); } } es_putc (':', es_stdout); es_printf ("%d:", algo); p = gcry_md_read (md, algo); n = gcry_md_get_algo_dlen (algo); for(i=0; i < n ; i++, p++ ) es_printf ("%02X", *p); es_fputs (":\n", es_stdout); } static void print_mds( const char *fname, int algo ) { estream_t fp; char buf[1024]; size_t n; gcry_md_hd_t md; if (!fname) { fp = es_stdin; es_set_binary (fp); } else { fp = es_fopen (fname, "rb" ); if (fp && is_secured_file (es_fileno (fp))) { es_fclose (fp); fp = NULL; gpg_err_set_errno (EPERM); } } if (!fp) { log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); return; } gcry_md_open (&md, 0, 0); if (algo) gcry_md_enable (md, algo); else { if (!gcry_md_test_algo (GCRY_MD_MD5)) gcry_md_enable (md, GCRY_MD_MD5); gcry_md_enable (md, GCRY_MD_SHA1); if (!gcry_md_test_algo (GCRY_MD_RMD160)) gcry_md_enable (md, GCRY_MD_RMD160); if (!gcry_md_test_algo (GCRY_MD_SHA224)) gcry_md_enable (md, GCRY_MD_SHA224); if (!gcry_md_test_algo (GCRY_MD_SHA256)) gcry_md_enable (md, GCRY_MD_SHA256); if (!gcry_md_test_algo (GCRY_MD_SHA384)) gcry_md_enable (md, GCRY_MD_SHA384); if (!gcry_md_test_algo (GCRY_MD_SHA512)) gcry_md_enable (md, GCRY_MD_SHA512); } while ((n=es_fread (buf, 1, DIM(buf), fp))) gcry_md_write (md, buf, n); if (es_ferror(fp)) log_error ("%s: %s\n", fname?fname:"[stdin]", strerror(errno)); else { gcry_md_final (md); if (opt.with_colons) { if ( algo ) print_hashline (md, algo, fname); else { if (!gcry_md_test_algo (GCRY_MD_MD5)) print_hashline( md, GCRY_MD_MD5, fname ); print_hashline( md, GCRY_MD_SHA1, fname ); if (!gcry_md_test_algo (GCRY_MD_RMD160)) print_hashline( md, GCRY_MD_RMD160, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA224)) print_hashline (md, GCRY_MD_SHA224, fname); if (!gcry_md_test_algo (GCRY_MD_SHA256)) print_hashline( md, GCRY_MD_SHA256, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA384)) print_hashline ( md, GCRY_MD_SHA384, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA512)) print_hashline ( md, GCRY_MD_SHA512, fname ); } } else { if (algo) print_hex (md, -algo, fname); else { if (!gcry_md_test_algo (GCRY_MD_MD5)) print_hex (md, GCRY_MD_MD5, fname); print_hex (md, GCRY_MD_SHA1, fname ); if (!gcry_md_test_algo (GCRY_MD_RMD160)) print_hex (md, GCRY_MD_RMD160, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA224)) print_hex (md, GCRY_MD_SHA224, fname); if (!gcry_md_test_algo (GCRY_MD_SHA256)) print_hex (md, GCRY_MD_SHA256, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA384)) print_hex (md, GCRY_MD_SHA384, fname ); if (!gcry_md_test_algo (GCRY_MD_SHA512)) print_hex (md, GCRY_MD_SHA512, fname ); } } } gcry_md_close (md); if (fp != es_stdin) es_fclose (fp); } /**************** * Check the supplied name,value string and add it to the notation * data to be used for signatures. which==0 for sig notations, and 1 * for cert notations. */ static void add_notation_data( const char *string, int which ) { struct notation *notation; notation=string_to_notation(string,utf8_strings); if(notation) { if(which) { notation->next=opt.cert_notations; opt.cert_notations=notation; } else { notation->next=opt.sig_notations; opt.sig_notations=notation; } } } static void add_policy_url( const char *string, int which ) { unsigned int i,critical=0; strlist_t sl; if(*string=='!') { string++; critical=1; } for(i=0;iflags |= 1; } static void add_keyserver_url( const char *string, int which ) { unsigned int i,critical=0; strlist_t sl; if(*string=='!') { string++; critical=1; } for(i=0;iflags |= 1; } static void read_sessionkey_from_fd (int fd) { int i, len; char *line; if (! gnupg_fd_valid (fd)) log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno)); for (line = NULL, i = len = 100; ; i++ ) { if (i >= len-1 ) { char *tmp = line; len += 100; line = xmalloc_secure (len); if (tmp) { memcpy (line, tmp, i); xfree (tmp); } else i=0; } if (read (fd, line + i, 1) != 1 || line[i] == '\n') break; } line[i] = 0; log_debug ("seskey: %s\n", line); gpgrt_annotate_leaked_object (line); opt.override_session_key = line; } diff --git a/g10/options.h b/g10/options.h index c10862687..fa649f8ca 100644 --- a/g10/options.h +++ b/g10/options.h @@ -1,447 +1,448 @@ /* options.h * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2007, 2010, 2011 Free Software Foundation, Inc. * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef G10_OPTIONS_H #define G10_OPTIONS_H #include #include "../common/types.h" #include #include "main.h" #include "packet.h" #include "tofu.h" #include "../common/session-env.h" #include "../common/compliance.h" /* Object to hold information pertaining to a keyserver; it also allows building a list of keyservers. For historic reasons this is not a strlist_t. */ struct keyserver_spec { struct keyserver_spec *next; char *uri; }; typedef struct keyserver_spec *keyserver_spec_t; /* Global options for GPG. */ EXTERN_UNLESS_MAIN_MODULE struct { int verbose; int quiet; unsigned debug; int armor; char *outfile; estream_t outfp; /* Hack, sometimes used in place of outfile. */ off_t max_output; /* If > 0 a hint with the expected number of input data bytes. This * is not necessary an exact number but intended to be used for * progress info and to decide on how to allocate buffers. */ uint64_t input_size_hint; /* The AEAD chunk size expressed as a power of 2. */ int chunk_size; int dry_run; int autostart; int list_only; int mimemode; int textmode; int expert; const char *def_sig_expire; int ask_sig_expire; const char *def_cert_expire; int ask_cert_expire; int batch; /* run in batch mode */ int answer_yes; /* answer yes on most questions */ int answer_no; /* answer no on most questions */ int check_sigs; /* check key signatures */ int with_colons; int with_key_data; int with_icao_spelling; /* Print ICAO spelling with fingerprints. */ int with_fingerprint; /* Option --with-fingerprint active. */ int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */ int with_keygrip; /* Option --with-keygrip active. */ int with_key_screening;/* Option --with-key-screening active. */ int with_tofu_info; /* Option --with-tofu_info active. */ int with_secret; /* Option --with-secret active. */ int with_wkd_hash; /* Option --with-wkd-hash. */ int with_key_origin; /* Option --with-key-origin. */ int fingerprint; /* list fingerprints */ int list_sigs; /* list signatures */ int no_armor; int list_packets; /* Option --list-packets active. */ int def_cipher_algo; int force_mdc; int disable_mdc; int force_aead; int def_digest_algo; int cert_digest_algo; int compress_algo; + int explicit_compress_option; /* A compress option was explicitly given. */ int compress_level; int bz2_compress_level; int bz2_decompress_lowmem; strlist_t def_secret_key; char *def_recipient; int def_recipient_self; strlist_t secret_keys_to_try; /* A list of mail addresses (addr-spec) provided by the user with * the option --sender. */ strlist_t sender_list; int def_cert_level; int min_cert_level; int ask_cert_level; int emit_version; /* 0 = none, 1 = major only, 2 = major and minor, 3 = full version, 4 = full version plus OS string. */ int marginals_needed; int completes_needed; int max_cert_depth; const char *agent_program; const char *keyboxd_program; const char *dirmngr_program; int disable_dirmngr; const char *def_new_key_algo; /* Options to be passed to the gpg-agent */ session_env_t session_env; char *lc_ctype; char *lc_messages; int skip_verify; int skip_hidden_recipients; /* TM_CLASSIC must be zero to accommodate trustdbsg generated before we started storing the trust model inside the trustdb. */ enum { TM_CLASSIC=0, TM_PGP=1, TM_EXTERNAL=2, TM_ALWAYS, TM_DIRECT, TM_AUTO, TM_TOFU, TM_TOFU_PGP } trust_model; enum tofu_policy tofu_default_policy; int force_ownertrust; enum gnupg_compliance_mode compliance; enum { KF_DEFAULT, KF_NONE, KF_SHORT, KF_LONG, KF_0xSHORT, KF_0xLONG } keyid_format; const char *set_filename; strlist_t comments; int throw_keyids; const char *photo_viewer; int s2k_mode; int s2k_digest_algo; int s2k_cipher_algo; unsigned char s2k_count; /* This is the encoded form, not the raw count */ int not_dash_escaped; int escape_from; int lock_once; keyserver_spec_t keyserver; /* The list of configured keyservers. */ struct { unsigned int options; unsigned int import_options; unsigned int export_options; char *http_proxy; } keyserver_options; int exec_disable; int exec_path_set; unsigned int import_options; unsigned int export_options; unsigned int list_options; unsigned int verify_options; const char *def_preference_list; const char *def_keyserver_url; prefitem_t *personal_cipher_prefs; prefitem_t *personal_digest_prefs; prefitem_t *personal_compress_prefs; struct weakhash *weak_digests; int no_perm_warn; char *temp_dir; int no_encrypt_to; int encrypt_to_default_key; int interactive; struct notation *sig_notations; struct notation *cert_notations; strlist_t sig_policy_url; strlist_t cert_policy_url; strlist_t sig_keyserver_url; strlist_t cert_subpackets; strlist_t sig_subpackets; int allow_non_selfsigned_uid; int allow_freeform_uid; int no_literal; ulong set_filesize; int fast_list_mode; int legacy_list_mode; int ignore_time_conflict; int ignore_valid_from; int ignore_crc_error; int ignore_mdc_error; int command_fd; const char *override_session_key; int show_session_key; const char *gpg_agent_info; int try_all_secrets; int no_expensive_trust_checks; int no_sig_cache; int no_auto_check_trustdb; int preserve_permissions; int no_homedir_creation; struct groupitem *grouplist; int mangle_dos_filenames; int enable_progress_filter; unsigned int screen_columns; unsigned int screen_lines; byte *show_subpackets; int rfc2440_text; unsigned int min_rsa_length; /* Used for compliance checks. */ /* If true, let write failures on the status-fd exit the process. */ int exit_on_status_write_error; /* If > 0, limit the number of card insertion prompts to this value. */ int limit_card_insert_tries; struct { /* If set, require an 0x19 backsig to be present on signatures made by signing subkeys. If not set, a missing backsig is not an error (but an invalid backsig still is). */ unsigned int require_cross_cert:1; unsigned int use_embedded_filename:1; unsigned int utf8_filename:1; unsigned int dsa2:1; unsigned int allow_old_cipher_algos:1; unsigned int allow_weak_digest_algos:1; unsigned int allow_weak_key_signatures:1; unsigned int override_compliance_check:1; unsigned int large_rsa:1; unsigned int disable_signer_uid:1; unsigned int include_key_block:1; unsigned int auto_key_import:1; /* Flag to enable experimental features from RFC4880bis. */ unsigned int rfc4880bis:1; /* Hack: --output is not given but OUTFILE was temporary set to "-". */ unsigned int dummy_outfile:1; /* Force the use of the OpenPGP card and do not allow the use of * another card. */ unsigned int use_only_openpgp_card:1; unsigned int full_timestrings:1; /* Force signing keys even if a key signature already exists. */ unsigned int force_sign_key:1; /* On key generation do not set the ownertrust. */ unsigned int no_auto_trust_new_key:1; /* The next flag is set internally iff IMPORT_SELF_SIGS_ONLY has * been set by the user and is not the default value. */ unsigned int expl_import_self_sigs_only:1; /* The next flag is set internally iff IMPORT_CLEAN has * been set by the user and is not the default value. */ unsigned int expl_import_clean:1; /* Fail if an operation can't be done in the requested compliance * mode. */ unsigned int require_compliance:1; } flags; /* Linked list of ways to find a key if the key isn't on the local keyring. */ struct akl { enum { AKL_NODEFAULT, AKL_LOCAL, AKL_CERT, AKL_PKA, AKL_DANE, AKL_WKD, AKL_LDAP, AKL_NTDS, AKL_KEYSERVER, AKL_SPEC } type; keyserver_spec_t spec; struct akl *next; } *auto_key_locate; /* The value of --key-origin. See parse_key_origin(). */ int key_origin; char *key_origin_url; int passphrase_repeat; int pinentry_mode; int request_origin; int unwrap_encryption; int only_sign_text_ids; int no_symkey_cache; /* Disable the cache used for --symmetric. */ int use_keyboxd; /* Use the external keyboxd as storage backend. */ /* Compatibility flags (COMPAT_FLAG_xxxx). */ unsigned int compat_flags; } opt; /* CTRL is used to keep some global variables we currently can't avoid. Future concurrent versions of gpg will put it into a per request structure CTRL. */ EXTERN_UNLESS_MAIN_MODULE struct { int in_auto_key_retrieve; /* True if we are doing an auto_key_retrieve. */ /* Hack to store the last error. We currently need it because the proc_packet machinery is not able to reliabale return error codes. Thus for the --server purposes we store some of the error codes here. FIXME! */ gpg_error_t lasterr; /* Kludge to silence some warnings using --secret-key-list. */ int silence_parse_warnings; } glo_ctrl; #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ #define DBG_CRYPTO_VALUE 4 /* debug crypto handling */ /* (may reveal sensitive data) */ #define DBG_FILTER_VALUE 8 /* debug internal filter handling */ #define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */ #define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ #define DBG_CACHE_VALUE 64 /* debug the caching */ #define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ #define DBG_TRUST_VALUE 256 /* debug the trustdb */ #define DBG_HASHING_VALUE 512 /* debug hashing operations */ #define DBG_IPC_VALUE 1024 /* debug assuan communication */ #define DBG_CLOCK_VALUE 4096 #define DBG_LOOKUP_VALUE 8192 /* debug the key lookup */ #define DBG_EXTPROG_VALUE 16384 /* debug external program calls */ /* Tests for the debugging flags. */ #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) #define DBG_MPI (opt.debug & DBG_MPI_VALUE) #define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) #define DBG_IPC (opt.debug & DBG_IPC_VALUE) #define DBG_CLOCK (opt.debug & DBG_CLOCK_VALUE) #define DBG_LOOKUP (opt.debug & DBG_LOOKUP_VALUE) #define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) /* FIXME: We need to check why we did not put this into opt. */ #define DBG_MEMORY memory_debug_mode #define DBG_MEMSTAT memory_stat_debug_mode EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode; EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; /* Compatibility flags */ /* #define COMPAT_FOO 1 */ /* Compliance test macors. */ #define GNUPG (opt.compliance==CO_GNUPG || opt.compliance==CO_DE_VS) #define RFC2440 (opt.compliance==CO_RFC2440) #define RFC4880 (opt.compliance==CO_RFC4880) #define PGP7 (opt.compliance==CO_PGP7) #define PGP8 (opt.compliance==CO_PGP8) #define PGPX (PGP7 || PGP8) /* Various option flags. Note that there should be no common string names between the IMPORT_ and EXPORT_ flags as they can be mixed in the keyserver-options option. */ #define IMPORT_LOCAL_SIGS (1<<0) #define IMPORT_REPAIR_PKS_SUBKEY_BUG (1<<1) #define IMPORT_FAST (1<<2) #define IMPORT_SHOW (1<<3) #define IMPORT_MERGE_ONLY (1<<4) #define IMPORT_MINIMAL (1<<5) #define IMPORT_CLEAN (1<<6) #define IMPORT_NO_SECKEY (1<<7) #define IMPORT_KEEP_OWNERTTRUST (1<<8) #define IMPORT_EXPORT (1<<9) #define IMPORT_RESTORE (1<<10) #define IMPORT_REPAIR_KEYS (1<<11) #define IMPORT_DRY_RUN (1<<12) #define IMPORT_SELF_SIGS_ONLY (1<<14) #define IMPORT_COLLAPSE_UIDS (1<<15) #define IMPORT_COLLAPSE_SUBKEYS (1<<16) #define IMPORT_BULK (1<<17) #define EXPORT_LOCAL_SIGS (1<<0) #define EXPORT_ATTRIBUTES (1<<1) #define EXPORT_SENSITIVE_REVKEYS (1<<2) #define EXPORT_RESET_SUBKEY_PASSWD (1<<3) #define EXPORT_MINIMAL (1<<4) #define EXPORT_CLEAN (1<<5) #define EXPORT_DANE_FORMAT (1<<7) #define EXPORT_BACKUP (1<<10) #define EXPORT_REVOCS (1<<11) #define EXPORT_MODE1003 (1<<12) #define LIST_SHOW_PHOTOS (1<<0) #define LIST_SHOW_POLICY_URLS (1<<1) #define LIST_SHOW_STD_NOTATIONS (1<<2) #define LIST_SHOW_USER_NOTATIONS (1<<3) #define LIST_SHOW_NOTATIONS (LIST_SHOW_STD_NOTATIONS|LIST_SHOW_USER_NOTATIONS) #define LIST_SHOW_KEYSERVER_URLS (1<<4) #define LIST_SHOW_UID_VALIDITY (1<<5) #define LIST_SHOW_UNUSABLE_UIDS (1<<6) #define LIST_SHOW_UNUSABLE_SUBKEYS (1<<7) #define LIST_SHOW_KEYRING (1<<8) #define LIST_SHOW_SIG_EXPIRE (1<<9) #define LIST_SHOW_SIG_SUBPACKETS (1<<10) #define LIST_SHOW_USAGE (1<<11) #define LIST_SHOW_ONLY_FPR_MBOX (1<<12) #define LIST_SORT_SIGS (1<<13) #define LIST_SHOW_PREF (1<<14) #define LIST_SHOW_PREF_VERBOSE (1<<15) #define VERIFY_SHOW_PHOTOS (1<<0) #define VERIFY_SHOW_POLICY_URLS (1<<1) #define VERIFY_SHOW_STD_NOTATIONS (1<<2) #define VERIFY_SHOW_USER_NOTATIONS (1<<3) #define VERIFY_SHOW_NOTATIONS (VERIFY_SHOW_STD_NOTATIONS|VERIFY_SHOW_USER_NOTATIONS) #define VERIFY_SHOW_KEYSERVER_URLS (1<<4) #define VERIFY_SHOW_UID_VALIDITY (1<<5) #define VERIFY_SHOW_UNUSABLE_UIDS (1<<6) #define VERIFY_SHOW_PRIMARY_UID_ONLY (1<<9) #define KEYSERVER_HTTP_PROXY (1<<0) #define KEYSERVER_TIMEOUT (1<<1) #define KEYSERVER_ADD_FAKE_V3 (1<<2) #define KEYSERVER_AUTO_KEY_RETRIEVE (1<<3) #define KEYSERVER_HONOR_KEYSERVER_URL (1<<4) #endif /*G10_OPTIONS_H*/ diff --git a/g10/sign.c b/g10/sign.c index 385254987..a66410ebd 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,1989 +1,2006 @@ /* sign.c - sign data * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2007, 2010, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include "gpg.h" #include "options.h" #include "packet.h" #include "../common/status.h" #include "../common/iobuf.h" #include "keydb.h" #include "../common/util.h" #include "main.h" #include "filter.h" #include "../common/ttyio.h" #include "trustdb.h" #include "../common/status.h" #include "../common/i18n.h" #include "pkglue.h" #include "../common/sysutils.h" #include "call-agent.h" #include "../common/mbox-util.h" #include "../common/compliance.h" #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" #else #define LF "\n" #endif /* Bitflags to convey hints on what kind of signayire is created. */ #define SIGNHINT_KEYSIG 1 #define SIGNHINT_SELFSIG 2 /* Hack */ static int recipient_digest_algo; /* A type for the extra data we hash into v5 signature packets. */ struct pt_extra_hash_data_s { unsigned char mode; u32 timestamp; unsigned char namelen; char name[1]; }; typedef struct pt_extra_hash_data_s *pt_extra_hash_data_t; /* * Create notations and other stuff. It is assumed that the strings in * STRLIST are already checked to contain only printable data and have * a valid NAME=VALUE format. */ static void mk_notation_policy_etc (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pk, PKT_public_key *pksk) { const char *string; char *p = NULL; strlist_t pu = NULL; struct notation *nd = NULL; struct expando_args args; log_assert (sig->version >= 4); memset (&args, 0, sizeof(args)); args.pk = pk; args.pksk = pksk; /* Notation data. */ if (IS_ATTST_SIGS(sig)) ; else if (IS_SIG(sig) && opt.sig_notations) nd = opt.sig_notations; else if (IS_CERT(sig) && opt.cert_notations) nd = opt.cert_notations; if (nd) { struct notation *item; for (item = nd; item; item = item->next) { item->altvalue = pct_expando (ctrl, item->value,&args); if (!item->altvalue) log_error (_("WARNING: unable to %%-expand notation " "(too large). Using unexpanded.\n")); } keygen_add_notations (sig, nd); for (item = nd; item; item = item->next) { xfree (item->altvalue); item->altvalue = NULL; } } /* Set policy URL. */ if (IS_ATTST_SIGS(sig)) ; else if (IS_SIG(sig) && opt.sig_policy_url) pu = opt.sig_policy_url; else if (IS_CERT(sig) && opt.cert_policy_url) pu = opt.cert_policy_url; for (; pu; pu = pu->next) { string = pu->d; p = pct_expando (ctrl, string, &args); if (!p) { log_error(_("WARNING: unable to %%-expand policy URL " "(too large). Using unexpanded.\n")); p = xstrdup(string); } build_sig_subpkt (sig, (SIGSUBPKT_POLICY | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)), p, strlen (p)); xfree (p); } /* Preferred keyserver URL. */ if (IS_SIG(sig) && opt.sig_keyserver_url) pu = opt.sig_keyserver_url; for (; pu; pu = pu->next) { string = pu->d; p = pct_expando (ctrl, string, &args); if (!p) { log_error (_("WARNING: unable to %%-expand preferred keyserver URL" " (too large). Using unexpanded.\n")); p = xstrdup (string); } build_sig_subpkt (sig, (SIGSUBPKT_PREF_KS | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)), p, strlen (p)); xfree (p); } /* Set signer's user id. */ if (IS_SIG (sig) && !opt.flags.disable_signer_uid) { char *mbox; /* For now we use the uid which was used to locate the key. */ if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name, 0))) { if (DBG_LOOKUP) log_debug ("setting Signer's UID to '%s'\n", mbox); build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, mbox, strlen (mbox)); xfree (mbox); } else if (opt.sender_list) { /* If a list of --sender was given we scan that list and use * the first one matching a user id of the current key. */ /* FIXME: We need to get the list of user ids for the PKSK * packet. That requires either a function to look it up * again or we need to extend the key packet struct to link * to the primary key which in turn could link to the user * ids. Too much of a change right now. Let's take just * one from the supplied list and hope that the caller * passed a matching one. */ build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, opt.sender_list->d, strlen (opt.sender_list->d)); } } } /* * Put the Key Block subpacket into SIG for key PKSK. Returns an * error code on failure. */ static gpg_error_t mk_sig_subpkt_key_block (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pksk) { gpg_error_t err; char *mbox; char *filterexp = NULL; int save_opt_armor = opt.armor; int save_opt_verbose = opt.verbose; char hexfpr[2*MAX_FINGERPRINT_LEN + 1]; void *data = NULL; size_t datalen; kbnode_t keyblock = NULL; push_export_filters (); opt.armor = 0; hexfingerprint (pksk, hexfpr, sizeof hexfpr); /* Get the user id so that we know which one to insert into the * key. */ if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name, 0))) { if (DBG_LOOKUP) log_debug ("including key with UID '%s' (specified)\n", mbox); filterexp = xasprintf ("keep-uid= -- mbox = %s", mbox); xfree (mbox); } else if (opt.sender_list) { /* If --sender was given we use the first one from that list. */ if (DBG_LOOKUP) log_debug ("including key with UID '%s' (--sender)\n", opt.sender_list->d); filterexp = xasprintf ("keep-uid= -- mbox = %s", opt.sender_list->d); } else /* Use the primary user id. */ { if (DBG_LOOKUP) log_debug ("including key with primary UID\n"); filterexp = xstrdup ("keep-uid= primary -t"); } if (DBG_LOOKUP) log_debug ("export filter expression: %s\n", filterexp); err = parse_and_set_export_filter (filterexp); if (err) goto leave; xfree (filterexp); filterexp = xasprintf ("drop-subkey= fpr <> %s && usage !~ e", hexfpr); if (DBG_LOOKUP) log_debug ("export filter expression: %s\n", filterexp); err = parse_and_set_export_filter (filterexp); if (err) goto leave; opt.verbose = 0; err = export_pubkey_buffer (ctrl, hexfpr, EXPORT_MINIMAL|EXPORT_CLEAN, "", 1, /* Prefix with the reserved byte. */ NULL, &keyblock, &data, &datalen); opt.verbose = save_opt_verbose; if (err) { log_error ("failed to get to be included key: %s\n", gpg_strerror (err)); goto leave; } build_sig_subpkt (sig, SIGSUBPKT_KEY_BLOCK, data, datalen); leave: xfree (data); release_kbnode (keyblock); xfree (filterexp); opt.armor = save_opt_armor; pop_export_filters (); return err; } /* * Helper to hash a user ID packet. */ static void hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid) { byte buf[5]; (void)sigversion; if (uid->attrib_data) { buf[0] = 0xd1; /* Indicates an attribute packet. */ buf[1] = uid->attrib_len >> 24; /* Always use 4 length bytes. */ buf[2] = uid->attrib_len >> 16; buf[3] = uid->attrib_len >> 8; buf[4] = uid->attrib_len; } else { buf[0] = 0xb4; /* Indicates a userid packet. */ buf[1] = uid->len >> 24; /* Always use 4 length bytes. */ buf[2] = uid->len >> 16; buf[3] = uid->len >> 8; buf[4] = uid->len; } gcry_md_write( md, buf, 5 ); if (uid->attrib_data) gcry_md_write (md, uid->attrib_data, uid->attrib_len ); else gcry_md_write (md, uid->name, uid->len ); } /* * Helper to hash some parts from the signature. EXTRAHASH gives the * extra data to be hashed into v5 signatures; it may by NULL for * detached signatures. */ static void hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig, pt_extra_hash_data_t extrahash) { byte buf[10]; int i; size_t n; gcry_md_putc (md, sig->version); gcry_md_putc (md, sig->sig_class); gcry_md_putc (md, sig->pubkey_algo); gcry_md_putc (md, sig->digest_algo); if (sig->hashed) { n = sig->hashed->len; gcry_md_putc (md, (n >> 8) ); gcry_md_putc (md, n ); gcry_md_write (md, sig->hashed->data, n ); n += 6; } else { gcry_md_putc (md, 0); /* Always hash the length of the subpacket. */ gcry_md_putc (md, 0); n = 6; } /* Hash data from the literal data packet. */ if (sig->version >= 5 && (sig->sig_class == 0x00 || sig->sig_class == 0x01)) { /* - One octet content format * - File name (one octet length followed by the name) * - Four octet timestamp */ if (extrahash) { buf[0] = extrahash->mode; buf[1] = extrahash->namelen; gcry_md_write (md, buf, 2); if (extrahash->namelen) gcry_md_write (md, extrahash->name, extrahash->namelen); buf[0] = extrahash->timestamp >> 24; buf[1] = extrahash->timestamp >> 16; buf[2] = extrahash->timestamp >> 8; buf[3] = extrahash->timestamp; gcry_md_write (md, buf, 4); } else /* Detached signatures */ { memset (buf, 0, 6); gcry_md_write (md, buf, 6); } } /* Add some magic aka known as postscript. The idea was to make it * impossible to make up a document with a v3 signature and then * turn this into a v4 signature for another document. The last * hashed 5 bytes of a v4 signature should never look like a the * last 5 bytes of a v3 signature. The length can be used to parse * from the end. */ i = 0; buf[i++] = sig->version; /* Hash convention version. */ buf[i++] = 0xff; /* Not any sig type value. */ if (sig->version >= 5) { /* Note: We don't hashed any data larger than 2^32 and thus we * can always use 0 here. See also note below. */ buf[i++] = 0; buf[i++] = 0; buf[i++] = 0; buf[i++] = 0; } buf[i++] = n >> 24; /* (n is only 16 bit, so this is always 0) */ buf[i++] = n >> 16; buf[i++] = n >> 8; buf[i++] = n; gcry_md_write (md, buf, i); } /* Perform the sign operation. If CACHE_NONCE is given the agent is * advised to use that cached passphrase for the key. SIGNHINTS has * hints so that we can do some additional checks. */ static int do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig, gcry_md_hd_t md, int mdalgo, const char *cache_nonce, unsigned int signhints) { gpg_error_t err; byte *dp; char *hexgrip; if (pksk->timestamp > sig->timestamp ) { ulong d = pksk->timestamp - sig->timestamp; log_info (ngettext("key %s was created %lu second" " in the future (time warp or clock problem)\n", "key %s was created %lu seconds" " in the future (time warp or clock problem)\n", d), keystr_from_pk (pksk), d); if (!opt.ignore_time_conflict) return gpg_error (GPG_ERR_TIME_CONFLICT); } print_pubkey_algo_note (pksk->pubkey_algo); if (!mdalgo) mdalgo = gcry_md_get_algo (md); if ((signhints & SIGNHINT_KEYSIG) && !(signhints & SIGNHINT_SELFSIG) && mdalgo == GCRY_MD_SHA1 && !opt.flags.allow_weak_key_signatures) { /* We do not allow the creation of third-party key signatures * using SHA-1 because we also reject them when verifying. Note * that this will render dsa1024 keys unsuitable for such * keysigs and in turn the WoT. */ print_sha1_keysig_rejected_note (); err = gpg_error (GPG_ERR_DIGEST_ALGO); goto leave; } /* Check compliance. */ if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo)) { log_error (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (mdalgo), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_DIGEST_ALGO); goto leave; } if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pksk->pubkey_algo, 0, pksk->pkey, nbits_from_pk (pksk), NULL)) { log_error (_("key %s may not be used for signing in %s mode\n"), keystr_from_pk (pksk), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_PUBKEY_ALGO); goto leave; } if (!gnupg_rng_is_compliant (opt.compliance)) { err = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", err); goto leave; } print_digest_algo_note (mdalgo); dp = gcry_md_read (md, mdalgo); sig->digest_algo = mdalgo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; mpi_release (sig->data[0]); sig->data[0] = NULL; mpi_release (sig->data[1]); sig->data[1] = NULL; err = hexkeygrip_from_pk (pksk, &hexgrip); if (!err) { char *desc; gcry_sexp_t s_sigval; desc = gpg_format_keydesc (ctrl, pksk, FORMAT_KEYDESC_NORMAL, 1); err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc, pksk->keyid, pksk->main_keyid, pksk->pubkey_algo, dp, gcry_md_get_algo_dlen (mdalgo), mdalgo, &s_sigval); xfree (desc); if (err) ; else if (pksk->pubkey_algo == GCRY_PK_RSA || pksk->pubkey_algo == GCRY_PK_RSA_S) sig->data[0] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_USG); else if (pksk->pubkey_algo == PUBKEY_ALGO_EDDSA && openpgp_oid_is_ed25519 (pksk->pkey[0])) { err = sexp_extract_param_sos_nlz (s_sigval, "r", &sig->data[0]); if (!err) err = sexp_extract_param_sos_nlz (s_sigval, "s", &sig->data[1]); } else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) { err = sexp_extract_param_sos (s_sigval, "r", &sig->data[0]); if (!err) err = sexp_extract_param_sos (s_sigval, "s", &sig->data[1]); } else { sig->data[0] = get_mpi_from_sexp (s_sigval, "r", GCRYMPI_FMT_USG); sig->data[1] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_USG); } gcry_sexp_release (s_sigval); } xfree (hexgrip); leave: if (err) log_error (_("signing failed: %s\n"), gpg_strerror (err)); else { if (opt.verbose) { char *ustr = get_user_id_string_native (ctrl, sig->keyid); log_info (_("%s/%s signature from: \"%s\"\n"), openpgp_pk_algo_name (pksk->pubkey_algo), openpgp_md_algo_name (sig->digest_algo), ustr); xfree (ustr); } } return err; } static int complete_sig (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md, const char *cache_nonce, unsigned int signhints) { int rc; /* if (!(rc = check_secret_key (pksk, 0))) */ rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce, signhints); return rc; } /* Return true if the key seems to be on a version 1 OpenPGP card. This works by asking the agent and may fail if the card has not yet been used with the agent. */ static int openpgp_card_v1_p (PKT_public_key *pk) { gpg_error_t err; int result; /* Shortcut if we are not using RSA: The v1 cards only support RSA thus there is no point in looking any further. */ if (!is_RSA (pk->pubkey_algo)) return 0; if (!pk->flags.serialno_valid) { char *hexgrip; err = hexkeygrip_from_pk (pk, &hexgrip); if (err) { log_error ("error computing a keygrip: %s\n", gpg_strerror (err)); return 0; /* Ooops. */ } xfree (pk->serialno); agent_get_keyinfo (NULL, hexgrip, &pk->serialno, NULL); xfree (hexgrip); pk->flags.serialno_valid = 1; } if (!pk->serialno) result = 0; /* Error from a past agent_get_keyinfo or no card. */ else { /* The version number of the card is included in the serialno. */ result = !strncmp (pk->serialno, "D2760001240101", 14); } return result; } /* Get a matching hash algorithm for DSA and ECDSA. */ static int match_dsa_hash (unsigned int qbytes) { if (qbytes <= 20) return DIGEST_ALGO_SHA1; if (qbytes <= 28) return DIGEST_ALGO_SHA224; if (qbytes <= 32) return DIGEST_ALGO_SHA256; if (qbytes <= 48) return DIGEST_ALGO_SHA384; if (qbytes <= 66 ) /* 66 corresponds to 521 (64 to 512) */ return DIGEST_ALGO_SHA512; return DEFAULT_DIGEST_ALGO; /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong answer we have if a digest larger than 512 bits is requested. */ } /* First try --digest-algo. If that isn't set, see if the recipient has a preferred algorithm (which is also filtered through --personal-digest-prefs). If we're making a signature without a particular recipient (i.e. signing, rather than signing+encrypting) then take the first algorithm in --personal-digest-prefs that is usable for the pubkey algorithm. If --personal-digest-prefs isn't set, then take the OpenPGP default (i.e. SHA-1). Note that EdDSA takes an input of arbitrary length and thus we don't enforce any particular algorithm like we do for standard ECDSA. However, we use SHA256 as the default algorithm. Possible improvement: Use the highest-ranked usable algorithm from the signing key prefs either before or after using the personal list? */ static int hash_for (PKT_public_key *pk) { if (opt.def_digest_algo) { return opt.def_digest_algo; } else if (recipient_digest_algo && !is_weak_digest (recipient_digest_algo)) { return recipient_digest_algo; } else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA) { if (opt.personal_digest_prefs) return opt.personal_digest_prefs[0].value; else if (gcry_mpi_get_nbits (pk->pkey[1]) > 256) return DIGEST_ALGO_SHA512; else return DIGEST_ALGO_SHA256; } else if (pk->pubkey_algo == PUBKEY_ALGO_DSA || pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]); if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA) qbytes = ecdsa_qbits_from_Q (qbytes); qbytes = qbytes/8; /* It's a DSA key, so find a hash that is the same size as q or larger. If q is 160, assume it is an old DSA key and use a 160-bit hash unless --enable-dsa2 is set, in which case act like a new DSA key that just happens to have a 160-bit q (i.e. allow truncation). If q is not 160, by definition it must be a new DSA key. We ignore the personal_digest_prefs for ECDSA because they should always macth the curve and truncated hashes are not useful either. Even worse, smartcards may reject non matching hash lengths for curves (e.g. using SHA-512 with brainpooolP385r1 on a Yubikey). */ if (pk->pubkey_algo == PUBKEY_ALGO_DSA && opt.personal_digest_prefs) { prefitem_t *prefs; if (qbytes != 20 || opt.flags.dsa2) { for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) if (gcry_md_get_algo_dlen (prefs->value) >= qbytes) return prefs->value; } else { for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) if (gcry_md_get_algo_dlen (prefs->value) == qbytes) return prefs->value; } } return match_dsa_hash(qbytes); } else if (openpgp_card_v1_p (pk)) { /* The sk lives on a smartcard, and old smartcards only handle SHA-1 and RIPEMD/160. Newer smartcards (v2.0) don't have this restriction anymore. Fortunately the serial number encodes the version of the card and thus we know that this key is on a v1 card. */ if(opt.personal_digest_prefs) { prefitem_t *prefs; for (prefs=opt.personal_digest_prefs;prefs->type;prefs++) if (prefs->value==DIGEST_ALGO_SHA1 || prefs->value==DIGEST_ALGO_RMD160) return prefs->value; } return DIGEST_ALGO_SHA1; } else if (opt.personal_digest_prefs) { /* It's not DSA, so we can use whatever the first hash algorithm is in the pref list */ return opt.personal_digest_prefs[0].value; } else return DEFAULT_DIGEST_ALGO; } static void print_status_sig_created (PKT_public_key *pk, PKT_signature *sig, int what) { byte array[MAX_FINGERPRINT_LEN]; char buf[100+MAX_FINGERPRINT_LEN*2]; size_t n; snprintf (buf, sizeof buf - 2*MAX_FINGERPRINT_LEN, "%c %d %d %02x %lu ", what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp ); fingerprint_from_pk (pk, array, &n); bin2hex (array, n, buf + strlen (buf)); write_status_text( STATUS_SIG_CREATED, buf ); } /* * Loop over the secret certificates in SK_LIST and build the one pass * signature packets. OpenPGP says that the data should be bracket by * the onepass-sig and signature-packet; so we build these onepass * packet here in reverse order. */ static int write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) { int skcount; SK_LIST sk_rover; for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next) skcount++; for (; skcount; skcount--) { PKT_public_key *pk; PKT_onepass_sig *ops; PACKET pkt; int i, rc; for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) if (++i == skcount) break; pk = sk_rover->pk; ops = xmalloc_clear (sizeof *ops); ops->sig_class = sigclass; ops->digest_algo = hash_for (pk); ops->pubkey_algo = pk->pubkey_algo; keyid_from_pk (pk, ops->keyid); ops->last = (skcount == 1); init_packet (&pkt); pkt.pkttype = PKT_ONEPASS_SIG; pkt.pkt.onepass_sig = ops; rc = build_packet (out, &pkt); free_packet (&pkt, NULL); if (rc) { log_error ("build onepass_sig packet failed: %s\n", gpg_strerror (rc)); return rc; } } return 0; } /* * Helper to write the plaintext (literal data) packet. At * R_EXTRAHASH a malloced object with the with the extra data hashed * into v5 signatures is stored. */ static int write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode, pt_extra_hash_data_t *r_extrahash) { PKT_plaintext *pt = NULL; u32 filesize; int rc = 0; if (!opt.no_literal) pt = setup_plaintext_name (fname, inp); /* Try to calculate the length of the data. */ if ( !iobuf_is_pipe_filename (fname) && *fname) { off_t tmpsize; int overflow; if (!(tmpsize = iobuf_get_filelength (inp, &overflow)) && !overflow && opt.verbose) log_info (_("WARNING: '%s' is an empty file\n"), fname); /* We can't encode the length of very large files because * OpenPGP uses only 32 bit for file sizes. So if the size of a * file is larger than 2^32 minus some bytes for packet headers, * we switch to partial length encoding. */ if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536)) filesize = tmpsize; else filesize = 0; /* Because the text_filter modifies the length of the * data, it is not possible to know the used length * without a double read of the file - to avoid that * we simple use partial length packets. */ if (ptmode == 't' || ptmode == 'u' || ptmode == 'm') filesize = 0; } else filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { PACKET pkt; /* Note that PT has been initialized above in no_literal mode. */ pt->timestamp = make_timestamp (); pt->mode = ptmode; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; init_packet (&pkt); pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ if ((rc = build_packet (out, &pkt))) log_error ("build_packet(PLAINTEXT) failed: %s\n", gpg_strerror (rc) ); *r_extrahash = xtrymalloc (sizeof **r_extrahash + pt->namelen); if (!*r_extrahash) rc = gpg_error_from_syserror (); else { (*r_extrahash)->mode = pt->mode; (*r_extrahash)->timestamp = pt->timestamp; (*r_extrahash)->namelen = pt->namelen; /* Note that the last byte of NAME won't be initialized * because we don't need it. */ memcpy ((*r_extrahash)->name, pt->name, pt->namelen); } pt->buf = NULL; free_packet (&pkt, NULL); } else { byte copy_buffer[4096]; int bytes_copied; *r_extrahash = xtrymalloc (sizeof **r_extrahash); if (!*r_extrahash) { rc = gpg_error_from_syserror (); goto leave; } /* FIXME: We need to parse INP to get the to be hashed data from * it. */ (*r_extrahash)->mode = 0; (*r_extrahash)->timestamp = 0; (*r_extrahash)->namelen = 0; while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1) if ((rc = iobuf_write (out, copy_buffer, bytes_copied))) { log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); break; } wipememory (copy_buffer, 4096); /* burn buffer */ } leave: return rc; } /* * Write the signatures from the SK_LIST to OUT. HASH must be a * non-finalized hash which will not be changes here. EXTRAHASH is * either NULL or the extra data tro be hashed into v5 signatures. */ static int write_signature_packets (ctrl_t ctrl, SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, pt_extra_hash_data_t extrahash, int sigclass, u32 timestamp, u32 duration, int status_letter, const char *cache_nonce) { SK_LIST sk_rover; /* Loop over the certificates with secret keys. */ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { PKT_public_key *pk; PKT_signature *sig; gcry_md_hd_t md; gpg_error_t err; pk = sk_rover->pk; /* Build the signature packet. */ sig = xtrycalloc (1, sizeof *sig); if (!sig) return gpg_error_from_syserror (); if (pk->version >= 5) sig->version = 5; /* Required for v5 keys. */ else sig->version = 4; /* Required. */ keyid_from_pk (pk, sig->keyid); sig->digest_algo = hash_for (pk); sig->pubkey_algo = pk->pubkey_algo; if (timestamp) sig->timestamp = timestamp; else sig->timestamp = make_timestamp(); if (duration) sig->expiredate = sig->timestamp + duration; sig->sig_class = sigclass; if (gcry_md_copy (&md, hash)) BUG (); build_sig_subpkt_from_sig (sig, pk); mk_notation_policy_etc (ctrl, sig, NULL, pk); if (opt.flags.include_key_block && IS_SIG (sig)) err = mk_sig_subpkt_key_block (ctrl, sig, pk); else err = 0; hash_sigversion_to_magic (md, sig, extrahash); gcry_md_final (md); if (!err) err = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0); gcry_md_close (md); if (!err) { /* Write the packet. */ PACKET pkt; init_packet (&pkt); pkt.pkttype = PKT_SIGNATURE; pkt.pkt.signature = sig; err = build_packet (out, &pkt); if (!err && is_status_enabled()) print_status_sig_created (pk, sig, status_letter); free_packet (&pkt, NULL); if (err) log_error ("build signature packet failed: %s\n", gpg_strerror (err)); } else free_seckey_enc (sig); if (err) return err; } return 0; } /* * Sign the files whose names are in FILENAME using all secret keys * which can be taken from LOCUSR, if this is NULL, use the default * secret key. * If DETACHED has the value true, make a detached signature. * If ENCRYPTFLAG is true, use REMUSER (or ask if it is NULL) to encrypt the * signed data for these users. If ENCRYPTFLAG is 2 symmetric encryption * is also used. * If FILENAMES->d is NULL read from stdin and ignore the detached mode. * If OUTFILE is not NULL; this file is used for output and the function * does not ask for overwrite permission; output is then always * uncompressed, non-armored and in binary mode. */ int sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, int encryptflag, strlist_t remusr, const char *outfile ) { const char *fname; armor_filter_context_t *afx; compress_filter_context_t zfx; md_filter_context_t mfx; text_filter_context_t tfx; progress_filter_context_t *pfx; encrypt_filter_context_t efx; iobuf_t inp = NULL; iobuf_t out = NULL; PACKET pkt; int rc = 0; PK_LIST pk_list = NULL; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; int multifile = 0; u32 duration=0; pt_extra_hash_data_t extrahash = NULL; + char peekbuf[32]; + int peekbuflen = 0; + pfx = new_progress_context (); afx = new_armor_context (); memset (&zfx, 0, sizeof zfx); memset (&mfx, 0, sizeof mfx); memset (&efx, 0, sizeof efx); efx.ctrl = ctrl; init_packet (&pkt); if (filenames) { fname = filenames->d; multifile = !!filenames->next; } else fname = NULL; if (fname && filenames->next && (!detached || encryptflag)) log_bug ("multiple files can only be detached signed"); if (encryptflag == 2 && (rc = setup_symkey (&efx.symkey_s2k, &efx.symkey_dek))) goto leave; if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval(1,opt.def_sig_expire); else duration = parse_expire_string(opt.def_sig_expire); /* Note: In the old non-agent version the following call used to * unprotect the secret key. This is now done on demand by the agent. */ if ((rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG ))) goto leave; if (encryptflag && (rc = build_pk_list (ctrl, remusr, &pk_list))) goto leave; /* Prepare iobufs. */ if (multifile) /* have list of filenames */ inp = NULL; /* we do it later */ else { inp = iobuf_open(fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", strerror (errno)); goto leave; } + peekbuflen = iobuf_ioctl (inp, IOBUF_IOCTL_PEEK, sizeof peekbuf, peekbuf); + if (peekbuflen < 0) + { + peekbuflen = 0; + if (DBG_FILTER) + log_debug ("peeking at input failed\n"); + } + handle_progress (pfx, inp, fname); } if (outfile) { if (is_secured_filename (outfile)) { out = NULL; gpg_err_set_errno (EPERM); } else out = iobuf_create (outfile, 0); if (!out) { rc = gpg_error_from_syserror (); log_error (_("can't create '%s': %s\n"), outfile, gpg_strerror (rc)); goto leave; } else if (opt.verbose) log_info (_("writing to '%s'\n"), outfile); } else if ((rc = open_outfile (-1, fname, opt.armor? 1 : detached? 2 : 0, 0, &out))) { goto leave; } /* Prepare to calculate the MD over the input. */ if (opt.textmode && !outfile && !multifile) { memset (&tfx, 0, sizeof tfx); iobuf_push_filter (inp, text_filter, &tfx); } if (gcry_md_open (&mfx.md, 0, 0)) BUG (); if (DBG_HASHING) gcry_md_debug (mfx.md, "sign"); /* If we're encrypting and signing, it is reasonable to pick the * hash algorithm to use out of the recipient key prefs. This is * best effort only, as in a DSA2 and smartcard world there are * cases where we cannot please everyone with a single hash (DSA2 * wants >160 and smartcards want =160). In the future this could * be more complex with different hashes for each sk, but the * current design requires a single hash for all SKs. */ if (pk_list) { if (opt.def_digest_algo) { if (!opt.expert && select_algo_from_prefs (pk_list,PREFTYPE_HASH, opt.def_digest_algo, NULL) != opt.def_digest_algo) { log_info (_("WARNING: forcing digest algorithm %s (%d)" " violates recipient preferences\n"), gcry_md_algo_name (opt.def_digest_algo), opt.def_digest_algo); } } else { int algo; int conflict = 0; struct pref_hint hint = { 0 }; hint.digest_length = 0; /* Of course, if the recipient asks for something * unreasonable (like the wrong hash for a DSA key) then * don't do it. Check all sk's - if any are DSA or live * on a smartcard, then the hash has restrictions and we * may not be able to give the recipient what they want. * For DSA, pass a hint for the largest q we have. Note * that this means that a q>160 key will override a q=160 * key and force the use of truncation for the q=160 key. * The alternative would be to ignore the recipient prefs * completely and get a different hash for each DSA key in * hash_for(). The override behavior here is more or less * reasonable as it is under the control of the user which * keys they sign with for a given message and the fact * that the message with multiple signatures won't be * usable on an implementation that doesn't understand * DSA2 anyway. */ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { int temp_hashlen = gcry_mpi_get_nbits (sk_rover->pk->pkey[1]); if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen); if (!temp_hashlen) conflict = 1; /* Better don't use the prefs. */ temp_hashlen = (temp_hashlen+7)/8; /* Fixup for that funny nistp521 (yes, 521) were * we need to use a 512 bit hash algo. */ if (temp_hashlen == 66) temp_hashlen = 64; } else temp_hashlen = (temp_hashlen+7)/8; /* Pick a hash that is large enough for our largest * Q or matches our Q. If there are several of them * we run into a conflict and don't use the * preferences. */ if (hint.digest_length < temp_hashlen) { if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { if (hint.exact) conflict = 1; hint.exact = 1; } hint.digest_length = temp_hashlen; } } } if (!conflict && (algo = select_algo_from_prefs (pk_list, PREFTYPE_HASH, -1, &hint)) > 0) { /* Note that we later check that the algo is not weak. */ recipient_digest_algo = algo; } } } for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); if (!multifile) iobuf_push_filter (inp, md_filter, &mfx); if (detached && !encryptflag) afx->what = 2; if (opt.armor && !outfile) push_armor_filter (afx, out); if (encryptflag) { efx.pk_list = pk_list; /* fixme: set efx.cfx.datalen if known */ iobuf_push_filter (out, encrypt_filter, &efx); } if (opt.compress_algo && !outfile && !detached) { int compr_algo = opt.compress_algo; - /* If not forced by user */ - if (compr_algo==-1) + if (!opt.explicit_compress_option + && is_file_compressed (peekbuf, peekbuflen)) + { + if (opt.verbose) + log_info(_("'%s' already compressed\n"), fname? fname: "[stdin]"); + compr_algo = 0; + } + else if (compr_algo==-1) { /* If we're not encrypting, then select_algo_from_prefs * will fail and we'll end up with the default. If we are * encrypting, select_algo_from_prefs cannot fail since * there is an assumed preference for uncompressed data. * Still, if it did fail, we'll also end up with the * default. */ if ((compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL)) == -1) { compr_algo = default_compress_algo(); } } else if (!opt.expert && pk_list && select_algo_from_prefs (pk_list, PREFTYPE_ZIP, compr_algo, NULL) != compr_algo) { log_info (_("WARNING: forcing compression algorithm %s (%d)" " violates recipient preferences\n"), compress_algo_to_string (compr_algo), compr_algo); } /* Algo 0 means no compression. */ if (compr_algo) push_compress_filter (out, &zfx, compr_algo); } /* Write the one-pass signature packets if needed */ if (!detached) { rc = write_onepass_sig_packets (sk_list, out, opt.textmode && !outfile ? 0x01:0x00); if (rc) goto leave; } write_status_begin_signing (mfx.md); /* Setup the inner packet. */ if (detached) { size_t iobuf_size = iobuf_set_buffer_size(0) * 1024; if (multifile) { strlist_t sl; if (opt.verbose) log_info (_("signing:") ); /* Must walk reverse trough this list. */ for (sl = strlist_last(filenames); sl; sl = strlist_prev( filenames, sl)) { inp = iobuf_open (sl->d); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), sl->d, gpg_strerror (rc)); goto leave; } handle_progress (pfx, inp, sl->d); if (opt.verbose) log_printf (" '%s'", sl->d ); if (opt.textmode) { memset (&tfx, 0, sizeof tfx); iobuf_push_filter (inp, text_filter, &tfx); } iobuf_push_filter (inp, md_filter, &mfx); while (iobuf_read (inp, NULL, iobuf_size) != -1) ; iobuf_close (inp); inp = NULL; } if (opt.verbose) log_printf ("\n"); } else { /* Read, so that the filter can calculate the digest. */ while (iobuf_read (inp, NULL, iobuf_size) != -1) ; } } else { rc = write_plaintext_packet (out, inp, fname, (opt.textmode && !outfile) ? (opt.mimemode? 'm' : 't') : 'b', &extrahash); } /* Catch errors from above. */ if (rc) goto leave; /* Write the signatures. */ rc = write_signature_packets (ctrl, sk_list, out, mfx.md, extrahash, opt.textmode && !outfile? 0x01 : 0x00, 0, duration, detached ? 'D':'S', NULL); if (rc) goto leave; leave: if (rc) iobuf_cancel (out); else { iobuf_close (out); if (encryptflag) write_status (STATUS_END_ENCRYPTION); } iobuf_close (inp); gcry_md_close (mfx.md); release_sk_list (sk_list); release_pk_list (pk_list); recipient_digest_algo = 0; release_progress_context (pfx); release_armor_context (afx); xfree (extrahash); return rc; } /* * Make a clear signature. Note that opt.armor is not needed. */ int clearsign_file (ctrl_t ctrl, const char *fname, strlist_t locusr, const char *outfile) { armor_filter_context_t *afx; progress_filter_context_t *pfx; gcry_md_hd_t textmd = NULL; iobuf_t inp = NULL; iobuf_t out = NULL; PACKET pkt; int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; u32 duration = 0; pt_extra_hash_data_t extrahash = NULL; pfx = new_progress_context (); afx = new_armor_context (); init_packet( &pkt ); if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval (1, opt.def_sig_expire); else duration = parse_expire_string (opt.def_sig_expire); /* Note: In the old non-agent version the following call used to * unprotect the secret key. This is now done on demand by the agent. */ if ((rc=build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG))) goto leave; /* Prepare iobufs. */ inp = iobuf_open (fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", gpg_strerror (rc)); goto leave; } handle_progress (pfx, inp, fname); if (outfile) { if (is_secured_filename (outfile)) { outfile = NULL; gpg_err_set_errno (EPERM); } else out = iobuf_create (outfile, 0); if (!out) { rc = gpg_error_from_syserror (); log_error (_("can't create '%s': %s\n"), outfile, gpg_strerror (rc)); goto leave; } else if (opt.verbose) log_info (_("writing to '%s'\n"), outfile); } else if ((rc = open_outfile (-1, fname, 1, 0, &out))) { goto leave; } iobuf_writestr (out, "-----BEGIN PGP SIGNED MESSAGE-----" LF); { const char *s; int any = 0; byte hashs_seen[256]; memset (hashs_seen, 0, sizeof hashs_seen); iobuf_writestr (out, "Hash: " ); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { int i = hash_for (sk_rover->pk); if (!hashs_seen[ i & 0xff ]) { s = gcry_md_algo_name (i); if (s) { hashs_seen[ i & 0xff ] = 1; if (any) iobuf_put (out, ','); iobuf_writestr (out, s); any = 1; } } } log_assert (any); iobuf_writestr (out, LF); } if (opt.not_dash_escaped) iobuf_writestr (out, "NotDashEscaped: You need "GPG_NAME " to verify this message" LF); iobuf_writestr (out, LF ); if (gcry_md_open (&textmd, 0, 0)) BUG (); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (textmd, hash_for(sk_rover->pk)); if (DBG_HASHING) gcry_md_debug (textmd, "clearsign"); copy_clearsig_text (out, inp, textmd, !opt.not_dash_escaped, opt.escape_from); /* fixme: check for read errors */ /* Now write the armor. */ afx->what = 2; push_armor_filter (afx, out); /* Prepare EXTRAHASH, so that it can be used for v5 signature. */ extrahash = xtrymalloc (sizeof *extrahash); if (!extrahash) { rc = gpg_error_from_syserror (); goto leave; } else { extrahash->mode = 't'; extrahash->timestamp = 0; extrahash->namelen = 0; } /* Write the signatures. */ rc = write_signature_packets (ctrl, sk_list, out, textmd, extrahash, 0x01, 0, duration, 'C', NULL); if (rc) goto leave; leave: if (rc) iobuf_cancel (out); else iobuf_close (out); iobuf_close (inp); gcry_md_close (textmd); release_sk_list (sk_list); release_progress_context (pfx); release_armor_context (afx); xfree (extrahash); return rc; } /* * Sign and conventionally encrypt the given file. * FIXME: Far too much code is duplicated - revamp the whole file. */ int sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr) { armor_filter_context_t *afx; progress_filter_context_t *pfx; compress_filter_context_t zfx; md_filter_context_t mfx; text_filter_context_t tfx; cipher_filter_context_t cfx; iobuf_t inp = NULL; iobuf_t out = NULL; PACKET pkt; STRING2KEY *s2k = NULL; int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; int algo; u32 duration = 0; int canceled; pt_extra_hash_data_t extrahash = NULL; pfx = new_progress_context (); afx = new_armor_context (); memset (&zfx, 0, sizeof zfx); memset (&mfx, 0, sizeof mfx); memset (&tfx, 0, sizeof tfx); memset (&cfx, 0, sizeof cfx); init_packet (&pkt); if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval (1, opt.def_sig_expire); else duration = parse_expire_string (opt.def_sig_expire); /* Note: In the old non-agent version the following call used to * unprotect the secret key. This is now done on demand by the agent. */ rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG); if (rc) goto leave; /* Prepare iobufs. */ inp = iobuf_open (fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", gpg_strerror (rc)); goto leave; } handle_progress (pfx, inp, fname); /* Prepare key. */ s2k = xmalloc_clear (sizeof *s2k); s2k->mode = opt.s2k_mode; s2k->hash_algo = S2K_DIGEST_ALGO; algo = default_cipher_algo (); cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, 0, &canceled); if (!cfx.dek || !cfx.dek->keylen) { rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE); log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc)); goto leave; } cfx.dek->use_aead = use_aead (NULL, cfx.dek->algo); if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); if (!opt.quiet || !opt.batch) log_info (_("%s.%s encryption will be used\n"), openpgp_cipher_algo_name (algo), cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead) /**/ : "CFB"); /* Now create the outfile. */ rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out); if (rc) goto leave; /* Prepare to calculate the MD over the input. */ if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); if (gcry_md_open (&mfx.md, 0, 0)) BUG (); if (DBG_HASHING) gcry_md_debug (mfx.md, "symc-sign"); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); iobuf_push_filter (inp, md_filter, &mfx); /* Push armor output filter */ if (opt.armor) push_armor_filter (afx, out); /* Write the symmetric key packet */ /* (current filters: armor)*/ { PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc ); enc->version = cfx.dek->use_aead ? 5 : 4; enc->cipher_algo = cfx.dek->algo; enc->aead_algo = cfx.dek->use_aead; enc->s2k = *s2k; pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if ((rc = build_packet (out, &pkt))) log_error ("build symkey packet failed: %s\n", gpg_strerror (rc)); xfree (enc); } /* Push the encryption filter */ iobuf_push_filter (out, cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &cfx); /* Push the compress filter */ if (default_compress_algo()) { if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead)) zfx.new_ctb = 1; push_compress_filter (out, &zfx,default_compress_algo() ); } /* Write the one-pass signature packets */ /* (current filters: zip - encrypt - armor) */ rc = write_onepass_sig_packets (sk_list, out, opt.textmode? 0x01:0x00); if (rc) goto leave; write_status_begin_signing (mfx.md); /* Pipe data through all filters; i.e. write the signed stuff. */ /* (current filters: zip - encrypt - armor) */ rc = write_plaintext_packet (out, inp, fname, opt.textmode ? (opt.mimemode?'m':'t'):'b', &extrahash); if (rc) goto leave; /* Write the signatures. */ /* (current filters: zip - encrypt - armor) */ rc = write_signature_packets (ctrl, sk_list, out, mfx.md, extrahash, opt.textmode? 0x01 : 0x00, 0, duration, 'S', NULL); if (rc) goto leave; leave: if (rc) iobuf_cancel (out); else { iobuf_close (out); write_status (STATUS_END_ENCRYPTION); } iobuf_close (inp); release_sk_list (sk_list); gcry_md_close (mfx.md); xfree (cfx.dek); xfree (s2k); release_progress_context (pfx); release_armor_context (afx); xfree (extrahash); return rc; } /* * Create a v4 signature in *RET_SIG. * * PK is the primary key to sign (required for all sigs) * UID is the user id to sign (required for 0x10..0x13, 0x30) * SUBPK is subkey to sign (required for 0x18, 0x19, 0x28) * * PKSK is the signing key * * SIGCLASS is the type of signature to create. * * DIGEST_ALGO is the digest algorithm. If it is 0 the function * selects an appropriate one. * * TIMESTAMP is the timestamp to use for the signature. 0 means "now" * * DURATION is the amount of time (in seconds) until the signature * expires. * * This function creates the following subpackets: issuer, created, * and expire (if duration is not 0). Additional subpackets can be * added using MKSUBPKT, which is called after these subpackets are * added and before the signature is generated. OPAQUE is passed to * MKSUBPKT. */ int make_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int sigclass, u32 timestamp, u32 duration, int (*mksubpkt)(PKT_signature *, void *), void *opaque, const char *cache_nonce) { PKT_signature *sig; int rc = 0; int sigversion; int digest_algo; gcry_md_hd_t md; u32 pk_keyid[2], pksk_keyid[2]; unsigned int signhints; log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x30 || sigclass == 0x28 ); if (pksk->version >= 5) sigversion = 5; else sigversion = 4; /* Select the digest algo to use. */ if (opt.cert_digest_algo) /* Forceful override by the user. */ digest_algo = opt.cert_digest_algo; else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA) /* Meet DSA requirements. */ digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA) /* Meet ECDSA requirements. */ digest_algo = match_dsa_hash (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8); else if (pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) { if (gcry_mpi_get_nbits (pksk->pkey[1]) > 256) digest_algo = DIGEST_ALGO_SHA512; else digest_algo = DIGEST_ALGO_SHA256; } else /* Use the default. */ digest_algo = DEFAULT_DIGEST_ALGO; signhints = SIGNHINT_KEYSIG; keyid_from_pk (pk, pk_keyid); keyid_from_pk (pksk, pksk_keyid); if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) signhints |= SIGNHINT_SELFSIG; if (gcry_md_open (&md, digest_algo, 0)) BUG (); /* Hash the public key certificate. */ hash_public_key (md, pk); if (sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28) { /* Hash the subkey binding/backsig/revocation. */ hash_public_key (md, subpk); } else if (sigclass != 0x1F && sigclass != 0x20) { /* Hash the user id. */ hash_uid (md, sigversion, uid); } /* Make the signature packet. */ sig = xmalloc_clear (sizeof *sig); sig->version = sigversion; sig->flags.exportable = 1; sig->flags.revocable = 1; keyid_from_pk (pksk, sig->keyid); sig->pubkey_algo = pksk->pubkey_algo; sig->digest_algo = digest_algo; sig->timestamp = timestamp? timestamp : make_timestamp (); if (duration) sig->expiredate = sig->timestamp + duration; sig->sig_class = sigclass; build_sig_subpkt_from_sig (sig, pksk); mk_notation_policy_etc (ctrl, sig, pk, pksk); /* Crucial that the call to mksubpkt comes LAST before the calls * to finalize the sig as that makes it possible for the mksubpkt * function to get a reliable pointer to the subpacket area. */ if (mksubpkt) rc = (*mksubpkt)(sig, opaque); if (!rc) { hash_sigversion_to_magic (md, sig, NULL); gcry_md_final (md); rc = complete_sig (ctrl, sig, pksk, md, cache_nonce, signhints); } gcry_md_close (md); if (rc) free_seckey_enc (sig); else *ret_sig = sig; return rc; } /* * Create a new signature packet based on an existing one. * Only user ID signatures are supported for now. * PK is the public key to work on. * PKSK is the key used to make the signature. * * TODO: Merge this with make_keysig_packet. */ gpg_error_t update_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_signature *orig_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int (*mksubpkt)(PKT_signature *, void *), void *opaque) { PKT_signature *sig; gpg_error_t rc = 0; int digest_algo; gcry_md_hd_t md; u32 pk_keyid[2], pksk_keyid[2]; unsigned int signhints = 0; if ((!orig_sig || !pk || !pksk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) || (orig_sig->sig_class == 0x18 && !subpk)) return GPG_ERR_GENERAL; /* Either use the override digest algo or in the normal case the * original digest algorithm. However, iff the original digest * algorithms is SHA-1 and we are in gnupg or de-vs compliance mode * we switch to SHA-256 (done by the macro). */ if (opt.cert_digest_algo) digest_algo = opt.cert_digest_algo; else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA || pksk->pubkey_algo == PUBKEY_ALGO_ECDSA || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) digest_algo = orig_sig->digest_algo; else if (orig_sig->digest_algo == DIGEST_ALGO_SHA1 || orig_sig->digest_algo == DIGEST_ALGO_RMD160) digest_algo = DEFAULT_DIGEST_ALGO; else digest_algo = orig_sig->digest_algo; signhints = SIGNHINT_KEYSIG; keyid_from_pk (pk, pk_keyid); keyid_from_pk (pksk, pksk_keyid); if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) signhints |= SIGNHINT_SELFSIG; if (gcry_md_open (&md, digest_algo, 0)) BUG (); /* Hash the public key certificate and the user id. */ hash_public_key (md, pk); if (orig_sig->sig_class == 0x18) hash_public_key (md, subpk); else hash_uid (md, orig_sig->version, uid); /* Create a new signature packet. */ sig = copy_signature (NULL, orig_sig); /* Don't generate version 3 signature, but newer. */ if (sig->version == 3) { if (pk->version > 3) sig->version = pk->version; else sig->version = 4; } sig->digest_algo = digest_algo; /* We need to create a new timestamp so that new sig expiration * calculations are done correctly... */ sig->timestamp = make_timestamp(); /* ... but we won't make a timestamp earlier than the existing * one. */ { int tmout = 0; while (sig->timestamp <= orig_sig->timestamp) { if (++tmout > 5 && !opt.ignore_time_conflict) { rc = gpg_error (GPG_ERR_TIME_CONFLICT); goto leave; } gnupg_sleep (1); sig->timestamp = make_timestamp(); } } /* Note that already expired sigs will remain expired (with a * duration of 1) since build-packet.c:build_sig_subpkt_from_sig * detects this case. */ /* Put the updated timestamp into the sig. Note that this will * automagically lower any sig expiration dates to correctly * correspond to the differences in the timestamps (i.e. the * duration will shrink). */ build_sig_subpkt_from_sig (sig, pksk); if (mksubpkt) rc = (*mksubpkt)(sig, opaque); if (!rc) { hash_sigversion_to_magic (md, sig, NULL); gcry_md_final (md); rc = complete_sig (ctrl, sig, pksk, md, NULL, signhints); } leave: gcry_md_close (md); if (rc) free_seckey_enc (sig); else *ret_sig = sig; return rc; }