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