Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34555714
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
136 KB
Subscribers
None
View Options
diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog
index 39df05d0b..716effbe8 100644
--- a/dirmngr/ChangeLog
+++ b/dirmngr/ChangeLog
@@ -1,1517 +1,1525 @@
+2011-01-25 Werner Koch <wk@g10code.com>
+
+ * dirmngr.c (handle_connections): Rewrite loop to use pth-select
+ so to sync timeouts to the full second.
+ (pth_thread_id): New.
+ * ldap-wrapper.c (ldap_wrapper_thread): Sync to the full second.
+ Increate pth_wait timeout from 1 to 2 seconds.
+
2011-01-20 Werner Koch <wk@g10code.com>
* server.c (release_ctrl_keyservers): New.
(cmd_keyserver, cmd_ks_seach, cmd_ks_get, cmd_ks_put): New.
* dirmngr.h (uri_item_t): New.
(struct server_control_s): Add field KEYSERVERS.
* ks-engine-hkp.c: New.
* ks-engine.h: New.
* ks-action.c, ks-action.h: New.
* server.c: Include ks-action.h.
(cmd_ks_search): New.
* Makefile.am (dirmngr_SOURCES): Add new files.
2011-01-19 Werner Koch <wk@g10code.com>
* dirmngr.c (main): Use es_printf for --gpgconf-list.
2010-12-14 Werner Koch <wk@g10code.com>
* cdb.h (struct cdb) [W32]: Add field CDB_MAPPING.
* cdblib.c (cdb_init) [W32]: Save mapping handle.
(cdb_free) [W32]: Don't leak the mapping handle from cdb_init by
using the saved one.
* crlcache.c (crl_cache_insert): Close unused matching files.
* dirmngr.c (main) [W32CE]: Change homedir in daemon mode to /gnupg.
2010-12-07 Werner Koch <wk@g10code.com>
* dirmngr.c (TIMERTICK_INTERVAL) [W32CE]: Change to 60s.
2010-11-23 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_LDFLAGS): Add extra_bin_ldflags.
(dirmngr_client_LDFLAGS): Ditto.
2010-10-21 Werner Koch <wk@g10code.com>
* dirmngr.c (main): Changed faked system time warning
2010-10-15 Werner Koch <wk@g10code.com>
* Makefile.am (CLEANFILES): Add no-libgcrypt.c.
2010-09-16 Werner Koch <wk@g10code.com>
* validate.c (validate_cert_chain): Use GPG_ERR_MISSING_ISSUER_CERT.
2010-08-13 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_SOURCES): Add w32-ldap-help.h.
* dirmngr_ldap.c (fetch_ldap): Call ldap_unbind.
* w32-ldap-help.h: New.
* dirmngr_ldap.c [W32CE]: Include w32-ldap-help.h and use the
mapped ldap functions.
2010-08-12 Werner Koch <wk@g10code.com>
* crlcache.c (update_dir, crl_cache_insert): s/unlink/gnupg_remove/.
* dirmngr.c (dirmngr_sighup_action): New.
* server.c (cmd_killdirmngr, cmd_reloaddirmngr): New.
(struct server_local_s): Add field STOPME.
(start_command_handler): Act on STOPME.
2010-08-06 Werner Koch <wk@g10code.com>
* dirmngr.c (JNLIB_NEED_AFLOCAL): Define macro.
(main): Use SUN_LEN macro.
(main) [W32]: Allow EEXIST in addition to EADDRINUSE.
2010-08-05 Werner Koch <wk@g10code.com>
* server.c (set_error, leave_cmd): New.
(cmd_validate, cmd_ldapserver, cmd_isvalid, cmd_checkcrl)
(cmd_checkocsp, cmd_lookup, cmd_listcrls, cmd_cachecert): Use
leave_cmd.
(cmd_getinfo): New.
(data_line_cookie_write, data_line_cookie_close): New.
(cmd_listcrls): Replace assuan_get_data_fp by es_fopencookie.
* misc.c (create_estream_ksba_reader, my_estream_ksba_reader_cb): New.
* certcache.c (load_certs_from_dir): Use create_estream_ksba_reader.
* crlcache.c (crl_cache_load): Ditto.
2010-08-03 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn
into functions for use in a 'for' control stmt.
2010-07-26 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (print_ldap_entries): Remove special fwrite case
for W32 because that is now handles by estream.
2010-07-25 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_SOURCES) [!USE_LDAPWRAPPER]: Build
ldap-wrapper-ce.
* ldap-wrapper-ce.c: New.
* dirmngr_ldap.c (opt): Remove global variable ...
(my_opt_t): ... and declare a type instead.
(main): Define a MY_OPT variable and change all references to OPT
to this.
(set_timeout, print_ldap_entries, fetch_ldap, process_url): Pass
MYOPT arg.
2010-07-24 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (main): Init common subsystems. Call
es_set_binary.
2010-07-19 Werner Koch <wk@g10code.com>
* dirmngr.c: Include ldap-wrapper.h.
(launch_reaper_thread): Move code to ...
* ldap-wrapper.c (ldap_wrapper_launch_thread): .. here. Change
callers.
(ldap_wrapper_thread): Rename to ...
(wrapper_thread): this and make local.
* ldap.c (destroy_wrapper, print_log_line)
(read_log_data, ldap_wrapper_thread)
(ldap_wrapper_wait_connections, ldap_wrapper_release_context)
(ldap_wrapper_connection_cleanup, reader_callback, ldap_wrapper):
Factor code out to ...
* ldap-wrapper.c: new.
(ldap_wrapper): Make public.
(read_buffer): Copy from ldap.c.
* ldap-wrapper.h: New.
* Makefile.am (dirmngr_SOURCES): Add new files.
2010-07-16 Werner Koch <wk@g10code.com>
* http.c, http.h: Remove.
* dirmngr-err.h: New.
* dirmngr.h: Include dirmngr-err.h instead of gpg-error.h
* cdblib.c: Replace assignments to ERRNO by a call to
gpg_err_set_errno. Include dirmngr-err.h.
(cdb_free) [__MINGW32CE__]: Do not use get_osfhandle.
* dirmngr.c [!HAVE_SIGNAL_H]: Don't include signal.h.
(USE_W32_SERVICE): New. Use this to control the use of the W32
service system.
2010-07-06 Werner Koch <wk@g10code.com>
* dirmngr.c (main): Print note on directory name changes.
Replace almost all uses of stdio by estream.
* b64dec.c, b64enc.c: Remove. They are duplicated in ../common/.
2010-06-28 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (my_i18n_init): Remove.
(main): Call i18n_init instead of above function.
* dirmngr-client.c (my_i18n_init): Remove.
(main): Call i18n_init instead of above function.
* Makefile.am (dirmngr_LDADD): Add ../gl/libgnu.
(dirmngr_ldap_LDADD, dirmngr_client_LDADD): Ditto.
2010-06-09 Werner Koch <wk@g10code.com>
* i18n.h: Remove.
* Makefile.am (no-libgcrypt.c): New rule.
* exechelp.h: Remove.
* exechelp.c: Remove.
(dirmngr_release_process): Change callers to use the gnupg func.
(dirmngr_wait_process): Likewise.
(dirmngr_kill_process): Likewise. This actually implements it for
W32.
* ldap.c (ldap_wrapper): s/get_dirmngr_ldap_path/gnupg_module_name/.
(ldap_wrapper_thread): Use gnupg_wait_process and adjust for
changed semantics.
(ldap_wrapper): Replace xcalloc by xtrycalloc. Replace spawn
mechanism.
* server.c (start_command_handler): Remove assuan_set_log_stream.
* validate.c: Remove gcrypt.h and ksba.h.
* ldapserver.c: s/util.h/dirmngr.h/.
* dirmngr.c (sleep) [W32]: Remove macro.
(main): s/sleep/gnupg_sleep/.
(pid_suffix_callback): Change arg type.
(my_gcry_logger): Remove.
(fixed_gcry_pth_init): New.
(main): Use it.
(FD2INT): Remove.
2010-06-08 Werner Koch <wk@g10code.com>
* misc.h (copy_time): Remove and replace by gnupg_copy_time which
allows to set a null date.
* misc.c (dump_isotime, get_time, get_isotime, set_time)
(check_isotime, add_isotime): Remove and replace all calls by the
versions from common/gettime.c.
* crlcache.c, misc.c, misc.h: s/dirmngr_isotime_t/gnupg_isotime_t/.
* server.c, ldap.c: Reorder include directives.
* crlcache.h, misc.h: Remove all include directives.
* certcache.c (cmp_simple_canon_sexp): Remove.
(compare_serialno): Rewrite using cmp_simple_canon_sexp from
common/sexputil.c
* error.h: Remove.
* dirmngr.c: Remove transitional option "--ignore-ocsp-servic-url".
(opts): Use ARGPARSE macros.
(i18n_init): Remove.
(main): Use GnuPG init functions.
* dirmngr.h: Remove duplicated stuff now taken from ../common.
* get-path.c, util.h: Remove.
* Makefile.am: Adjust to GnuPG system.
* estream.c, estream.h, estream-printf.c, estream-printf.h: Remove.
2010-06-07 Werner Koch <wk@g10code.com>
* OAUTHORS, ONEWS, ChangeLog.1: New.
* ChangeLog, Makefile.am, b64dec.c, b64enc.c, cdb.h, cdblib.c
* certcache.c, certcache.h, crlcache.c, crlcache.h, crlfetch.c
* crlfetch.h, dirmngr-client.c, dirmngr.c, dirmngr.h
* dirmngr_ldap.c, error.h, estream-printf.c, estream-printf.h
* estream.c, estream.h, exechelp.c, exechelp.h, get-path.c, http.c
* http.h, i18n.h, ldap-url.c, ldap-url.h, ldap.c, ldapserver.c
* ldapserver.h, misc.c, misc.h, ocsp.c, ocsp.h, server.c, util.h
* validate.c, validate.h: Imported from the current SVN of the
dirmngr package (only src/).
2010-03-13 Werner Koch <wk@g10code.com>
* dirmngr.c (int_and_ptr_u): New.
(pid_suffix_callback): Trick out compiler.
(start_connection_thread): Ditto.
(handle_connections): Ditto.
2010-03-09 Werner Koch <wk@g10code.com>
* dirmngr.c (set_debug): Allow numerical values.
2009-12-15 Werner Koch <wk@g10code.com>
* dirmngr.c: Add option --ignore-cert-extension.
(parse_rereadable_options): Implement.
* dirmngr.h (opt): Add IGNORED_CERT_EXTENSIONS.
* validate.c (unknown_criticals): Handle ignored extensions.
2009-12-08 Marcus Brinkmann <marcus@g10code.de>
* dirmngr-client.c (start_dirmngr): Convert posix FDs to assuan fds.
2009-11-25 Marcus Brinkmann <marcus@g10code.de>
* server.c (start_command_handler): Use assuan_fd_t and
assuan_fdopen on fds.
2009-11-05 Marcus Brinkmann <marcus@g10code.de>
* server.c (start_command_handler): Update use of
assuan_init_socket_server.
* dirmngr-client.c (start_dirmngr): Update use of
assuan_pipe_connect and assuan_socket_connect.
2009-11-04 Werner Koch <wk@g10code.com>
* server.c (register_commands): Add help arg to
assuan_register_command. Change all command comments to strings.
2009-11-02 Marcus Brinkmann <marcus@g10code.de>
* server.c (reset_notify): Take LINE argument, return gpg_error_t.
2009-10-16 Marcus Brinkmann <marcus@g10code.com>
* Makefile.am: (dirmngr_LDADD): Link to $(LIBASSUAN_LIBS) instead
of $(LIBASSUAN_PTH_LIBS).
* dirmngr.c: Invoke ASSUAN_SYSTEM_PTH_IMPL.
(main): Call assuan_set_system_hooks and assuan_sock_init.
2009-09-22 Marcus Brinkmann <marcus@g10code.de>
* dirmngr.c (main): Update to new Assuan interface.
* server.c (option_handler, cmd_ldapserver, cmd_isvalid)
(cmd_checkcrl, cmd_checkocsp, cmd_lookup, cmd_loadcrl)
(cmd_listcrls, cmd_cachecert, cmd_validate): Return gpg_error_t
instead int.
(register_commands): Likewise for member HANDLER.
(start_command_handler): Allocate context with assuan_new before
starting server. Release on error.
* dirmngr-client.c (main): Update to new Assuan interface.
(start_dirmngr): Allocate context with assuan_new before
connecting to server. Release on error.
2009-08-12 Werner Koch <wk@g10code.com>
* dirmngr-client.c (squid_loop_body): Flush stdout. Suggested by
Philip Shin.
2009-08-07 Werner Koch <wk@g10code.com>
* crlfetch.c (my_es_read): Add explicit check for EOF.
* http.c (struct http_context_s): Turn IN_DATA and IS_HTTP_0_9 to
bit fields.
(struct cookie_s): Add CONTENT_LENGTH_VALID and CONTENT_LENGTH.
(parse_response): Parse the Content-Length header.
(cookie_read): Handle content length.
(http_open): Make NEED_HEADER the semi-default.
* http.h (HTTP_FLAG_IGNORE_CL): New.
2009-08-04 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper_thread): Factor some code out to ...
(read_log_data): ... new. Close the log fd on error.
(ldap_wrapper_thread): Delay cleanup until the log fd is closed.
(SAFE_PTH_CLOSE): New. Use it instead of pth_close.
2009-07-31 Werner Koch <wk@g10code.com>
* server.c (cmd_loadcrl): Add option --url.
* dirmngr-client.c (do_loadcrl): Make use of --url.
* crlfetch.c (crl_fetch): Remove HTTP_FLAG_NO_SHUTDOWN. Add
flag HTTP_FLAG_LOG_RESP with active DBG_LOOKUP.
* http.c: Require estream. Remove P_ES macro.
(write_server): Remove.
(my_read_line): Remove. Replace all callers by es_read_line.
(send_request): Use es_asprintf. Always store the cookie.
(http_wait_response): Remove the need to dup the socket. USe new
shutdown flag.
* http.h (HTTP_FLAG_NO_SHUTDOWN): Rename to HTTP_FLAG_SHUTDOWN.
* estream.c, estream.h, estream-printf.c, estream-printf.h: Update
from current libestream. This is provide es_asprintf.
2009-07-20 Werner Koch <wk@g10code.com>
* dirmngr.c (pid_suffix_callback): New.
(main): Use log_set_pid_suffix_cb.
(start_connection_thread): Put the fd into the tls.
* ldap.c (ldap_wrapper_thread): Print ldap worker stati.
(ldap_wrapper_release_context): Print a debug info.
(end_cert_fetch_ldap): Release the reader. Might fix bug#999.
2009-06-17 Werner Koch <wk@g10code.com>
* util.h: Remove unused dotlock.h.
2009-05-26 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper): Show reader object in diagnostics.
* crlcache.c (crl_cache_reload_crl): Ditto. Change debug messages
to regular diagnostics.
* dirmngr_ldap.c (print_ldap_entries): Add extra diagnostics.
2009-04-03 Werner Koch <wk@g10code.com>
* dirmngr.h (struct server_local_s): Move back to ...
* server.c (struct server_local_s): ... here.
(get_ldapservers_from_ctrl): New.
* ldapserver.h (ldapserver_iter_begin): Use it.
2008-10-29 Marcus Brinkmann <marcus@g10code.de>
* estream.c (es_getline): Add explicit cast to silence gcc -W
warning.
* crlcache.c (finish_sig_check): Likewise.
* dirmngr.c (opts): Add missing initializer to silence gcc
-W warning.
* server.c (register_commands): Likewise.
* dirmngr-client.c (opts): Likewise.
* dirmngr_ldap.c (opts): Likewise.
* dirmngr-client.c (status_cb, inq_cert, data_cb): Change return
type to gpg_error_t to silence gcc warning.
2008-10-21 Werner Koch <wk@g10code.com>
* certcache.c (load_certs_from_dir): Accept ".der" files.
* server.c (get_istrusted_from_client): New.
* validate.c (validate_cert_chain): Add new optional arg
R_TRUST_ANCHOR. Adjust all callers
* crlcache.c (crl_cache_entry_s): Add fields USER_TRUST_REQ
and CHECK_TRUST_ANCHOR.
(release_one_cache_entry): Release CHECK_TRUST_ANCHOR.
(list_one_crl_entry): Print info about the new fields.
(open_dir, write_dir_line_crl): Support the new U-flag.
(crl_parse_insert): Add arg R_TRUST_ANCHOR and set it accordingly.
(crl_cache_insert): Store trust anchor in entry object.
(cache_isvalid): Ask client for trust is needed.
* crlcache.c (open_dir): Replace xcalloc by xtrycalloc.
(next_line_from_file): Ditt. Add arg to return the gpg error.
Change all callers.
(update_dir): Replace sprintf and malloc by estream_asprintf.
(crl_cache_insert): Ditto.
(crl_cache_isvalid): Replace xmalloc by xtrymalloc.
(get_auth_key_id): Ditto.
(crl_cache_insert): Ditto.
* crlcache.c (start_sig_check): Remove HAVE_GCRY_MD_DEBUG test.
* validate.c (check_cert_sig): Ditto. Remove workaround for bug
in libgcrypt 1.2.
* estream.c, estream.h, estream-printf.c, estream-printf.h: Update
from current libestream (svn rev 61).
2008-09-30 Marcus Brinkmann <marcus@g10code.com>
* get-path.c (get_dirmngr_ldap_path): Revert last change.
Instead, use dirmngr_libexecdir().
(find_program_at_standard_place): Don't define for now.
2008-09-30 Marcus Brinkmann <marcus@g10code.com>
* get-path.c (dirmngr_cachedir): Make COMP a pointer to const to
silence gcc warning.
(get_dirmngr_ldap_path): Look for dirmngr_ldap in the installation
directory.
2008-08-06 Marcus Brinkmann <marcus@g10code.com>
* dirmngr.c (main): Mark the ldapserverlist-file option as
read-only.
2008-07-31 Werner Koch <wk@g10code.com>
* crlcache.c (start_sig_check) [!HAVE_GCRY_MD_DEBUG]: Use
gcry_md_start_debug
2008-06-16 Werner Koch <wk@g10code.com>
* get-path.c (w32_commondir): New.
(dirmngr_sysconfdir): Use it here.
(dirmngr_datadir): Ditto.
2008-06-12 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (dirmngr_SOURCES): Add ldapserver.h and ldapserver.c.
* ldapserver.h, ldapserver.c: New files.
* ldap.c: Include "ldapserver.h".
(url_fetch_ldap): Use iterator to get session servers as well.
(attr_fetch_ldap, start_default_fetch_ldap): Likewise.
* dirmngr.c: Include "ldapserver.h".
(free_ldapservers_list): Removed. Change callers to
ldapserver_list_free.
(parse_ldapserver_file): Use ldapserver_parse_one.
* server.c: Include "ldapserver.h".
(cmd_ldapserver): New command.
(register_commands): Add new command LDAPSERVER.
(reset_notify): New function.
(start_command_handler): Register reset notify handler.
Deallocate session server list.
(lookup_cert_by_pattern): Use iterator to get session servers as well.
(struct server_local_s): Move to ...
* dirmngr.h (struct server_local_s): ... here. Add new member
ldapservers.
2008-06-10 Werner Koch <wk@g10code.com>
Support PEM encoded CRLs. Fixes bug#927.
* crlfetch.c (struct reader_cb_context_s): New.
(struct file_reader_map_s): Replace FP by new context.
(register_file_reader, get_file_reader): Adjust accordingly.
(my_es_read): Detect Base64 encoded CRL and decode if needed.
(crl_fetch): Pass new context to the callback.
(crl_close_reader): Cleanup the new context.
* b64dec.c: New. Taken from GnuPG.
* util.h (struct b64state): Add new fields STOP_SEEN and
INVALID_ENCODING.
2008-05-26 Marcus Brinkmann <marcus@g10code.com>
* dirmngr.c (main) [HAVE_W32_SYSTEM]: Switch to system
configuration on gpgconf related commands, and make all options
unchangeable.
2008-03-25 Marcus Brinkmann <marcus@g10code.de>
* dirmngr_ldap.c (print_ldap_entries): Add code alternative for
W32 console stdout (unused at this point).
2008-03-21 Marcus Brinkmann <marcus@g10code.de>
* estream.c (ESTREAM_MUTEX_DESTROY): New macro.
(es_create, es_destroy): Use it.
2008-02-21 Werner Koch <wk@g10code.com>
* validate.c (check_cert_sig) [HAVE_GCRY_MD_DEBUG]: Use new debug
function if available.
* crlcache.c (abort_sig_check): Mark unused arg.
* exechelp.c (dirmngr_release_process) [!W32]: Mark unsed arg.
* validate.c (is_root_cert): New. Taken from GnuPG.
(validate_cert_chain): Use it in place of the simple DN compare.
2008-02-15 Marcus Brinkmann <marcus@g10code.de>
* dirmngr.c (main): Reinitialize assuan log stream if necessary.
* crlcache.c (update_dir) [HAVE_W32_SYSTEM]: Remove destination
file before rename.
(crl_cache_insert) [HAVE_W32_SYSTEM]: Remove destination file
before rename.
2008-02-14 Marcus Brinkmann <marcus@g10code.de>
* validate.c (check_cert_policy): Use ksba_free instead of xfree.
(validate_cert_chain): Likewise. Free SUBJECT on error.
(cert_usage_p): Likewise.
* crlcache.c (finish_sig_check): Undo last change.
(finish_sig_check): Close md.
(abort_sig_check): New function.
(crl_parse_insert): Use abort_sig_check to clean up.
* crlcache.c (crl_cache_insert): Clean up CDB on error.
2008-02-13 Marcus Brinkmann <marcus@g10code.de>
* crlcache.c (finish_sig_check): Call gcry_md_stop_debug.
* exechelp.h (dirmngr_release_process): New prototype.
* exechelp.c (dirmngr_release_process): New function.
* ldap.c (ldap_wrapper_thread): Release pid.
(destroy_wrapper): Likewise.
* dirmngr.c (launch_reaper_thread): Destroy tattr.
(handle_connections): Likewise.
2008-02-12 Marcus Brinkmann <marcus@g10code.de>
* ldap.c (pth_close) [! HAVE_W32_SYSTEM]: New macro.
(struct wrapper_context_s): New member log_ev.
(destroy_wrapper): Check FDs for != -1 rather than != 0. Use
pth_close instead of close. Free CTX->log_ev.
(ldap_wrapper_thread): Rewritten to use pth_wait instead of
select. Also use pth_read instead of read and pth_close instead
of close.
(ldap_wrapper): Initialize CTX->log_ev.
(reader_callback): Use pth_close instead of close.
* exechelp.c (create_inheritable_pipe) [HAVE_W32_SYSTEM]: Removed.
(dirmngr_spawn_process) [HAVE_W32_SYSTEM]: Use pth_pipe instead.
* dirmngr_ldap.c [HAVE_W32_SYSTEM]: Include <fcntl.h>.
(main) [HAVE_W32_SYSTEM]: Set mode of stdout to binary.
2008-02-01 Werner Koch <wk@g10code.com>
* ldap.c: Remove all ldap headers as they are unused.
* dirmngr_ldap.c (LDAP_DEPRECATED): New, to have OpenLDAP use the
old standard API.
2008-01-10 Werner Koch <wk@g10code.com>
* dirmngr-client.c: New option --local.
(do_lookup): Use it.
* server.c (lookup_cert_by_pattern): Implement local lookup.
(return_one_cert): New.
* certcache.c (hexsn_to_sexp): New.
(classify_pattern, get_certs_bypattern): New.
* misc.c (unhexify): Allow passing NULL for RESULT.
(cert_log_subject): Do not call ksba_free on an unused variable.
2008-01-02 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (dirmngr_LDADD, dirmngr_ldap_LDADD)
(dirmngr_client_LDADD): Add $(LIBICONV). Reported by Michael
Nottebrock.
2007-12-11 Werner Koch <wk@g10code.com>
* server.c (option_handler): New option audit-events.
* dirmngr.h (struct server_control_s): Add member AUDIT_EVENTS.
2007-11-26 Marcus Brinkmann <marcus@g10code.de>
* get-path.c (dirmngr_cachedir): Create intermediate directories.
(default_socket_name): Use CSIDL_WINDOWS.
2007-11-21 Werner Koch <wk@g10code.com>
* server.c (lookup_cert_by_pattern): Add args SINGLE and CACHE_ONLY.
(cmd_lookup): Add options --single and --cache-only.
2007-11-16 Werner Koch <wk@g10code.com>
* certcache.c (load_certs_from_dir): Also log the subject DN.
* misc.c (cert_log_subject): New.
2007-11-14 Werner Koch <wk@g10code.com>
* dirmngr-client.c: Replace --lookup-url by --url.
(main): Remove extra code for --lookup-url.
(do_lookup): Remove LOOKUP_URL arg and use the
global option OPT.URL.
* server.c (has_leading_option): New.
(cmd_lookup): Use it.
* crlfetch.c (fetch_cert_by_url): Use GPG_ERR_INV_CERT_OBJ.
(fetch_cert_by_url): Use gpg_error_from_syserror.
2007-11-14 Moritz <moritz@gnu.org> (wk)
* dirmngr-client.c: New command: --lookup-url <URL>.
(do_lookup): New parameter: lookup_url. If TRUE, include "--url"
switch in LOOKUP transaction.
(enum): New entry: oLookupUrl.
(opts): Likewise.
(main): Handle oLookupUrl. New variable: cmd_lookup_url, set
during option parsing, pass to do_lookup() and substitute some
occurences of "cmd_lookup" with "cmd_lookup OR cmd_lookup_url".
* crlfetch.c (fetch_cert_by_url): New function, uses
url_fetch_ldap() to create a reader object and libksba functions
to read a single cert from that reader.
* server.c (lookup_cert_by_url, lookup_cert_by_pattern): New
functions.
(cmd_lookup): Moved almost complete code ...
(lookup_cert_by_pattern): ... here.
(cmd_lookup): Support new optional argument: --url. Depending on
the presence of that switch, call lookup_cert_by_url() or
lookup_cert_by_pattern().
(lookup_cert_by_url): Heavily stripped down version of
lookup_cert_by_pattern(), using fetch_cert_by_url.
2007-10-24 Marcus Brinkmann <marcus@g10code.de>
* exechelp.c (dirmngr_spawn_process): Fix child handles.
2007-10-05 Marcus Brinkmann <marcus@g10code.de>
* dirmngr.h: Include assuan.h.
(start_command_handler): Change type of FD to assuan_fd_t.
* dirmngr.c: Do not include w32-afunix.h.
(socket_nonce): New global variable.
(create_server_socket): Use assuan socket wrappers. Remove W32
specific stuff. Save the server nonce.
(check_nonce): New function.
(start_connection_thread): Call it.
(handle_connections): Change args to assuan_fd_t.
* server.c (start_command_handler): Change type of FD to assuan_fd_t.
2007-09-12 Marcus Brinkmann <marcus@g10code.de>
* dirmngr.c (main): Percent escape pathnames in --gpgconf-list output.
2007-08-27 Moritz Schulte <moritz@g10code.com>
* src/Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SOCKETDIR based on
$(localstatedir).
* src/get-path.c (default_socket_name): Use DIRMNGR_SOCKETDIR
instead of hard-coded "/var/run/dirmngr".
2007-08-16 Werner Koch <wk@g10code.com>
* get-path.c (get_dirmngr_ldap_path): Make PATHNAME const.
* dirmngr.c (my_ksba_hash_buffer): Mark unused arg.
(dirmngr_init_default_ctrl): Ditto.
(my_gcry_logger): Ditto.
* dirmngr-client.c (status_cb): Ditto.
* dirmngr_ldap.c (catch_alarm): Ditto.
* estream-printf.c (pr_bytes_so_far): Ditto.
* estream.c (es_func_fd_create): Ditto.
(es_func_fp_create): Ditto.
(es_write_hexstring): Ditto.
* server.c (cmd_listcrls): Ditto.
(cmd_cachecert): Ditto.
* crlcache.c (cache_isvalid): Ditto.
* ocsp.c (do_ocsp_request): Ditto.
* ldap.c (ldap_wrapper_thread): Ditto.
* http.c (http_register_tls_callback): Ditto.
(connect_server): Ditto.
(write_server) [!HTTP_USE_ESTREAM]: Don't build.
2007-08-14 Werner Koch <wk@g10code.com>
* get-path.c (dirmngr_cachedir) [W32]: Use CSIDL_LOCAL_APPDATA.
2007-08-13 Werner Koch <wk@g10code.com>
* dirmngr.c (handle_connections): Use a timeout in the accept
function. Block signals while creating a new thread.
(shutdown_pending): Needs to be volatile as also accessed bt the
service function.
(w32_service_control): Do not use the regular log fucntions here.
(handle_tick): New.
(main): With system_service in effect use aDaemon as default
command.
(main) [W32]: Only temporary redefine main for the sake of Emacs's
"C-x 4 a".
* dirmngr-client.c (main) [W32]: Initialize sockets.
(start_dirmngr): Use default_socket_name instead of a constant.
* Makefile.am (dirmngr_client_SOURCES): Add get-path.c
2007-08-09 Werner Koch <wk@g10code.com>
* dirmngr.c (parse_ocsp_signer): New.
(parse_rereadable_options): Set opt.ocsp_signer to this.
* dirmngr.h (fingerprint_list_t): New.
* ocsp.c (ocsp_isvalid, check_signature, validate_responder_cert):
Allow for several default ocscp signers.
(ocsp_isvalid): Return GPG_ERR_NO_DATA for an unknwon status.
* dirmngr-client.c: New option --force-default-responder.
* server.c (has_option, skip_options): New.
(cmd_checkocsp): Add option --force-default-responder.
(cmd_isvalid): Ditto. Also add option --only-ocsp.
* ocsp.c (ocsp_isvalid): New arg FORCE_DEFAULT_RESPONDER.
* dirmngr.c: New option --ocsp-max-period.
* ocsp.c (ocsp_isvalid): Implement it and take care that a missing
next_update is to be ignored.
* crlfetch.c (my_es_read): New. Use it instead of es_read.
* estream.h, estream.c, estream-printf.c: Updated from current
libestream SVN.
2007-08-08 Werner Koch <wk@g10code.com>
* crlcache.c (crl_parse_insert): Hack to allow for a missing
nextUpdate.
* dirmngr_ldap.c (print_ldap_entries): Strip the extension from
the want_attr.
* exechelp.c (dirmngr_wait_process): Reworked for clear error
semantics.
* ldap.c (ldap_wrapper_thread): Adjust for new
dirmngr_wait_process semantics.
2007-08-07 Werner Koch <wk@g10code.com>
* get-path.c (default_socket_name) [!W32]: Fixed syntax error.
* ldap.c (X509CACERT, make_url, fetch_next_cert_ldap): Support
x509caCert as used by the Bundesnetzagentur.
(ldap_wrapper): Do not pass the prgtram name as the first
argument. dirmngr_spawn_process takes care of that.
2007-08-04 Marcus Brinkmann <marcus@g10code.de>
* dirmngr.h (opt): Add member system_service.
* dirmngr.c (opts) [HAVE_W32_SYSTEM]: New entry for option
--service.
(DEFAULT_SOCKET_NAME): Removed.
(service_handle, service_status,
w32_service_control) [HAVE_W32_SYSTEM]: New symbols.
(main) [HAVE_W32_SYSTEM]: New entry point for --service. Rename
old function to ...
(real_main) [HAVE_W32_SYSTEM]: ... this. Use default_socket_name
instead of DEFAULT_SOCKET_NAME, and similar for other paths.
Allow colons in Windows socket path name, and implement --service
option.
* util.h (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir,
dirmngr_cachedir, default_socket_name): New prototypes.
* get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir)
(dirmngr_datadir, dirmngr_cachedir, default_socket_name): New
functions.
(DIRSEP_C, DIRSEP_S): New macros.
2007-08-03 Marcus Brinkmann <marcus@g10code.de>
* get-path.c: Really add the file this time.
2007-07-31 Marcus Brinkmann <marcus@g10code.de>
* crlfetch.c: Include "estream.h".
(crl_fetch): Use es_read callback instead a file handle.
(crl_close_reader): Use es_fclose instead of fclose.
(struct file_reader_map_s): Change type of FP to estream_t.
(register_file_reader, crl_fetch, crl_close_reader): Likewise.
* ocsp.c: Include "estream.h".
(read_response): Change type of FP to estream_t.
(read_response, do_ocsp_request): Use es_* variants of I/O
functions.
* http.c: Include <pth.h>.
(http_wait_response) [HAVE_W32_SYSTEM]: Use DuplicateHandle.
(cookie_read): Use pth_read instead read.
(cookie_write): Use pth_write instead write.
2007-07-30 Marcus Brinkmann <marcus@g10code.de>
* ldap-url.c (ldap_str2charray): Fix buglet in ldap_utf8_strchr
invocation.
2007-07-27 Marcus Brinkmann <marcus@g10code.de>
* estream.h, estream.c: Update from recent GnuPG.
* get-path.c: New file.
* Makefile.am (dirmngr_SOURCES): Add get-path.c.
* util.h (default_homedir, get_dirmngr_ldap_path): New prototypes.
* dirmngr.c (main): Use default_homedir().
* ldap-url.h: Remove japanese white space (sorry!).
2007-07-26 Marcus Brinkmann <marcus@g10code.de>
* ldap.c (pth_yield): Remove macro.
* ldap.c (pth_yield) [HAVE_W32_SYSTEM]: Define to Sleep(0).
* dirmngr_ldap.c [HAVE_W32_SYSTEM]: Do not include <ldap.h>, but
<winsock2.h>, <winldap.h> and "ldap-url.h".
* ldap.c [HAVE_W32_SYSTEM]: Do not include <ldap.h>, but
<winsock2.h> and <winldap.h>.
* ldap-url.c: Do not include <ldap.h>, but <winsock2.h>,
<winldap.h> and "ldap-url.h".
(LDAP_P): New macro.
* ldap-url.h: New file.
* Makefile.am (ldap_url): Add ldap-url.h.
* Makefile.am (ldap_url): New variable.
(dirmngr_ldap_SOURCES): Add $(ldap_url).
(dirmngr_ldap_LDADD): Add $(LIBOBJS).
* ldap-url.c: New file, excerpted from OpenLDAP.
* dirmngr.c (main) [HAVE_W32_SYSTEM]: Avoid the daemonization.
* dirmngr_ldap.c: Include "util.h".
(main) [HAVE_W32_SYSTEM]: Don't set up alarm.
(set_timeout) [HAVE_W32_SYSTEM]: Likewise.
* ldap.c [HAVE_W32_SYSTEM]: Add macros for setenv and pth_yield.
* no-libgcrypt.h (NO_LIBGCRYPT): Define.
* util.h [NO_LIBGCRYPT]: Don't include <gcrypt.h>.
2007-07-23 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (dirmngr_SOURCES): Add exechelp.h and exechelp.c.
* exechelp.h, exechelp.c: New files.
* ldap.c: Don't include <sys/wait.h> but "exechelp.h".
(destroy_wrapper, ldap_wrapper_thread,
ldap_wrapper_connection_cleanup): Use dirmngr_kill_process instead
of kill.
(ldap_wrapper_thread): Use dirmngr_wait_process instead of
waitpid.
(ldap_wrapper): Use dirmngr_spawn_process.
2007-07-20 Marcus Brinkmann <marcus@g10code.de>
* certcache.c (cert_cache_lock): Do not initialize statically.
(init_cache_lock): New function.
(cert_cache_init): Call init_cache_lock.
* estream.h, estream.c, estream-printf.h, estream-printf.c: New
files.
* Makefile.am (dirmngr_SOURCES): Add estream.c, estream.h,
estream-printf.c, estream-printf.h.
* http.c: Update to latest version from GnuPG.
* Makefile.am (cdb_sources)
* cdblib.c: Port to windows (backport from tinycdb 0.76).
* crlcache.c [HAVE_W32_SYSTEM]: Don't include sys/utsname.h.
[MKDIR_TAKES_ONE_ARG]: Define mkdir as a macro for such systems.
(update_dir, crl_cache_insert) [HAVE_W32_SYSTEM]: Don't get uname.
* server.c (start_command_handler) [HAVE_W32_SYSTEM]: Don't log
peer credentials.
* dirmngr.c [HAVE_W32_SYSTEM]: Do not include sys/socket.h or
sys/un.h, but ../jnlib/w32-afunix.h.
(sleep) [HAVE_W32_SYSTEM]: New macro.
(main) [HAVE_W32_SYSTEM]: Don't mess with SIGPIPE. Use W32 socket
API.
(handle_signal) [HAVE_W32_SYSTEM]: Deactivate the bunch of the
code.
(handle_connections) [HAVE_W32_SYSTEM]: don't handle signals.
2006-11-29 Werner Koch <wk@g10code.com>
* dirmngr.c (my_strusage): Use macro for the bug report address
and the copyright line.
* dirmngr-client.c (my_strusage): Ditto.
* dirmngr_ldap.c (my_strusage): Ditto.
* Makefile.am: Do not link against LIBICONV.
2006-11-19 Werner Koch <wk@g10code.com>
* dirmngr.c: Include i18n.h.
2006-11-17 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_LDADD): Use LIBASSUAN_PTH_LIBS.
2006-11-16 Werner Koch <wk@g10code.com>
* server.c (start_command_handler): Replaced
assuan_init_connected_socket_server by assuan_init_socket_server_ext.
* crlcache.c (update_dir): Put a diagnostic into DIR.txt.
(open_dir): Detect invalid and duplicate entries.
(update_dir): Fixed search for second field.
2006-10-23 Werner Koch <wk@g10code.com>
* dirmngr.c (main): New command --gpgconf-test.
2006-09-14 Werner Koch <wk@g10code.com>
* server.c (start_command_handler): In vebose mode print
information about the peer. This may later be used to restrict
certain commands.
2006-09-12 Werner Koch <wk@g10code.com>
* server.c (start_command_handler): Print a more informative hello
line.
* dirmngr.c: Moved config_filename into the opt struct.
2006-09-11 Werner Koch <wk@g10code.com>
Changed everything to use Assuan with gpg-error codes.
* maperror.c: Removed.
* server.c (map_to_assuan_status): Removed.
* dirmngr.c (main): Set assuan error source.
* dirmngr-client.c (main): Ditto.
2006-09-04 Werner Koch <wk@g10code.com>
* crlfetch.c (crl_fetch): Implement HTTP redirection.
* ocsp.c (do_ocsp_request): Ditto.
New HTTP code version taken from gnupg svn release 4236.
* http.c (http_get_header): New.
(capitalize_header_name, store_header): New.
(parse_response): Store headers away.
(send_request): Return GPG_ERR_NOT_FOUND if connect_server failed.
* http.h: New flag HTTP_FLAG_NEED_HEADER.
2006-09-01 Werner Koch <wk@g10code.com>
* crlfetch.c (register_file_reader, get_file_reader): New.
(crl_fetch): Register the file pointer for HTTP.
(crl_close_reader): And release it.
* http.c, http.h: Updated from GnuPG SVN trunk. Changed all users
to adopt the new API.
* dirmngr.h: Moved inclusion of jnlib header to ...
* util.h: .. here. This is required becuase http.c includes only
a file util.h but makes use of log_foo. Include gcrypt.h so that
gcry_malloc et al are declared.
2006-08-31 Werner Koch <wk@g10code.com>
* ocsp.c (check_signature): Make use of the responder id.
2006-08-30 Werner Koch <wk@g10code.com>
* validate.c (check_cert_sig): Workaround for rimemd160.
(allowed_ca): Always allow trusted CAs.
* dirmngr.h (cert_ref_t): New.
(struct server_control_s): Add field OCSP_CERTS.
* server.c (start_command_handler): Release new field
* ocsp.c (release_ctrl_ocsp_certs): New.
(check_signature): Store certificates in OCSP_CERTS.
* certcache.c (find_issuing_cert): Reset error if cert was found
by subject.
(put_cert): Add new arg FPR_BUFFER. Changed callers.
(cache_cert_silent): New.
* dirmngr.c (parse_rereadable_options): New options
--ocsp-max-clock-skew and --ocsp-current-period.
* ocsp.c (ocsp_isvalid): Use them here.
* ocsp.c (validate_responder_cert): New optional arg signer_cert.
(check_signature_core): Ditto.
(check_signature): Use the default signer certificate here.
2006-06-27 Werner Koch <wk@g10code.com>
* dirmngr-client.c (inq_cert): Take care of SENDCERT_SKI.
2006-06-26 Werner Koch <wk@g10code.com>
* crlcache.c (lock_db_file): Count open files when needed.
(find_entry): Fixed deleted case.
2006-06-23 Werner Koch <wk@g10code.com>
* misc.c (cert_log_name): New.
* certcache.c (load_certs_from_dir): Also print certificate name.
(find_cert_bysn): Release ISSDN.
* validate.h: New VALIDATE_MODE_CERT.
* server.c (cmd_validate): Use it here so that no policy checks
are done. Try to validated a cached copy of the target.
* validate.c (validate_cert_chain): Implement a validation cache.
(check_revocations): Print more diagnostics. Actually use the
loop variable and not the head of the list.
(validate_cert_chain): Do not check revocations of CRL issuer
certificates in plain CRL check mode.
* ocsp.c (ocsp_isvalid): Make sure it is reset for a status of
revoked.
2006-06-22 Werner Koch <wk@g10code.com>
* validate.c (cert_use_crl_p): New.
(cert_usage_p): Add a mode 6 for CRL signing.
(validate_cert_chain): Check that the certificate may be used for
CRL signing. Print a note when not running as system daemon.
(validate_cert_chain): Reduce the maximum depth from 50 to 10.
* certcache.c (find_cert_bysn): Minor restructuring
(find_cert_bysubject): Ditto. Use get_cert_local when called
without KEYID.
* crlcache.c (get_crlissuer_cert_bysn): Removed.
(get_crlissuer_cert): Removed.
(crl_parse_insert): Use find_cert_bysubject and find_cert_bysn
instead of the removed functions.
2006-06-19 Werner Koch <wk@g10code.com>
* certcache.c (compare_serialno): Silly me. Using 0 as true is
that hard; tsss. Fixed call cases except for the only working one
which are both numbers of the same length.
2006-05-15 Werner Koch <wk@g10code.com>
* crlfetch.c (crl_fetch): Use no-shutdown flag for HTTP. This
seems to be required for "IBM_HTTP_Server/2.0.47.1 Apache/2.0.47
(Unix)".
* http.c (parse_tuple): Set flag to to indicate no value.
(build_rel_path): Take care of it.
* crlcache.c (crl_cache_reload_crl): Also iterate over all names
within a DP.
2005-09-28 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (dirmngr_LDADD): Add @LIBINTL@ and @LIBICONV@.
(dirmngr_ldap_LDADD): Likewise.
(dirmngr_client_LDADD): Likewise.
2005-09-12 Werner Koch <wk@g10code.com>
* dirmngr.c: Fixed description to match the one in gpgconf.
2005-06-15 Werner Koch <wk@g10code.com>
* server.c (cmd_lookup): Take care of NO_DATA which might get
returned also by start_cert_fetch().
2005-04-20 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper_wait_connections): Set a shutdown flag.
(ldap_wrapper_thread): Handle shutdown in a special way.
2005-04-19 Werner Koch <wk@g10code.com>
* server.c (get_cert_local, get_issuing_cert_local)
(get_cert_local_ski): Bail out if called without a local context.
2005-04-18 Werner Koch <wk@g10code.com>
* certcache.c (find_issuing_cert): Fixed last resort method which
should be finding by subject and not by issuer. Try to locate it
also using the keyIdentifier method. Improve error reporting.
(cmp_simple_canon_sexp): New.
(find_cert_bysubject): New.
(find_cert_bysn): Ask back to the caller before trying an extarnl
lookup.
* server.c (get_cert_local_ski): New.
* crlcache.c (crl_parse_insert): Also try to locate issuer
certificate using the keyIdentifier. Improved error reporting.
2005-04-14 Werner Koch <wk@g10code.com>
* ldap.c (start_cert_fetch_ldap): Really return ERR.
2005-03-17 Werner Koch <wk@g10code.com>
* http.c (parse_response): Changed MAXLEN and LEN to size_t to
match the requirement of read_line.
* http.h (http_context_s): Ditto for BUFFER_SIZE.
2005-03-15 Werner Koch <wk@g10code.com>
* ldap.c: Included time.h. Reported by Bernhard Herzog.
2005-03-09 Werner Koch <wk@g10code.com>
* dirmngr.c: Add a note to the help listing check the man page for
other options.
2005-02-01 Werner Koch <wk@g10code.com>
* crlcache.c (crl_parse_insert): Renamed a few variables and
changed diagnostic strings for clarity.
(get_issuer_cert): Renamed to get_crlissuer_cert. Try to locate
the certificate from the cache using the subject name. Use new
fetch function.
(get_crlissuer_cert_bysn): New.
(crl_parse_insert): Use it here.
* crlfetch.c (ca_cert_fetch): Changed interface.
(fetch_next_ksba_cert): New.
* ldap.c (run_ldap_wrapper): Add arg MULTI_MODE. Changed all
callers.
(start_default_fetch_ldap): New
* certcache.c (get_cert_bysubject): New.
(clean_cache_slot, put_cert): Store the subject DN if available.
(MAX_EXTRA_CACHED_CERTS): Increase limit of cachable certificates
to 1000.
(find_cert_bysn): Loop until a certificate with a matching S/N has
been found.
* dirmngr.c (main): Add honor-http-proxy to the gpgconf list.
2005-01-31 Werner Koch <wk@g10code.com>
* ldap.c: Started to work on support for userSMIMECertificates.
* dirmngr.c (main): Make sure to always pass a server control
structure to the caching functions. Reported by Neil Dunbar.
2005-01-05 Werner Koch <wk@g10code.com>
* dirmngr-client.c (read_pem_certificate): Skip trailing percent
escaped linefeeds.
2005-01-03 Werner Koch <wk@g10code.com>
* dirmngr-client.c (read_pem_certificate): New.
(read_certificate): Divert to it depending on pem option.
(squid_loop_body): New.
(main): New options --pem and --squid-mode.
2004-12-17 Werner Koch <wk@g10code.com>
* dirmngr.c (launch_ripper_thread): Renamed to launch_reaper_thread.
(shutdown_reaper): New. Use it for --server and --daemon.
* ldap.c (ldap_wrapper_wait_connections): New.
2004-12-17 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_ldap_LDADD): Adjusted for new LDAP checks.
2004-12-16 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper): Peek on the output to detect empty output
early.
2004-12-15 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper): Print a diagnostic after forking for the
ldap wrapper.
* certcache.h (find_cert_bysn): Add this prototype.
* crlcache.c (start_sig_check): Write CRL hash debug file.
(finish_sig_check): Dump the signer's certificate.
(crl_parse_insert): Try to get the issuing cert by authKeyId.
Moved certificate retrieval after item processing.
2004-12-13 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (catch_alarm, set_timeout): new.
(main): Install alarm handler. Add new option --only-search-timeout.
(print_ldap_entries, fetch_ldap): Use set_timeout ();
* dirmngr.h: Make LDAPTIMEOUT a simple unsigned int. Change all
initializations.
* ldap.c (start_cert_fetch_ldap, run_ldap_wrapper): Pass timeout
option to the wrapper.
(INACTIVITY_TIMEOUT): Depend on LDAPTIMEOUT.
(run_ldap_wrapper): Add arg IGNORE_TIMEOUT.
(ldap_wrapper_thread): Check for special timeout exit code.
* dirmngr.c: Workaround a typo in gpgconf for
ignore-ocsp-service-url.
2004-12-10 Werner Koch <wk@g10code.com>
* ldap.c (url_fetch_ldap): Use TMP and not a HOST which is always
NULL.
* misc.c (host_and_port_from_url): Fixed bad encoding detection.
2004-12-03 Werner Koch <wk@g10code.com>
* crlcache.c (crl_cache_load): Re-implement it.
* dirmngr-client.c: New command --load-crl
(do_loadcrl): New.
* dirmngr.c (parse_rereadable_options, main): Make --allow-ocsp,
--ocsp-responder, --ocsp-signer and --max-replies re-readable.
* ocsp.c (check_signature): try to get the cert from the cache
first.
(ocsp_isvalid): Print the next and this update times on time
conflict.
* certcache.c (load_certs_from_dir): Print the fingerprint for
trusted certificates.
(get_cert_byhexfpr): New.
* misc.c (get_fingerprint_hexstring_colon): New.
2004-12-01 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_LDADD): Don't use LDAP_LIBS.
* validate.c (validate_cert_chain): Fixed test; as written in the
comment we want to do this only in daemon mode. For clarity
reworked by using a linked list of certificates and include root
and tragte certificate.
(check_revocations): Likewise. Introduced a recursion sentinel.
2004-11-30 Werner Koch <wk@g10code.com>
* crlfetch.c (ca_cert_fetch, crl_fetch_default): Do not use the
binary prefix as this will be handled in the driver.
* dirmngr_ldap.c: New option --log-with-pid.
(fetch_ldap): Handle LDAP_NO_SUCH_OBJECT.
* ldap.c (run_ldap_wrapper, start_cert_fetch_ldap): Use new log
option.
2004-11-25 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_ldap_CFLAGS): Added GPG_ERROR_CFLAGS.
Noted by Bernhard Herzog.
2004-11-24 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper): Fixed default name of the ldap wrapper.
* b64enc.c (b64enc_start, b64enc_finish): Use standard strdup/free
to manage memory.
* dirmngr.c: New options --ignore-http-dp, --ignore-ldap-dp and
--ignore-ocsp-service-url.
* crlcache.c (crl_cache_reload_crl): Implement them.
* ocsp.c (ocsp_isvalid): Ditto.
2004-11-23 Werner Koch <wk@g10code.com>
* ldap.c (ldap_wrapper_thread, reader_callback, ldap_wrapper):
Keep a timestamp and terminate the wrapper after some time of
inactivity.
* dirmngr-client.c (do_lookup): New.
(main): New option --lookup.
(data_cb): New.
* b64enc.c: New. Taken from GnuPG 1.9.
* no-libgcrypt.c (gcry_strdup): Added.
* ocsp.c (ocsp_isvalid): New arg CERT and lookup the issuer
certificate using the standard methods.
* server.c (cmd_lookup): Truncation is now also an indication for
error.
(cmd_checkocsp): Implemented.
* dirmngr_ldap.c (fetch_ldap): Write an error marker for a
truncated search.
* ldap.c (add_server_to_servers): Reactivated.
(url_fetch_ldap): Call it here and try all configured servers in
case of a a failed lookup.
(fetch_next_cert_ldap): Detect the truncation error flag.
* misc.c (host_and_port_from_url, remove_percent_escapes): New.
2004-11-22 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (main): New option --proxy.
* ocsp.c (do_ocsp_request): Take care of opt.disable_http.
* crlfetch.c (crl_fetch): Honor the --honor-http-proxy variable.
(crl_fetch): Take care of opt.disable_http and disable_ldap.
(crl_fetch_default, ca_cert_fetch, start_cert_fetch):
* ldap.c (run_ldap_wrapper): New arg PROXY.
(url_fetch_ldap, attr_fetch_ldap, start_cert_fetch_ldap): Pass it.
* http.c (http_open_document): Add arg PROXY.
(http_open): Ditto.
(send_request): Ditto and implement it as an override.
* ocsp.c (validate_responder_cert): Use validate_cert_chain.
* Makefile.am (AM_CPPFLAGS): Add macros for a few system
directories.
* dirmngr.h (opt): New members homedir_data, homedir_cache,
ldap_wrapper_program, system_daemon, honor_http_proxy, http_proxy,
ldap_proxy, only_ldap_proxy, disable_ldap, disable_http.
* dirmngr.c (main): Initialize new opt members HOMEDIR_DATA and
HOMEDIR_CACHE.
(parse_rereadable_options): New options --ldap-wrapper-program,
--http-wrapper-program, --disable-ldap, --disable-http,
--honor-http-proxy, --http-proxy, --ldap-proxy, --only-ldap-proxy.
(reread_configuration): New.
* ldap.c (ldap_wrapper): Use the correct name for the wrapper.
* crlcache.c (DBDIR_D): Make it depend on opt.SYSTEM_DAEMON.
(cleanup_cache_dir, open_dir, update_dir, make_db_file_name)
(crl_cache_insert, create_directory_if_needed): Use opt.HOMEDIR_CACHE
* validate.c (check_revocations): New.
* crlcache.c (crl_cache_isvalid): Factored most code out to
(cache_isvalid): .. new.
(crl_cache_cert_isvalid): New.
* server.c (cmd_checkcrl): Cleaned up by using this new function.
(reload_crl): Moved to ..
* crlcache.c (crl_cache_reload_crl): .. here and made global.
* certcache.c (cert_compute_fpr): Renamed from computer_fpr and
made global.
(find_cert_bysn): Try to lookup missing certs.
(cert_cache_init): Intialize using opt.HOMEDIR_DATA.
2004-11-19 Werner Koch <wk@g10code.com>
* dirmngr-client.c (status_cb): New. Use it in very verbose mode.
* server.c (start_command_handler): Malloc the control structure
and properly release it. Removed the primary_connection
hack. Cleanup running wrappers.
(dirmngr_status): Return an error code.
(dirmngr_tick): Return an error code and detect a
cancellation. Use wall time and not CPU time.
* validate.c (validate_cert_chain): Add CTRL arg and changed callers.
* crlcache.c (crl_cache_isvalid):
* crlfetch.c (ca_cert_fetch, start_cert_fetch, crl_fetch_default)
(crl_fetch): Ditto.
* ldap.c (ldap_wrapper, run_ldap_wrapper, url_fetch_ldap)
(attr_fetch_ldap, start_cert_fetch_ldap): Ditto.
(ldap_wrapper_release_context): Reset the stored CTRL.
(reader_callback): Periodically call dirmngr_tick.
(ldap_wrapper_release_context): Print an error message for read
errors.
(ldap_wrapper_connection_cleanup): New.
2004-11-18 Werner Koch <wk@g10code.com>
* dirmngr.c (main): Do not cd / if not running detached.
* dirmngr-client.c: New options --cache-cert and --validate.
(do_cache, do_validate): New.
* server.c (cmd_cachecert, cmd_validate): New.
* crlcache.c (get_issuer_cert): Make use of the certificate cache.
(crl_parse_insert): Validate the issuer certificate.
* dirmngr.c (handle_signal): Reinitialize the certificate cache on
a HUP.
(struct opts): Add --homedir to enable the already implemented code.
(handle_signal): Print stats on SIGUSR1.
* certcache.c (clean_cache_slot, cert_cache_init)
(cert_cache_deinit): New.
(acquire_cache_read_lock, acquire_cache_write_lock)
(release_cache_lock): New. Use them where needed.
(put_cert): Renamed from put_loaded_cert.
(cache_cert): New.
(cert_cache_print_stats): New.
(compare_serialno): Fixed.
2004-11-16 Werner Koch <wk@g10code.com>
* Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SYSCONFDIR and
DIRMNGR_LIBEXECDIR.
* misc.c (dump_isotime, dump_string, dump_cert): New. Taken from
gnupg 1.9.
(dump_serial): New.
2004-11-15 Werner Koch <wk@g10code.com>
* validate.c: New. Based on gnupg's certchain.c
* ldap.c (get_cert_ldap): Removed.
(read_buffer): New.
(start_cert_fetch_ldap, fetch_next_cert_ldap)
(end_cert_fetch_ldap): Rewritten to make use of the ldap wrapper.
2004-11-12 Werner Koch <wk@g10code.com>
* http.c (insert_escapes): Print the percent sign too.
* dirmngr-client.c (inq_cert): Ignore "SENDCERT" and
"SENDISSUERCERT".
* server.c (do_get_cert_local): Limit the length of a retruned
certificate. Return NULL without an error if an empry value has
been received.
* crlfetch.c (ca_cert_fetch): Use the ksba_reader_object.
(setup_funopen, fun_reader, fun_closer): Removed.
* crlcache.c (get_issuer_cert): Adjust accordingly.
* ldap.c (attr_fetch_ldap_internal, attr_fetch_fun_closer)
(attr_fetch_fun_reader, url_fetch_ldap_internal)
(get_attr_from_result_ldap): Removed.
(destroy_wrapper, print_log_line, ldap_wrapper_thread)
(ldap_wrapper_release_context, reader_callback, ldap_wrapper)
(run_ldap_wrapper): New.
(url_fetch_ldap): Make use of the new ldap wrapper and return a
ksba reader object instead of a stdio stream.
(attr_fetch_ldap): Ditto.
(make_url, escape4url): New.
2004-11-11 Werner Koch <wk@g10code.com>
* dirmngr.c (launch_ripper_thread): New.
(main): Start it wheere appropriate. Always ignore SIGPIPE.
(start_connection_thread): Maintain a connection count.
(handle_signal, handle_connections): Use it here instead of the
thread count.
* crlcache.c (crl_cache_insert): Changed to use ksba reader
object. Changed all callers to pass this argument.
2004-11-08 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c: New.
* crlcache.c (crl_cache_init): Don't return a cache object but
keep it module local. We only need one.
(crl_cache_deinit): Don't take cache object but work on existing
one.
(get_current_cache): New.
(crl_cache_insert, crl_cache_list, crl_cache_load): Use the global
cache object and removed the cache arg. Changed all callers.
* dirmngr-client.c: New option --ping.
* dirmngr.c (main): New option --daemon. Initialize PTH.
(handle_connections, start_connection_thread): New.
(handle_signal): New.
(parse_rereadable_options): New. Changed main to make use of it.
(set_debug): Don't bail out on invalid debug levels.
(main): Init the crl_chache for server and daemon mode.
* server.c (start_command_handler): New arg FD. Changed callers.
2004-11-06 Werner Koch <wk@g10code.com>
* server.c (map_assuan_err): Factored out to ..
* maperror.c: .. new file.
* util.h: Add prototype
2004-11-05 Werner Koch <wk@g10code.com>
* no-libgcrypt.c: New, used as helper for dirmngr-client which
does not need libgcrypt proper but jnlib references the memory
functions. Taken from gnupg 1.9.12.
* dirmngr.h: Factored i18n and xmalloc code out to ..
* i18n.h, util.h: .. New.
* dirmngr-client.c: New. Some code taken from gnupg 1.9.12.
* Makefile.am (bin_PROGRAMS) Add dirmngr-client.
2004-11-04 Werner Koch <wk@g10code.com>
* src/server.c (get_fingerprint_from_line, cmd_checkcrl)
(cmd_checkocsp): New.
(register_commands): Register new commands.
(inquire_cert_and_load_crl): Factored most code out to ..
(reload_crl): .. new function.
* src/certcache.h, src/certcache.c: New.
* src/Makefile.am (dirmngr_SOURCES): Add new files.
2004-11-04 Werner Koch <wk@g10code.com>
Please note that earlier entries are found in the top level
ChangeLog.
[Update after merge with GnuPG: see ./ChangeLog.1]
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index ae922fa31..678cf3df2 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -1,1853 +1,1922 @@
/* dirmngr.c - LDAP access
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
- * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010 g10 Code GmbH
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010, 2011 g10 Code GmbH
*
* This file is part of DirMngr.
*
* DirMngr is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DirMngr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <time.h>
#include <fcntl.h>
#ifndef HAVE_W32_SYSTEM
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#include <pth.h>
#define JNLIB_NEED_LOG_LOGV
#define JNLIB_NEED_AFLOCAL
#include "dirmngr.h"
-#include <assuan.h>
+#include <assuan.h>
#include "certcache.h"
#include "crlcache.h"
#include "crlfetch.h"
#include "misc.h"
#include "ldapserver.h"
#include "asshelp.h"
#include "ldap-wrapper.h"
/* The plain Windows version uses the windows service system. For
example to start the service you may use "sc start dirmngr".
WindowsCE does not support this; the service system over there is
based on a single process with all services being DLLs - we can't
support this easily. */
#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
# define USE_W32_SERVICE 1
#endif
enum cmd_and_opt_values {
aNull = 0,
oCsh = 'c',
oQuiet = 'q',
oSh = 's',
oVerbose = 'v',
oNoVerbose = 500,
-
+
aServer,
aDaemon,
aService,
aListCRLs,
aLoadCRL,
aFetchCRL,
aShutdown,
aFlush,
aGPGConfList,
aGPGConfTest,
oOptions,
oDebug,
oDebugAll,
oDebugWait,
oDebugLevel,
oNoGreeting,
oNoOptions,
oHomedir,
oNoDetach,
oLogFile,
oBatch,
oDisableHTTP,
oDisableLDAP,
oIgnoreLDAPDP,
oIgnoreHTTPDP,
oIgnoreOCSPSvcUrl,
oHonorHTTPProxy,
oHTTPProxy,
oLDAPProxy,
oOnlyLDAPProxy,
oLDAPFile,
oLDAPTimeout,
oLDAPAddServers,
oOCSPResponder,
oOCSPSigner,
oOCSPMaxClockSkew,
oOCSPMaxPeriod,
oOCSPCurrentPeriod,
oMaxReplies,
oFakedSystemTime,
oForce,
oAllowOCSP,
oSocketName,
oLDAPWrapperProgram,
oHTTPWrapperProgram,
oIgnoreCertExtension,
aTest
};
static ARGPARSE_OPTS opts[] = {
-
+
ARGPARSE_group (300, N_("@Commands:\n ")),
ARGPARSE_c (aServer, "server", N_("run in server mode (foreground)") ),
ARGPARSE_c (aDaemon, "daemon", N_("run in daemon mode (background)") ),
#ifdef USE_W32_SERVICE
ARGPARSE_c (aService, "service", N_("run as windows service (background)")),
#endif
ARGPARSE_c (aListCRLs, "list-crls", N_("list the contents of the CRL cache")),
ARGPARSE_c (aLoadCRL, "load-crl", N_("|FILE|load CRL from FILE into cache")),
ARGPARSE_c (aFetchCRL, "fetch-crl", N_("|URL|fetch a CRL from URL")),
ARGPARSE_c (aShutdown, "shutdown", N_("shutdown the dirmngr")),
ARGPARSE_c (aFlush, "flush", N_("flush the cache")),
ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
ARGPARSE_group (301, N_("@\nOptions:\n ")),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
ARGPARSE_s_n (oSh, "sh", N_("sh-style command output")),
ARGPARSE_s_n (oCsh, "csh", N_("csh-style command output")),
ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
ARGPARSE_s_s (oDebugLevel, "debug-level",
N_("|LEVEL|set the debugging level to LEVEL")),
ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
ARGPARSE_s_s (oLogFile, "log-file",
N_("|FILE|write server mode logs to FILE")),
ARGPARSE_s_n (oBatch, "batch", N_("run without asking a user")),
ARGPARSE_s_n (oForce, "force", N_("force loading of outdated CRLs")),
ARGPARSE_s_n (oAllowOCSP, "allow-ocsp", N_("allow sending OCSP requests")),
ARGPARSE_s_n (oDisableHTTP, "disable-http", N_("inhibit the use of HTTP")),
ARGPARSE_s_n (oDisableLDAP, "disable-ldap", N_("inhibit the use of LDAP")),
ARGPARSE_s_n (oIgnoreHTTPDP,"ignore-http-dp",
N_("ignore HTTP CRL distribution points")),
ARGPARSE_s_n (oIgnoreLDAPDP,"ignore-ldap-dp",
N_("ignore LDAP CRL distribution points")),
ARGPARSE_s_n (oIgnoreOCSPSvcUrl, "ignore-ocsp-service-url",
N_("ignore certificate contained OCSP service URLs")),
ARGPARSE_s_s (oHTTPProxy, "http-proxy",
N_("|URL|redirect all HTTP requests to URL")),
ARGPARSE_s_s (oLDAPProxy, "ldap-proxy",
N_("|HOST|use HOST for LDAP queries")),
ARGPARSE_s_n (oOnlyLDAPProxy, "only-ldap-proxy",
N_("do not use fallback hosts with --ldap-proxy")),
ARGPARSE_s_s (oLDAPFile, "ldapserverlist-file",
N_("|FILE|read LDAP server list from FILE")),
ARGPARSE_s_n (oLDAPAddServers, "add-servers",
N_("add new servers discovered in CRL distribution"
" points to serverlist")),
ARGPARSE_s_i (oLDAPTimeout, "ldaptimeout",
N_("|N|set LDAP timeout to N seconds")),
ARGPARSE_s_s (oOCSPResponder, "ocsp-responder",
N_("|URL|use OCSP responder at URL")),
- ARGPARSE_s_s (oOCSPSigner, "ocsp-signer",
- N_("|FPR|OCSP response signed by FPR")),
+ ARGPARSE_s_s (oOCSPSigner, "ocsp-signer",
+ N_("|FPR|OCSP response signed by FPR")),
ARGPARSE_s_i (oOCSPMaxClockSkew, "ocsp-max-clock-skew", "@"),
ARGPARSE_s_i (oOCSPMaxPeriod, "ocsp-max-period", "@"),
ARGPARSE_s_i (oOCSPCurrentPeriod, "ocsp-current-period", "@"),
- ARGPARSE_s_i (oMaxReplies, "max-replies",
+ ARGPARSE_s_i (oMaxReplies, "max-replies",
N_("|N|do not return more than N items in one query")),
ARGPARSE_s_s (oSocketName, "socket-name", "@"), /* Only for debugging. */
ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/
ARGPARSE_p_u (oDebug, "debug", "@"),
ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
- ARGPARSE_s_s (oHomedir, "homedir", "@"),
+ ARGPARSE_s_s (oHomedir, "homedir", "@"),
ARGPARSE_s_s (oLDAPWrapperProgram, "ldap-wrapper-program", "@"),
ARGPARSE_s_s (oHTTPWrapperProgram, "http-wrapper-program", "@"),
ARGPARSE_s_n (oHonorHTTPProxy, "honor-http-proxy", "@"),
ARGPARSE_s_s (oIgnoreCertExtension,"ignore-cert-extension", "@"),
ARGPARSE_group (302,N_("@\n(See the \"info\" manual for a complete listing "
"of all commands and options)\n")),
ARGPARSE_end ()
};
#define DEFAULT_MAX_REPLIES 10
#define DEFAULT_LDAP_TIMEOUT 100 /* arbitrary large timeout */
/* For the cleanup handler we need to keep track of the socket's name. */
static const char *socket_name;
/* We need to keep track of the server's nonces (these are dummies for
POSIX systems). */
static assuan_sock_nonce_t socket_nonce;
/* Only if this flag has been set we will remove the socket file. */
static int cleanup_socket;
/* Keep track of the current log file so that we can avoid updating
the log file after a SIGHUP if it didn't changed. Malloced. */
static char *current_logfile;
/* Helper to implement --debug-level. */
static const char *debug_level;
/* Flag indicating that a shutdown has been requested. */
static volatile int shutdown_pending;
/* Counter for the active connections. */
static int active_connections;
/* The timer tick used for housekeeping stuff. For Windows we use a
longer period as the SetWaitableTimer seems to signal earlier than
the 2 seconds. CHECK_OWN_SOCKET_INTERVAL defines how often we
check our own socket in standard socket mode. If that value is 0
we don't check at all. All values are in seconds. */
#if defined(HAVE_W32CE_SYSTEM)
# define TIMERTICK_INTERVAL (60)
#elif defined(HAVE_W32_SYSTEM)
# define TIMERTICK_INTERVAL (4)
#else
# define TIMERTICK_INTERVAL (2)
#endif
/* This union is used to avoid compiler warnings in case a pointer is
64 bit and an int 32 bit. We store an integer in a pointer and get
it back later (pth_key_getdata et al.). */
union int_and_ptr_u
{
int aint;
assuan_fd_t afd;
void *aptr;
};
/* The key used to store the current file descriptor in the thread
local storage. We use this in conjunction with the
log_set_pid_suffix_cb feature.. */
#ifndef HAVE_W32_SYSTEM
static int my_tlskey_current_fd;
#endif
/* Prototypes. */
static void cleanup (void);
static ldap_server_t parse_ldapserver_file (const char* filename);
static fingerprint_list_t parse_ocsp_signer (const char *string);
static void handle_connections (assuan_fd_t listen_fd);
/* Pth wrapper function definitions. */
ASSUAN_SYSTEM_PTH_IMPL;
GCRY_THREAD_OPTION_PTH_IMPL;
static int fixed_gcry_pth_init (void)
{
return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0;
}
+#ifndef PTH_HAVE_PTH_THREAD_ID
+static unsigned long pth_thread_id (void)
+{
+ return (unsigned long)pth_self ();
+}
+#endif
+
static const char *
my_strusage( int level )
{
const char *p;
- switch ( level )
+ switch ( level )
{
case 11: p = "dirmngr (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
/* TRANSLATORS: @EMAIL@ will get replaced by the actual bug
reporting address. This is so that we can change the
reporting address without breaking the translations. */
case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
case 49: p = PACKAGE_BUGREPORT; break;
case 1:
case 40: p = _("Usage: dirmngr [options] (-h for help)");
break;
case 41: p = _("Syntax: dirmngr [options] [command [args]]\n"
"LDAP and OCSP access for GnuPG\n");
break;
-
+
default: p = NULL;
}
return p;
}
/* Callback from libksba to hash a provided buffer. Our current
implementation does only allow SHA-1 for hashing. This may be
extended by mapping the name, testing for algorithm availibility
and adjust the length checks accordingly. */
-static gpg_error_t
+static gpg_error_t
my_ksba_hash_buffer (void *arg, const char *oid,
const void *buffer, size_t length, size_t resultsize,
unsigned char *result, size_t *resultlen)
{
(void)arg;
- if (oid && strcmp (oid, "1.3.14.3.2.26"))
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
+ if (oid && strcmp (oid, "1.3.14.3.2.26"))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
if (resultsize < 20)
return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
- gcry_md_hash_buffer (2, result, buffer, length);
+ gcry_md_hash_buffer (2, result, buffer, length);
*resultlen = 20;
return 0;
}
/* Setup the debugging. With a LEVEL of NULL only the active debug
flags are propagated to the subsystems. With LEVEL set, a specific
set of debug flags is set; thus overriding all flags already
set. */
static void
set_debug (void)
{
int numok = (debug_level && digitp (debug_level));
int numlvl = numok? atoi (debug_level) : 0;
if (!debug_level)
;
else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
opt.debug = 0;
else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
opt.debug = DBG_ASSUAN_VALUE;
else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE|DBG_LOOKUP_VALUE);
else if (!strcmp (debug_level, "expert") || (numok && numlvl <= 8))
opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE|DBG_LOOKUP_VALUE
|DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
else if (!strcmp (debug_level, "guru") || numok)
{
opt.debug = ~0;
/* Unless the "guru" string has been used we don't want to allow
hashing debugging. The rationale is that people tend to
select the highest debug value and would then clutter their
- disk with debug files which may reveal confidential data. */
+ disk with debug files which may reveal confidential data. */
if (numok)
opt.debug &= ~(DBG_HASHING_VALUE);
}
else
{
log_error (_("invalid debug-level `%s' given\n"), debug_level);
log_info (_("valid debug levels are: %s\n"),
"none, basic, advanced, expert, guru");
opt.debug = 0; /* Reset debugging, so that prior debug
statements won't have an undesired effect. */
}
if (opt.debug && !opt.verbose)
{
opt.verbose = 1;
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
}
if (opt.debug && opt.quiet)
opt.quiet = 0;
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
}
-
+
static void
wrong_args (const char *text)
{
es_fputs (_("usage: dirmngr [options] "), es_stderr);
es_fputs (text, es_stderr);
es_putc ('\n', es_stderr);
dirmngr_exit (2);
}
/* Helper to stop the reaper thread for the ldap wrapper. */
static void
shutdown_reaper (void)
{
ldap_wrapper_wait_connections ();
}
/* Handle options which are allowed to be reset after program start.
Return true if the current option in PARGS could be handled and
false if not. As a special feature, passing a value of NULL for
PARGS, resets the options to the default. REREAD should be set
true if it is not the initial option parsing. */
static int
parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
{
if (!pargs)
{ /* Reset mode. */
opt.quiet = 0;
opt.verbose = 0;
opt.debug = 0;
opt.ldap_wrapper_program = NULL;
opt.disable_http = 0;
- opt.disable_ldap = 0;
- opt.honor_http_proxy = 0;
- opt.http_proxy = NULL;
- opt.ldap_proxy = NULL;
+ opt.disable_ldap = 0;
+ opt.honor_http_proxy = 0;
+ opt.http_proxy = NULL;
+ opt.ldap_proxy = NULL;
opt.only_ldap_proxy = 0;
opt.ignore_http_dp = 0;
opt.ignore_ldap_dp = 0;
opt.ignore_ocsp_service_url = 0;
opt.allow_ocsp = 0;
opt.ocsp_responder = NULL;
opt.ocsp_max_clock_skew = 10 * 60; /* 10 minutes. */
opt.ocsp_max_period = 90 * 86400; /* 90 days. */
opt.ocsp_current_period = 3 * 60 * 60; /* 3 hours. */
opt.max_replies = DEFAULT_MAX_REPLIES;
while (opt.ocsp_signer)
{
fingerprint_list_t tmp = opt.ocsp_signer->next;
xfree (opt.ocsp_signer);
opt.ocsp_signer = tmp;
}
FREE_STRLIST (opt.ignored_cert_extensions);
return 1;
}
switch (pargs->r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oDebug: opt.debug |= pargs->r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oDebugLevel: debug_level = pargs->r.ret_str; break;
case oLogFile:
if (!reread)
return 0; /* Not handled. */
if (!current_logfile || !pargs->r.ret_str
|| strcmp (current_logfile, pargs->r.ret_str))
{
log_set_file (pargs->r.ret_str);
xfree (current_logfile);
current_logfile = xtrystrdup (pargs->r.ret_str);
}
break;
case oLDAPWrapperProgram:
opt.ldap_wrapper_program = pargs->r.ret_str;
break;
case oHTTPWrapperProgram:
opt.http_wrapper_program = pargs->r.ret_str;
break;
case oDisableHTTP: opt.disable_http = 1; break;
case oDisableLDAP: opt.disable_ldap = 1; break;
case oHonorHTTPProxy: opt.honor_http_proxy = 1; break;
case oHTTPProxy: opt.http_proxy = pargs->r.ret_str; break;
case oLDAPProxy: opt.ldap_proxy = pargs->r.ret_str; break;
case oOnlyLDAPProxy: opt.only_ldap_proxy = 1; break;
case oIgnoreHTTPDP: opt.ignore_http_dp = 1; break;
case oIgnoreLDAPDP: opt.ignore_ldap_dp = 1; break;
case oIgnoreOCSPSvcUrl: opt.ignore_ocsp_service_url = 1; break;
case oAllowOCSP: opt.allow_ocsp = 1; break;
case oOCSPResponder: opt.ocsp_responder = pargs->r.ret_str; break;
- case oOCSPSigner:
+ case oOCSPSigner:
opt.ocsp_signer = parse_ocsp_signer (pargs->r.ret_str);
break;
case oOCSPMaxClockSkew: opt.ocsp_max_clock_skew = pargs->r.ret_int; break;
case oOCSPMaxPeriod: opt.ocsp_max_period = pargs->r.ret_int; break;
case oOCSPCurrentPeriod: opt.ocsp_current_period = pargs->r.ret_int; break;
case oMaxReplies: opt.max_replies = pargs->r.ret_int; break;
case oIgnoreCertExtension:
add_to_strlist (&opt.ignored_cert_extensions, pargs->r.ret_str);
break;
default:
return 0; /* Not handled. */
}
return 1; /* Handled. */
}
#ifdef USE_W32_SERVICE
/* The global status of our service. */
SERVICE_STATUS_HANDLE service_handle;
SERVICE_STATUS service_status;
DWORD WINAPI
w32_service_control (DWORD control, DWORD event_type, LPVOID event_data,
LPVOID context)
{
/* event_type and event_data are not used here. */
switch (control)
{
case SERVICE_CONTROL_SHUTDOWN:
/* For shutdown we will try to force termination. */
service_status.dwCurrentState = SERVICE_STOP_PENDING;
- SetServiceStatus (service_handle, &service_status);
+ SetServiceStatus (service_handle, &service_status);
shutdown_pending = 3;
break;
case SERVICE_CONTROL_STOP:
service_status.dwCurrentState = SERVICE_STOP_PENDING;
- SetServiceStatus (service_handle, &service_status);
+ SetServiceStatus (service_handle, &service_status);
shutdown_pending = 1;
break;
default:
break;
}
return 0;
}
#endif /*USE_W32_SERVICE*/
#ifndef HAVE_W32_SYSTEM
static int
pid_suffix_callback (unsigned long *r_suffix)
{
union int_and_ptr_u value;
value.aptr = pth_key_getdata (my_tlskey_current_fd);
*r_suffix = value.aint;
return (*r_suffix != -1); /* Use decimal representation. */
}
#endif /*!HAVE_W32_SYSTEM*/
#ifdef USE_W32_SERVICE
# define main real_main
#endif
int
main (int argc, char **argv)
{
#ifdef USE_W32_SERVICE
# undef main
#endif
enum cmd_and_opt_values cmd = 0;
ARGPARSE_ARGS pargs;
int orig_argc;
char **orig_argv;
FILE *configfp = NULL;
char *configname = NULL;
const char *shell;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int greeting = 0;
int nogreeting = 0;
int nodetach = 0;
int csh_style = 0;
char *logfile = NULL;
char *ldapfile = NULL;
int debug_wait = 0;
int rc;
int homedir_seen = 0;
struct assuan_malloc_hooks malloc_hooks;
#ifdef USE_W32_SERVICE
/* The option will be set by main() below if we should run as a
system daemon. */
if (opt.system_service)
{
service_handle
= RegisterServiceCtrlHandlerEx ("DirMngr",
&w32_service_control, NULL /*FIXME*/);
if (service_handle == 0)
log_error ("failed to register service control handler: ec=%d",
(int) GetLastError ());
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
service_status.dwCurrentState = SERVICE_START_PENDING;
service_status.dwControlsAccepted
= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
service_status.dwWin32ExitCode = NO_ERROR;
service_status.dwServiceSpecificExitCode = NO_ERROR;
service_status.dwCheckPoint = 0;
service_status.dwWaitHint = 10000; /* 10 seconds timeout. */
- SetServiceStatus (service_handle, &service_status);
+ SetServiceStatus (service_handle, &service_status);
}
#endif /*USE_W32_SERVICE*/
set_strusage (my_strusage);
- log_set_prefix ("dirmngr", 1|4);
+ log_set_prefix ("dirmngr", 1|4);
/* Make sure that our subsystems are ready. */
i18n_init ();
init_common_subsystems (&argc, &argv);
/* Libgcrypt requires us to register the threading model first.
Note that this will also do the pth_init. */
gcry_threads_pth.init = fixed_gcry_pth_init;
rc = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
if (rc)
{
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
gpg_strerror (rc));
}
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-
+
/* Check that the libraries are suitable. Do it here because
the option parsing may need services of the libraries. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
if (!ksba_check_version (NEED_KSBA_VERSION) )
log_fatal( _("%s is too old (need %s, have %s)\n"), "libksba",
NEED_KSBA_VERSION, ksba_check_version (NULL) );
ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
ksba_set_hash_buffer_function (my_ksba_hash_buffer, NULL);
/* Init Assuan. */
malloc_hooks.malloc = gcry_malloc;
malloc_hooks.realloc = gcry_realloc;
malloc_hooks.free = gcry_free;
assuan_set_malloc_hooks (&malloc_hooks);
assuan_set_assuan_log_prefix (log_get_prefix (NULL));
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
assuan_set_system_hooks (ASSUAN_SYSTEM_PTH);
assuan_sock_init ();
setup_libassuan_logging (&opt.debug);
setup_libgcrypt_logging ();
/* Setup defaults. */
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
opt.homedir = default_homedir ();
/* Now with Pth running we can set the logging callback. Our
windows implementation does not yet feature the Pth TLS
functions. */
#ifndef HAVE_W32_SYSTEM
if (pth_key_create (&my_tlskey_current_fd, NULL))
if (pth_key_setdata (my_tlskey_current_fd, NULL))
log_set_pid_suffix_cb (pid_suffix_callback);
#endif /*!HAVE_W32_SYSTEM*/
-
+
/* Reset rereadable options to default values. */
- parse_rereadable_options (NULL, 0);
+ parse_rereadable_options (NULL, 0);
/* LDAP defaults. */
opt.add_new_ldapservers = 0;
opt.ldaptimeout = DEFAULT_LDAP_TIMEOUT;
/* Other defaults. */
socket_name = dirmngr_socket_name ();
/* Check whether we have a config file given on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
while (arg_parse( &pargs, opts))
{
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
parse_debug++;
else if (pargs.r_opt == oOptions)
{ /* Yes there is one, so we do not try the default one, but
read the option file when it is encountered at the
commandline */
default_config = 0;
}
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
{
opt.homedir = pargs.r.ret_str;
homedir_seen = 1;
}
else if (pargs.r_opt == aDaemon)
opt.system_daemon = 1;
else if (pargs.r_opt == aService)
{
/* Redundant. The main function takes care of it. */
opt.system_service = 1;
opt.system_daemon = 1;
}
#ifdef HAVE_W32_SYSTEM
else if (pargs.r_opt == aGPGConfList || pargs.r_opt == aGPGConfTest)
/* We set this so we switch to the system configuration
directory below. This is a crutch to solve the problem
that the user configuration is never used on Windows. Also
see below at aGPGConfList. */
opt.system_daemon = 1;
#endif
}
/* If --daemon has been given on the command line but not --homedir,
we switch to /etc/dirmngr as default home directory. Note, that
this also overrides the GNUPGHOME environment variable. */
if (opt.system_daemon && !homedir_seen)
{
#ifdef HAVE_W32CE_SYSTEM
opt.homedir == DIRSEP_S "gnupg";
#else
opt.homedir = gnupg_sysconfdir ();
#endif
opt.homedir_data = gnupg_datadir ();
opt.homedir_cache = gnupg_cachedir ();
}
if (default_config)
configname = make_filename (opt.homedir, "dirmngr.conf", NULL );
-
+
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
next_pass:
if (configname)
{
configlineno = 0;
configfp = fopen (configname, "r");
if (!configfp)
{
if (default_config)
{
if( parse_debug )
log_info (_("NOTE: no default option file `%s'\n"),
configname );
}
else
{
log_error (_("option file `%s': %s\n"),
configname, strerror(errno) );
exit(2);
}
- xfree (configname);
+ xfree (configname);
configname = NULL;
}
if (parse_debug && configname )
log_info (_("reading options from `%s'\n"), configname );
default_config = 0;
}
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
{
if (parse_rereadable_options (&pargs, 0))
continue; /* Already handled */
switch (pargs.r_opt)
{
- case aServer:
+ case aServer:
case aDaemon:
case aService:
- case aShutdown:
- case aFlush:
- case aListCRLs:
- case aLoadCRL:
+ case aShutdown:
+ case aFlush:
+ case aListCRLs:
+ case aLoadCRL:
case aFetchCRL:
case aGPGConfList:
case aGPGConfTest:
cmd = pargs.r_opt;
break;
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oBatch: opt.batch=1; break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
/* Config files may not be nested (silently ignore them) */
if (!configfp)
{
xfree(configname);
configname = xstrdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: /* Ignore this option here. */; break;
case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
case oLDAPFile: ldapfile = pargs.r.ret_str; break;
case oLDAPAddServers: opt.add_new_ldapservers = 1; break;
- case oLDAPTimeout:
- opt.ldaptimeout = pargs.r.ret_int;
+ case oLDAPTimeout:
+ opt.ldaptimeout = pargs.r.ret_int;
break;
case oFakedSystemTime:
gnupg_set_time ((time_t)pargs.r.ret_ulong, 0);
break;
case oForce: opt.force = 1; break;
case oSocketName: socket_name = pargs.r.ret_str; break;
default : pargs.err = configfp? 1:2; break;
}
}
if (configfp)
{
fclose (configfp);
configfp = NULL;
/* Keep a copy of the name so that it can be read on SIGHUP. */
opt.config_filename = configname;
configname = NULL;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (log_get_errorcount(0))
exit(2);
if (nogreeting )
greeting = 0;
if (!opt.homedir_data)
opt.homedir_data = opt.homedir;
if (!opt.homedir_cache)
opt.homedir_cache = opt.homedir;
if (greeting)
{
es_fprintf (es_stderr, "%s %s; %s\n",
strusage(11), strusage(13), strusage(14) );
es_fprintf (es_stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
log_info ("NOTE: this is a development version!\n");
#endif
if (!access ("/etc/dirmngr", F_OK) && !strncmp (opt.homedir, "/etc/", 5))
- log_info
+ log_info
("NOTE: DirMngr is now a proper part of GnuPG. The configuration and"
" other directory names changed. Please check that no other version"
" of dirmngr is still installed. To disable this warning, remove the"
" directory `/etc/dirmngr'.\n");
-
+
if (gnupg_faked_time_p ())
{
gnupg_isotime_t tbuf;
log_info (_("WARNING: running with faked system time: "));
gnupg_get_isotime (tbuf);
dump_isotime (tbuf);
log_printf ("\n");
}
set_debug ();
/* Get LDAP server list from file. */
- if (!ldapfile)
+ if (!ldapfile)
{
ldapfile = make_filename (opt.homedir,
opt.system_daemon?
"ldapservers.conf":"dirmngr_ldapservers.conf",
NULL);
opt.ldapservers = parse_ldapserver_file (ldapfile);
xfree (ldapfile);
}
else
opt.ldapservers = parse_ldapserver_file (ldapfile);
#ifndef HAVE_W32_SYSTEM
/* We need to ignore the PIPE signal because the we might log to a
socket and that code handles EPIPE properly. The ldap wrapper
also requires us to ignore this silly signal. Assuan would set
this signal to ignore anyway.*/
signal (SIGPIPE, SIG_IGN);
#endif
/* Ready. Now to our duties. */
if (!cmd && opt.system_service)
cmd = aDaemon;
else if (!cmd)
cmd = aServer;
rc = 0;
if (cmd == aServer)
{
/* Note that this server mode is maily useful for debugging. */
if (argc)
wrong_args ("--server");
if (logfile)
{
log_set_file (logfile);
log_set_prefix (NULL, 2|4);
}
-
+
if (debug_wait)
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
gnupg_sleep (debug_wait);
log_debug ("... okay\n");
}
ldap_wrapper_launch_thread ();
cert_cache_init ();
crl_cache_init ();
start_command_handler (ASSUAN_INVALID_FD);
shutdown_reaper ();
}
else if (cmd == aDaemon)
{
assuan_fd_t fd;
pid_t pid;
int len;
struct sockaddr_un serv_addr;
if (argc)
wrong_args ("--daemon");
-
+
/* Now start with logging to a file if this is desired. */
if (logfile)
{
log_set_file (logfile);
log_set_prefix (NULL, (JNLIB_LOG_WITH_PREFIX
|JNLIB_LOG_WITH_TIME
|JNLIB_LOG_WITH_PID));
current_logfile = xstrdup (logfile);
}
#ifndef HAVE_W32_SYSTEM
if (strchr (socket_name, ':'))
{
log_error (_("colons are not allowed in the socket name\n"));
dirmngr_exit (1);
}
#endif
- if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
+ if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
{
log_error (_("name of socket too long\n"));
dirmngr_exit (1);
}
-
+
fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0);
if (fd == ASSUAN_INVALID_FD)
{
log_error (_("can't create socket: %s\n"), strerror (errno));
cleanup ();
dirmngr_exit (1);
}
memset (&serv_addr, 0, sizeof serv_addr);
serv_addr.sun_family = AF_UNIX;
strcpy (serv_addr.sun_path, socket_name);
len = SUN_LEN (&serv_addr);
rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
- if (rc == -1
+ if (rc == -1
&& (errno == EADDRINUSE
#ifdef HAVE_W32_SYSTEM
|| errno == EEXIST
#endif
))
{
/* Fixme: We should test whether a dirmngr is already running. */
gnupg_remove (socket_name);
rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
}
- if (rc != -1
+ if (rc != -1
&& (rc = assuan_sock_get_nonce ((struct sockaddr*) &serv_addr, len, &socket_nonce)))
log_error (_("error getting nonce for the socket\n"));
if (rc == -1)
{
log_error (_("error binding socket to `%s': %s\n"),
serv_addr.sun_path, gpg_strerror (gpg_error_from_errno (errno)));
assuan_sock_close (fd);
dirmngr_exit (1);
}
cleanup_socket = 1;
-
+
if (listen (FD2INT (fd), 5) == -1)
{
log_error (_("listen() failed: %s\n"), strerror (errno));
assuan_sock_close (fd);
dirmngr_exit (1);
}
if (opt.verbose)
log_info (_("listening on socket `%s'\n"), socket_name );
es_fflush (NULL);
/* Note: We keep the dirmngr_info output only for the sake of
existing scripts which might use this to detect a successful
start of the dirmngr. */
#ifdef HAVE_W32_SYSTEM
pid = getpid ();
es_printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid);
#else
pid = pth_fork ();
- if (pid == (pid_t)-1)
+ if (pid == (pid_t)-1)
{
log_fatal (_("error forking process: %s\n"), strerror (errno));
dirmngr_exit (1);
}
- if (pid)
+ if (pid)
{ /* We are the parent */
char *infostr;
-
+
/* Don't let cleanup() remove the socket - the child is
responsible for doing that. */
cleanup_socket = 0;
close (fd);
-
+
/* Create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "DIRMNGR_INFO=%s:%lu:1",
socket_name, (ulong)pid ) < 0)
{
log_error (_("out of core\n"));
kill (pid, SIGTERM);
dirmngr_exit (1);
}
/* Print the environment string, so that the caller can use
shell's eval to set it. But see above. */
if (csh_style)
{
*strchr (infostr, '=') = ' ';
es_printf ( "setenv %s\n", infostr);
}
else
{
es_printf ( "%s; export DIRMNGR_INFO;\n", infostr);
}
free (infostr);
- exit (0);
+ exit (0);
/*NEVER REACHED*/
} /* end parent */
-
-
- /*
+
+
+ /*
This is the child
*/
/* Detach from tty and put process into a new session */
if (!nodetach )
- {
+ {
int i;
unsigned int oldflags;
/* Close stdin, stdout and stderr unless it is the log stream */
for (i=0; i <= 2; i++)
{
if (!log_test_fd (i) && i != fd )
close (i);
}
if (setsid() == -1)
{
log_error ("setsid() failed: %s\n", strerror(errno) );
dirmngr_exit (1);
}
log_get_prefix (&oldflags);
log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED);
opt.running_detached = 1;
if (chdir("/"))
{
log_error ("chdir to / failed: %s\n", strerror (errno));
dirmngr_exit (1);
}
}
#endif
ldap_wrapper_launch_thread ();
cert_cache_init ();
crl_cache_init ();
#ifdef USE_W32_SERVICE
if (opt.system_service)
{
service_status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (service_handle, &service_status);
}
#endif
handle_connections (fd);
assuan_sock_close (fd);
shutdown_reaper ();
#ifdef USE_W32_SERVICE
if (opt.system_service)
{
service_status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (service_handle, &service_status);
}
#endif
}
else if (cmd == aListCRLs)
{
/* Just list the CRL cache and exit. */
if (argc)
wrong_args ("--list-crls");
ldap_wrapper_launch_thread ();
crl_cache_init ();
crl_cache_list (es_stdout);
}
else if (cmd == aLoadCRL)
{
struct server_control_s ctrlbuf;
memset (&ctrlbuf, 0, sizeof ctrlbuf);
dirmngr_init_default_ctrl (&ctrlbuf);
ldap_wrapper_launch_thread ();
cert_cache_init ();
crl_cache_init ();
if (!argc)
rc = crl_cache_load (&ctrlbuf, NULL);
else
{
for (; !rc && argc; argc--, argv++)
rc = crl_cache_load (&ctrlbuf, *argv);
}
}
else if (cmd == aFetchCRL)
{
ksba_reader_t reader;
struct server_control_s ctrlbuf;
if (argc != 1)
wrong_args ("--fetch-crl URL");
memset (&ctrlbuf, 0, sizeof ctrlbuf);
dirmngr_init_default_ctrl (&ctrlbuf);
ldap_wrapper_launch_thread ();
cert_cache_init ();
crl_cache_init ();
rc = crl_fetch (&ctrlbuf, argv[0], &reader);
if (rc)
log_error (_("fetching CRL from `%s' failed: %s\n"),
argv[0], gpg_strerror (rc));
else
{
- rc = crl_cache_insert (&ctrlbuf, argv[0], reader);
+ rc = crl_cache_insert (&ctrlbuf, argv[0], reader);
if (rc)
log_error (_("processing CRL from `%s' failed: %s\n"),
argv[0], gpg_strerror (rc));
crl_close_reader (reader);
}
}
else if (cmd == aFlush)
{
/* Delete cache and exit. */
if (argc)
wrong_args ("--flush");
rc = crl_cache_flush();
}
else if (cmd == aGPGConfTest)
dirmngr_exit (0);
else if (cmd == aGPGConfList)
{
unsigned long flags = 0;
char *filename;
char *filename_esc;
/* List options and default values in the GPG Conf format. */
/* The following list is taken from gnupg/tools/gpgconf-comp.c. */
/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */
#define GC_OPT_FLAG_NONE 0UL
/* The DEFAULT flag for an option indicates that the option has a
default value. */
#define GC_OPT_FLAG_DEFAULT (1UL << 4)
/* The DEF_DESC flag for an option indicates that the option has a
default, which is described by the value of the default field. */
#define GC_OPT_FLAG_DEF_DESC (1UL << 5)
/* The NO_ARG_DESC flag for an option indicates that the argument has
a default, which is described by the value of the ARGDEF field. */
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
#define GC_OPT_FLAG_NO_CHANGE (1UL <<7)
#ifdef HAVE_W32_SYSTEM
/* On Windows systems, dirmngr always runs as system daemon, and
the per-user configuration is never used. So we short-cut
everything to use the global system configuration of dirmngr
above, and here we set the no change flag to make these
read-only. */
flags |= GC_OPT_FLAG_NO_CHANGE;
#endif
/* First the configuration file. This is not an option, but it
is vital information for GPG Conf. */
if (!opt.config_filename)
opt.config_filename = make_filename (opt.homedir,
"dirmngr.conf", NULL );
filename = percent_escape (opt.config_filename, NULL);
es_printf ("gpgconf-dirmngr.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename);
xfree (filename);
es_printf ("verbose:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("quiet:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("debug-level:%lu:\"none\n", flags | GC_OPT_FLAG_DEFAULT);
es_printf ("log-file:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("force:%lu:\n", flags | GC_OPT_FLAG_NONE);
/* --csh and --sh are mutually exclusive, something we can not
express in GPG Conf. --options is only usable from the
command line, really. --debug-all interacts with --debug,
and having both of them is thus problematic. --no-detach is
also only usable on the command line. --batch is unused. */
- filename = make_filename (opt.homedir,
+ filename = make_filename (opt.homedir,
opt.system_daemon?
"ldapservers.conf":"dirmngr_ldapservers.conf",
NULL);
filename_esc = percent_escape (filename, NULL);
es_printf ("ldapserverlist-file:%lu:\"%s\n", flags | GC_OPT_FLAG_DEFAULT,
filename_esc);
xfree (filename_esc);
xfree (filename);
es_printf ("ldaptimeout:%lu:%u\n",
flags | GC_OPT_FLAG_DEFAULT, DEFAULT_LDAP_TIMEOUT);
es_printf ("max-replies:%lu:%u\n",
flags | GC_OPT_FLAG_DEFAULT, DEFAULT_MAX_REPLIES);
es_printf ("allow-ocsp:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ocsp-responder:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ocsp-signer:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("faked-system-time:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("no-greeting:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("disable-http:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("disable-ldap:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("honor-http-proxy:%lu\n", flags | GC_OPT_FLAG_NONE);
es_printf ("http-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("only-ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ignore-ldap-dp:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ignore-http-dp:%lu:\n", flags | GC_OPT_FLAG_NONE);
es_printf ("ignore-ocsp-service-url:%lu:\n", flags | GC_OPT_FLAG_NONE);
/* Note: The next one is to fix a typo in gpgconf - should be
removed eventually. */
es_printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE);
}
cleanup ();
return !!rc;
}
#ifdef USE_W32_SERVICE
int
main (int argc, char *argv[])
{
int i;
/* Find out if we run in daemon mode or on the command line. */
for (i = 1; i < argc; i++)
if (!strcmp (argv[i], "--service"))
{
opt.system_service = 1;
opt.system_daemon = 1;
break;
}
if (!opt.system_service)
return real_main (argc, argv);
else
{
SERVICE_TABLE_ENTRY DispatchTable [] =
{
/* Ignore warning. */
{ "DirMngr", &real_main },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher (DispatchTable))
return 1;
return 0;
}
}
#endif /*USE_W32_SERVICE*/
static void
cleanup (void)
{
crl_cache_deinit ();
cert_cache_deinit (1);
ldapserver_list_free (opt.ldapservers);
opt.ldapservers = NULL;
if (cleanup_socket)
{
cleanup_socket = 0;
if (socket_name && *socket_name)
gnupg_remove (socket_name);
}
}
-void
+void
dirmngr_exit (int rc)
{
cleanup ();
exit (rc);
}
void
dirmngr_init_default_ctrl (ctrl_t ctrl)
{
(void)ctrl;
/* Nothing for now. */
}
/* Create a list of LDAP servers from the file FILENAME. Returns the
- list or NULL in case of errors.
+ list or NULL in case of errors.
The format fo such a file is line oriented where empty lines and
lines starting with a hash mark are ignored. All other lines are
assumed to be colon seprated with these fields:
1. field: Hostname
2. field: Portnumber
- 3. field: Username
+ 3. field: Username
4. field: Password
5. field: Base DN
*/
static ldap_server_t
parse_ldapserver_file (const char* filename)
{
char buffer[1024];
char *p;
ldap_server_t server, serverstart, *serverend;
int c;
unsigned int lineno = 0;
estream_t fp;
fp = es_fopen (filename, "r");
if (!fp)
{
log_error (_("error opening `%s': %s\n"), filename, strerror (errno));
return NULL;
}
serverstart = NULL;
serverend = &serverstart;
while (es_fgets (buffer, sizeof buffer, fp))
{
lineno++;
if (!*buffer || buffer[strlen(buffer)-1] != '\n')
{
if (*buffer && es_feof (fp))
; /* Last line not terminated - continue. */
else
{
log_error (_("%s:%u: line too long - skipped\n"),
filename, lineno);
while ( (c=es_fgetc (fp)) != EOF && c != '\n')
; /* Skip until end of line. */
continue;
}
}
/* Skip empty and comment lines.*/
for (p=buffer; spacep (p); p++)
;
if (!*p || *p == '\n' || *p == '#')
continue;
/* Parse the colon separated fields. */
server = ldapserver_parse_one (buffer, filename, lineno);
if (server)
{
*serverend = server;
serverend = &server->next;
}
- }
-
+ }
+
if (es_ferror (fp))
log_error (_("error reading `%s': %s\n"), filename, strerror (errno));
es_fclose (fp);
return serverstart;
}
static fingerprint_list_t
parse_ocsp_signer (const char *string)
{
gpg_error_t err;
char *fname;
estream_t fp;
char line[256];
char *p;
fingerprint_list_t list, *list_tail, item;
unsigned int lnr = 0;
int c, i, j;
int errflag = 0;
/* Check whether this is not a filename and treat it as a direct
fingerprint specification. */
if (!strpbrk (string, "/.~\\"))
{
item = xcalloc (1, sizeof *item);
for (i=j=0; (string[i] == ':' || hexdigitp (string+i)) && j < 40; i++)
if ( string[i] != ':' )
item->hexfpr[j++] = string[i] >= 'a'? (string[i] & 0xdf): string[i];
item->hexfpr[j] = 0;
if (j != 40 || !(spacep (string+i) || !string[i]))
{
- log_error (_("%s:%u: invalid fingerprint detected\n"),
+ log_error (_("%s:%u: invalid fingerprint detected\n"),
"--ocsp-signer", 0);
xfree (item);
return NULL;
}
return item;
}
-
+
/* Well, it is a filename. */
if (*string == '/' || (*string == '~' && string[1] == '/'))
fname = make_filename (string, NULL);
else
{
if (string[0] == '.' && string[1] == '/' )
string += 2;
fname = make_filename (opt.homedir, string, NULL);
}
fp = es_fopen (fname, "r");
if (!fp)
{
err = gpg_error_from_syserror ();
log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
xfree (fname);
return NULL;
}
list = NULL;
list_tail = &list;
for (;;)
{
if (!es_fgets (line, DIM(line)-1, fp) )
{
if (!es_feof (fp))
{
err = gpg_error_from_syserror ();
log_error (_("%s:%u: read error: %s\n"),
fname, lnr, gpg_strerror (err));
errflag = 1;
}
es_fclose (fp);
if (errflag)
{
while (list)
{
fingerprint_list_t tmp = list->next;
xfree (list);
list = tmp;
}
}
xfree (fname);
return list; /* Ready. */
}
lnr++;
if (!*line || line[strlen(line)-1] != '\n')
{
/* Eat until end of line. */
while ( (c=es_getc (fp)) != EOF && c != '\n')
;
err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
/* */: GPG_ERR_INCOMPLETE_LINE);
- log_error (_("%s:%u: read error: %s\n"),
+ log_error (_("%s:%u: read error: %s\n"),
fname, lnr, gpg_strerror (err));
errflag = 1;
continue;
}
/* Allow for empty lines and spaces */
for (p=line; spacep (p); p++)
;
if (!*p || *p == '\n' || *p == '#')
continue;
item = xcalloc (1, sizeof *item);
*list_tail = item;
list_tail = &item->next;
for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++)
if ( p[i] != ':' )
item->hexfpr[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
item->hexfpr[j] = 0;
if (j != 40 || !(spacep (p+i) || p[i] == '\n'))
{
log_error (_("%s:%u: invalid fingerprint detected\n"), fname, lnr);
errflag = 1;
}
i++;
while (spacep (p+i))
i++;
if (p[i] && p[i] != '\n')
log_info (_("%s:%u: garbage at end of line ignored\n"), fname, lnr);
}
/*NOTREACHED*/
}
/*
- Stuff used in daemon mode.
+ Stuff used in daemon mode.
*/
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
- signal handler.
+ signal handler.
Fixme: Due to the way the argument parsing works, we create a
memory leak here for all string type arguments. There is currently
no clean way to tell whether the memory for the argument has been
allocated or points into the process' original arguments. Unless
we have a mechanism to tell this, we need to live on with this. */
static void
reread_configuration (void)
{
ARGPARSE_ARGS pargs;
FILE *fp;
unsigned int configlineno = 0;
int dummy;
if (!opt.config_filename)
return; /* No config file. */
fp = fopen (opt.config_filename, "r");
if (!fp)
{
log_error (_("option file `%s': %s\n"),
opt.config_filename, strerror(errno) );
return;
}
parse_rereadable_options (NULL, 1); /* Start from the default values. */
memset (&pargs, 0, sizeof pargs);
dummy = 0;
pargs.argc = &dummy;
pargs.flags = 1; /* do not remove the args */
while (optfile_parse (fp, opt.config_filename, &configlineno, &pargs, opts) )
{
if (pargs.r_opt < -1)
pargs.err = 1; /* Print a warning. */
else /* Try to parse this option - ignore unchangeable ones. */
parse_rereadable_options (&pargs, 1);
}
fclose (fp);
set_debug ();
}
/* A global function which allows us to trigger the reload stuff from
other places. */
void
dirmngr_sighup_action (void)
{
log_info (_("SIGHUP received - "
"re-reading configuration and flushing caches\n"));
reread_configuration ();
cert_cache_deinit (0);
crl_cache_deinit ();
cert_cache_init ();
crl_cache_init ();
}
/* The signal handler. */
static void
handle_signal (int signo)
{
switch (signo)
{
#ifndef HAVE_W32_SYSTEM
case SIGHUP:
dirmngr_sighup_action ();
break;
-
+
case SIGUSR1:
cert_cache_print_stats ();
break;
-
+
case SIGUSR2:
log_info (_("SIGUSR2 received - no action defined\n"));
break;
case SIGTERM:
if (!shutdown_pending)
log_info (_("SIGTERM received - shutting down ...\n"));
else
log_info (_("SIGTERM received - still %d active connections\n"),
active_connections);
shutdown_pending++;
if (shutdown_pending > 2)
{
log_info (_("shutdown forced\n"));
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
cleanup ();
dirmngr_exit (0);
}
break;
-
+
case SIGINT:
log_info (_("SIGINT received - immediate shutdown\n"));
log_info( "%s %s stopped\n", strusage(11), strusage(13));
cleanup ();
dirmngr_exit (0);
break;
#endif
default:
log_info (_("signal %d received - no action defined\n"), signo);
}
}
/* This is the worker for the ticker. It is called every few seconds
and may only do fast operations. */
static void
handle_tick (void)
{
/* Nothing real to do right now. Actually we need the timeout only
for W32 where we don't use signals and need a way for the loop to
check for the shutdown flag. */
#ifdef HAVE_W32_SYSTEM
if (shutdown_pending)
log_info (_("SIGTERM received - shutting down ...\n"));
if (shutdown_pending > 2)
{
log_info (_("shutdown forced\n"));
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
cleanup ();
dirmngr_exit (0);
}
#endif /*HAVE_W32_SYSTEM*/
}
/* Check the nonce on a new connection. This is a NOP unless we we
are using our Unix domain socket emulation under Windows. */
-static int
+static int
check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
{
if (assuan_sock_check_nonce (fd, nonce))
{
- log_info (_("error reading nonce on fd %d: %s\n"),
+ log_info (_("error reading nonce on fd %d: %s\n"),
FD2INT (fd), strerror (errno));
assuan_sock_close (fd);
return -1;
}
else
return 0;
}
/* Helper to call a connection's main fucntion. */
static void *
start_connection_thread (void *arg)
{
union int_and_ptr_u argval;
- assuan_fd_t fd;
+ gnupg_fd_t fd;
argval.aptr = arg;
fd = argval.afd;
if (check_nonce (fd, &socket_nonce))
- return NULL;
+ {
+ log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
+ return NULL;
+ }
#ifndef HAVE_W32_SYSTEM
pth_key_setdata (my_tlskey_current_fd, argval.aptr);
#endif
active_connections++;
if (opt.verbose)
log_info (_("handler for fd %d started\n"), FD2INT (fd));
start_command_handler (fd);
if (opt.verbose)
log_info (_("handler for fd %d terminated\n"), FD2INT (fd));
active_connections--;
#ifndef HAVE_W32_SYSTEM
argval.afd = ASSUAN_INVALID_FD;
pth_key_setdata (my_tlskey_current_fd, argval.aptr);
#endif
-
+
return NULL;
}
/* Main loop in daemon mode. */
static void
handle_connections (assuan_fd_t listen_fd)
{
pth_attr_t tattr;
pth_event_t ev, time_ev;
- sigset_t sigs, oldsigs;
+ sigset_t sigs;
int signo;
struct sockaddr_un paddr;
socklen_t plen = sizeof( paddr );
- assuan_fd_t fd;
+ gnupg_fd_t fd;
+ int nfd, ret;
+ fd_set fdset, read_fdset;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 1024*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "dirmngr");
#ifndef HAVE_W32_SYSTEM /* FIXME */
+ /* Make sure that the signals we are going to handle are not blocked
+ and create an event object for them. We also set the default
+ action to ignore because we use an Pth event to get notified
+ about signals. This avoids that the default action is taken in
+ case soemthing goes wrong within Pth. The problem might also be
+ a Pth bug. */
sigemptyset (&sigs );
- sigaddset (&sigs, SIGHUP);
- sigaddset (&sigs, SIGUSR1);
- sigaddset (&sigs, SIGUSR2);
- sigaddset (&sigs, SIGINT);
- sigaddset (&sigs, SIGTERM);
+ {
+ static const int mysigs[] = { SIGHUP, SIGUSR1, SIGUSR2, SIGINT, SIGTERM };
+ struct sigaction sa;
+ int i;
+
+ for (i=0; i < DIM (mysigs); i++)
+ {
+ sigemptyset (&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigaction (mysigs[i], &sa, NULL);
+
+ sigaddset (&sigs, mysigs[i]);
+ }
+ }
+
+ pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
#else
+ /* Use a dummy event. */
sigs = 0;
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
#endif
time_ev = NULL;
+ /* Setup the fdset. It has only one member. This is because we use
+ pth_select instead of pth_accept to properly sync timeouts with
+ to full second. */
+ FD_ZERO (&fdset);
+ FD_SET (FD2INT (listen_fd), &fdset);
+ nfd = FD2INT (listen_fd);
+
+ /* Main loop. */
for (;;)
{
+ /* Make sure that our signals are not blocked. */
+ pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
+
+ /* Shutdown test. */
if (shutdown_pending)
{
if (!active_connections)
break; /* ready */
- /* Do not accept anymore connections but wait for existing
- connections to terminate. */
- signo = 0;
- pth_wait (ev);
- if (pth_event_occurred (ev) && signo)
- handle_signal (signo);
- continue;
+ /* Do not accept new connections but keep on running the
+ loop to cope with the timer events. */
+ FD_ZERO (&fdset);
}
+ /* Create a timeout event if needed. To help with power saving
+ we syncronize the ticks to the next full second. */
if (!time_ev)
- time_ev = pth_event (PTH_EVENT_TIME,
- pth_timeout (TIMERTICK_INTERVAL, 0));
+ {
+ pth_time_t nexttick;
+
+ nexttick = pth_timeout (TIMERTICK_INTERVAL, 0);
+ if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */
+ {
+ nexttick.tv_sec++;
+ nexttick.tv_usec = 0;
+ }
+ time_ev = pth_event (PTH_EVENT_TIME, nexttick);
+ }
+
+ /* Take a copy of the fdset. */
+ read_fdset = fdset;
if (time_ev)
pth_event_concat (ev, time_ev, NULL);
- fd = (assuan_fd_t) pth_accept_ev (FD2INT (listen_fd), (struct sockaddr *)&paddr, &plen, ev);
+
+ ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
+
if (time_ev)
pth_event_isolate (time_ev);
- if (fd == ASSUAN_INVALID_FD)
+ if (ret == -1)
{
if (pth_event_occurred (ev)
|| (time_ev && pth_event_occurred (time_ev)) )
{
if (pth_event_occurred (ev))
handle_signal (signo);
if (time_ev && pth_event_occurred (time_ev))
{
pth_event_free (time_ev, PTH_FREE_ALL);
time_ev = NULL;
handle_tick ();
}
continue;
}
- log_error (_("accept failed: %s - waiting 1s\n"), strerror (errno));
+ log_error (_("pth_select failed: %s - waiting 1s\n"),
+ strerror (errno));
pth_sleep (1);
continue;
}
if (pth_event_occurred (ev))
{
handle_signal (signo);
}
if (time_ev && pth_event_occurred (time_ev))
{
pth_event_free (time_ev, PTH_FREE_ALL);
time_ev = NULL;
handle_tick ();
}
/* We now might create a new thread and because we don't want
any signals (as we are handling them here) to be delivered to
a new thread we need to block those signals. */
- pth_sigmask (SIG_BLOCK, &sigs, &oldsigs);
-
- /* Create thread to handle this connection. */
- {
- union int_and_ptr_u argval;
-
- argval.afd = fd;
- if (!pth_spawn (tattr, start_connection_thread, argval.aptr))
- {
- log_error (_("error spawning connection handler: %s\n"),
- strerror (errno) );
- assuan_sock_close (fd);
- }
- }
+ pth_sigmask (SIG_BLOCK, &sigs, NULL);
- /* Restore the signal mask. */
- pth_sigmask (SIG_SETMASK, &oldsigs, NULL);
+ if (!shutdown_pending && FD_ISSET (FD2INT (listen_fd), &read_fdset))
+ {
+ plen = sizeof paddr;
+ fd = INT2FD (pth_accept (FD2INT(listen_fd),
+ (struct sockaddr *)&paddr, &plen));
+ if (fd == GNUPG_INVALID_FD)
+ {
+ log_error ("accept failed: %s\n", strerror (errno));
+ }
+ else
+ {
+ char threadname[50];
+ union int_and_ptr_u argval;
+
+ argval.afd = fd;
+ snprintf (threadname, sizeof threadname-1,
+ "conn fd=%d", FD2INT(fd));
+ threadname[sizeof threadname -1] = 0;
+ pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
+ if (!pth_spawn (tattr, start_connection_thread, argval.aptr))
+ {
+ log_error ("error spawning connection handler: %s\n",
+ strerror (errno) );
+ assuan_sock_close (fd);
+ }
+ }
+ fd = GNUPG_INVALID_FD;
+ }
}
-
+
pth_event_free (ev, PTH_FREE_ALL);
if (time_ev)
pth_event_free (time_ev, PTH_FREE_ALL);
pth_attr_destroy (tattr);
cleanup ();
log_info ("%s %s stopped\n", strusage(11), strusage(13));
}
diff --git a/dirmngr/ldap-wrapper.c b/dirmngr/ldap-wrapper.c
index 25ec15513..fa5bf3c6b 100644
--- a/dirmngr/ldap-wrapper.c
+++ b/dirmngr/ldap-wrapper.c
@@ -1,750 +1,759 @@
/* ldap-wrapper.c - LDAP access via a wrapper process
* Copyright (C) 2004, 2005, 2007, 2008 g10 Code GmbH
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
We can't use LDAP directly for these reasons:
1. On some systems the LDAP library uses (indirectly) pthreads and
that is not compatible with PTh.
2. It is huge library in particular if TLS comes into play. So
problems with unfreed memory might turn up and we don't want
this in a long running daemon.
3. There is no easy way for timeouts. In particular the timeout
value does not work for DNS lookups (well, this is usual) and it
seems not to work while loading a large attribute like a
CRL. Having a separate process allows us to either tell the
process to commit suicide or have our own housekepping function
kill it after some time. The latter also allows proper
cancellation of a query at any point of time.
4. Given that we are going out to the network and usually get back
a long response, the fork/exec overhead is acceptable.
Note that under WindowsCE the number of processes is strongly
limited (32 processes including the kernel processes) and thus we
don't use the process approach but implement a different wrapper in
ldap-wrapper-ce.c.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pth.h>
#include "dirmngr.h"
#include "exechelp.h"
#include "misc.h"
#include "ldap-wrapper.h"
#ifdef HAVE_W32_SYSTEM
#define setenv(a,b,c) SetEnvironmentVariable ((a),(b))
#else
#define pth_close(fd) close(fd)
#endif
#ifndef USE_LDAPWRAPPER
# error This module is not expected to be build.
#endif
/* In case sysconf does not return a value we need to have a limit. */
#ifdef _POSIX_OPEN_MAX
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
#else
#define MAX_OPEN_FDS 20
#endif
#define INACTIVITY_TIMEOUT (opt.ldaptimeout + 60*5) /* seconds */
/* To keep track of the LDAP wrapper state we use this structure. */
struct wrapper_context_s
{
struct wrapper_context_s *next;
pid_t pid; /* The pid of the wrapper process. */
int printable_pid; /* Helper to print diagnostics after the process has
been cleaned up. */
int fd; /* Connected with stdout of the ldap wrapper. */
gpg_error_t fd_error; /* Set to the gpg_error of the last read error
if any. */
int log_fd; /* Connected with stderr of the ldap wrapper. */
pth_event_t log_ev;
ctrl_t ctrl; /* Connection data. */
int ready; /* Internally used to mark to be removed contexts. */
ksba_reader_t reader; /* The ksba reader object or NULL. */
char *line; /* Used to print the log lines (malloced). */
size_t linesize;/* Allocated size of LINE. */
size_t linelen; /* Use size of LINE. */
time_t stamp; /* The last time we noticed ativity. */
};
/* We keep a global list of spawed wrapper process. A separate thread
makes use of this list to log error messages and to watch out for
finished processes. */
static struct wrapper_context_s *wrapper_list;
/* We need to know whether we are shutting down the process. */
static int shutting_down;
/* Close the pth file descriptor FD and set it to -1. */
#define SAFE_PTH_CLOSE(fd) \
do { int _fd = fd; if (_fd != -1) { pth_close (_fd); fd = -1;} } while (0)
/* Read a fixed amount of data from READER into BUFFER. */
static gpg_error_t
read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
{
gpg_error_t err;
size_t nread;
while (count)
{
err = ksba_reader_read (reader, buffer, count, &nread);
if (err)
return err;
buffer += nread;
count -= nread;
}
return 0;
}
/* Release the wrapper context and kill a running wrapper process. */
static void
destroy_wrapper (struct wrapper_context_s *ctx)
{
if (ctx->pid != (pid_t)(-1))
{
gnupg_kill_process (ctx->pid);
gnupg_release_process (ctx->pid);
}
ksba_reader_release (ctx->reader);
SAFE_PTH_CLOSE (ctx->fd);
SAFE_PTH_CLOSE (ctx->log_fd);
if (ctx->log_ev)
pth_event_free (ctx->log_ev, PTH_FREE_THIS);
xfree (ctx->line);
xfree (ctx);
}
/* Print the content of LINE to thye log stream but make sure to only
print complete lines. Using NULL for LINE will flush any pending
output. LINE may be modified by this fucntion. */
static void
print_log_line (struct wrapper_context_s *ctx, char *line)
{
char *s;
size_t n;
if (!line)
{
if (ctx->line && ctx->linelen)
{
log_info ("%s\n", ctx->line);
ctx->linelen = 0;
}
return;
}
while ((s = strchr (line, '\n')))
{
*s = 0;
if (ctx->line && ctx->linelen)
{
log_info ("%s", ctx->line);
ctx->linelen = 0;
log_printf ("%s\n", line);
}
else
log_info ("%s\n", line);
line = s + 1;
}
n = strlen (line);
if (n)
{
if (ctx->linelen + n + 1 >= ctx->linesize)
{
char *tmp;
size_t newsize;
newsize = ctx->linesize + ((n + 255) & ~255) + 1;
tmp = (ctx->line ? xtryrealloc (ctx->line, newsize)
: xtrymalloc (newsize));
if (!tmp)
{
log_error (_("error printing log line: %s\n"), strerror (errno));
return;
}
ctx->line = tmp;
ctx->linesize = newsize;
}
memcpy (ctx->line + ctx->linelen, line, n);
ctx->linelen += n;
ctx->line[ctx->linelen] = 0;
}
}
/* Read data from the log stream. Returns true if the log stream
indicated EOF or error. */
static int
read_log_data (struct wrapper_context_s *ctx)
{
int n;
char line[256];
/* We must use the pth_read function for pipes, always. */
do
n = pth_read (ctx->log_fd, line, sizeof line - 1);
while (n < 0 && errno == EINTR);
if (n <= 0) /* EOF or error. */
{
if (n < 0)
log_error (_("error reading log from ldap wrapper %d: %s\n"),
ctx->pid, strerror (errno));
print_log_line (ctx, NULL);
SAFE_PTH_CLOSE (ctx->log_fd);
pth_event_free (ctx->log_ev, PTH_FREE_THIS);
ctx->log_ev = NULL;
return 1;
}
line[n] = 0;
print_log_line (ctx, line);
if (ctx->stamp != (time_t)(-1))
ctx->stamp = time (NULL);
return 0;
}
/* This function is run by a separate thread to maintain the list of
wrappers and to log error messages from these wrappers. */
void *
ldap_wrapper_thread (void *dummy)
{
int nfds;
struct wrapper_context_s *ctx;
struct wrapper_context_s *ctx_prev;
time_t current_time;
(void)dummy;
for (;;)
{
pth_event_t timeout_ev;
int any_action = 0;
+ pth_time_t nexttick;
- timeout_ev = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0));
+ /* We timeout the pth_wait every 2 seconds. To help with power
+ saving we syncronize the timeouts to the next full second. */
+ nexttick = pth_timeout (2, 0);
+ if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */
+ {
+ nexttick.tv_sec++;
+ nexttick.tv_usec = 0;
+ }
+ timeout_ev = pth_event (PTH_EVENT_TIME, nexttick);
if (! timeout_ev)
{
log_error (_("pth_event failed: %s\n"), strerror (errno));
pth_sleep (10);
continue;
}
for (ctx = wrapper_list; ctx; ctx = ctx->next)
{
if (ctx->log_fd != -1)
{
pth_event_isolate (ctx->log_ev);
pth_event_concat (timeout_ev, ctx->log_ev, NULL);
}
}
/* Note that the read FDs are actually handles. Thus, we can
not use pth_select, but have to use pth_wait. */
nfds = pth_wait (timeout_ev);
if (nfds < 0)
{
pth_event_free (timeout_ev, PTH_FREE_THIS);
log_error (_("pth_wait failed: %s\n"), strerror (errno));
pth_sleep (10);
continue;
}
if (pth_event_status (timeout_ev) == PTH_STATUS_OCCURRED)
nfds--;
pth_event_free (timeout_ev, PTH_FREE_THIS);
current_time = time (NULL);
if (current_time > INACTIVITY_TIMEOUT)
current_time -= INACTIVITY_TIMEOUT;
/* Note that there is no need to lock the list because we always
add entries at the head (with a pending event status) and
thus traversing the list will even work if we have a context
switch in waitpid (which should anyway only happen with Pth's
hard system call mapping). */
for (ctx = wrapper_list; ctx; ctx = ctx->next)
{
/* Check whether there is any logging to be done. */
if (nfds && ctx->log_fd != -1
&& pth_event_status (ctx->log_ev) == PTH_STATUS_OCCURRED)
{
if (read_log_data (ctx))
any_action = 1;
}
/* Check whether the process is still running. */
if (ctx->pid != (pid_t)(-1))
{
gpg_error_t err;
int status;
err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
&status);
if (!err)
{
log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
any_action = 1;
}
else if (gpg_err_code (err) == GPG_ERR_GENERAL)
{
if (status == 10)
log_info (_("ldap wrapper %d ready: timeout\n"),
(int)ctx->pid);
else
log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
(int)ctx->pid, status);
ctx->ready = 1;
gnupg_release_process (ctx->pid);
ctx->pid = (pid_t)(-1);
any_action = 1;
}
else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
{
log_error (_("waiting for ldap wrapper %d failed: %s\n"),
(int)ctx->pid, gpg_strerror (err));
any_action = 1;
}
}
/* Check whether we should terminate the process. */
if (ctx->pid != (pid_t)(-1)
&& ctx->stamp != (time_t)(-1) && ctx->stamp < current_time)
{
gnupg_kill_process (ctx->pid);
ctx->stamp = (time_t)(-1);
log_info (_("ldap wrapper %d stalled - killing\n"),
(int)ctx->pid);
/* We need to close the log fd because the cleanup loop
waits for it. */
SAFE_PTH_CLOSE (ctx->log_fd);
any_action = 1;
}
}
/* If something has been printed to the log file or we got an
EOF from a wrapper, we now print the list of active
wrappers. */
if (any_action && DBG_LOOKUP)
{
log_info ("ldap worker stati:\n");
for (ctx = wrapper_list; ctx; ctx = ctx->next)
log_info (" c=%p pid=%d/%d rdr=%p ctrl=%p/%d la=%lu rdy=%d\n",
ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->reader,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
(unsigned long)ctx->stamp, ctx->ready);
}
/* Use a separate loop to check whether ready marked wrappers
may be removed. We may only do so if the ksba reader object
is not anymore in use or we are in shutdown state. */
again:
for (ctx_prev=NULL, ctx=wrapper_list; ctx; ctx_prev=ctx, ctx=ctx->next)
if (ctx->ready
&& ((ctx->log_fd == -1 && !ctx->reader) || shutting_down))
{
if (ctx_prev)
ctx_prev->next = ctx->next;
else
wrapper_list = ctx->next;
destroy_wrapper (ctx);
/* We need to restart because destroy_wrapper might have
done a context switch. */
goto again;
}
}
/*NOTREACHED*/
return NULL; /* Make the compiler happy. */
}
/* Start the reaper thread for the ldap wrapper. */
void
ldap_wrapper_launch_thread (void)
{
static int done;
pth_attr_t tattr;
if (done)
return;
done = 1;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "ldap-reaper");
if (!pth_spawn (tattr, ldap_wrapper_thread, NULL))
{
log_error (_("error spawning ldap wrapper reaper thread: %s\n"),
strerror (errno) );
dirmngr_exit (1);
}
pth_attr_destroy (tattr);
}
/* Wait until all ldap wrappers have terminated. We assume that the
kill has already been sent to all of them. */
void
ldap_wrapper_wait_connections ()
{
shutting_down = 1;
while (wrapper_list)
pth_yield (NULL);
}
/* This function is to be used to release a context associated with the
given reader object. */
void
ldap_wrapper_release_context (ksba_reader_t reader)
{
struct wrapper_context_s *ctx;
if (!reader )
return;
for (ctx=wrapper_list; ctx; ctx=ctx->next)
if (ctx->reader == reader)
{
if (DBG_LOOKUP)
log_info ("releasing ldap worker c=%p pid=%d/%d rdr=%p ctrl=%p/%d\n",
ctx,
(int)ctx->pid, (int)ctx->printable_pid,
ctx->reader,
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
ctx->reader = NULL;
SAFE_PTH_CLOSE (ctx->fd);
if (ctx->ctrl)
{
ctx->ctrl->refcount--;
ctx->ctrl = NULL;
}
if (ctx->fd_error)
log_info (_("reading from ldap wrapper %d failed: %s\n"),
ctx->printable_pid, gpg_strerror (ctx->fd_error));
break;
}
}
/* Cleanup all resources held by the connection associated with
CTRL. This is used after a cancel to kill running wrappers. */
void
ldap_wrapper_connection_cleanup (ctrl_t ctrl)
{
struct wrapper_context_s *ctx;
for (ctx=wrapper_list; ctx; ctx=ctx->next)
if (ctx->ctrl && ctx->ctrl == ctrl)
{
ctx->ctrl->refcount--;
ctx->ctrl = NULL;
if (ctx->pid != (pid_t)(-1))
gnupg_kill_process (ctx->pid);
if (ctx->fd_error)
log_info (_("reading from ldap wrapper %d failed: %s\n"),
ctx->printable_pid, gpg_strerror (ctx->fd_error));
}
}
/* This is the callback used by the ldap wrapper to feed the ksba
reader with the wrappers stdout. See the description of
ksba_reader_set_cb for details. */
static int
reader_callback (void *cb_value, char *buffer, size_t count, size_t *nread)
{
struct wrapper_context_s *ctx = cb_value;
size_t nleft = count;
/* FIXME: We might want to add some internal buffering because the
ksba code does not do any buffering for itself (because a ksba
reader may be detached from another stream to read other data and
the it would be cumbersome to get back already buffered
stuff). */
if (!buffer && !count && !nread)
return -1; /* Rewind is not supported. */
/* If we ever encountered a read error don't allow to continue and
possible overwrite the last error cause. Bail out also if the
file descriptor has been closed. */
if (ctx->fd_error || ctx->fd == -1)
{
*nread = 0;
return -1;
}
while (nleft > 0)
{
int n;
pth_event_t evt;
gpg_error_t err;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0));
n = pth_read_ev (ctx->fd, buffer, nleft, evt);
if (n < 0 && evt && pth_event_occurred (evt))
{
n = 0;
err = dirmngr_tick (ctx->ctrl);
if (err)
{
ctx->fd_error = err;
SAFE_PTH_CLOSE (ctx->fd);
if (evt)
pth_event_free (evt, PTH_FREE_THIS);
return -1;
}
}
else if (n < 0)
{
ctx->fd_error = gpg_error_from_errno (errno);
SAFE_PTH_CLOSE (ctx->fd);
if (evt)
pth_event_free (evt, PTH_FREE_THIS);
return -1;
}
else if (!n)
{
if (nleft == count)
{
if (evt)
pth_event_free (evt, PTH_FREE_THIS);
return -1; /* EOF. */
}
break;
}
nleft -= n;
buffer += n;
if (evt)
pth_event_free (evt, PTH_FREE_THIS);
if (n > 0 && ctx->stamp != (time_t)(-1))
ctx->stamp = time (NULL);
}
*nread = count - nleft;
return 0;
}
/* Fork and exec the LDAP wrapper and returns a new libksba reader
object at READER. ARGV is a NULL terminated list of arguments for
the wrapper. The function returns 0 on success or an error code.
Special hack to avoid passing a password through the command line
which is globally visible: If the first element of ARGV is "--pass"
it will be removed and instead the environment variable
DIRMNGR_LDAP_PASS will be set to the next value of ARGV. On modern
OSes the environment is not visible to other users. For those old
systems where it can't be avoided, we don't want to go into the
hassle of passing the password via stdin; it's just too complicated
and an LDAP password used for public directory lookups should not
be that confidential. */
gpg_error_t
ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
{
gpg_error_t err;
pid_t pid;
struct wrapper_context_s *ctx;
int i;
int j;
const char **arg_list;
const char *pgmname;
int outpipe[2], errpipe[2];
/* It would be too simple to connect stderr just to our logging
stream. The problem is that if we are running multi-threaded
everything gets intermixed. Clearly we don't want this. So the
only viable solutions are either to have another thread
responsible for logging the messages or to add an option to the
wrapper module to do the logging on its own. Given that we anyway
need a way to rip the child process and this is best done using a
general ripping thread, that thread can do the logging too. */
*reader = NULL;
/* Files: We need to prepare stdin and stdout. We get stderr from
the function. */
if (!opt.ldap_wrapper_program || !*opt.ldap_wrapper_program)
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR_LDAP);
else
pgmname = opt.ldap_wrapper_program;
/* Create command line argument array. */
for (i = 0; argv[i]; i++)
;
arg_list = xtrycalloc (i + 2, sizeof *arg_list);
if (!arg_list)
{
err = gpg_error_from_syserror ();
log_error (_("error allocating memory: %s\n"), strerror (errno));
return err;
}
for (i = j = 0; argv[i]; i++, j++)
if (!i && argv[i + 1] && !strcmp (*argv, "--pass"))
{
arg_list[j] = "--env-pass";
setenv ("DIRMNGR_LDAP_PASS", argv[1], 1);
i++;
}
else
arg_list[j] = (char*) argv[i];
ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx)
{
err = gpg_error_from_syserror ();
log_error (_("error allocating memory: %s\n"), strerror (errno));
xfree (arg_list);
return err;
}
err = gnupg_create_inbound_pipe (outpipe);
if (!err)
{
err = gnupg_create_inbound_pipe (errpipe);
if (err)
{
close (outpipe[0]);
close (outpipe[1]);
}
}
if (err)
{
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
xfree (arg_list);
xfree (ctx);
return err;
}
err = gnupg_spawn_process_fd (pgmname, arg_list,
-1, outpipe[1], errpipe[1], &pid);
xfree (arg_list);
close (outpipe[1]);
close (errpipe[1]);
if (err)
{
close (outpipe[0]);
close (errpipe[0]);
xfree (ctx);
return err;
}
ctx->pid = pid;
ctx->printable_pid = (int) pid;
ctx->fd = outpipe[0];
ctx->log_fd = errpipe[0];
ctx->log_ev = pth_event (PTH_EVENT_FD | PTH_UNTIL_FD_READABLE, ctx->log_fd);
if (! ctx->log_ev)
{
xfree (ctx);
return gpg_error_from_syserror ();
}
ctx->ctrl = ctrl;
ctrl->refcount++;
ctx->stamp = time (NULL);
err = ksba_reader_new (reader);
if (!err)
err = ksba_reader_set_cb (*reader, reader_callback, ctx);
if (err)
{
log_error (_("error initializing reader object: %s\n"),
gpg_strerror (err));
destroy_wrapper (ctx);
ksba_reader_release (*reader);
*reader = NULL;
return err;
}
/* Hook the context into our list of running wrappers. */
ctx->reader = *reader;
ctx->next = wrapper_list;
wrapper_list = ctx;
if (opt.verbose)
log_info ("ldap wrapper %d started (reader %p)\n",
(int)ctx->pid, ctx->reader);
/* Need to wait for the first byte so we are able to detect an empty
output and not let the consumer see an EOF without further error
indications. The CRL loading logic assumes that after return
from this function, a failed search (e.g. host not found ) is
indicated right away. */
{
unsigned char c;
err = read_buffer (*reader, &c, 1);
if (err)
{
ldap_wrapper_release_context (*reader);
ksba_reader_release (*reader);
*reader = NULL;
if (gpg_err_code (err) == GPG_ERR_EOF)
return gpg_error (GPG_ERR_NO_DATA);
else
return err;
}
ksba_reader_unread (*reader, &c, 1);
}
return 0;
}
diff --git a/po/remove-potcdate.sed b/po/remove-potcdate.sed
deleted file mode 100644
index edb38d704..000000000
--- a/po/remove-potcdate.sed
+++ /dev/null
@@ -1,11 +0,0 @@
-/^"POT-Creation-Date: .*"$/{
-x
-s/P/P/
-ta
-g
-d
-bb
-:a
-x
-:b
-}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jan 16, 1:05 AM (16 h, 26 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
00/6f/bb2dddf159b39a882776c362801f
Attached To
rG GnuPG
Event Timeline
Log In to Comment