1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

New option --list-config for gpgconf.

This commit is contained in:
Werner Koch 2007-10-23 18:13:27 +00:00
parent 57deea63c5
commit fca02368da
9 changed files with 179 additions and 35 deletions

2
NEWS
View File

@ -9,6 +9,8 @@ Noteworthy changes in version 2.0.8
* Enhanced gpg-connect-agent with a small scripting language. * Enhanced gpg-connect-agent with a small scripting language.
* New option --list-config for gpgconf.
Noteworthy changes in version 2.0.7 (2007-09-10) Noteworthy changes in version 2.0.7 (2007-09-10)
------------------------------------------------ ------------------------------------------------

View File

@ -1,3 +1,7 @@
2007-10-23 Werner Koch <wk@g10code.com>
* tools.texi (Listing global options): New.
2007-10-19 Werner Koch <wk@g10code.com> 2007-10-19 Werner Koch <wk@g10code.com>
* tools.texi (Controlling gpg-connect-agent): Updated. * tools.texi (Controlling gpg-connect-agent): Updated.

View File

@ -9,8 +9,8 @@
# white space character, are ignored. The line is separated by white # white space character, are ignored. The line is separated by white
# space into fields. The first field is used to match the user or # space into fields. The first field is used to match the user or
# group and must start at the first column, the file is processes # group and must start at the first column, the file is processes
# sequential until a matching rle is found. A rule may contain # sequential until a matching rule is found. A rule may contain
# several lines, continuation lines are indicated by a indenting them. # several lines; continuation lines are indicated by a indenting them.
# #
# Syntax of a line: # Syntax of a line:
# <key>|WS <component> <option> ["["<flag>"]"] [<value>] # <key>|WS <component> <option> ["["<flag>"]"] [<value>]
@ -38,8 +38,8 @@
# gpg-agent min-passphrase-nonalpha [no-change] 1 # gpg-agent min-passphrase-nonalpha [no-change] 1
# gpg-agent max-passphrase-days [no-change] 700 # gpg-agent max-passphrase-days [no-change] 700
# gpg-agent enable-passphrase-history [no-change] # gpg-agent enable-passphrase-history [no-change]
# gpg-agent enforce-passphrase-policy [default] # gpg-agent enforce-passphrase-constraints [default]
# gpg-agent enforce-passphrase-policy [no-change] # gpg-agent enforce-passphrase-constraints [no-change]
# gpg-agent max-cache-ttl [no-change] 10800 # gpg-agent max-cache-ttl [no-change] 10800
# gpg-agent max-cache-ttl-ssh [no-change] 10800 # gpg-agent max-cache-ttl-ssh [no-change] 10800
# gpg-agent allow-mark-trusted [default] # gpg-agent allow-mark-trusted [default]

View File

@ -197,13 +197,14 @@ program that uses @command{gpgconf} in this way will be called GUI
throughout this section. throughout this section.
@menu @menu
* Invoking gpgconf:: List of all commands and options. * Invoking gpgconf:: List of all commands and options.
* Format conventions:: Formatting conventions relevant for all commands. * Format conventions:: Formatting conventions relevant for all commands.
* Listing components:: List all gpgconf components. * Listing components:: List all gpgconf components.
* Checking programs:: Check all programs know to gpgconf. * Checking programs:: Check all programs know to gpgconf.
* Listing options:: List all options of a component. * Listing options:: List all options of a component.
* Changing options:: Changing options of a component. * Changing options:: Changing options of a component.
* Files used by gpgconf:: What files are used by gpgconf. * Listing global options:: List all global options.
* Files used by gpgconf:: What files are used by gpgconf.
@end menu @end menu
@manpause @manpause
@ -232,6 +233,10 @@ Change the options of the component @var{component}.
Update all configuration files with values taken from the global Update all configuration files with values taken from the global
configuration file (usually @file{/etc/gnupg/gpgconf.conf}). configuration file (usually @file{/etc/gnupg/gpgconf.conf}).
@item --list-config [@var{filename}]
List the global configuration file in a colon separated format. If
@var{filename} is given, check that file instead.
@item --check-config [@var{filename}] @item --check-config [@var{filename}]
Run a syntax check on the global configuration file. If @var{filename} Run a syntax check on the global configuration file. If @var{filename}
is given, check that file instead. is given, check that file instead.
@ -767,6 +772,64 @@ $ echo 'force:16:' | gpgconf --change-options dirmngr
The @code{--runtime} option can influence when the changes take The @code{--runtime} option can influence when the changes take
effect. effect.
@node Listing global options
@subsection Listing global options
Sometimes it is useful for applications to look at the global options
file @file{gpgconf.conf}.
The colon separated listing format is record oriented and uses the first
field to identify the record type:
@table @code
@item k
This describes a key record to start the definition of a new ruleset for
a user/group. The format of a key record is:
@code{k:@var{user}:@var{group}:}
@table @var
@item user
This is the user field of the key. It is percent escaped. See the
definition of the gpgconf.conf format for details.
@item group
This is the group field of the key. It is percent escaped.
@end table
@item r
This describes a rule record. All rule records up to the next key record
make up a rule set for that key. The format of a rule record is:
@code{r:::@var{component}:@var{option}:@var{flags}:@var{value}:}
@table @var
@item component
This is the component part of a rule. It is a plain string.
@item option
This is the option part of a rule. It is a plain string.
@item flag
This is the flags part of a rule. There may be only one flag per rule
but by using the same component and option, several flags may be
assigned to an option. It is a plain string.
@item value
This is the optional value for the option. It is a percent escaped
string with a single quotation mark to indicate a string. The quotation
mark is only required to distinguish between no value specified and an
empty string.
@end table
@end table
@noindent
Unknown record typs should be ignored. Note that there is intentionally
no feature to change the global option file through @command{gpgconf}.
@mansect files @mansect files
@node Files used by gpgconf @node Files used by gpgconf
@subsection Files used by gpgconf @subsection Files used by gpgconf

View File

@ -714,7 +714,7 @@ agent_clear_pin_cache (const char *sn)
/* Note: All strings shall be UTF-8. On success the caler needs to /* Note: All strings shall be UTF-8. On success the caller needs to
free the string stored at R_PASSPHRASE. On error NULL will be free the string stored at R_PASSPHRASE. On error NULL will be
stored at R_PASSPHRASE and an appropriate fpf error code stored at R_PASSPHRASE and an appropriate fpf error code
returned. */ returned. */

View File

@ -1,6 +1,13 @@
2007-10-23 Werner Koch <wk@g10code.com> 2007-10-23 Werner Koch <wk@g10code.com>
* gpgconf-comp.c (gc_options_gpg_agent): Repalce accidently used * gpgconf-comp.c (gc_process_gpgconf_conf): Add arg
LISTFP. Changed all callers.
* gpgconf.h: Add gc_error.
* gpgconf.c: Add command --list-config.
(get_outfp): New.
(main): Make --output work.
* gpgconf-comp.c (gc_options_gpg_agent): Replace accidently used
GC_BACKEND_SCDAEMON. We should consider to create these tables GC_BACKEND_SCDAEMON. We should consider to create these tables
from plain files. from plain files.

View File

@ -337,7 +337,7 @@ static struct
argument value. */ argument value. */
#define GC_OPT_FLAG_LIST (1UL << 2) #define GC_OPT_FLAG_LIST (1UL << 2)
/* The NO_CHANGE flag for an option indicates that the user should not /* The NO_CHANGE flag for an option indicates that the user should not
be allowed to chnage this option using the standard gpgconf method. be allowed to change this option using the standard gpgconf method.
Frontends using gpgconf should grey out such options, so that only Frontends using gpgconf should grey out such options, so that only
the current value is displayed. */ the current value is displayed. */
#define GC_OPT_FLAG_NO_CHANGE (1UL <<7) #define GC_OPT_FLAG_NO_CHANGE (1UL <<7)
@ -522,7 +522,7 @@ static gc_option_t gc_options_gpg_agent[] =
{ "Passphrase policy", { "Passphrase policy",
GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
"gnupg", N_("Options enforcing a passphrase policy") }, "gnupg", N_("Options enforcing a passphrase policy") },
{ "enforce-passphrases-constraints", GC_OPT_FLAG_RUNTIME, { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
GC_LEVEL_EXPERT, "gnupg", GC_LEVEL_EXPERT, "gnupg",
N_("do not allow to bypass the passphrase policy"), N_("do not allow to bypass the passphrase policy"),
GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
@ -542,7 +542,7 @@ static gc_option_t gc_options_gpg_agent[] =
GC_LEVEL_EXPERT, "gnupg", GC_LEVEL_EXPERT, "gnupg",
N_("|N|expire the passphrase after N days"), N_("|N|expire the passphrase after N days"),
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
{ "enable-passphrases-history", GC_OPT_FLAG_RUNTIME, { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
GC_LEVEL_EXPERT, "gnupg", GC_LEVEL_EXPERT, "gnupg",
N_("do not allow the reuse of old passphrases"), N_("do not allow the reuse of old passphrases"),
GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
@ -3094,12 +3094,14 @@ key_matches_user_or_group (char *user)
default name will be used. With UPDATE set to true the internal default name will be used. With UPDATE set to true the internal
tables are actually updated; if not set, only a syntax check is tables are actually updated; if not set, only a syntax check is
done. If DEFAULTS is true the global options are written to the done. If DEFAULTS is true the global options are written to the
configuration files. configuration files. If LISTFP is set, no changes are done but the
configuration file is printed to LISTFP in a colon separated format.
Returns 0 on success or if the config file is not present; -1 is Returns 0 on success or if the config file is not present; -1 is
returned on error. */ returned on error. */
int int
gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults) gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
FILE *listfp)
{ {
int result = 0; int result = 0;
char *line = NULL; char *line = NULL;
@ -3112,9 +3114,11 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults)
int runtime[GC_BACKEND_NR]; int runtime[GC_BACKEND_NR];
int used_components[GC_COMPONENT_NR]; int used_components[GC_COMPONENT_NR];
int backend_id, component_id; int backend_id, component_id;
char *fname = (char *) fname_arg; char *fname;
if (!fname) if (fname_arg)
fname = xstrdup (fname_arg);
else
fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL); fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL);
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
@ -3126,7 +3130,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults)
if (!config) if (!config)
{ {
/* Do not print an error if the file is not available, except /* Do not print an error if the file is not available, except
when runnign in syntax check mode. */ when running in syntax check mode. */
if (errno != ENOENT || !update) if (errno != ENOENT || !update)
{ {
gc_error (0, errno, "can not open global config file `%s'", fname); gc_error (0, errno, "can not open global config file `%s'", fname);
@ -3295,12 +3299,41 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults)
fname, lineno); fname, lineno);
result = -1; result = -1;
} }
/* In list mode we print out all records. */
if (listfp && !result)
{
/* If this is a new ruleset, print a key record. */
if (!is_continuation)
{
char *group = strchr (key, ':');
if (group)
{
*group++ = 0;
if ((p = strchr (group, ':')))
*p = 0; /* We better strip any extra stuff. */
}
fprintf (listfp, "k:%s:", my_percent_escape (key));
fprintf (listfp, "%s:\n", group? my_percent_escape (group):"");
}
/* All other lines are rule records. */
fprintf (listfp, "r:::%s:%s:%s:",
gc_component[component_id].name,
option_info->name? option_info->name : "",
flags? flags : "");
if (value != empty)
fprintf (listfp, "\"%s", my_percent_escape (value));
putc (':', listfp);
putc ('\n', listfp);
}
/* Check whether the key matches but do this only if we are not /* Check whether the key matches but do this only if we are not
running in syntax check mode. */ running in syntax check mode. */
if ( update if ( update
&& !result && !result && !listfp
&& (got_match || (key && key_matches_user_or_group (key))) ) && (got_match || (key && key_matches_user_or_group (key))) )
{ {
int newflags = 0; int newflags = 0;
@ -3348,7 +3381,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults)
xfree (line); xfree (line);
/* If it all worked, process the options. */ /* If it all worked, process the options. */
if (!result && update && defaults) if (!result && update && defaults && !listfp)
{ {
/* We need to switch off the runtime update, so that we can do /* We need to switch off the runtime update, so that we can do
it later all at once. */ it later all at once. */

View File

@ -44,6 +44,7 @@ enum cmd_and_opt_values
aListOptions, aListOptions,
aChangeOptions, aChangeOptions,
aApplyDefaults, aApplyDefaults,
aListConfig,
aCheckConfig aCheckConfig
}; };
@ -60,6 +61,8 @@ static ARGPARSE_OPTS opts[] =
{ aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") }, { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") },
{ aApplyDefaults, "apply-defaults", 256, { aApplyDefaults, "apply-defaults", 256,
N_("apply global default values") }, N_("apply global default values") },
{ aListConfig, "list-config", 256,
N_("list global configuration file") },
{ aCheckConfig, "check-config", 256, { aCheckConfig, "check-config", 256,
N_("check global configuration file") }, N_("check global configuration file") },
@ -104,6 +107,27 @@ my_strusage( int level )
} }
/* Return the fp for the output. This is usually stdout unless
--output has been used. In the latter case this function opens
that file. */
static FILE *
get_outfp (FILE **fp)
{
if (!*fp)
{
if (opt.outfile)
{
*fp = fopen (opt.outfile, "w");
if (!*fp)
gc_error (1, errno, "can not open `%s'", opt.outfile);
}
else
*fp = stdout;
}
return *fp;
}
/* gpgconf main. */ /* gpgconf main. */
int int
main (int argc, char **argv) main (int argc, char **argv)
@ -112,6 +136,7 @@ main (int argc, char **argv)
const char *fname; const char *fname;
int no_more_options = 0; int no_more_options = 0;
enum cmd_and_opt_values cmd = 0; enum cmd_and_opt_values cmd = 0;
FILE *outfp = NULL;
set_strusage (my_strusage); set_strusage (my_strusage);
log_set_prefix ("gpgconf", 1); log_set_prefix ("gpgconf", 1);
@ -143,6 +168,7 @@ main (int argc, char **argv)
case aListOptions: case aListOptions:
case aChangeOptions: case aChangeOptions:
case aApplyDefaults: case aApplyDefaults:
case aListConfig:
case aCheckConfig: case aCheckConfig:
cmd = pargs.r_opt; cmd = pargs.r_opt;
break; break;
@ -161,12 +187,12 @@ main (int argc, char **argv)
case aListComponents: case aListComponents:
default: default:
/* List all components. */ /* List all components. */
gc_component_list_components (stdout); gc_component_list_components (get_outfp (&outfp));
break; break;
case aCheckPrograms: case aCheckPrograms:
/* Check all programs. */ /* Check all programs. */
gc_component_check_programs (stdout); gc_component_check_programs (get_outfp (&outfp));
break; break;
case aListOptions: case aListOptions:
@ -189,17 +215,22 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
gc_component_retrieve_options (idx); gc_component_retrieve_options (idx);
if (gc_process_gpgconf_conf (NULL, 1, 0)) if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
exit (1); exit (1);
if (cmd == aListOptions) if (cmd == aListOptions)
gc_component_list_options (idx, stdout); gc_component_list_options (idx, get_outfp (&outfp));
else else
gc_component_change_options (idx, stdin); gc_component_change_options (idx, stdin);
} }
break; break;
case aListConfig:
if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp)))
exit (1);
break;
case aCheckConfig: case aCheckConfig:
if (gc_process_gpgconf_conf (fname, 0, 0)) if (gc_process_gpgconf_conf (fname, 0, 0, NULL))
exit (1); exit (1);
break; break;
@ -213,14 +244,15 @@ main (int argc, char **argv)
exit (2); exit (2);
} }
gc_component_retrieve_options (-1); gc_component_retrieve_options (-1);
if (gc_process_gpgconf_conf (NULL, 1, 1)) if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
exit (1); exit (1);
break; break;
} }
if (outfp && outfp != stdout)
if (fclose (outfp))
gc_error (1, errno, "error closing `%s'", opt.outfile);
return 0; return 0;
} }

View File

@ -37,6 +37,8 @@ struct
/*-- gpgconf-comp.c --*/ /*-- gpgconf-comp.c --*/
void gc_error (int status, int errnum, const char *fmt, ...);
/* List all components that are available. */ /* List all components that are available. */
void gc_component_list_components (FILE *out); void gc_component_list_components (FILE *out);
@ -58,7 +60,8 @@ void gc_component_list_options (int component, FILE *out);
void gc_component_change_options (int component, FILE *in); void gc_component_change_options (int component, FILE *in);
/* Process global configuration file. */ /* Process global configuration file. */
int gc_process_gpgconf_conf (const char *fname, int update, int defaults); int gc_process_gpgconf_conf (const char *fname, int update, int defaults,
FILE *listfp);
#endif /*GPGCONF_H*/ #endif /*GPGCONF_H*/