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