Line data Source code
1 : /* gpgconf-comp.c - Configuration utility for GnuPG.
2 : * Copyright (C) 2004, 2007, 2008, 2009, 2010,
3 : * 2011 Free Software Foundation, Inc.
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful, but
13 : * WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : * General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with GnuPG; if not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 : #include <stdlib.h>
25 : #include <stdio.h>
26 : #include <string.h>
27 : #include <fcntl.h>
28 : #include <unistd.h>
29 : #include <sys/types.h>
30 : #include <assert.h>
31 : #include <errno.h>
32 : #include <time.h>
33 : #include <stdarg.h>
34 : #ifdef HAVE_SIGNAL_H
35 : # include <signal.h>
36 : #endif
37 : #include <ctype.h>
38 : #ifdef HAVE_W32_SYSTEM
39 : # define WIN32_LEAN_AND_MEAN 1
40 : # include <windows.h>
41 : #else
42 : # include <pwd.h>
43 : # include <grp.h>
44 : #endif
45 :
46 : /* For log_logv(), asctimestamp(), gnupg_get_time (). */
47 : #include "util.h"
48 : #include "i18n.h"
49 : #include "exechelp.h"
50 :
51 : #include "gc-opt-flags.h"
52 : #include "gpgconf.h"
53 :
54 : /* There is a problem with gpg 1.4 under Windows: --gpgconf-list
55 : returns a plain filename without escaping. As long as we have not
56 : fixed that we need to use gpg2. */
57 : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
58 : #define GPGNAME "gpg2"
59 : #else
60 : #define GPGNAME GPG_NAME
61 : #endif
62 :
63 :
64 : /* TODO:
65 : Components: Add more components and their options.
66 : Robustness: Do more validation. Call programs to do validation for us.
67 : Add options to change backend binary path.
68 : Extract binary path for some backends from gpgsm/gpg config.
69 : */
70 :
71 :
72 : #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
73 : void gc_error (int status, int errnum, const char *fmt, ...) \
74 : __attribute__ ((format (printf, 3, 4)));
75 : #endif
76 :
77 : /* Output a diagnostic message. If ERRNUM is not 0, then the output
78 : is followed by a colon, a white space, and the error string for the
79 : error number ERRNUM. In any case the output is finished by a
80 : newline. The message is prepended by the program name, a colon,
81 : and a whitespace. The output may be further formatted or
82 : redirected by the jnlib logging facility. */
83 : void
84 46 : gc_error (int status, int errnum, const char *fmt, ...)
85 : {
86 : va_list arg_ptr;
87 :
88 46 : va_start (arg_ptr, fmt);
89 46 : log_logv (GPGRT_LOG_ERROR, fmt, arg_ptr);
90 46 : va_end (arg_ptr);
91 :
92 46 : if (errnum)
93 46 : log_printf (": %s\n", strerror (errnum));
94 : else
95 0 : log_printf ("\n");
96 :
97 46 : if (status)
98 : {
99 46 : log_printf (NULL);
100 46 : log_printf ("fatal error (exit status %i)\n", status);
101 46 : exit (status);
102 : }
103 0 : }
104 :
105 :
106 : /* Forward declaration. */
107 : static void gpg_agent_runtime_change (int killflag);
108 : static void scdaemon_runtime_change (int killflag);
109 : static void dirmngr_runtime_change (int killflag);
110 :
111 : /* Backend configuration. Backends are used to decide how the default
112 : and current value of an option can be determined, and how the
113 : option can be changed. To every option in every component belongs
114 : exactly one backend that controls and determines the option. Some
115 : backends are programs from the GPG system. Others might be
116 : implemented by GPGConf itself. If you change this enum, don't
117 : forget to update GC_BACKEND below. */
118 : typedef enum
119 : {
120 : /* Any backend, used for find_option (). */
121 : GC_BACKEND_ANY,
122 :
123 : /* The Gnu Privacy Guard. */
124 : GC_BACKEND_GPG,
125 :
126 : /* The Gnu Privacy Guard for S/MIME. */
127 : GC_BACKEND_GPGSM,
128 :
129 : /* The GPG Agent. */
130 : GC_BACKEND_GPG_AGENT,
131 :
132 : /* The GnuPG SCDaemon. */
133 : GC_BACKEND_SCDAEMON,
134 :
135 : /* The GnuPG directory manager. */
136 : GC_BACKEND_DIRMNGR,
137 :
138 : /* The LDAP server list file for the director manager. */
139 : GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
140 :
141 : /* The Pinentry (not a part of GnuPG, proper). */
142 : GC_BACKEND_PINENTRY,
143 :
144 : /* The number of the above entries. */
145 : GC_BACKEND_NR
146 : } gc_backend_t;
147 :
148 :
149 : /* To be able to implement generic algorithms for the various
150 : backends, we collect all information about them in this struct. */
151 : static struct
152 : {
153 : /* The name of the backend. */
154 : const char *name;
155 :
156 : /* The name of the program that acts as the backend. Some backends
157 : don't have an associated program, but are implemented directly by
158 : GPGConf. In this case, PROGRAM is NULL. */
159 : char *program;
160 :
161 : /* The module name (GNUPG_MODULE_NAME_foo) as defined by
162 : ../common/util.h. This value is used to get the actual installed
163 : path of the program. 0 is used if no backend program is
164 : available. */
165 : char module_name;
166 :
167 : /* The runtime change callback. If KILLFLAG is true the component
168 : is killed and not just reloaded. */
169 : void (*runtime_change) (int killflag);
170 :
171 : /* The option name for the configuration filename of this backend.
172 : This must be an absolute filename. It can be an option from a
173 : different backend (but then ordering of the options might
174 : matter). Note: This must be unique among all components. */
175 : const char *option_config_filename;
176 :
177 : /* If this is a file backend rather than a program backend, then
178 : this is the name of the option associated with the file. */
179 : const char *option_name;
180 : } gc_backend[GC_BACKEND_NR] =
181 : {
182 : { NULL }, /* GC_BACKEND_ANY dummy entry. */
183 : { GPG_DISP_NAME, GPGNAME, GNUPG_MODULE_NAME_GPG,
184 : NULL, GPGCONF_NAME "-" GPG_NAME ".conf" },
185 : { GPGSM_DISP_NAME, GPGSM_NAME, GNUPG_MODULE_NAME_GPGSM,
186 : NULL, GPGCONF_NAME "-" GPGSM_NAME ".conf" },
187 : { GPG_AGENT_DISP_NAME, GPG_AGENT_NAME, GNUPG_MODULE_NAME_AGENT,
188 : gpg_agent_runtime_change, GPGCONF_NAME"-" GPG_AGENT_NAME ".conf" },
189 : { SCDAEMON_DISP_NAME, SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON,
190 : scdaemon_runtime_change, GPGCONF_NAME"-" SCDAEMON_NAME ".conf" },
191 : { DIRMNGR_DISP_NAME, DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR,
192 : dirmngr_runtime_change, GPGCONF_NAME "-" DIRMNGR_NAME ".conf" },
193 : { DIRMNGR_DISP_NAME " LDAP Server List", NULL, 0,
194 : NULL, "ldapserverlist-file", "LDAP Server" },
195 : { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
196 : NULL, GPGCONF_NAME "-pinentry.conf" },
197 : };
198 :
199 :
200 : /* Option configuration. */
201 :
202 : /* An option might take an argument, or not. Argument types can be
203 : basic or complex. Basic types are generic and easy to validate.
204 : Complex types provide more specific information about the intended
205 : use, but can be difficult to validate. If you add to this enum,
206 : don't forget to update GC_ARG_TYPE below. YOU MUST NOT CHANGE THE
207 : NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL
208 : INTERFACE. */
209 : typedef enum
210 : {
211 : /* Basic argument types. */
212 :
213 : /* No argument. */
214 : GC_ARG_TYPE_NONE = 0,
215 :
216 : /* A String argument. */
217 : GC_ARG_TYPE_STRING = 1,
218 :
219 : /* A signed integer argument. */
220 : GC_ARG_TYPE_INT32 = 2,
221 :
222 : /* An unsigned integer argument. */
223 : GC_ARG_TYPE_UINT32 = 3,
224 :
225 : /* ADD NEW BASIC TYPE ENTRIES HERE. */
226 :
227 : /* Complex argument types. */
228 :
229 : /* A complete filename. */
230 : GC_ARG_TYPE_FILENAME = 32,
231 :
232 : /* An LDAP server in the format
233 : HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */
234 : GC_ARG_TYPE_LDAP_SERVER = 33,
235 :
236 : /* A 40 character fingerprint. */
237 : GC_ARG_TYPE_KEY_FPR = 34,
238 :
239 : /* A user ID or key ID or fingerprint for a certificate. */
240 : GC_ARG_TYPE_PUB_KEY = 35,
241 :
242 : /* A user ID or key ID or fingerprint for a certificate with a key. */
243 : GC_ARG_TYPE_SEC_KEY = 36,
244 :
245 : /* A alias list made up of a key, an equal sign and a space
246 : separated list of values. */
247 : GC_ARG_TYPE_ALIAS_LIST = 37,
248 :
249 : /* ADD NEW COMPLEX TYPE ENTRIES HERE. */
250 :
251 : /* The number of the above entries. */
252 : GC_ARG_TYPE_NR
253 : } gc_arg_type_t;
254 :
255 :
256 : /* For every argument, we record some information about it in the
257 : following struct. */
258 : static struct
259 : {
260 : /* For every argument type exists a basic argument type that can be
261 : used as a fallback for input and validation purposes. */
262 : gc_arg_type_t fallback;
263 :
264 : /* Human-readable name of the type. */
265 : const char *name;
266 : } gc_arg_type[GC_ARG_TYPE_NR] =
267 : {
268 : /* The basic argument types have their own types as fallback. */
269 : { GC_ARG_TYPE_NONE, "none" },
270 : { GC_ARG_TYPE_STRING, "string" },
271 : { GC_ARG_TYPE_INT32, "int32" },
272 : { GC_ARG_TYPE_UINT32, "uint32" },
273 :
274 : /* Reserved basic type entries for future extension. */
275 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
276 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
277 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
278 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
279 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
280 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
281 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
282 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
283 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
284 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
285 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
286 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
287 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
288 : { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
289 :
290 : /* The complex argument types have a basic type as fallback. */
291 : { GC_ARG_TYPE_STRING, "filename" },
292 : { GC_ARG_TYPE_STRING, "ldap server" },
293 : { GC_ARG_TYPE_STRING, "key fpr" },
294 : { GC_ARG_TYPE_STRING, "pub key" },
295 : { GC_ARG_TYPE_STRING, "sec key" },
296 : { GC_ARG_TYPE_STRING, "alias list" },
297 : };
298 :
299 :
300 : /* Every option has an associated expert level, than can be used to
301 : hide advanced and expert options from beginners. If you add to
302 : this list, don't forget to update GC_LEVEL below. YOU MUST NOT
303 : CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
304 : EXTERNAL INTERFACE. */
305 : typedef enum
306 : {
307 : /* The basic options should always be displayed. */
308 : GC_LEVEL_BASIC,
309 :
310 : /* The advanced options may be hidden from beginners. */
311 : GC_LEVEL_ADVANCED,
312 :
313 : /* The expert options should only be displayed to experts. */
314 : GC_LEVEL_EXPERT,
315 :
316 : /* The invisible options should normally never be displayed. */
317 : GC_LEVEL_INVISIBLE,
318 :
319 : /* The internal options are never exported, they mark options that
320 : are recorded for internal use only. */
321 : GC_LEVEL_INTERNAL,
322 :
323 : /* ADD NEW ENTRIES HERE. */
324 :
325 : /* The number of the above entries. */
326 : GC_LEVEL_NR
327 : } gc_expert_level_t;
328 :
329 : /* A description for each expert level. */
330 : static struct
331 : {
332 : const char *name;
333 : } gc_level[] =
334 : {
335 : { "basic" },
336 : { "advanced" },
337 : { "expert" },
338 : { "invisible" },
339 : { "internal" }
340 : };
341 :
342 :
343 : /* Option flags. The flags which are used by the backends are defined
344 : by gc-opt-flags.h, included above.
345 :
346 : YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE
347 : PART OF THE EXTERNAL INTERFACE. */
348 :
349 : /* Some entries in the option list are not options, but mark the
350 : beginning of a new group of options. These entries have the GROUP
351 : flag set. */
352 : #define GC_OPT_FLAG_GROUP (1UL << 0)
353 : /* The ARG_OPT flag for an option indicates that the argument is
354 : optional. This is never set for GC_ARG_TYPE_NONE options. */
355 : #define GC_OPT_FLAG_ARG_OPT (1UL << 1)
356 : /* The LIST flag for an option indicates that the option can occur
357 : several times. A comma separated list of arguments is used as the
358 : argument value. */
359 : #define GC_OPT_FLAG_LIST (1UL << 2)
360 :
361 :
362 : /* A human-readable description for each flag. */
363 : static struct
364 : {
365 : const char *name;
366 : } gc_flag[] =
367 : {
368 : { "group" },
369 : { "optional arg" },
370 : { "list" },
371 : { "runtime" },
372 : { "default" },
373 : { "default desc" },
374 : { "no arg desc" },
375 : { "no change" }
376 : };
377 :
378 :
379 : /* To each option, or group marker, the information in the GC_OPTION
380 : struct is provided. If you change this, don't forget to update the
381 : option list of each component. */
382 : struct gc_option
383 : {
384 : /* If this is NULL, then this is a terminator in an array of unknown
385 : length. Otherwise, if this entry is a group marker (see FLAGS),
386 : then this is the name of the group described by this entry.
387 : Otherwise it is the name of the option described by this
388 : entry. The name must not contain a colon. */
389 : const char *name;
390 :
391 : /* The option flags. If the GROUP flag is set, then this entry is a
392 : group marker, not an option, and only the fields LEVEL,
393 : DESC_DOMAIN and DESC are valid. In all other cases, this entry
394 : describes a new option and all fields are valid. */
395 : unsigned long flags;
396 :
397 : /* The expert level. This field is valid for options and groups. A
398 : group has the expert level of the lowest-level option in the
399 : group. */
400 : gc_expert_level_t level;
401 :
402 : /* A gettext domain in which the following description can be found.
403 : If this is NULL, then DESC is not translated. Valid for groups
404 : and options.
405 :
406 : Note that we try to keep the description of groups within the
407 : gnupg domain.
408 :
409 : IMPORTANT: If you add a new domain please make sure to add a code
410 : set switching call to the function my_dgettext further below. */
411 : const char *desc_domain;
412 :
413 : /* A gettext description for this group or option. If it starts
414 : with a '|', then the string up to the next '|' describes the
415 : argument, and the description follows the second '|'.
416 :
417 : In general enclosing these description in N_() is not required
418 : because the description should be identical to the one in the
419 : help menu of the respective program. */
420 : const char *desc;
421 :
422 : /* The following fields are only valid for options. */
423 :
424 : /* The type of the option argument. */
425 : gc_arg_type_t arg_type;
426 :
427 : /* The backend that implements this option. */
428 : gc_backend_t backend;
429 :
430 : /* The following fields are set to NULL at startup (because all
431 : option's are declared as static variables). They are at the end
432 : of the list so that they can be omitted from the option
433 : declarations. */
434 :
435 : /* This is true if the option is supported by this version of the
436 : backend. */
437 : int active;
438 :
439 : /* The default value for this option. This is NULL if the option is
440 : not present in the backend, the empty string if no default is
441 : available, and otherwise a quoted string. */
442 : char *default_value;
443 :
444 : /* The default argument is only valid if the "optional arg" flag is
445 : set, and specifies the default argument (value) that is used if
446 : the argument is omitted. */
447 : char *default_arg;
448 :
449 : /* The current value of this option. */
450 : char *value;
451 :
452 : /* The new flags for this option. The only defined flag is actually
453 : GC_OPT_FLAG_DEFAULT, and it means that the option should be
454 : deleted. In this case, NEW_VALUE is NULL. */
455 : unsigned long new_flags;
456 :
457 : /* The new value of this option. */
458 : char *new_value;
459 : };
460 : typedef struct gc_option gc_option_t;
461 :
462 : /* Use this macro to terminate an option list. */
463 : #define GC_OPTION_NULL { NULL }
464 :
465 :
466 : #ifndef BUILD_WITH_AGENT
467 : #define gc_options_gpg_agent NULL
468 : #else
469 : /* The options of the GC_COMPONENT_GPG_AGENT component. */
470 : static gc_option_t gc_options_gpg_agent[] =
471 : {
472 : /* The configuration file to which we write the changes. */
473 : { GPGCONF_NAME"-" GPG_AGENT_NAME ".conf",
474 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
475 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
476 :
477 : { "Monitor",
478 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
479 : "gnupg", N_("Options controlling the diagnostic output") },
480 : { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
481 : "gnupg", "verbose",
482 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
483 : { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
484 : "gnupg", "be somewhat more quiet",
485 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
486 : { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
487 : NULL, NULL,
488 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
489 :
490 : { "Configuration",
491 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
492 : "gnupg", N_("Options controlling the configuration") },
493 : { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
494 : "gnupg", "|FILE|read options from FILE",
495 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
496 : { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
497 : "gnupg", "do not use the SCdaemon",
498 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
499 : { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
500 : "gnupg", "enable ssh support",
501 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
502 : { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
503 : "gnupg", "enable putty support",
504 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
505 :
506 : { "Debug",
507 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
508 : "gnupg", N_("Options useful for debugging") },
509 : { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
510 : "gnupg", "|LEVEL|set the debugging level to LEVEL",
511 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
512 : { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
513 : "gnupg", N_("|FILE|write server mode logs to FILE"),
514 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
515 : { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
516 : NULL, NULL,
517 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
518 :
519 : { "Security",
520 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
521 : "gnupg", N_("Options controlling the security") },
522 : { "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
523 : GC_LEVEL_BASIC, "gnupg",
524 : "|N|expire cached PINs after N seconds",
525 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
526 : { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
527 : GC_LEVEL_ADVANCED, "gnupg",
528 : N_("|N|expire SSH keys after N seconds"),
529 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
530 : { "max-cache-ttl", GC_OPT_FLAG_RUNTIME,
531 : GC_LEVEL_EXPERT, "gnupg",
532 : N_("|N|set maximum PIN cache lifetime to N seconds"),
533 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
534 : { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
535 : GC_LEVEL_EXPERT, "gnupg",
536 : N_("|N|set maximum SSH key lifetime to N seconds"),
537 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
538 : { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
539 : GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing",
540 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
541 : { "allow-emacs-pinentry", GC_OPT_FLAG_RUNTIME,
542 : GC_LEVEL_ADVANCED,
543 : "gnupg", "allow passphrase to be prompted through Emacs",
544 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
545 : { "no-allow-external-cache", GC_OPT_FLAG_RUNTIME,
546 : GC_LEVEL_BASIC, "gnupg", "disallow the use of an external password cache",
547 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
548 : { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
549 : GC_LEVEL_ADVANCED, "gnupg", "disallow clients to mark keys as \"trusted\"",
550 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
551 : { "no-allow-loopback-pinentry", GC_OPT_FLAG_RUNTIME,
552 : GC_LEVEL_EXPERT, "gnupg", "disallow caller to override the pinentry",
553 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
554 : { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
555 : "gnupg", "do not grab keyboard and mouse",
556 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
557 :
558 : { "Passphrase policy",
559 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
560 : "gnupg", N_("Options enforcing a passphrase policy") },
561 : { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
562 : GC_LEVEL_EXPERT, "gnupg",
563 : N_("do not allow bypassing the passphrase policy"),
564 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
565 : { "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
566 : GC_LEVEL_ADVANCED, "gnupg",
567 : N_("|N|set minimal required length for new passphrases to N"),
568 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
569 : { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
570 : GC_LEVEL_EXPERT, "gnupg",
571 : N_("|N|require at least N non-alpha characters for a new passphrase"),
572 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
573 : { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
574 : GC_LEVEL_EXPERT,
575 : "gnupg", N_("|FILE|check new passphrases against pattern in FILE"),
576 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
577 : { "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
578 : GC_LEVEL_EXPERT, "gnupg",
579 : N_("|N|expire the passphrase after N days"),
580 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
581 : { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
582 : GC_LEVEL_EXPERT, "gnupg",
583 : N_("do not allow the reuse of old passphrases"),
584 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
585 : { "pinentry-timeout", GC_OPT_FLAG_RUNTIME,
586 : GC_LEVEL_ADVANCED, "gnupg",
587 : N_("|N|set the Pinentry timeout to N seconds"),
588 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
589 :
590 : GC_OPTION_NULL
591 : };
592 : #endif /*BUILD_WITH_AGENT*/
593 :
594 :
595 : #ifndef BUILD_WITH_SCDAEMON
596 : #define gc_options_scdaemon NULL
597 : #else
598 : /* The options of the GC_COMPONENT_SCDAEMON component. */
599 : static gc_option_t gc_options_scdaemon[] =
600 : {
601 : /* The configuration file to which we write the changes. */
602 : { GPGCONF_NAME"-"SCDAEMON_NAME".conf",
603 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
604 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
605 :
606 : { "Monitor",
607 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
608 : "gnupg", N_("Options controlling the diagnostic output") },
609 : { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
610 : "gnupg", "verbose",
611 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
612 : { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
613 : "gnupg", "be somewhat more quiet",
614 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
615 : { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
616 : NULL, NULL,
617 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
618 :
619 : { "Configuration",
620 : GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
621 : "gnupg", N_("Options controlling the configuration") },
622 : { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
623 : "gnupg", "|FILE|read options from FILE",
624 : GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
625 : { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
626 : "gnupg", "|N|connect to reader at port N",
627 : GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
628 : { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
629 : "gnupg", "|NAME|use NAME as ct-API driver",
630 : GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
631 : { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
632 : "gnupg", "|NAME|use NAME as PC/SC driver",
633 : GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
634 : { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
635 : "gnupg", "do not use the internal CCID driver",
636 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
637 : { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
638 : "gnupg", "do not use a reader's pinpad",
639 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
640 : { "enable-pinpad-varlen",
641 : GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
642 : "gnupg", "use variable length input for pinpad",
643 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
644 : { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
645 : "gnupg", "|N|disconnect the card after N seconds of inactivity",
646 : GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
647 :
648 : { "Debug",
649 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
650 : "gnupg", N_("Options useful for debugging") },
651 : { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
652 : "gnupg", "|LEVEL|set the debugging level to LEVEL",
653 : GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
654 : { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
655 : "gnupg", N_("|FILE|write a log to FILE"),
656 : GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
657 :
658 : { "Security",
659 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
660 : "gnupg", N_("Options controlling the security") },
661 : { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
662 : "gnupg", "deny the use of admin card commands",
663 : GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
664 :
665 :
666 : GC_OPTION_NULL
667 : };
668 : #endif /*BUILD_WITH_SCDAEMON*/
669 :
670 : #ifndef BUILD_WITH_GPG
671 : #define gc_options_gpg NULL
672 : #else
673 : /* The options of the GC_COMPONENT_GPG component. */
674 : static gc_option_t gc_options_gpg[] =
675 : {
676 : /* The configuration file to which we write the changes. */
677 : { GPGCONF_NAME"-"GPG_NAME".conf",
678 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
679 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
680 :
681 : { "Monitor",
682 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
683 : "gnupg", N_("Options controlling the diagnostic output") },
684 : { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
685 : "gnupg", "verbose",
686 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
687 : { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
688 : "gnupg", "be somewhat more quiet",
689 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
690 : { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
691 : NULL, NULL,
692 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
693 :
694 : { "Configuration",
695 : GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
696 : "gnupg", N_("Options controlling the configuration") },
697 : { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
698 : "gnupg", N_("|NAME|use NAME as default secret key"),
699 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
700 : { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
701 : "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
702 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
703 : { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED,
704 : "gnupg", N_("|SPEC|set up email aliases"),
705 : GC_ARG_TYPE_ALIAS_LIST, GC_BACKEND_GPG },
706 : { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
707 : "gnupg", "|FILE|read options from FILE",
708 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
709 : { "default_pubkey_algo",
710 : (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
711 : NULL, NULL,
712 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
713 :
714 :
715 : { "Debug",
716 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
717 : "gnupg", N_("Options useful for debugging") },
718 : { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
719 : "gnupg", "|LEVEL|set the debugging level to LEVEL",
720 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
721 : { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
722 : "gnupg", N_("|FILE|write server mode logs to FILE"),
723 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
724 : /* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */
725 : /* NULL, NULL, */
726 : /* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */
727 :
728 : { "Keyserver",
729 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
730 : "gnupg", N_("Configuration for Keyservers") },
731 : { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
732 : "gnupg", N_("|URL|use keyserver at URL"), /* Deprecated - use dirmngr */
733 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
734 : { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
735 : "gnupg", N_("allow PKA lookups (DNS requests)"),
736 : GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
737 : { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
738 : "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
739 : GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
740 :
741 :
742 : GC_OPTION_NULL
743 : };
744 : #endif /*BUILD_WITH_GPG*/
745 :
746 :
747 : #ifndef BUILD_WITH_GPGSM
748 : #define gc_options_gpgsm NULL
749 : #else
750 : /* The options of the GC_COMPONENT_GPGSM component. */
751 : static gc_option_t gc_options_gpgsm[] =
752 : {
753 : /* The configuration file to which we write the changes. */
754 : { GPGCONF_NAME"-"GPGSM_NAME".conf",
755 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
756 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
757 :
758 : { "Monitor",
759 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
760 : "gnupg", N_("Options controlling the diagnostic output") },
761 : { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
762 : "gnupg", "verbose",
763 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
764 : { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
765 : "gnupg", "be somewhat more quiet",
766 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
767 : { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
768 : NULL, NULL,
769 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
770 :
771 : { "Configuration",
772 : GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
773 : "gnupg", N_("Options controlling the configuration") },
774 : { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
775 : "gnupg", N_("|NAME|use NAME as default secret key"),
776 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
777 : { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
778 : "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
779 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
780 : { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
781 : "gnupg", "|FILE|read options from FILE",
782 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
783 : { "prefer-system-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
784 : "gnupg", "use system's dirmngr if available",
785 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
786 : { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
787 : "gnupg", N_("disable all access to the dirmngr"),
788 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
789 : { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
790 : "gnupg", N_("|NAME|use encoding NAME for PKCS#12 passphrases"),
791 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
792 : { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
793 : "gnupg", N_("|SPEC|use this keyserver to lookup keys"),
794 : GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_GPGSM },
795 : { "default_pubkey_algo",
796 : (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
797 : NULL, NULL,
798 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
799 :
800 : { "Debug",
801 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
802 : "gnupg", N_("Options useful for debugging") },
803 : { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
804 : "gnupg", "|LEVEL|set the debugging level to LEVEL",
805 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
806 : { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
807 : "gnupg", N_("|FILE|write server mode logs to FILE"),
808 : GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
809 : { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
810 : NULL, NULL,
811 : GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM },
812 :
813 : { "Security",
814 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
815 : "gnupg", N_("Options controlling the security") },
816 : { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
817 : "gnupg", "never consult a CRL",
818 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
819 : { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
820 : "gnupg", N_("do not check CRLs for root certificates"),
821 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
822 : { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
823 : "gnupg", "check validity using OCSP",
824 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
825 : { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
826 : "gnupg", "|N|number of certificates to include",
827 : GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM },
828 : { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
829 : "gnupg", "do not check certificate policies",
830 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
831 : { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
832 : "gnupg", "fetch missing issuer certificates",
833 : GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
834 : { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
835 : "gnupg", "|NAME|use cipher algorithm NAME",
836 : GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
837 :
838 : GC_OPTION_NULL
839 : };
840 : #endif /*BUILD_WITH_GPGSM*/
841 :
842 :
843 : #ifndef BUILD_WITH_DIRMNGR
844 : #define gc_options_dirmngr NULL
845 : #else
846 : /* The options of the GC_COMPONENT_DIRMNGR component. */
847 : static gc_option_t gc_options_dirmngr[] =
848 : {
849 : /* The configuration file to which we write the changes. */
850 : { GPGCONF_NAME"-"DIRMNGR_NAME".conf",
851 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
852 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
853 :
854 : { "Monitor",
855 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
856 : "gnupg", N_("Options controlling the diagnostic output") },
857 : { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
858 : "dirmngr", "verbose",
859 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
860 : { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
861 : "dirmngr", "be somewhat more quiet",
862 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
863 : { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
864 : NULL, NULL,
865 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
866 :
867 : { "Format",
868 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
869 : "gnupg", N_("Options controlling the format of the output") },
870 : { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
871 : "dirmngr", "sh-style command output",
872 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
873 : { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
874 : "dirmngr", "csh-style command output",
875 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
876 :
877 : { "Configuration",
878 : GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
879 : "gnupg", N_("Options controlling the configuration") },
880 : { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
881 : "dirmngr", "|FILE|read options from FILE",
882 : GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
883 :
884 : { "Debug",
885 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
886 : "gnupg", N_("Options useful for debugging") },
887 : { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
888 : "dirmngr", "|LEVEL|set the debugging level to LEVEL",
889 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
890 : { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
891 : "dirmngr", "do not detach from the console",
892 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
893 : { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
894 : "dirmngr", N_("|FILE|write server mode logs to FILE"),
895 : GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
896 : { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
897 : NULL, NULL,
898 : GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
899 : { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
900 : NULL, NULL,
901 : GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
902 :
903 : { "Enforcement",
904 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
905 : "gnupg", N_("Options controlling the interactivity and enforcement") },
906 : { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
907 : "dirmngr", "run without asking a user",
908 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
909 : { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
910 : "dirmngr", "force loading of outdated CRLs",
911 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
912 : { "allow-version-check", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
913 : "dirmngr", "allow online software version check",
914 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
915 :
916 : { "Tor",
917 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
918 : "gnupg", N_("Options controlling the use of Tor") },
919 : { "use-tor", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
920 : "dirmngr", "route all network traffic via TOR",
921 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
922 :
923 : { "Keyserver",
924 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
925 : "gnupg", N_("Configuration for Keyservers") },
926 : { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
927 : "gnupg", N_("|URL|use keyserver at URL"),
928 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
929 :
930 : { "HTTP",
931 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
932 : "gnupg", N_("Configuration for HTTP servers") },
933 : { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
934 : "dirmngr", "inhibit the use of HTTP",
935 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
936 : { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
937 : "dirmngr", "ignore HTTP CRL distribution points",
938 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
939 : { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
940 : "dirmngr", "|URL|redirect all HTTP requests to URL",
941 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
942 : { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
943 : "gnupg", N_("use system's HTTP proxy setting"),
944 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
945 :
946 : { "LDAP",
947 : GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
948 : "gnupg", N_("Configuration of LDAP servers to use") },
949 : { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
950 : "dirmngr", "inhibit the use of LDAP",
951 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
952 : { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
953 : "dirmngr", "ignore LDAP CRL distribution points",
954 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
955 : { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
956 : "dirmngr", "|HOST|use HOST for LDAP queries",
957 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
958 : { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
959 : "dirmngr", "do not use fallback hosts with --ldap-proxy",
960 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
961 : { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
962 : "dirmngr", "add new servers discovered in CRL distribution points"
963 : " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
964 : { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
965 : "dirmngr", "|N|set LDAP timeout to N seconds",
966 : GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
967 : /* The following entry must not be removed, as it is required for
968 : the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST. */
969 : { "ldapserverlist-file",
970 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
971 : "dirmngr", "|FILE|read LDAP server list from FILE",
972 : GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
973 : /* This entry must come after at least one entry for
974 : GC_BACKEND_DIRMNGR in this component, so that the entry for
975 : "ldapserverlist-file will be initialized before this one. */
976 : { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
977 : "gnupg", N_("LDAP server list"),
978 : GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
979 : { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
980 : "dirmngr", "|N|do not return more than N items in one query",
981 : GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
982 :
983 : { "OCSP",
984 : GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
985 : "gnupg", N_("Configuration for OCSP") },
986 : { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
987 : "dirmngr", "allow sending OCSP requests",
988 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
989 : { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
990 : "dirmngr", "ignore certificate contained OCSP service URLs",
991 : GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
992 : { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
993 : "dirmngr", "|URL|use OCSP responder at URL",
994 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
995 : { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
996 : "dirmngr", "|FPR|OCSP response signed by FPR",
997 : GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
998 :
999 :
1000 : GC_OPTION_NULL
1001 : };
1002 : #endif /*BUILD_WITH_DIRMNGR*/
1003 :
1004 :
1005 : /* The options of the GC_COMPONENT_PINENTRY component. */
1006 : static gc_option_t gc_options_pinentry[] =
1007 : {
1008 : /* A dummy option to allow gc_component_list_components to find the
1009 : pinentry backend. Needs to be a conf file. */
1010 : { GPGCONF_NAME"-pinentry.conf",
1011 : GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
1012 : NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_PINENTRY },
1013 :
1014 : GC_OPTION_NULL
1015 : };
1016 :
1017 :
1018 :
1019 : /* Component system. Each component is a set of options that can be
1020 : configured at the same time. If you change this, don't forget to
1021 : update GC_COMPONENT below. */
1022 : typedef enum
1023 : {
1024 : /* The classic GPG for OpenPGP. */
1025 : GC_COMPONENT_GPG,
1026 :
1027 : /* The GPG Agent. */
1028 : GC_COMPONENT_GPG_AGENT,
1029 :
1030 : /* The Smardcard Daemon. */
1031 : GC_COMPONENT_SCDAEMON,
1032 :
1033 : /* GPG for S/MIME. */
1034 : GC_COMPONENT_GPGSM,
1035 :
1036 : /* The LDAP Directory Manager for CRLs. */
1037 : GC_COMPONENT_DIRMNGR,
1038 :
1039 : /* The external Pinentry. */
1040 : GC_COMPONENT_PINENTRY,
1041 :
1042 : /* The number of components. */
1043 : GC_COMPONENT_NR
1044 : } gc_component_t;
1045 :
1046 :
1047 : /* The information associated with each component. */
1048 : static struct
1049 : {
1050 : /* The name of this component. Must not contain a colon (':')
1051 : character. */
1052 : const char *name;
1053 :
1054 : /* The gettext domain for the description DESC. If this is NULL,
1055 : then the description is not translated. */
1056 : const char *desc_domain;
1057 :
1058 : /* The description for this domain. */
1059 : const char *desc;
1060 :
1061 : /* The list of options for this component, terminated by
1062 : GC_OPTION_NULL. */
1063 : gc_option_t *options;
1064 : } gc_component[] =
1065 : {
1066 : { "gpg", "gnupg", N_("OpenPGP"), gc_options_gpg },
1067 : { "gpg-agent","gnupg", N_("Private Keys"), gc_options_gpg_agent },
1068 : { "scdaemon", "gnupg", N_("Smartcards"), gc_options_scdaemon },
1069 : { "gpgsm", "gnupg", N_("S/MIME"), gc_options_gpgsm },
1070 : { "dirmngr", "gnupg", N_("Network"), gc_options_dirmngr },
1071 : { "pinentry", "gnupg", N_("Passphrase Entry"), gc_options_pinentry }
1072 : };
1073 :
1074 :
1075 :
1076 : /* Structure used to collect error output of the backend programs. */
1077 : struct error_line_s;
1078 : typedef struct error_line_s *error_line_t;
1079 : struct error_line_s
1080 : {
1081 : error_line_t next; /* Link to next item. */
1082 : const char *fname; /* Name of the config file (points into BUFFER). */
1083 : unsigned int lineno; /* Line number of the config file. */
1084 : const char *errtext; /* Text of the error message (points into BUFFER). */
1085 : char buffer[1]; /* Helper buffer. */
1086 : };
1087 :
1088 :
1089 :
1090 : /* Engine specific support. */
1091 : static void
1092 0 : gpg_agent_runtime_change (int killflag)
1093 : {
1094 0 : gpg_error_t err = 0;
1095 : const char *pgmname;
1096 : const char *argv[5];
1097 : pid_t pid;
1098 0 : char *abs_homedir = NULL;
1099 0 : int i = 0;
1100 :
1101 0 : pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
1102 0 : if (!gnupg_default_homedir_p ())
1103 : {
1104 0 : abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
1105 0 : if (!abs_homedir)
1106 0 : err = gpg_error_from_syserror ();
1107 :
1108 0 : argv[i++] = "--homedir";
1109 0 : argv[i++] = abs_homedir;
1110 : }
1111 0 : argv[i++] = "--no-autostart";
1112 0 : argv[i++] = killflag? "KILLAGENT" : "RELOADAGENT";
1113 0 : argv[i++] = NULL;
1114 :
1115 0 : if (!err)
1116 0 : err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
1117 0 : if (!err)
1118 0 : err = gnupg_wait_process (pgmname, pid, 1, NULL);
1119 0 : if (err)
1120 0 : gc_error (0, 0, "error running '%s %s': %s",
1121 : pgmname, argv[1], gpg_strerror (err));
1122 0 : gnupg_release_process (pid);
1123 0 : xfree (abs_homedir);
1124 0 : }
1125 :
1126 :
1127 : static void
1128 0 : scdaemon_runtime_change (int killflag)
1129 : {
1130 0 : gpg_error_t err = 0;
1131 : const char *pgmname;
1132 : const char *argv[9];
1133 : pid_t pid;
1134 0 : char *abs_homedir = NULL;
1135 0 : int i = 0;
1136 :
1137 : (void)killflag; /* For scdaemon kill and reload are synonyms. */
1138 :
1139 : /* We use "GETINFO app_running" to see whether the agent is already
1140 : running and kill it only in this case. This avoids an explicit
1141 : starting of the agent in case it is not yet running. There is
1142 : obviously a race condition but that should not harm too much. */
1143 :
1144 0 : pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
1145 0 : if (!gnupg_default_homedir_p ())
1146 : {
1147 0 : abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
1148 0 : if (!abs_homedir)
1149 0 : err = gpg_error_from_syserror ();
1150 :
1151 0 : argv[i++] = "--homedir";
1152 0 : argv[i++] = abs_homedir;
1153 : }
1154 0 : argv[i++] = "-s";
1155 0 : argv[i++] = "--no-autostart";
1156 0 : argv[i++] = "GETINFO scd_running";
1157 0 : argv[i++] = "/if ${! $?}";
1158 0 : argv[i++] = "scd killscd";
1159 0 : argv[i++] = "/end";
1160 0 : argv[i++] = NULL;
1161 :
1162 0 : if (!err)
1163 0 : err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
1164 0 : if (!err)
1165 0 : err = gnupg_wait_process (pgmname, pid, 1, NULL);
1166 0 : if (err)
1167 0 : gc_error (0, 0, "error running '%s %s': %s",
1168 : pgmname, argv[4], gpg_strerror (err));
1169 0 : gnupg_release_process (pid);
1170 0 : xfree (abs_homedir);
1171 0 : }
1172 :
1173 :
1174 : static void
1175 0 : dirmngr_runtime_change (int killflag)
1176 : {
1177 0 : gpg_error_t err = 0;
1178 : const char *pgmname;
1179 : const char *argv[6];
1180 : pid_t pid;
1181 0 : char *abs_homedir = NULL;
1182 :
1183 0 : pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
1184 0 : argv[0] = "--no-autostart";
1185 0 : argv[1] = "--dirmngr";
1186 0 : argv[2] = killflag? "KILLDIRMNGR" : "RELOADDIRMNGR";
1187 0 : if (gnupg_default_homedir_p ())
1188 0 : argv[3] = NULL;
1189 : else
1190 : {
1191 0 : abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
1192 0 : if (!abs_homedir)
1193 0 : err = gpg_error_from_syserror ();
1194 :
1195 0 : argv[3] = "--homedir";
1196 0 : argv[4] = abs_homedir;
1197 0 : argv[5] = NULL;
1198 : }
1199 :
1200 0 : if (!err)
1201 0 : err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
1202 0 : if (!err)
1203 0 : err = gnupg_wait_process (pgmname, pid, 1, NULL);
1204 0 : if (err)
1205 0 : gc_error (0, 0, "error running '%s %s': %s",
1206 : pgmname, argv[2], gpg_strerror (err));
1207 0 : gnupg_release_process (pid);
1208 0 : xfree (abs_homedir);
1209 0 : }
1210 :
1211 :
1212 : /* Launch the gpg-agent or the dirmngr if not already running. */
1213 : gpg_error_t
1214 0 : gc_component_launch (int component)
1215 : {
1216 : gpg_error_t err;
1217 : const char *pgmname;
1218 : const char *argv[3];
1219 : int i;
1220 : pid_t pid;
1221 :
1222 0 : if (!(component == GC_COMPONENT_GPG_AGENT
1223 : || component == GC_COMPONENT_DIRMNGR))
1224 : {
1225 0 : es_fputs (_("Component not suitable for launching"), es_stderr);
1226 0 : es_putc ('\n', es_stderr);
1227 0 : exit (1);
1228 : }
1229 :
1230 0 : pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
1231 0 : i = 0;
1232 0 : if (component == GC_COMPONENT_DIRMNGR)
1233 0 : argv[i++] = "--dirmngr";
1234 0 : argv[i++] = "NOP";
1235 0 : argv[i] = NULL;
1236 :
1237 0 : err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
1238 0 : if (!err)
1239 0 : err = gnupg_wait_process (pgmname, pid, 1, NULL);
1240 0 : if (err)
1241 0 : gc_error (0, 0, "error running '%s%s%s': %s",
1242 : pgmname,
1243 : component == GC_COMPONENT_DIRMNGR? " --dirmngr":"",
1244 : " NOP",
1245 : gpg_strerror (err));
1246 0 : gnupg_release_process (pid);
1247 0 : return err;
1248 : }
1249 :
1250 :
1251 : /* Unconditionally restart COMPONENT. */
1252 : void
1253 0 : gc_component_kill (int component)
1254 : {
1255 : int runtime[GC_BACKEND_NR];
1256 : gc_option_t *option;
1257 : gc_backend_t backend;
1258 :
1259 : /* Set a flag for the backends to be reloaded. */
1260 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1261 0 : runtime[backend] = 0;
1262 :
1263 0 : if (component >= 0)
1264 : {
1265 0 : assert (component < GC_COMPONENT_NR);
1266 0 : option = gc_component[component].options;
1267 0 : for (; option && option->name; option++)
1268 0 : runtime[option->backend] = 1;
1269 : }
1270 :
1271 : /* Do the restart for the selected backends. */
1272 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1273 : {
1274 0 : if (runtime[backend] && gc_backend[backend].runtime_change)
1275 0 : (*gc_backend[backend].runtime_change) (1);
1276 : }
1277 0 : }
1278 :
1279 :
1280 : /* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
1281 : void
1282 0 : gc_component_reload (int component)
1283 : {
1284 : int runtime[GC_BACKEND_NR];
1285 : gc_option_t *option;
1286 : gc_backend_t backend;
1287 :
1288 : /* Set a flag for the backends to be reloaded. */
1289 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1290 0 : runtime[backend] = 0;
1291 :
1292 0 : if (component == -1)
1293 : {
1294 0 : for (component = 0; component < GC_COMPONENT_NR; component++)
1295 : {
1296 0 : option = gc_component[component].options;
1297 0 : for (; option && option->name; option++)
1298 0 : runtime[option->backend] = 1;
1299 : }
1300 : }
1301 : else
1302 : {
1303 0 : assert (component < GC_COMPONENT_NR);
1304 0 : option = gc_component[component].options;
1305 0 : for (; option && option->name; option++)
1306 0 : runtime[option->backend] = 1;
1307 : }
1308 :
1309 : /* Do the reload for all selected backends. */
1310 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1311 : {
1312 0 : if (runtime[backend] && gc_backend[backend].runtime_change)
1313 0 : (*gc_backend[backend].runtime_change) (0);
1314 : }
1315 0 : }
1316 :
1317 :
1318 :
1319 : /* More or less Robust version of dgettext. It has the side effect of
1320 : switching the codeset to utf-8 because this is what we want to
1321 : output. In theory it is posible to keep the original code set and
1322 : switch back for regular disgnostic output (redefine "_(" for that)
1323 : but given the natur of this tool, being something invoked from
1324 : other pograms, it does not make much sense. */
1325 : static const char *
1326 0 : my_dgettext (const char *domain, const char *msgid)
1327 : {
1328 : #ifdef USE_SIMPLE_GETTEXT
1329 : if (domain)
1330 : {
1331 : static int switched_codeset;
1332 : char *text;
1333 :
1334 : if (!switched_codeset)
1335 : {
1336 : switched_codeset = 1;
1337 : gettext_use_utf8 (1);
1338 : }
1339 :
1340 : if (!strcmp (domain, "gnupg"))
1341 : domain = PACKAGE_GT;
1342 :
1343 : /* FIXME: we have no dgettext, thus we can't switch. */
1344 :
1345 : text = (char*)gettext (msgid);
1346 : return text ? text : msgid;
1347 : }
1348 : else
1349 : return msgid;
1350 : #elif defined(ENABLE_NLS)
1351 0 : if (domain)
1352 : {
1353 : static int switched_codeset;
1354 : char *text;
1355 :
1356 0 : if (!switched_codeset)
1357 : {
1358 0 : switched_codeset = 1;
1359 0 : bind_textdomain_codeset (PACKAGE_GT, "utf-8");
1360 :
1361 0 : bindtextdomain (DIRMNGR_NAME, LOCALEDIR);
1362 0 : bind_textdomain_codeset (DIRMNGR_NAME, "utf-8");
1363 :
1364 : }
1365 :
1366 : /* Note: This is a hack to actually use the gnupg2 domain as
1367 : long we are in a transition phase where gnupg 1.x and 1.9 may
1368 : coexist. */
1369 0 : if (!strcmp (domain, "gnupg"))
1370 0 : domain = PACKAGE_GT;
1371 :
1372 0 : text = dgettext (domain, msgid);
1373 0 : return text ? text : msgid;
1374 : }
1375 : else
1376 0 : return msgid;
1377 : #else
1378 : (void)domain;
1379 : return msgid;
1380 : #endif
1381 : }
1382 :
1383 :
1384 : /* Percent-Escape special characters. The string is valid until the
1385 : next invocation of the function. */
1386 : char *
1387 0 : gc_percent_escape (const char *src)
1388 : {
1389 : static char *esc_str;
1390 : static int esc_str_len;
1391 0 : int new_len = 3 * strlen (src) + 1;
1392 : char *dst;
1393 :
1394 0 : if (esc_str_len < new_len)
1395 : {
1396 0 : char *new_esc_str = realloc (esc_str, new_len);
1397 0 : if (!new_esc_str)
1398 0 : gc_error (1, errno, "can not escape string");
1399 0 : esc_str = new_esc_str;
1400 0 : esc_str_len = new_len;
1401 : }
1402 :
1403 0 : dst = esc_str;
1404 0 : while (*src)
1405 : {
1406 0 : if (*src == '%')
1407 : {
1408 0 : *(dst++) = '%';
1409 0 : *(dst++) = '2';
1410 0 : *(dst++) = '5';
1411 : }
1412 0 : else if (*src == ':')
1413 : {
1414 : /* The colon is used as field separator. */
1415 0 : *(dst++) = '%';
1416 0 : *(dst++) = '3';
1417 0 : *(dst++) = 'a';
1418 : }
1419 0 : else if (*src == ',')
1420 : {
1421 : /* The comma is used as list separator. */
1422 0 : *(dst++) = '%';
1423 0 : *(dst++) = '2';
1424 0 : *(dst++) = 'c';
1425 : }
1426 : else
1427 0 : *(dst++) = *(src);
1428 0 : src++;
1429 : }
1430 0 : *dst = '\0';
1431 0 : return esc_str;
1432 : }
1433 :
1434 :
1435 :
1436 : /* Percent-Deescape special characters. The string is valid until the
1437 : next invocation of the function. */
1438 : static char *
1439 0 : percent_deescape (const char *src)
1440 : {
1441 : static char *str;
1442 : static int str_len;
1443 0 : int new_len = 3 * strlen (src) + 1;
1444 : char *dst;
1445 :
1446 0 : if (str_len < new_len)
1447 : {
1448 0 : char *new_str = realloc (str, new_len);
1449 0 : if (!new_str)
1450 0 : gc_error (1, errno, "can not deescape string");
1451 0 : str = new_str;
1452 0 : str_len = new_len;
1453 : }
1454 :
1455 0 : dst = str;
1456 0 : while (*src)
1457 : {
1458 0 : if (*src == '%')
1459 : {
1460 0 : int val = hextobyte (src + 1);
1461 :
1462 0 : if (val < 0)
1463 0 : gc_error (1, 0, "malformed end of string %s", src);
1464 :
1465 0 : *(dst++) = (char) val;
1466 0 : src += 3;
1467 : }
1468 : else
1469 0 : *(dst++) = *(src++);
1470 : }
1471 0 : *dst = '\0';
1472 0 : return str;
1473 : }
1474 :
1475 :
1476 : /* List all components that are available. */
1477 : void
1478 0 : gc_component_list_components (estream_t out)
1479 : {
1480 : gc_component_t component;
1481 : gc_option_t *option;
1482 : gc_backend_t backend;
1483 : int backend_seen[GC_BACKEND_NR];
1484 : const char *desc;
1485 : const char *pgmname;
1486 :
1487 0 : for (component = 0; component < GC_COMPONENT_NR; component++)
1488 : {
1489 0 : option = gc_component[component].options;
1490 0 : if (option)
1491 : {
1492 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1493 0 : backend_seen[backend] = 0;
1494 :
1495 0 : pgmname = "";
1496 0 : for (; option && option->name; option++)
1497 : {
1498 0 : if ((option->flags & GC_OPT_FLAG_GROUP))
1499 0 : continue;
1500 0 : backend = option->backend;
1501 0 : if (backend_seen[backend])
1502 0 : continue;
1503 0 : backend_seen[backend] = 1;
1504 0 : assert (backend != GC_BACKEND_ANY);
1505 0 : if (gc_backend[backend].program
1506 0 : && !gc_backend[backend].module_name)
1507 0 : continue;
1508 0 : pgmname = gnupg_module_name (gc_backend[backend].module_name);
1509 0 : break;
1510 : }
1511 :
1512 0 : desc = gc_component[component].desc;
1513 0 : desc = my_dgettext (gc_component[component].desc_domain, desc);
1514 0 : es_fprintf (out, "%s:%s:",
1515 : gc_component[component].name, gc_percent_escape (desc));
1516 0 : es_fprintf (out, "%s\n", gc_percent_escape (pgmname));
1517 : }
1518 : }
1519 0 : }
1520 :
1521 :
1522 :
1523 : static int
1524 0 : all_digits_p (const char *p, size_t len)
1525 : {
1526 0 : if (!len)
1527 0 : return 0; /* No. */
1528 0 : for (; len; len--, p++)
1529 0 : if (!isascii (*p) || !isdigit (*p))
1530 0 : return 0; /* No. */
1531 0 : return 1; /* Yes. */
1532 : }
1533 :
1534 :
1535 : /* Collect all error lines from stream FP. Only lines prefixed with
1536 : TAG are considered. Returns a list of error line items (which may
1537 : be empty). There is no error return. */
1538 : static error_line_t
1539 0 : collect_error_output (estream_t fp, const char *tag)
1540 : {
1541 : char buffer[1024];
1542 : char *p, *p2, *p3;
1543 : int c, cont_line;
1544 : unsigned int pos;
1545 : error_line_t eitem, errlines, *errlines_tail;
1546 0 : size_t taglen = strlen (tag);
1547 :
1548 0 : errlines = NULL;
1549 0 : errlines_tail = &errlines;
1550 0 : pos = 0;
1551 0 : cont_line = 0;
1552 0 : while ((c=es_getc (fp)) != EOF)
1553 : {
1554 0 : buffer[pos++] = c;
1555 0 : if (pos >= sizeof buffer - 5 || c == '\n')
1556 : {
1557 0 : buffer[pos - (c == '\n')] = 0;
1558 0 : if (cont_line)
1559 : ; /*Ignore continuations of previous line. */
1560 0 : else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':')
1561 : {
1562 : /* "gpgsm: foo:4: bla" */
1563 : /* Yep, we are interested in this line. */
1564 0 : p = buffer + taglen + 1;
1565 0 : while (*p == ' ' || *p == '\t')
1566 0 : p++;
1567 0 : trim_trailing_spaces (p); /* Get rid of extra CRs. */
1568 0 : if (!*p)
1569 : ; /* Empty lines are ignored. */
1570 0 : else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':'))
1571 0 : && all_digits_p (p2+1, p3 - (p2+1)))
1572 : {
1573 : /* Line in standard compiler format. */
1574 0 : p3++;
1575 0 : while (*p3 == ' ' || *p3 == '\t')
1576 0 : p3++;
1577 0 : eitem = xmalloc (sizeof *eitem + strlen (p));
1578 0 : eitem->next = NULL;
1579 0 : strcpy (eitem->buffer, p);
1580 0 : eitem->fname = eitem->buffer;
1581 0 : eitem->buffer[p2-p] = 0;
1582 0 : eitem->errtext = eitem->buffer + (p3 - p);
1583 : /* (we already checked that there are only ascii
1584 : digits followed by a colon) */
1585 0 : eitem->lineno = 0;
1586 0 : for (p2++; isdigit (*p2); p2++)
1587 0 : eitem->lineno = eitem->lineno*10 + (*p2 - '0');
1588 0 : *errlines_tail = eitem;
1589 0 : errlines_tail = &eitem->next;
1590 : }
1591 : else
1592 : {
1593 : /* Other error output. */
1594 0 : eitem = xmalloc (sizeof *eitem + strlen (p));
1595 0 : eitem->next = NULL;
1596 0 : strcpy (eitem->buffer, p);
1597 0 : eitem->fname = NULL;
1598 0 : eitem->errtext = eitem->buffer;
1599 0 : eitem->lineno = 0;
1600 0 : *errlines_tail = eitem;
1601 0 : errlines_tail = &eitem->next;
1602 : }
1603 : }
1604 0 : pos = 0;
1605 : /* If this was not a complete line mark that we are in a
1606 : continuation. */
1607 0 : cont_line = (c != '\n');
1608 : }
1609 : }
1610 :
1611 : /* We ignore error lines not terminated by a LF. */
1612 0 : return errlines;
1613 : }
1614 :
1615 :
1616 : /* Check the options of a single component. Returns 0 if everything
1617 : is OK. */
1618 : int
1619 0 : gc_component_check_options (int component, estream_t out, const char *conf_file)
1620 : {
1621 : gpg_error_t err;
1622 : unsigned int result;
1623 : int backend_seen[GC_BACKEND_NR];
1624 : gc_backend_t backend;
1625 : gc_option_t *option;
1626 : const char *pgmname;
1627 : const char *argv[4];
1628 : int i;
1629 : pid_t pid;
1630 : int exitcode;
1631 : estream_t errfp;
1632 : error_line_t errlines;
1633 :
1634 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
1635 0 : backend_seen[backend] = 0;
1636 :
1637 0 : option = gc_component[component].options;
1638 0 : for (; option && option->name; option++)
1639 : {
1640 0 : if ((option->flags & GC_OPT_FLAG_GROUP))
1641 0 : continue;
1642 0 : backend = option->backend;
1643 0 : if (backend_seen[backend])
1644 0 : continue;
1645 0 : backend_seen[backend] = 1;
1646 0 : assert (backend != GC_BACKEND_ANY);
1647 0 : if (!gc_backend[backend].program)
1648 0 : continue;
1649 0 : if (!gc_backend[backend].module_name)
1650 0 : continue;
1651 :
1652 0 : break;
1653 : }
1654 0 : if (! option || ! option->name)
1655 0 : return 0;
1656 :
1657 0 : pgmname = gnupg_module_name (gc_backend[backend].module_name);
1658 0 : i = 0;
1659 0 : if (conf_file)
1660 : {
1661 0 : argv[i++] = "--options";
1662 0 : argv[i++] = conf_file;
1663 : }
1664 0 : if (component == GC_COMPONENT_PINENTRY)
1665 0 : argv[i++] = "--version";
1666 : else
1667 0 : argv[i++] = "--gpgconf-test";
1668 0 : argv[i++] = NULL;
1669 :
1670 0 : result = 0;
1671 0 : errlines = NULL;
1672 0 : err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
1673 : NULL, NULL, &errfp, &pid);
1674 0 : if (err)
1675 0 : result |= 1; /* Program could not be run. */
1676 : else
1677 : {
1678 0 : errlines = collect_error_output (errfp,
1679 : gc_component[component].name);
1680 0 : if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
1681 : {
1682 0 : if (exitcode == -1)
1683 0 : result |= 1; /* Program could not be run or it
1684 : terminated abnormally. */
1685 0 : result |= 2; /* Program returned an error. */
1686 : }
1687 0 : gnupg_release_process (pid);
1688 0 : es_fclose (errfp);
1689 : }
1690 :
1691 : /* If the program could not be run, we can't tell whether
1692 : the config file is good. */
1693 0 : if (result & 1)
1694 0 : result |= 2;
1695 :
1696 0 : if (out)
1697 : {
1698 : const char *desc;
1699 : error_line_t errptr;
1700 :
1701 0 : desc = gc_component[component].desc;
1702 0 : desc = my_dgettext (gc_component[component].desc_domain, desc);
1703 0 : es_fprintf (out, "%s:%s:",
1704 : gc_component[component].name, gc_percent_escape (desc));
1705 0 : es_fputs (gc_percent_escape (pgmname), out);
1706 0 : es_fprintf (out, ":%d:%d:", !(result & 1), !(result & 2));
1707 0 : for (errptr = errlines; errptr; errptr = errptr->next)
1708 : {
1709 0 : if (errptr != errlines)
1710 0 : es_fputs ("\n:::::", out); /* Continuation line. */
1711 0 : if (errptr->fname)
1712 0 : es_fputs (gc_percent_escape (errptr->fname), out);
1713 0 : es_putc (':', out);
1714 0 : if (errptr->fname)
1715 0 : es_fprintf (out, "%u", errptr->lineno);
1716 0 : es_putc (':', out);
1717 0 : es_fputs (gc_percent_escape (errptr->errtext), out);
1718 0 : es_putc (':', out);
1719 : }
1720 0 : es_putc ('\n', out);
1721 : }
1722 :
1723 0 : while (errlines)
1724 : {
1725 0 : error_line_t tmp = errlines->next;
1726 0 : xfree (errlines);
1727 0 : errlines = tmp;
1728 : }
1729 :
1730 0 : return result;
1731 : }
1732 :
1733 :
1734 :
1735 : /* Check all components that are available. */
1736 : void
1737 0 : gc_check_programs (estream_t out)
1738 : {
1739 : gc_component_t component;
1740 :
1741 0 : for (component = 0; component < GC_COMPONENT_NR; component++)
1742 0 : gc_component_check_options (component, out, NULL);
1743 0 : }
1744 :
1745 :
1746 :
1747 : /* Find the component with the name NAME. Returns -1 if not
1748 : found. */
1749 : int
1750 0 : gc_component_find (const char *name)
1751 : {
1752 : gc_component_t idx;
1753 :
1754 0 : for (idx = 0; idx < GC_COMPONENT_NR; idx++)
1755 : {
1756 0 : if (gc_component[idx].options
1757 0 : && !strcmp (name, gc_component[idx].name))
1758 0 : return idx;
1759 : }
1760 0 : return -1;
1761 : }
1762 :
1763 :
1764 : /* List the option OPTION. */
1765 : static void
1766 0 : list_one_option (const gc_option_t *option, estream_t out)
1767 : {
1768 0 : const char *desc = NULL;
1769 0 : char *arg_name = NULL;
1770 :
1771 0 : if (option->desc)
1772 : {
1773 0 : desc = my_dgettext (option->desc_domain, option->desc);
1774 :
1775 0 : if (*desc == '|')
1776 : {
1777 0 : const char *arg_tail = strchr (&desc[1], '|');
1778 :
1779 0 : if (arg_tail)
1780 : {
1781 0 : int arg_len = arg_tail - &desc[1];
1782 0 : arg_name = xmalloc (arg_len + 1);
1783 0 : memcpy (arg_name, &desc[1], arg_len);
1784 0 : arg_name[arg_len] = '\0';
1785 0 : desc = arg_tail + 1;
1786 : }
1787 : }
1788 : }
1789 :
1790 :
1791 : /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS
1792 : PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE ANY
1793 : FIELDS. */
1794 :
1795 : /* The name field. */
1796 0 : es_fprintf (out, "%s", option->name);
1797 :
1798 : /* The flags field. */
1799 0 : es_fprintf (out, ":%lu", option->flags);
1800 0 : if (opt.verbose)
1801 : {
1802 0 : es_putc (' ', out);
1803 :
1804 0 : if (!option->flags)
1805 0 : es_fprintf (out, "none");
1806 : else
1807 : {
1808 0 : unsigned long flags = option->flags;
1809 0 : unsigned long flag = 0;
1810 0 : unsigned long first = 1;
1811 :
1812 0 : while (flags)
1813 : {
1814 0 : if (flags & 1)
1815 : {
1816 0 : if (first)
1817 0 : first = 0;
1818 : else
1819 0 : es_putc (',', out);
1820 0 : es_fprintf (out, "%s", gc_flag[flag].name);
1821 : }
1822 0 : flags >>= 1;
1823 0 : flag++;
1824 : }
1825 : }
1826 : }
1827 :
1828 : /* The level field. */
1829 0 : es_fprintf (out, ":%u", option->level);
1830 0 : if (opt.verbose)
1831 0 : es_fprintf (out, " %s", gc_level[option->level].name);
1832 :
1833 : /* The description field. */
1834 0 : es_fprintf (out, ":%s", desc ? gc_percent_escape (desc) : "");
1835 :
1836 : /* The type field. */
1837 0 : es_fprintf (out, ":%u", option->arg_type);
1838 0 : if (opt.verbose)
1839 0 : es_fprintf (out, " %s", gc_arg_type[option->arg_type].name);
1840 :
1841 : /* The alternate type field. */
1842 0 : es_fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
1843 0 : if (opt.verbose)
1844 0 : es_fprintf (out, " %s",
1845 0 : gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
1846 :
1847 : /* The argument name field. */
1848 0 : es_fprintf (out, ":%s", arg_name ? gc_percent_escape (arg_name) : "");
1849 0 : xfree (arg_name);
1850 :
1851 : /* The default value field. */
1852 0 : es_fprintf (out, ":%s", option->default_value ? option->default_value : "");
1853 :
1854 : /* The default argument field. */
1855 0 : es_fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
1856 :
1857 : /* The value field. */
1858 0 : if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
1859 0 : && (option->flags & GC_OPT_FLAG_LIST)
1860 0 : && option->value)
1861 : /* The special format "1,1,1,1,...,1" is converted to a number
1862 : here. */
1863 0 : es_fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2));
1864 : else
1865 0 : es_fprintf (out, ":%s", option->value ? option->value : "");
1866 :
1867 : /* ADD NEW FIELDS HERE. */
1868 :
1869 0 : es_putc ('\n', out);
1870 0 : }
1871 :
1872 :
1873 : /* List all options of the component COMPONENT. */
1874 : void
1875 0 : gc_component_list_options (int component, estream_t out)
1876 : {
1877 0 : const gc_option_t *option = gc_component[component].options;
1878 :
1879 0 : while (option && option->name)
1880 : {
1881 : /* Do not output unknown or internal options. */
1882 0 : if (!(option->flags & GC_OPT_FLAG_GROUP)
1883 0 : && (!option->active || option->level == GC_LEVEL_INTERNAL))
1884 : {
1885 0 : option++;
1886 0 : continue;
1887 : }
1888 :
1889 0 : if (option->flags & GC_OPT_FLAG_GROUP)
1890 : {
1891 0 : const gc_option_t *group_option = option + 1;
1892 0 : gc_expert_level_t level = GC_LEVEL_NR;
1893 :
1894 : /* The manual states that the group level is always the
1895 : minimum of the levels of all contained options. Due to
1896 : different active options, and because it is hard to
1897 : maintain manually, we calculate it here. The value in
1898 : the global static table is ignored. */
1899 :
1900 0 : while (group_option->name)
1901 : {
1902 0 : if (group_option->flags & GC_OPT_FLAG_GROUP)
1903 0 : break;
1904 0 : if (group_option->level < level)
1905 0 : level = group_option->level;
1906 0 : group_option++;
1907 : }
1908 :
1909 : /* Check if group is empty. */
1910 0 : if (level != GC_LEVEL_NR)
1911 : {
1912 : gc_option_t opt_copy;
1913 :
1914 : /* Fix up the group level. */
1915 0 : memcpy (&opt_copy, option, sizeof (opt_copy));
1916 0 : opt_copy.level = level;
1917 0 : list_one_option (&opt_copy, out);
1918 : }
1919 : }
1920 : else
1921 0 : list_one_option (option, out);
1922 :
1923 0 : option++;
1924 : }
1925 0 : }
1926 :
1927 :
1928 : /* Find the option NAME in component COMPONENT, for the backend
1929 : BACKEND. If BACKEND is GC_BACKEND_ANY, any backend will match. */
1930 : static gc_option_t *
1931 0 : find_option (gc_component_t component, const char *name,
1932 : gc_backend_t backend)
1933 : {
1934 0 : gc_option_t *option = gc_component[component].options;
1935 0 : while (option->name)
1936 : {
1937 0 : if (!(option->flags & GC_OPT_FLAG_GROUP)
1938 0 : && !strcmp (option->name, name)
1939 0 : && (backend == GC_BACKEND_ANY || option->backend == backend))
1940 : break;
1941 0 : option++;
1942 : }
1943 0 : return option->name ? option : NULL;
1944 : }
1945 :
1946 :
1947 : /* Determine the configuration filename for the component COMPONENT
1948 : and backend BACKEND. */
1949 : static char *
1950 0 : get_config_filename (gc_component_t component, gc_backend_t backend)
1951 : {
1952 0 : char *filename = NULL;
1953 0 : gc_option_t *option = find_option
1954 : (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
1955 0 : assert (option);
1956 0 : assert (option->arg_type == GC_ARG_TYPE_FILENAME);
1957 0 : assert (!(option->flags & GC_OPT_FLAG_LIST));
1958 :
1959 0 : if (!option->active || !option->default_value)
1960 0 : gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
1961 : gc_backend[backend].option_config_filename,
1962 : gc_backend[backend].name);
1963 :
1964 0 : if (option->value && *option->value)
1965 0 : filename = percent_deescape (&option->value[1]);
1966 0 : else if (option->default_value && *option->default_value)
1967 0 : filename = percent_deescape (&option->default_value[1]);
1968 : else
1969 0 : filename = "";
1970 :
1971 : #if HAVE_W32CE_SYSTEM
1972 : if (!(filename[0] == '/' || filename[0] == '\\'))
1973 : #elif defined(HAVE_DOSISH_SYSTEM)
1974 : if (!(filename[0]
1975 : && filename[1] == ':'
1976 : && (filename[2] == '/' || filename[2] == '\\')))
1977 : #else
1978 0 : if (filename[0] != '/')
1979 : #endif
1980 0 : gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
1981 : gc_backend[backend].option_config_filename,
1982 : gc_backend[backend].name);
1983 :
1984 0 : return filename;
1985 : }
1986 :
1987 :
1988 : /* Retrieve the options for the component COMPONENT from backend
1989 : BACKEND, which we already know is a program-type backend. */
1990 : static void
1991 0 : retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
1992 : {
1993 : gpg_error_t err;
1994 : const char *pgmname;
1995 : const char *argv[2];
1996 : estream_t outfp;
1997 : int exitcode;
1998 : pid_t pid;
1999 0 : char *line = NULL;
2000 0 : size_t line_len = 0;
2001 : ssize_t length;
2002 : estream_t config;
2003 : char *config_filename;
2004 :
2005 0 : pgmname = (gc_backend[backend].module_name
2006 0 : ? gnupg_module_name (gc_backend[backend].module_name)
2007 0 : : gc_backend[backend].program );
2008 0 : argv[0] = "--gpgconf-list";
2009 0 : argv[1] = NULL;
2010 :
2011 0 : err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
2012 : NULL, &outfp, NULL, &pid);
2013 0 : if (err)
2014 : {
2015 0 : gc_error (1, 0, "could not gather active options from '%s': %s",
2016 : pgmname, gpg_strerror (err));
2017 : }
2018 :
2019 0 : while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
2020 : {
2021 : gc_option_t *option;
2022 : char *linep;
2023 0 : unsigned long flags = 0;
2024 0 : char *default_value = NULL;
2025 :
2026 : /* Strip newline and carriage return, if present. */
2027 0 : while (length > 0
2028 0 : && (line[length - 1] == '\n' || line[length - 1] == '\r'))
2029 0 : line[--length] = '\0';
2030 :
2031 0 : linep = strchr (line, ':');
2032 0 : if (linep)
2033 0 : *(linep++) = '\0';
2034 :
2035 : /* Extract additional flags. Default to none. */
2036 0 : if (linep)
2037 : {
2038 : char *end;
2039 : char *tail;
2040 :
2041 0 : end = strchr (linep, ':');
2042 0 : if (end)
2043 0 : *(end++) = '\0';
2044 :
2045 0 : gpg_err_set_errno (0);
2046 0 : flags = strtoul (linep, &tail, 0);
2047 0 : if (errno)
2048 0 : gc_error (1, errno, "malformed flags in option %s from %s",
2049 : line, pgmname);
2050 0 : if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
2051 0 : gc_error (1, 0, "garbage after flags in option %s from %s",
2052 : line, pgmname);
2053 :
2054 0 : linep = end;
2055 : }
2056 :
2057 : /* Extract default value, if present. Default to empty if
2058 : not. */
2059 0 : if (linep)
2060 : {
2061 : char *end;
2062 :
2063 0 : end = strchr (linep, ':');
2064 0 : if (end)
2065 0 : *(end++) = '\0';
2066 :
2067 0 : if (flags & GC_OPT_FLAG_DEFAULT)
2068 0 : default_value = linep;
2069 :
2070 0 : linep = end;
2071 : }
2072 :
2073 : /* Look up the option in the component and install the
2074 : configuration data. */
2075 0 : option = find_option (component, line, backend);
2076 0 : if (option)
2077 : {
2078 0 : if (option->active)
2079 0 : gc_error (1, errno, "option %s returned twice from %s",
2080 : line, pgmname);
2081 0 : option->active = 1;
2082 :
2083 0 : option->flags |= flags;
2084 0 : if (default_value && *default_value)
2085 0 : option->default_value = xstrdup (default_value);
2086 : }
2087 : }
2088 0 : if (length < 0 || es_ferror (outfp))
2089 0 : gc_error (1, errno, "error reading from %s", pgmname);
2090 0 : if (es_fclose (outfp))
2091 0 : gc_error (1, errno, "error closing %s", pgmname);
2092 :
2093 0 : err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
2094 0 : if (err)
2095 0 : gc_error (1, 0, "running %s failed (exitcode=%d): %s",
2096 : pgmname, exitcode, gpg_strerror (err));
2097 0 : gnupg_release_process (pid);
2098 :
2099 :
2100 : /* At this point, we can parse the configuration file. */
2101 0 : config_filename = get_config_filename (component, backend);
2102 :
2103 0 : config = es_fopen (config_filename, "r");
2104 0 : if (!config)
2105 0 : gc_error (0, errno, "warning: can not open config file %s",
2106 : config_filename);
2107 : else
2108 : {
2109 0 : while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
2110 : {
2111 : char *name;
2112 : char *value;
2113 : gc_option_t *option;
2114 :
2115 0 : name = line;
2116 0 : while (*name == ' ' || *name == '\t')
2117 0 : name++;
2118 0 : if (!*name || *name == '#' || *name == '\r' || *name == '\n')
2119 0 : continue;
2120 :
2121 0 : value = name;
2122 0 : while (*value && *value != ' ' && *value != '\t'
2123 0 : && *value != '#' && *value != '\r' && *value != '\n')
2124 0 : value++;
2125 0 : if (*value == ' ' || *value == '\t')
2126 0 : {
2127 : char *end;
2128 :
2129 0 : *(value++) = '\0';
2130 0 : while (*value == ' ' || *value == '\t')
2131 0 : value++;
2132 :
2133 0 : end = value;
2134 0 : while (*end && *end != '#' && *end != '\r' && *end != '\n')
2135 0 : end++;
2136 0 : while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
2137 0 : end--;
2138 0 : *end = '\0';
2139 : }
2140 : else
2141 0 : *value = '\0';
2142 :
2143 : /* Look up the option in the component and install the
2144 : configuration data. */
2145 0 : option = find_option (component, line, backend);
2146 0 : if (option)
2147 : {
2148 : char *opt_value;
2149 :
2150 0 : if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
2151 : {
2152 0 : if (*value)
2153 0 : gc_error (0, 0,
2154 : "warning: ignoring argument %s for option %s",
2155 : value, name);
2156 0 : opt_value = xstrdup ("1");
2157 : }
2158 0 : else if (gc_arg_type[option->arg_type].fallback
2159 : == GC_ARG_TYPE_STRING)
2160 0 : opt_value = xasprintf ("\"%s", gc_percent_escape (value));
2161 : else
2162 : {
2163 : /* FIXME: Verify that the number is sane. */
2164 0 : opt_value = xstrdup (value);
2165 : }
2166 :
2167 : /* Now enter the option into the table. */
2168 0 : if (!(option->flags & GC_OPT_FLAG_LIST))
2169 : {
2170 0 : if (option->value)
2171 0 : free (option->value);
2172 0 : option->value = opt_value;
2173 : }
2174 : else
2175 : {
2176 0 : if (!option->value)
2177 0 : option->value = opt_value;
2178 : else
2179 : {
2180 0 : char *opt_val = opt_value;
2181 :
2182 0 : option->value = xasprintf ("%s,%s", option->value,
2183 : opt_val);
2184 0 : xfree (opt_value);
2185 : }
2186 : }
2187 : }
2188 : }
2189 :
2190 0 : if (length < 0 || es_ferror (config))
2191 0 : gc_error (1, errno, "error reading from %s", config_filename);
2192 0 : if (es_fclose (config))
2193 0 : gc_error (1, errno, "error closing %s", config_filename);
2194 : }
2195 :
2196 0 : xfree (line);
2197 0 : }
2198 :
2199 :
2200 : /* Retrieve the options for the component COMPONENT from backend
2201 : BACKEND, which we already know is of type file list. */
2202 : static void
2203 0 : retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
2204 : {
2205 : gc_option_t *list_option;
2206 : gc_option_t *config_option;
2207 : char *list_filename;
2208 : FILE *list_file;
2209 0 : char *line = NULL;
2210 0 : size_t line_len = 0;
2211 : ssize_t length;
2212 0 : char *list = NULL;
2213 :
2214 0 : list_option = find_option (component,
2215 : gc_backend[backend].option_name, GC_BACKEND_ANY);
2216 0 : assert (list_option);
2217 0 : assert (!list_option->active);
2218 :
2219 0 : list_filename = get_config_filename (component, backend);
2220 0 : list_file = fopen (list_filename, "r");
2221 0 : if (!list_file)
2222 0 : gc_error (0, errno, "warning: can not open list file %s", list_filename);
2223 : else
2224 : {
2225 :
2226 0 : while ((length = read_line (list_file, &line, &line_len, NULL)) > 0)
2227 : {
2228 : char *start;
2229 : char *end;
2230 : char *new_list;
2231 :
2232 0 : start = line;
2233 0 : while (*start == ' ' || *start == '\t')
2234 0 : start++;
2235 0 : if (!*start || *start == '#' || *start == '\r' || *start == '\n')
2236 0 : continue;
2237 :
2238 0 : end = start;
2239 0 : while (*end && *end != '#' && *end != '\r' && *end != '\n')
2240 0 : end++;
2241 : /* Walk back to skip trailing white spaces. Looks evil, but
2242 : works because of the conditions on START and END imposed
2243 : at this point (END is at least START + 1, and START is
2244 : not a whitespace character). */
2245 0 : while (*(end - 1) == ' ' || *(end - 1) == '\t')
2246 0 : end--;
2247 0 : *end = '\0';
2248 : /* FIXME: Oh, no! This is so lame! Should use realloc and
2249 : really append. */
2250 0 : if (list)
2251 : {
2252 0 : new_list = xasprintf ("%s,\"%s", list, gc_percent_escape (start));
2253 0 : xfree (list);
2254 0 : list = new_list;
2255 : }
2256 : else
2257 0 : list = xasprintf ("\"%s", gc_percent_escape (start));
2258 : }
2259 0 : if (length < 0 || ferror (list_file))
2260 0 : gc_error (1, errno, "can not read list file %s", list_filename);
2261 : }
2262 :
2263 0 : list_option->active = 1;
2264 0 : list_option->value = list;
2265 :
2266 : /* Fix up the read-only flag. */
2267 0 : config_option = find_option
2268 : (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
2269 0 : if (config_option->flags & GC_OPT_FLAG_NO_CHANGE)
2270 0 : list_option->flags |= GC_OPT_FLAG_NO_CHANGE;
2271 :
2272 0 : if (list_file && fclose (list_file))
2273 0 : gc_error (1, errno, "error closing %s", list_filename);
2274 0 : xfree (line);
2275 0 : }
2276 :
2277 :
2278 : /* Retrieve the currently active options and their defaults from all
2279 : involved backends for this component. Using -1 for component will
2280 : retrieve all options from all components. */
2281 : void
2282 0 : gc_component_retrieve_options (int component)
2283 : {
2284 0 : int process_all = 0;
2285 : int backend_seen[GC_BACKEND_NR];
2286 : gc_backend_t backend;
2287 : gc_option_t *option;
2288 :
2289 0 : if (component == GC_COMPONENT_PINENTRY)
2290 0 : return; /* Dummy module for now. */
2291 :
2292 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
2293 0 : backend_seen[backend] = 0;
2294 :
2295 0 : if (component == -1)
2296 : {
2297 0 : process_all = 1;
2298 0 : component = 0;
2299 0 : assert (component < GC_COMPONENT_NR);
2300 : }
2301 :
2302 : do
2303 : {
2304 0 : option = gc_component[component].options;
2305 :
2306 0 : while (option && option->name)
2307 : {
2308 0 : if (!(option->flags & GC_OPT_FLAG_GROUP))
2309 : {
2310 0 : backend = option->backend;
2311 :
2312 0 : if (backend_seen[backend])
2313 : {
2314 0 : option++;
2315 0 : continue;
2316 : }
2317 0 : backend_seen[backend] = 1;
2318 :
2319 0 : assert (backend != GC_BACKEND_ANY);
2320 :
2321 0 : if (gc_backend[backend].program)
2322 0 : retrieve_options_from_program (component, backend);
2323 : else
2324 0 : retrieve_options_from_file (component, backend);
2325 : }
2326 0 : option++;
2327 : }
2328 : }
2329 0 : while (process_all && ++component < GC_COMPONENT_NR);
2330 :
2331 : }
2332 :
2333 :
2334 :
2335 : /* Perform a simple validity check based on the type. Return in
2336 : NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of
2337 : type GC_ARG_TYPE_NONE. */
2338 : static void
2339 0 : option_check_validity (gc_option_t *option, unsigned long flags,
2340 : char *new_value, unsigned long *new_value_nr)
2341 : {
2342 : char *arg;
2343 :
2344 0 : if (!option->active)
2345 0 : gc_error (1, 0, "option %s not supported by backend %s",
2346 0 : option->name, gc_backend[option->backend].name);
2347 :
2348 0 : if (option->new_flags || option->new_value)
2349 0 : gc_error (1, 0, "option %s already changed", option->name);
2350 :
2351 0 : if (flags & GC_OPT_FLAG_DEFAULT)
2352 : {
2353 0 : if (*new_value)
2354 0 : gc_error (1, 0, "argument %s provided for deleted option %s",
2355 : new_value, option->name);
2356 :
2357 0 : return;
2358 : }
2359 :
2360 : /* GC_ARG_TYPE_NONE options have special list treatment. */
2361 0 : if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
2362 : {
2363 : char *tail;
2364 :
2365 0 : gpg_err_set_errno (0);
2366 0 : *new_value_nr = strtoul (new_value, &tail, 0);
2367 :
2368 0 : if (errno)
2369 0 : gc_error (1, errno, "invalid argument for option %s",
2370 : option->name);
2371 0 : if (*tail)
2372 0 : gc_error (1, 0, "garbage after argument for option %s",
2373 : option->name);
2374 :
2375 0 : if (!(option->flags & GC_OPT_FLAG_LIST))
2376 : {
2377 0 : if (*new_value_nr != 1)
2378 0 : gc_error (1, 0, "argument for non-list option %s of type 0 "
2379 : "(none) must be 1", option->name);
2380 : }
2381 : else
2382 : {
2383 0 : if (*new_value_nr == 0)
2384 0 : gc_error (1, 0, "argument for option %s of type 0 (none) "
2385 : "must be positive", option->name);
2386 : }
2387 :
2388 0 : return;
2389 : }
2390 :
2391 0 : arg = new_value;
2392 : do
2393 : {
2394 0 : if (*arg == '\0' || *arg == ',')
2395 : {
2396 0 : if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
2397 0 : gc_error (1, 0, "argument required for option %s", option->name);
2398 :
2399 0 : if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
2400 0 : gc_error (1, 0, "list found for non-list option %s", option->name);
2401 : }
2402 0 : else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
2403 : {
2404 0 : if (*arg != '"')
2405 0 : gc_error (1, 0, "string argument for option %s must begin "
2406 : "with a quote (\") character", option->name);
2407 :
2408 : /* FIXME: We do not allow empty string arguments for now, as
2409 : we do not quote arguments in configuration files, and
2410 : thus no argument is indistinguishable from the empty
2411 : string. */
2412 0 : if (arg[1] == '\0' || arg[1] == ',')
2413 0 : gc_error (1, 0, "empty string argument for option %s is "
2414 : "currently not allowed. Please report this!",
2415 : option->name);
2416 : }
2417 0 : else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
2418 : {
2419 : long res;
2420 :
2421 0 : gpg_err_set_errno (0);
2422 0 : res = strtol (arg, &arg, 0);
2423 : (void) res;
2424 :
2425 0 : if (errno)
2426 0 : gc_error (1, errno, "invalid argument for option %s",
2427 : option->name);
2428 :
2429 0 : if (*arg != '\0' && *arg != ',')
2430 0 : gc_error (1, 0, "garbage after argument for option %s",
2431 : option->name);
2432 : }
2433 0 : else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32)
2434 : {
2435 : unsigned long res;
2436 :
2437 0 : gpg_err_set_errno (0);
2438 0 : res = strtoul (arg, &arg, 0);
2439 : (void) res;
2440 :
2441 0 : if (errno)
2442 0 : gc_error (1, errno, "invalid argument for option %s",
2443 : option->name);
2444 :
2445 0 : if (*arg != '\0' && *arg != ',')
2446 0 : gc_error (1, 0, "garbage after argument for option %s",
2447 : option->name);
2448 : }
2449 0 : arg = strchr (arg, ',');
2450 0 : if (arg)
2451 0 : arg++;
2452 : }
2453 0 : while (arg && *arg);
2454 : }
2455 :
2456 : #ifdef HAVE_W32_SYSTEM
2457 : int
2458 : copy_file (const char *src_name, const char *dst_name)
2459 : {
2460 : #define BUF_LEN 4096
2461 : char buffer[BUF_LEN];
2462 : int len;
2463 : FILE *src;
2464 : FILE *dst;
2465 :
2466 : src = fopen (src_name, "r");
2467 : if (src == NULL)
2468 : return -1;
2469 :
2470 : dst = fopen (dst_name, "w");
2471 : if (dst == NULL)
2472 : {
2473 : int saved_err = errno;
2474 : fclose (src);
2475 : gpg_err_set_errno (saved_err);
2476 : return -1;
2477 : }
2478 :
2479 : do
2480 : {
2481 : int written;
2482 :
2483 : len = fread (buffer, 1, BUF_LEN, src);
2484 : if (len == 0)
2485 : break;
2486 : written = fwrite (buffer, 1, len, dst);
2487 : if (written != len)
2488 : break;
2489 : }
2490 : while (!feof (src) && !ferror (src) && !ferror (dst));
2491 :
2492 : if (ferror (src) || ferror (dst) || !feof (src))
2493 : {
2494 : int saved_errno = errno;
2495 : fclose (src);
2496 : fclose (dst);
2497 : unlink (dst_name);
2498 : gpg_err_set_errno (saved_errno);
2499 : return -1;
2500 : }
2501 :
2502 : if (fclose (dst))
2503 : gc_error (1, errno, "error closing %s", dst_name);
2504 : if (fclose (src))
2505 : gc_error (1, errno, "error closing %s", src_name);
2506 :
2507 : return 0;
2508 : }
2509 : #endif /* HAVE_W32_SYSTEM */
2510 :
2511 :
2512 : /* Create and verify the new configuration file for the specified
2513 : backend and component. Returns 0 on success and -1 on error. */
2514 : static int
2515 0 : change_options_file (gc_component_t component, gc_backend_t backend,
2516 : char **src_filenamep, char **dest_filenamep,
2517 : char **orig_filenamep)
2518 : {
2519 : static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###";
2520 : /* True if we are within the marker in the config file. */
2521 0 : int in_marker = 0;
2522 : gc_option_t *option;
2523 0 : char *line = NULL;
2524 : size_t line_len;
2525 : ssize_t length;
2526 : int res;
2527 : int fd;
2528 0 : FILE *src_file = NULL;
2529 0 : FILE *dest_file = NULL;
2530 : char *src_filename;
2531 : char *dest_filename;
2532 : char *orig_filename;
2533 : char *arg;
2534 0 : char *cur_arg = NULL;
2535 :
2536 0 : option = find_option (component,
2537 : gc_backend[backend].option_name, GC_BACKEND_ANY);
2538 0 : assert (option);
2539 0 : assert (option->active);
2540 0 : assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
2541 :
2542 : /* FIXME. Throughout the function, do better error reporting. */
2543 : /* Note that get_config_filename() calls percent_deescape(), so we
2544 : call this before processing the arguments. */
2545 0 : dest_filename = xstrdup (get_config_filename (component, backend));
2546 0 : src_filename = xasprintf ("%s.%s.%i.new",
2547 : dest_filename, GPGCONF_NAME, (int)getpid ());
2548 0 : orig_filename = xasprintf ("%s.%s.%i.bak",
2549 : dest_filename, GPGCONF_NAME, (int)getpid ());
2550 :
2551 0 : arg = option->new_value;
2552 0 : if (arg && arg[0] == '\0')
2553 0 : arg = NULL;
2554 0 : else if (arg)
2555 : {
2556 : char *end;
2557 :
2558 0 : arg++;
2559 0 : end = strchr (arg, ',');
2560 0 : if (end)
2561 0 : *end = '\0';
2562 :
2563 0 : cur_arg = percent_deescape (arg);
2564 0 : if (end)
2565 : {
2566 0 : *end = ',';
2567 0 : arg = end + 1;
2568 : }
2569 : else
2570 0 : arg = NULL;
2571 : }
2572 :
2573 : #ifdef HAVE_W32_SYSTEM
2574 : res = copy_file (dest_filename, orig_filename);
2575 : #else
2576 0 : res = link (dest_filename, orig_filename);
2577 : #endif
2578 0 : if (res < 0 && errno != ENOENT)
2579 : {
2580 0 : xfree (dest_filename);
2581 0 : return -1;
2582 : }
2583 0 : if (res < 0)
2584 : {
2585 0 : xfree (orig_filename);
2586 0 : orig_filename = NULL;
2587 : }
2588 :
2589 : /* We now initialize the return strings, so the caller can do the
2590 : cleanup for us. */
2591 0 : *src_filenamep = src_filename;
2592 0 : *dest_filenamep = dest_filename;
2593 0 : *orig_filenamep = orig_filename;
2594 :
2595 : /* Use open() so that we can use O_EXCL. */
2596 0 : fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
2597 0 : if (fd < 0)
2598 0 : return -1;
2599 0 : src_file = fdopen (fd, "w");
2600 0 : res = errno;
2601 0 : if (!src_file)
2602 : {
2603 0 : gpg_err_set_errno (res);
2604 0 : return -1;
2605 : }
2606 :
2607 : /* Only if ORIG_FILENAME is not NULL did the configuration file
2608 : exist already. In this case, we will copy its content into the
2609 : new configuration file, changing it to our liking in the
2610 : process. */
2611 0 : if (orig_filename)
2612 : {
2613 0 : dest_file = fopen (dest_filename, "r");
2614 0 : if (!dest_file)
2615 0 : goto change_file_one_err;
2616 :
2617 0 : while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
2618 : {
2619 0 : int disable = 0;
2620 : char *start;
2621 :
2622 0 : if (!strncmp (marker, line, sizeof (marker) - 1))
2623 : {
2624 0 : if (!in_marker)
2625 0 : in_marker = 1;
2626 : else
2627 0 : break;
2628 : }
2629 :
2630 0 : start = line;
2631 0 : while (*start == ' ' || *start == '\t')
2632 0 : start++;
2633 0 : if (*start && *start != '\r' && *start != '\n' && *start != '#')
2634 : {
2635 : char *end;
2636 : char *endp;
2637 : char saved_end;
2638 :
2639 0 : endp = start;
2640 0 : end = endp;
2641 :
2642 : /* Search for the end of the line. */
2643 0 : while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
2644 : {
2645 0 : endp++;
2646 0 : if (*endp && *endp != ' ' && *endp != '\t'
2647 0 : && *endp != '\r' && *endp != '\n' && *endp != '#')
2648 0 : end = endp + 1;
2649 : }
2650 0 : saved_end = *end;
2651 0 : *end = '\0';
2652 :
2653 0 : if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
2654 0 : || !cur_arg || strcmp (start, cur_arg))
2655 0 : disable = 1;
2656 : else
2657 : {
2658 : /* Find next argument. */
2659 0 : if (arg)
2660 : {
2661 : char *arg_end;
2662 :
2663 0 : arg++;
2664 0 : arg_end = strchr (arg, ',');
2665 0 : if (arg_end)
2666 0 : *arg_end = '\0';
2667 :
2668 0 : cur_arg = percent_deescape (arg);
2669 0 : if (arg_end)
2670 : {
2671 0 : *arg_end = ',';
2672 0 : arg = arg_end + 1;
2673 : }
2674 : else
2675 0 : arg = NULL;
2676 : }
2677 : else
2678 0 : cur_arg = NULL;
2679 : }
2680 :
2681 0 : *end = saved_end;
2682 : }
2683 :
2684 0 : if (disable)
2685 : {
2686 0 : if (!in_marker)
2687 : {
2688 0 : fprintf (src_file,
2689 : "# %s disabled this option here at %s\n",
2690 0 : GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
2691 0 : if (ferror (src_file))
2692 0 : goto change_file_one_err;
2693 0 : fprintf (src_file, "# %s", line);
2694 0 : if (ferror (src_file))
2695 0 : goto change_file_one_err;
2696 : }
2697 : }
2698 : else
2699 : {
2700 0 : fprintf (src_file, "%s", line);
2701 0 : if (ferror (src_file))
2702 0 : goto change_file_one_err;
2703 : }
2704 : }
2705 0 : if (length < 0 || ferror (dest_file))
2706 : goto change_file_one_err;
2707 : }
2708 :
2709 0 : if (!in_marker)
2710 : {
2711 : /* There was no marker. This is the first time we edit the
2712 : file. We add our own marker at the end of the file and
2713 : proceed. Note that we first write a newline, this guards us
2714 : against files which lack the newline at the end of the last
2715 : line, while it doesn't hurt us in all other cases. */
2716 0 : fprintf (src_file, "\n%s\n", marker);
2717 0 : if (ferror (src_file))
2718 0 : goto change_file_one_err;
2719 : }
2720 :
2721 : /* At this point, we have copied everything up to the end marker
2722 : into the new file, except for the arguments we are going to add.
2723 : Now, dump the new arguments and write the end marker, possibly
2724 : followed by the rest of the original file. */
2725 0 : while (cur_arg)
2726 : {
2727 0 : fprintf (src_file, "%s\n", cur_arg);
2728 :
2729 : /* Find next argument. */
2730 0 : if (arg)
2731 : {
2732 : char *end;
2733 :
2734 0 : arg++;
2735 0 : end = strchr (arg, ',');
2736 0 : if (end)
2737 0 : *end = '\0';
2738 :
2739 0 : cur_arg = percent_deescape (arg);
2740 0 : if (end)
2741 : {
2742 0 : *end = ',';
2743 0 : arg = end + 1;
2744 : }
2745 : else
2746 0 : arg = NULL;
2747 : }
2748 : else
2749 0 : cur_arg = NULL;
2750 : }
2751 :
2752 0 : fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
2753 0 : if (ferror (src_file))
2754 0 : goto change_file_one_err;
2755 :
2756 0 : if (!in_marker)
2757 : {
2758 0 : fprintf (src_file, "# %s edited this configuration file.\n",
2759 : GPGCONF_DISP_NAME);
2760 0 : if (ferror (src_file))
2761 0 : goto change_file_one_err;
2762 0 : fprintf (src_file, "# It will disable options before this marked "
2763 : "block, but it will\n");
2764 0 : if (ferror (src_file))
2765 0 : goto change_file_one_err;
2766 0 : fprintf (src_file, "# never change anything below these lines.\n");
2767 0 : if (ferror (src_file))
2768 0 : goto change_file_one_err;
2769 : }
2770 0 : if (dest_file)
2771 : {
2772 0 : while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
2773 : {
2774 0 : fprintf (src_file, "%s", line);
2775 0 : if (ferror (src_file))
2776 0 : goto change_file_one_err;
2777 : }
2778 0 : if (length < 0 || ferror (dest_file))
2779 : goto change_file_one_err;
2780 : }
2781 0 : xfree (line);
2782 0 : line = NULL;
2783 :
2784 0 : res = fclose (src_file);
2785 0 : if (res)
2786 : {
2787 0 : res = errno;
2788 0 : close (fd);
2789 0 : if (dest_file)
2790 0 : fclose (dest_file);
2791 0 : gpg_err_set_errno (res);
2792 0 : return -1;
2793 : }
2794 0 : close (fd);
2795 0 : if (dest_file)
2796 : {
2797 0 : res = fclose (dest_file);
2798 0 : if (res)
2799 0 : return -1;
2800 : }
2801 0 : return 0;
2802 :
2803 : change_file_one_err:
2804 0 : xfree (line);
2805 0 : res = errno;
2806 0 : if (src_file)
2807 : {
2808 0 : fclose (src_file);
2809 0 : close (fd);
2810 : }
2811 0 : if (dest_file)
2812 0 : fclose (dest_file);
2813 0 : gpg_err_set_errno (res);
2814 0 : return -1;
2815 : }
2816 :
2817 :
2818 : /* Create and verify the new configuration file for the specified
2819 : backend and component. Returns 0 on success and -1 on error. */
2820 : static int
2821 0 : change_options_program (gc_component_t component, gc_backend_t backend,
2822 : char **src_filenamep, char **dest_filenamep,
2823 : char **orig_filenamep)
2824 : {
2825 : static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###";
2826 : /* True if we are within the marker in the config file. */
2827 0 : int in_marker = 0;
2828 : gc_option_t *option;
2829 0 : char *line = NULL;
2830 : size_t line_len;
2831 : ssize_t length;
2832 : int res;
2833 : int fd;
2834 0 : FILE *src_file = NULL;
2835 0 : FILE *dest_file = NULL;
2836 : char *src_filename;
2837 : char *dest_filename;
2838 : char *orig_filename;
2839 : /* Special hack for gpg, see below. */
2840 0 : int utf8strings_seen = 0;
2841 :
2842 : /* FIXME. Throughout the function, do better error reporting. */
2843 0 : dest_filename = xstrdup (get_config_filename (component, backend));
2844 0 : src_filename = xasprintf ("%s.%s.%i.new",
2845 : dest_filename, GPGCONF_NAME, (int)getpid ());
2846 0 : orig_filename = xasprintf ("%s.%s.%i.bak",
2847 : dest_filename, GPGCONF_NAME, (int)getpid ());
2848 :
2849 : #ifdef HAVE_W32_SYSTEM
2850 : res = copy_file (dest_filename, orig_filename);
2851 : #else
2852 0 : res = link (dest_filename, orig_filename);
2853 : #endif
2854 0 : if (res < 0 && errno != ENOENT)
2855 0 : return -1;
2856 0 : if (res < 0)
2857 : {
2858 0 : xfree (orig_filename);
2859 0 : orig_filename = NULL;
2860 : }
2861 :
2862 : /* We now initialize the return strings, so the caller can do the
2863 : cleanup for us. */
2864 0 : *src_filenamep = src_filename;
2865 0 : *dest_filenamep = dest_filename;
2866 0 : *orig_filenamep = orig_filename;
2867 :
2868 : /* Use open() so that we can use O_EXCL. */
2869 0 : fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
2870 0 : if (fd < 0)
2871 0 : return -1;
2872 0 : src_file = fdopen (fd, "w");
2873 0 : res = errno;
2874 0 : if (!src_file)
2875 : {
2876 0 : gpg_err_set_errno (res);
2877 0 : return -1;
2878 : }
2879 :
2880 : /* Only if ORIG_FILENAME is not NULL did the configuration file
2881 : exist already. In this case, we will copy its content into the
2882 : new configuration file, changing it to our liking in the
2883 : process. */
2884 0 : if (orig_filename)
2885 : {
2886 0 : dest_file = fopen (dest_filename, "r");
2887 0 : if (!dest_file)
2888 0 : goto change_one_err;
2889 :
2890 0 : while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
2891 : {
2892 0 : int disable = 0;
2893 : char *start;
2894 :
2895 0 : if (!strncmp (marker, line, sizeof (marker) - 1))
2896 : {
2897 0 : if (!in_marker)
2898 0 : in_marker = 1;
2899 : else
2900 0 : break;
2901 : }
2902 0 : else if (backend == GC_BACKEND_GPG && in_marker
2903 0 : && ! strcmp ("utf8-strings\n", line))
2904 : {
2905 : /* Strip duplicated entries. */
2906 0 : if (utf8strings_seen)
2907 0 : disable = 1;
2908 : else
2909 0 : utf8strings_seen = 1;
2910 : }
2911 :
2912 0 : start = line;
2913 0 : while (*start == ' ' || *start == '\t')
2914 0 : start++;
2915 0 : if (*start && *start != '\r' && *start != '\n' && *start != '#')
2916 : {
2917 : char *end;
2918 : char saved_end;
2919 :
2920 0 : end = start;
2921 0 : while (*end && *end != ' ' && *end != '\t'
2922 0 : && *end != '\r' && *end != '\n' && *end != '#')
2923 0 : end++;
2924 0 : saved_end = *end;
2925 0 : *end = '\0';
2926 :
2927 0 : option = find_option (component, start, backend);
2928 0 : *end = saved_end;
2929 0 : if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
2930 0 : || option->new_value))
2931 0 : disable = 1;
2932 : }
2933 0 : if (disable)
2934 : {
2935 0 : if (!in_marker)
2936 : {
2937 0 : fprintf (src_file,
2938 : "# %s disabled this option here at %s\n",
2939 0 : GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
2940 0 : if (ferror (src_file))
2941 0 : goto change_one_err;
2942 0 : fprintf (src_file, "# %s", line);
2943 0 : if (ferror (src_file))
2944 0 : goto change_one_err;
2945 : }
2946 : }
2947 : else
2948 : {
2949 0 : fprintf (src_file, "%s", line);
2950 0 : if (ferror (src_file))
2951 0 : goto change_one_err;
2952 : }
2953 : }
2954 0 : if (length < 0 || ferror (dest_file))
2955 : goto change_one_err;
2956 : }
2957 :
2958 0 : if (!in_marker)
2959 : {
2960 : /* There was no marker. This is the first time we edit the
2961 : file. We add our own marker at the end of the file and
2962 : proceed. Note that we first write a newline, this guards us
2963 : against files which lack the newline at the end of the last
2964 : line, while it doesn't hurt us in all other cases. */
2965 0 : fprintf (src_file, "\n%s\n", marker);
2966 0 : if (ferror (src_file))
2967 0 : goto change_one_err;
2968 : }
2969 : /* At this point, we have copied everything up to the end marker
2970 : into the new file, except for the options we are going to change.
2971 : Now, dump the changed options (except for those we are going to
2972 : revert to their default), and write the end marker, possibly
2973 : followed by the rest of the original file. */
2974 :
2975 : /* We have to turn on UTF8 strings for GnuPG. */
2976 0 : if (backend == GC_BACKEND_GPG && ! utf8strings_seen)
2977 0 : fprintf (src_file, "utf8-strings\n");
2978 :
2979 0 : option = gc_component[component].options;
2980 0 : while (option->name)
2981 : {
2982 0 : if (!(option->flags & GC_OPT_FLAG_GROUP)
2983 0 : && option->backend == backend
2984 0 : && option->new_value)
2985 : {
2986 0 : char *arg = option->new_value;
2987 :
2988 : do
2989 : {
2990 0 : if (*arg == '\0' || *arg == ',')
2991 : {
2992 0 : fprintf (src_file, "%s\n", option->name);
2993 0 : if (ferror (src_file))
2994 0 : goto change_one_err;
2995 : }
2996 0 : else if (gc_arg_type[option->arg_type].fallback
2997 : == GC_ARG_TYPE_NONE)
2998 : {
2999 0 : assert (*arg == '1');
3000 0 : fprintf (src_file, "%s\n", option->name);
3001 0 : if (ferror (src_file))
3002 0 : goto change_one_err;
3003 :
3004 0 : arg++;
3005 : }
3006 0 : else if (gc_arg_type[option->arg_type].fallback
3007 : == GC_ARG_TYPE_STRING)
3008 : {
3009 : char *end;
3010 :
3011 0 : assert (*arg == '"');
3012 0 : arg++;
3013 :
3014 0 : end = strchr (arg, ',');
3015 0 : if (end)
3016 0 : *end = '\0';
3017 :
3018 0 : fprintf (src_file, "%s %s\n", option->name,
3019 : percent_deescape (arg));
3020 0 : if (ferror (src_file))
3021 0 : goto change_one_err;
3022 :
3023 0 : if (end)
3024 0 : *end = ',';
3025 0 : arg = end;
3026 : }
3027 : else
3028 : {
3029 : char *end;
3030 :
3031 0 : end = strchr (arg, ',');
3032 0 : if (end)
3033 0 : *end = '\0';
3034 :
3035 0 : fprintf (src_file, "%s %s\n", option->name, arg);
3036 0 : if (ferror (src_file))
3037 0 : goto change_one_err;
3038 :
3039 0 : if (end)
3040 0 : *end = ',';
3041 0 : arg = end;
3042 : }
3043 :
3044 0 : assert (arg == NULL || *arg == '\0' || *arg == ',');
3045 0 : if (arg && *arg == ',')
3046 0 : arg++;
3047 : }
3048 0 : while (arg && *arg);
3049 : }
3050 0 : option++;
3051 : }
3052 :
3053 0 : fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
3054 0 : if (ferror (src_file))
3055 0 : goto change_one_err;
3056 :
3057 0 : if (!in_marker)
3058 : {
3059 0 : fprintf (src_file, "# %s edited this configuration file.\n",
3060 : GPGCONF_DISP_NAME);
3061 0 : if (ferror (src_file))
3062 0 : goto change_one_err;
3063 0 : fprintf (src_file, "# It will disable options before this marked "
3064 : "block, but it will\n");
3065 0 : if (ferror (src_file))
3066 0 : goto change_one_err;
3067 0 : fprintf (src_file, "# never change anything below these lines.\n");
3068 0 : if (ferror (src_file))
3069 0 : goto change_one_err;
3070 : }
3071 0 : if (dest_file)
3072 : {
3073 0 : while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
3074 : {
3075 0 : fprintf (src_file, "%s", line);
3076 0 : if (ferror (src_file))
3077 0 : goto change_one_err;
3078 : }
3079 0 : if (length < 0 || ferror (dest_file))
3080 : goto change_one_err;
3081 : }
3082 0 : xfree (line);
3083 0 : line = NULL;
3084 :
3085 0 : res = fclose (src_file);
3086 0 : if (res)
3087 : {
3088 0 : res = errno;
3089 0 : close (fd);
3090 0 : if (dest_file)
3091 0 : fclose (dest_file);
3092 0 : gpg_err_set_errno (res);
3093 0 : return -1;
3094 : }
3095 0 : close (fd);
3096 0 : if (dest_file)
3097 : {
3098 0 : res = fclose (dest_file);
3099 0 : if (res)
3100 0 : return -1;
3101 : }
3102 0 : return 0;
3103 :
3104 : change_one_err:
3105 0 : xfree (line);
3106 0 : res = errno;
3107 0 : if (src_file)
3108 : {
3109 0 : fclose (src_file);
3110 0 : close (fd);
3111 : }
3112 0 : if (dest_file)
3113 0 : fclose (dest_file);
3114 0 : gpg_err_set_errno (res);
3115 0 : return -1;
3116 : }
3117 :
3118 :
3119 : /* Common code for gc_component_change_options and
3120 : gc_process_gpgconf_conf. */
3121 : static void
3122 0 : change_one_value (gc_option_t *option, int *runtime,
3123 : unsigned long flags, char *new_value)
3124 : {
3125 0 : unsigned long new_value_nr = 0;
3126 :
3127 0 : option_check_validity (option, flags, new_value, &new_value_nr);
3128 :
3129 0 : if (option->flags & GC_OPT_FLAG_RUNTIME)
3130 0 : runtime[option->backend] = 1;
3131 :
3132 0 : option->new_flags = flags;
3133 0 : if (!(flags & GC_OPT_FLAG_DEFAULT))
3134 : {
3135 0 : if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
3136 0 : && (option->flags & GC_OPT_FLAG_LIST))
3137 0 : {
3138 : char *str;
3139 :
3140 : /* We convert the number to a list of 1's for convenient
3141 : list handling. */
3142 0 : assert (new_value_nr > 0);
3143 0 : option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1);
3144 0 : str = option->new_value;
3145 0 : *(str++) = '1';
3146 0 : while (--new_value_nr > 0)
3147 : {
3148 0 : *(str++) = ',';
3149 0 : *(str++) = '1';
3150 : }
3151 0 : *(str++) = '\0';
3152 : }
3153 : else
3154 0 : option->new_value = xstrdup (new_value);
3155 : }
3156 0 : }
3157 :
3158 :
3159 : /* Read the modifications from IN and apply them. If IN is NULL the
3160 : modifications are expected to already have been set to the global
3161 : table. */
3162 : void
3163 0 : gc_component_change_options (int component, estream_t in, estream_t out)
3164 : {
3165 0 : int err = 0;
3166 : int runtime[GC_BACKEND_NR];
3167 : char *src_filename[GC_BACKEND_NR];
3168 : char *dest_filename[GC_BACKEND_NR];
3169 : char *orig_filename[GC_BACKEND_NR];
3170 : gc_backend_t backend;
3171 : gc_option_t *option;
3172 0 : char *line = NULL;
3173 0 : size_t line_len = 0;
3174 : ssize_t length;
3175 :
3176 0 : if (component == GC_COMPONENT_PINENTRY)
3177 0 : return; /* Dummy component for now. */
3178 :
3179 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
3180 : {
3181 0 : runtime[backend] = 0;
3182 0 : src_filename[backend] = NULL;
3183 0 : dest_filename[backend] = NULL;
3184 0 : orig_filename[backend] = NULL;
3185 : }
3186 :
3187 0 : if (in)
3188 : {
3189 : /* Read options from the file IN. */
3190 0 : while ((length = es_read_line (in, &line, &line_len, NULL)) > 0)
3191 : {
3192 : char *linep;
3193 0 : unsigned long flags = 0;
3194 0 : char *new_value = "";
3195 :
3196 : /* Strip newline and carriage return, if present. */
3197 0 : while (length > 0
3198 0 : && (line[length - 1] == '\n' || line[length - 1] == '\r'))
3199 0 : line[--length] = '\0';
3200 :
3201 0 : linep = strchr (line, ':');
3202 0 : if (linep)
3203 0 : *(linep++) = '\0';
3204 :
3205 : /* Extract additional flags. Default to none. */
3206 0 : if (linep)
3207 : {
3208 : char *end;
3209 : char *tail;
3210 :
3211 0 : end = strchr (linep, ':');
3212 0 : if (end)
3213 0 : *(end++) = '\0';
3214 :
3215 0 : gpg_err_set_errno (0);
3216 0 : flags = strtoul (linep, &tail, 0);
3217 0 : if (errno)
3218 0 : gc_error (1, errno, "malformed flags in option %s", line);
3219 0 : if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
3220 0 : gc_error (1, 0, "garbage after flags in option %s", line);
3221 :
3222 0 : linep = end;
3223 : }
3224 :
3225 : /* Don't allow setting of the no change flag. */
3226 0 : flags &= ~GC_OPT_FLAG_NO_CHANGE;
3227 :
3228 : /* Extract default value, if present. Default to empty if not. */
3229 0 : if (linep)
3230 : {
3231 : char *end;
3232 0 : end = strchr (linep, ':');
3233 0 : if (end)
3234 0 : *(end++) = '\0';
3235 0 : new_value = linep;
3236 0 : linep = end;
3237 : }
3238 :
3239 0 : option = find_option (component, line, GC_BACKEND_ANY);
3240 0 : if (!option)
3241 0 : gc_error (1, 0, "unknown option %s", line);
3242 :
3243 0 : if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
3244 : {
3245 0 : gc_error (0, 0, "ignoring new value for option %s",
3246 : option->name);
3247 0 : continue;
3248 : }
3249 :
3250 0 : change_one_value (option, runtime, flags, new_value);
3251 : }
3252 : }
3253 :
3254 : /* Now that we have collected and locally verified the changes,
3255 : write them out to new configuration files, verify them
3256 : externally, and then commit them. */
3257 0 : option = gc_component[component].options;
3258 0 : while (option && option->name)
3259 : {
3260 : /* Go on if we have already seen this backend, or if there is
3261 : nothing to do. */
3262 0 : if (src_filename[option->backend]
3263 0 : || !(option->new_flags || option->new_value))
3264 : {
3265 0 : option++;
3266 0 : continue;
3267 : }
3268 :
3269 0 : if (gc_backend[option->backend].program)
3270 : {
3271 0 : err = change_options_program (component, option->backend,
3272 0 : &src_filename[option->backend],
3273 0 : &dest_filename[option->backend],
3274 0 : &orig_filename[option->backend]);
3275 0 : if (! err)
3276 : {
3277 : /* External verification. */
3278 0 : err = gc_component_check_options (component, out,
3279 0 : src_filename[option->backend]);
3280 0 : if (err)
3281 : {
3282 0 : gc_error (0, 0,
3283 0 : _("External verification of component %s failed"),
3284 : gc_component[component].name);
3285 0 : gpg_err_set_errno (EINVAL);
3286 : }
3287 : }
3288 :
3289 : }
3290 : else
3291 0 : err = change_options_file (component, option->backend,
3292 0 : &src_filename[option->backend],
3293 0 : &dest_filename[option->backend],
3294 0 : &orig_filename[option->backend]);
3295 :
3296 0 : if (err)
3297 0 : break;
3298 :
3299 0 : option++;
3300 : }
3301 :
3302 0 : if (! err && ! opt.dry_run)
3303 : {
3304 : int i;
3305 :
3306 0 : for (i = 0; i < GC_BACKEND_NR; i++)
3307 : {
3308 0 : if (src_filename[i])
3309 : {
3310 : /* FIXME: Make a verification here. */
3311 :
3312 0 : assert (dest_filename[i]);
3313 :
3314 0 : if (orig_filename[i])
3315 : {
3316 : #ifdef HAVE_W32_SYSTEM
3317 : /* There is no atomic update on W32. */
3318 : err = unlink (dest_filename[i]);
3319 : #endif /* HAVE_W32_SYSTEM */
3320 0 : if (!err)
3321 0 : err = rename (src_filename[i], dest_filename[i]);
3322 : }
3323 : else
3324 : {
3325 : #ifdef HAVE_W32_SYSTEM
3326 : /* We skip the unlink if we expect the file not to
3327 : be there. */
3328 : err = rename (src_filename[i], dest_filename[i]);
3329 : #else /* HAVE_W32_SYSTEM */
3330 : /* This is a bit safer than rename() because we
3331 : expect DEST_FILENAME not to be there. If it
3332 : happens to be there, this will fail. */
3333 0 : err = link (src_filename[i], dest_filename[i]);
3334 0 : if (!err)
3335 0 : err = unlink (src_filename[i]);
3336 : #endif /* !HAVE_W32_SYSTEM */
3337 : }
3338 0 : if (err)
3339 0 : break;
3340 0 : src_filename[i] = NULL;
3341 : }
3342 : }
3343 : }
3344 :
3345 0 : if (err || opt.dry_run)
3346 : {
3347 : int i;
3348 0 : int saved_errno = errno;
3349 :
3350 : /* An error occurred or a dry-run is requested. */
3351 0 : for (i = 0; i < GC_BACKEND_NR; i++)
3352 : {
3353 0 : if (src_filename[i])
3354 : {
3355 : /* The change was not yet committed. */
3356 0 : unlink (src_filename[i]);
3357 0 : if (orig_filename[i])
3358 0 : unlink (orig_filename[i]);
3359 : }
3360 : else
3361 : {
3362 : /* The changes were already committed. FIXME: This is a
3363 : tad dangerous, as we don't know if we don't overwrite
3364 : a version of the file that is even newer than the one
3365 : we just installed. */
3366 0 : if (orig_filename[i])
3367 : {
3368 : #ifdef HAVE_W32_SYSTEM
3369 : /* There is no atomic update on W32. */
3370 : unlink (dest_filename[i]);
3371 : #endif /* HAVE_W32_SYSTEM */
3372 0 : rename (orig_filename[i], dest_filename[i]);
3373 : }
3374 : else
3375 0 : unlink (dest_filename[i]);
3376 : }
3377 : }
3378 0 : if (err)
3379 0 : gc_error (1, saved_errno, "could not commit changes");
3380 :
3381 : /* Fall-through for dry run. */
3382 0 : goto leave;
3383 : }
3384 :
3385 : /* If it all worked, notify the daemons of the changes. */
3386 0 : if (opt.runtime)
3387 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
3388 : {
3389 0 : if (runtime[backend] && gc_backend[backend].runtime_change)
3390 0 : (*gc_backend[backend].runtime_change) (0);
3391 : }
3392 :
3393 : /* Move the per-process backup file into its place. */
3394 0 : for (backend = 0; backend < GC_BACKEND_NR; backend++)
3395 0 : if (orig_filename[backend])
3396 : {
3397 : char *backup_filename;
3398 :
3399 0 : assert (dest_filename[backend]);
3400 :
3401 0 : backup_filename = xasprintf ("%s.%s.bak",
3402 : dest_filename[backend], GPGCONF_NAME);
3403 :
3404 : #ifdef HAVE_W32_SYSTEM
3405 : /* There is no atomic update on W32. */
3406 : unlink (backup_filename);
3407 : #endif /* HAVE_W32_SYSTEM */
3408 0 : rename (orig_filename[backend], backup_filename);
3409 : }
3410 :
3411 : leave:
3412 0 : xfree (line);
3413 : }
3414 :
3415 :
3416 : /* Check whether USER matches the current user of one of its group.
3417 : This function may change USER. Returns true is there is a
3418 : match. */
3419 : static int
3420 0 : key_matches_user_or_group (char *user)
3421 : {
3422 : char *group;
3423 :
3424 0 : if (*user == '*' && user[1] == 0)
3425 0 : return 1; /* A single asterisk matches all users. */
3426 :
3427 0 : group = strchr (user, ':');
3428 0 : if (group)
3429 0 : *group++ = 0;
3430 :
3431 : #ifdef HAVE_W32_SYSTEM
3432 : /* Under Windows we don't support groups. */
3433 : if (group && *group)
3434 : gc_error (0, 0, _("Note that group specifications are ignored\n"));
3435 : #ifndef HAVE_W32CE_SYSTEM
3436 : if (*user)
3437 : {
3438 : static char *my_name;
3439 :
3440 : if (!my_name)
3441 : {
3442 : char tmp[1];
3443 : DWORD size = 1;
3444 :
3445 : GetUserNameA (tmp, &size);
3446 : my_name = xmalloc (size);
3447 : if (!GetUserNameA (my_name, &size))
3448 : gc_error (1,0, "error getting current user name: %s",
3449 : w32_strerror (-1));
3450 : }
3451 :
3452 : if (!strcmp (user, my_name))
3453 : return 1; /* Found. */
3454 : }
3455 : #endif /*HAVE_W32CE_SYSTEM*/
3456 : #else /*!HAVE_W32_SYSTEM*/
3457 : /* First check whether the user matches. */
3458 0 : if (*user)
3459 : {
3460 : static char *my_name;
3461 :
3462 0 : if (!my_name)
3463 : {
3464 0 : struct passwd *pw = getpwuid ( getuid () );
3465 0 : if (!pw)
3466 0 : gc_error (1, errno, "getpwuid failed for current user");
3467 0 : my_name = xstrdup (pw->pw_name);
3468 : }
3469 0 : if (!strcmp (user, my_name))
3470 0 : return 1; /* Found. */
3471 : }
3472 :
3473 : /* If that failed, check whether a group matches. */
3474 0 : if (group && *group)
3475 : {
3476 : static char *my_group;
3477 : static char **my_supgroups;
3478 : int n;
3479 :
3480 0 : if (!my_group)
3481 : {
3482 0 : struct group *gr = getgrgid ( getgid () );
3483 0 : if (!gr)
3484 0 : gc_error (1, errno, "getgrgid failed for current user");
3485 0 : my_group = xstrdup (gr->gr_name);
3486 : }
3487 0 : if (!strcmp (group, my_group))
3488 0 : return 1; /* Found. */
3489 :
3490 0 : if (!my_supgroups)
3491 : {
3492 : int ngids;
3493 : gid_t *gids;
3494 :
3495 0 : ngids = getgroups (0, NULL);
3496 0 : gids = xcalloc (ngids+1, sizeof *gids);
3497 0 : ngids = getgroups (ngids, gids);
3498 0 : if (ngids < 0)
3499 0 : gc_error (1, errno, "getgroups failed for current user");
3500 0 : my_supgroups = xcalloc (ngids+1, sizeof *my_supgroups);
3501 0 : for (n=0; n < ngids; n++)
3502 : {
3503 0 : struct group *gr = getgrgid ( gids[n] );
3504 0 : if (!gr)
3505 0 : gc_error (1, errno, "getgrgid failed for supplementary group");
3506 0 : my_supgroups[n] = xstrdup (gr->gr_name);
3507 : }
3508 0 : xfree (gids);
3509 : }
3510 :
3511 0 : for (n=0; my_supgroups[n]; n++)
3512 0 : if (!strcmp (group, my_supgroups[n]))
3513 0 : return 1; /* Found. */
3514 : }
3515 : #endif /*!HAVE_W32_SYSTEM*/
3516 0 : return 0; /* No match. */
3517 : }
3518 :
3519 :
3520 :
3521 : /* Read and process the global configuration file for gpgconf. This
3522 : optional file is used to update our internal tables at runtime and
3523 : may also be used to set new default values. If FNAME is NULL the
3524 : default name will be used. With UPDATE set to true the internal
3525 : tables are actually updated; if not set, only a syntax check is
3526 : done. If DEFAULTS is true the global options are written to the
3527 : configuration files. If LISTFP is set, no changes are done but the
3528 : configuration file is printed to LISTFP in a colon separated format.
3529 :
3530 : Returns 0 on success or if the config file is not present; -1 is
3531 : returned on error. */
3532 : int
3533 0 : gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
3534 : estream_t listfp)
3535 : {
3536 0 : int result = 0;
3537 0 : char *line = NULL;
3538 0 : size_t line_len = 0;
3539 : ssize_t length;
3540 : FILE *config;
3541 0 : int lineno = 0;
3542 0 : int in_rule = 0;
3543 0 : int got_match = 0;
3544 : int runtime[GC_BACKEND_NR];
3545 : int backend_id, component_id;
3546 : char *fname;
3547 :
3548 0 : if (fname_arg)
3549 0 : fname = xstrdup (fname_arg);
3550 : else
3551 0 : fname = make_filename (gnupg_sysconfdir (), GPGCONF_NAME EXTSEP_S "conf",
3552 : NULL);
3553 :
3554 0 : for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
3555 0 : runtime[backend_id] = 0;
3556 :
3557 0 : config = fopen (fname, "r");
3558 0 : if (!config)
3559 : {
3560 : /* Do not print an error if the file is not available, except
3561 : when running in syntax check mode. */
3562 0 : if (errno != ENOENT || !update)
3563 : {
3564 0 : gc_error (0, errno, "can not open global config file '%s'", fname);
3565 0 : result = -1;
3566 : }
3567 0 : xfree (fname);
3568 0 : return result;
3569 : }
3570 :
3571 0 : while ((length = read_line (config, &line, &line_len, NULL)) > 0)
3572 : {
3573 : char *key, *component, *option, *flags, *value;
3574 : char *empty;
3575 0 : gc_option_t *option_info = NULL;
3576 : char *p;
3577 : int is_continuation;
3578 :
3579 0 : lineno++;
3580 0 : key = line;
3581 0 : while (*key == ' ' || *key == '\t')
3582 0 : key++;
3583 0 : if (!*key || *key == '#' || *key == '\r' || *key == '\n')
3584 0 : continue;
3585 :
3586 0 : is_continuation = (key != line);
3587 :
3588 : /* Parse the key field. */
3589 0 : if (!is_continuation && got_match)
3590 : break; /* Finish after the first match. */
3591 0 : else if (!is_continuation)
3592 : {
3593 0 : in_rule = 0;
3594 0 : for (p=key+1; *p && !strchr (" \t\r\n", *p); p++)
3595 : ;
3596 0 : if (!*p)
3597 : {
3598 0 : gc_error (0, 0, "missing rule at '%s', line %d", fname, lineno);
3599 0 : result = -1;
3600 0 : continue;
3601 : }
3602 0 : *p++ = 0;
3603 0 : component = p;
3604 : }
3605 0 : else if (!in_rule)
3606 : {
3607 0 : gc_error (0, 0, "continuation but no rule at '%s', line %d",
3608 : fname, lineno);
3609 0 : result = -1;
3610 0 : continue;
3611 : }
3612 : else
3613 : {
3614 0 : component = key;
3615 0 : key = NULL;
3616 : }
3617 :
3618 0 : in_rule = 1;
3619 :
3620 : /* Parse the component. */
3621 0 : while (*component == ' ' || *component == '\t')
3622 0 : component++;
3623 0 : for (p=component; *p && !strchr (" \t\r\n", *p); p++)
3624 : ;
3625 0 : if (p == component)
3626 : {
3627 0 : gc_error (0, 0, "missing component at '%s', line %d",
3628 : fname, lineno);
3629 0 : result = -1;
3630 0 : continue;
3631 : }
3632 0 : empty = p;
3633 0 : *p++ = 0;
3634 0 : option = p;
3635 0 : component_id = gc_component_find (component);
3636 0 : if (component_id < 0)
3637 : {
3638 0 : gc_error (0, 0, "unknown component at '%s', line %d",
3639 : fname, lineno);
3640 0 : result = -1;
3641 : }
3642 :
3643 : /* Parse the option name. */
3644 0 : while (*option == ' ' || *option == '\t')
3645 0 : option++;
3646 0 : for (p=option; *p && !strchr (" \t\r\n", *p); p++)
3647 : ;
3648 0 : if (p == option)
3649 : {
3650 0 : gc_error (0, 0, "missing option at '%s', line %d",
3651 : fname, lineno);
3652 0 : result = -1;
3653 0 : continue;
3654 : }
3655 0 : *p++ = 0;
3656 0 : flags = p;
3657 0 : if ( component_id != -1)
3658 : {
3659 0 : option_info = find_option (component_id, option, GC_BACKEND_ANY);
3660 0 : if (!option_info)
3661 : {
3662 0 : gc_error (0, 0, "unknown option at '%s', line %d",
3663 : fname, lineno);
3664 0 : result = -1;
3665 : }
3666 : }
3667 :
3668 :
3669 : /* Parse the optional flags. */
3670 0 : while (*flags == ' ' || *flags == '\t')
3671 0 : flags++;
3672 0 : if (*flags == '[')
3673 : {
3674 0 : flags++;
3675 0 : p = strchr (flags, ']');
3676 0 : if (!p)
3677 : {
3678 0 : gc_error (0, 0, "syntax error in rule at '%s', line %d",
3679 : fname, lineno);
3680 0 : result = -1;
3681 0 : continue;
3682 : }
3683 0 : *p++ = 0;
3684 0 : value = p;
3685 : }
3686 : else /* No flags given. */
3687 : {
3688 0 : value = flags;
3689 0 : flags = NULL;
3690 : }
3691 :
3692 : /* Parse the optional value. */
3693 0 : while (*value == ' ' || *value == '\t')
3694 0 : value++;
3695 0 : for (p=value; *p && !strchr ("\r\n", *p); p++)
3696 : ;
3697 0 : if (p == value)
3698 0 : value = empty; /* No value given; let it point to an empty string. */
3699 : else
3700 : {
3701 : /* Strip trailing white space. */
3702 0 : *p = 0;
3703 0 : for (p--; p > value && (*p == ' ' || *p == '\t'); p--)
3704 0 : *p = 0;
3705 : }
3706 :
3707 : /* Check flag combinations. */
3708 0 : if (!flags)
3709 : ;
3710 0 : else if (!strcmp (flags, "default"))
3711 : {
3712 0 : if (*value)
3713 : {
3714 0 : gc_error (0, 0, "flag \"default\" may not be combined "
3715 : "with a value at '%s', line %d",
3716 : fname, lineno);
3717 0 : result = -1;
3718 : }
3719 : }
3720 0 : else if (!strcmp (flags, "change"))
3721 : ;
3722 0 : else if (!strcmp (flags, "no-change"))
3723 : ;
3724 : else
3725 : {
3726 0 : gc_error (0, 0, "unknown flag at '%s', line %d",
3727 : fname, lineno);
3728 0 : result = -1;
3729 : }
3730 :
3731 : /* In list mode we print out all records. */
3732 0 : if (listfp && !result)
3733 : {
3734 : /* If this is a new ruleset, print a key record. */
3735 0 : if (!is_continuation)
3736 : {
3737 0 : char *group = strchr (key, ':');
3738 0 : if (group)
3739 : {
3740 0 : *group++ = 0;
3741 0 : if ((p = strchr (group, ':')))
3742 0 : *p = 0; /* We better strip any extra stuff. */
3743 : }
3744 :
3745 0 : es_fprintf (listfp, "k:%s:", gc_percent_escape (key));
3746 0 : es_fprintf (listfp, "%s\n", group? gc_percent_escape (group):"");
3747 : }
3748 :
3749 : /* All other lines are rule records. */
3750 0 : es_fprintf (listfp, "r:::%s:%s:%s:",
3751 : gc_component[component_id].name,
3752 0 : option_info->name? option_info->name : "",
3753 : flags? flags : "");
3754 0 : if (value != empty)
3755 0 : es_fprintf (listfp, "\"%s", gc_percent_escape (value));
3756 :
3757 0 : es_putc ('\n', listfp);
3758 : }
3759 :
3760 : /* Check whether the key matches but do this only if we are not
3761 : running in syntax check mode. */
3762 0 : if ( update
3763 0 : && !result && !listfp
3764 0 : && (got_match || (key && key_matches_user_or_group (key))) )
3765 : {
3766 0 : int newflags = 0;
3767 :
3768 0 : got_match = 1;
3769 :
3770 : /* Apply the flags from gpgconf.conf. */
3771 0 : if (!flags)
3772 : ;
3773 0 : else if (!strcmp (flags, "default"))
3774 0 : newflags |= GC_OPT_FLAG_DEFAULT;
3775 0 : else if (!strcmp (flags, "no-change"))
3776 0 : option_info->flags |= GC_OPT_FLAG_NO_CHANGE;
3777 0 : else if (!strcmp (flags, "change"))
3778 0 : option_info->flags &= ~GC_OPT_FLAG_NO_CHANGE;
3779 :
3780 0 : if (defaults)
3781 : {
3782 : /* Here we explicitly allow updating the value again. */
3783 0 : if (newflags)
3784 : {
3785 0 : option_info->new_flags = 0;
3786 : }
3787 0 : if (*value)
3788 : {
3789 0 : xfree (option_info->new_value);
3790 0 : option_info->new_value = NULL;
3791 : }
3792 0 : change_one_value (option_info, runtime, newflags, value);
3793 : }
3794 : }
3795 : }
3796 :
3797 0 : if (length < 0 || ferror (config))
3798 : {
3799 0 : gc_error (0, errno, "error reading from '%s'", fname);
3800 0 : result = -1;
3801 : }
3802 0 : if (fclose (config))
3803 0 : gc_error (0, errno, "error closing '%s'", fname);
3804 :
3805 0 : xfree (line);
3806 :
3807 : /* If it all worked, process the options. */
3808 0 : if (!result && update && defaults && !listfp)
3809 : {
3810 : /* We need to switch off the runtime update, so that we can do
3811 : it later all at once. */
3812 0 : int save_opt_runtime = opt.runtime;
3813 0 : opt.runtime = 0;
3814 :
3815 0 : for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
3816 : {
3817 0 : gc_component_change_options (component_id, NULL, NULL);
3818 : }
3819 0 : opt.runtime = save_opt_runtime;
3820 :
3821 0 : if (opt.runtime)
3822 : {
3823 0 : for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
3824 0 : if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
3825 0 : (*gc_backend[backend_id].runtime_change) (0);
3826 : }
3827 : }
3828 :
3829 0 : xfree (fname);
3830 0 : return result;
3831 : }
|