summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2005-07-27 16:18:59 +0200
committerWerner Koch <wk@gnupg.org>2005-07-27 16:18:59 +0200
commitcd570629b28f7fe08dba6366a399439a58eecc50 (patch)
tree3d23aea0d919c7ed53a3ad0d3c373cf7b0ca42a3
parentAdd a note that CVS is beeing migrated to Subversion (diff)
downloadgnupg2-cd570629b28f7fe08dba6366a399439a58eecc50.tar.xz
gnupg2-cd570629b28f7fe08dba6366a399439a58eecc50.zip
Removed directories which are only used by the 1.9 branch
-rw-r--r--agent/ChangeLog565
-rw-r--r--agent/Makefile.am62
-rw-r--r--agent/agent.h226
-rw-r--r--agent/cache.c314
-rw-r--r--agent/call-scd.c661
-rw-r--r--agent/command.c782
-rw-r--r--agent/divert-scd.c319
-rw-r--r--agent/findkey.c359
-rw-r--r--agent/genkey.c240
-rw-r--r--agent/gpg-agent.c1063
-rw-r--r--agent/keyformat.txt163
-rw-r--r--agent/learncard.c448
-rw-r--r--agent/minip12.c1140
-rw-r--r--agent/minip12.h33
-rw-r--r--agent/pkdecrypt.c138
-rw-r--r--agent/pksign.c185
-rw-r--r--agent/protect-tool.c977
-rw-r--r--agent/protect.c971
-rw-r--r--agent/query.c473
-rw-r--r--agent/sexp-parse.h98
-rw-r--r--agent/simple-pwquery.c486
-rw-r--r--agent/simple-pwquery.h69
-rw-r--r--agent/trans.c42
-rw-r--r--agent/trustlist.c306
-rw-r--r--common/ChangeLog219
-rw-r--r--common/Makefile.am58
-rw-r--r--common/README11
-rw-r--r--common/cryptmiss.c39
-rw-r--r--common/errors.h110
-rw-r--r--common/fopencookie.c37
-rw-r--r--common/fseeko.c40
-rw-r--r--common/ftello.c45
-rw-r--r--common/gettime.c250
-rw-r--r--common/i18n.h47
-rw-r--r--common/iobuf.c2415
-rw-r--r--common/iobuf.h170
-rw-r--r--common/isascii.c29
-rw-r--r--common/maperror.c157
-rw-r--r--common/membuf.c89
-rw-r--r--common/membuf.h41
-rw-r--r--common/miscellaneous.c126
-rw-r--r--common/mkdtemp.c99
-rwxr-xr-xcommon/mkerrors72
-rwxr-xr-xcommon/mkerrtok67
-rw-r--r--common/putc_unlocked.c31
-rw-r--r--common/signal.c226
-rw-r--r--common/simple-pwquery.c486
-rw-r--r--common/simple-pwquery.h69
-rw-r--r--common/sysutils.c206
-rw-r--r--common/sysutils.h30
-rw-r--r--common/ttyio.c508
-rw-r--r--common/ttyio.h40
-rw-r--r--common/util.h120
-rw-r--r--common/vasprintf.c169
-rw-r--r--common/yesno.c96
-rw-r--r--scd/ChangeLog242
-rw-r--r--scd/Makefile.am72
-rw-r--r--scd/apdu.c558
-rw-r--r--scd/apdu.h73
-rw-r--r--scd/app-common.h128
-rw-r--r--scd/app-openpgp.c1482
-rw-r--r--scd/app.c278
-rw-r--r--scd/atr.c287
-rw-r--r--scd/atr.h28
-rw-r--r--scd/card-common.h73
-rw-r--r--scd/card-dinsig.c260
-rw-r--r--scd/card-p15.c502
-rw-r--r--scd/card.c564
-rw-r--r--scd/command.c1034
-rw-r--r--scd/iso7816.c371
-rw-r--r--scd/iso7816.h56
-rw-r--r--scd/sc-copykeys.c731
-rw-r--r--scd/sc-investigate.c209
-rw-r--r--scd/scdaemon.c638
-rw-r--r--scd/scdaemon.h127
-rw-r--r--sm/ChangeLog816
-rw-r--r--sm/Makefile.am55
-rw-r--r--sm/base64.c624
-rw-r--r--sm/call-agent.c713
-rw-r--r--sm/call-dirmngr.c632
-rw-r--r--sm/certchain.c793
-rw-r--r--sm/certcheck.c300
-rw-r--r--sm/certdump.c457
-rw-r--r--sm/certlist.c315
-rw-r--r--sm/certreqgen.c699
-rw-r--r--sm/decrypt.c506
-rw-r--r--sm/delete.c165
-rw-r--r--sm/encrypt.c550
-rw-r--r--sm/export.c249
-rw-r--r--sm/fingerprint.c271
-rw-r--r--sm/gpgsm.c1458
-rw-r--r--sm/gpgsm.h274
-rw-r--r--sm/import.c349
-rw-r--r--sm/keydb.c1282
-rw-r--r--sm/keydb.h73
-rw-r--r--sm/keylist.c617
-rw-r--r--sm/misc.c32
-rw-r--r--sm/server.c1070
-rw-r--r--sm/sign.c621
-rw-r--r--sm/verify.c550
100 files changed, 0 insertions, 37406 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
deleted file mode 100644
index 10f4d45fa..000000000
--- a/agent/ChangeLog
+++ /dev/null
@@ -1,565 +0,0 @@
-2003-07-31 Werner Koch <wk@gnupg.org>
-
- * Makefile.am (gpg_agent_LDADD): Added INTLLIBS.
- (gpg_protect_tool_SOURCES): Added simple-pwquery.[ch]
-
-2003-07-27 Werner Koch <wk@gnupg.org>
-
- Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
-
-2003-07-15 Werner Koch <wk@gnupg.org>
-
- * simple-pwquery.c, simple-pwquery.h: Moved to ../common.
- * Makefile.am (gpg_protect_tool_LDADD): Add simple-pwquery.o.
- Removed it from xx_SOURCES.
-
-2003-07-04 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (handle_connections): Kludge to allow use of Pth 1
- and 2.
-
-2003-06-30 Werner Koch <wk@gnupg.org>
-
- * call-scd.c (learn_status_cb): Store the serialno in PARM.
-
-2003-06-26 Werner Koch <wk@gnupg.org>
-
- * call-scd.c (agent_card_serialno): Don't do a RESET anymore.
-
-2003-06-25 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_scd): New.
- * call-scd.c (agent_card_scd): New.
- * divert-scd.c (divert_generic_cmd): New
-
- * call-scd.c (agent_card_learn): New callback args SINFO.
- (learn_status_cb): Pass all other status lines to the sinfo
- callback.
- * learncard.c (release_sinfo, sinfo_cb): New.
- (agent_handle_learn): Pass the new cb to the learn function and
- pass the collected information back to the client's assuan
- connection.
-
- * gpg-agent.c (main): Moved pth_init before gcry_check_version.
-
-2003-06-24 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (handle_connections): Adjusted for Pth 2.0
-
- Adjusted for changes in the libgcrypt API. Some more fixes for the
- libgpg-error stuff.
-
-2003-06-04 Werner Koch <wk@gnupg.org>
-
- Renamed error codes from INVALID to INV and removed _ERROR suffixes.
-
-2003-06-03 Werner Koch <wk@gnupg.org>
-
- Changed all error codes in all files to the new libgpg-error scheme.
-
- * agent.h: Include gpg-error.h and errno.h
- * Makefile.am: Link with libgpg-error
-
- * query.c: assuan.h is now a system header.
- * genkey.c (agent_genkey): Fixed silly use of xmalloc by
- xtrymalloc.
-
-2003-04-29 Werner Koch <wk@gnupg.org>
-
- * command.c (register_commands): Adjusted for new Assuan semantics.
-
- * Makefile.am: Don't override LDFLAGS.
-
-2002-12-04 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c: New variable config_filename.
- (parse_rereadable_options): New.
- (main): Use it here. Add setting of default values, set
- config_filename.
- (reread_configuration): Filled with actual code.
-
-2002-12-03 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c (read_key): Don't run make_canonical on a NULL
- buffer.
-
- * command.c (parse_hexstring): New.
- (cmd_sethash): Use it.
- (parse_keygrip): New.
- (cmd_havekey, cmd_sigkey): Use it.
- (cmd_passwd): New.
- * genkey.c (agent_protect_and_store): New.
- (store_key): Add arg FORCE.
- (agent_genkey): Pass false to this force of store_key.
-
-2002-11-13 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): Switch all messages to utf-8.
-
- * simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and
- stdin with ttyname.
-
- * cache.c (new_data): Uiih - /sizeof d/sizeof *d/.
-
-2002-11-10 Werner Koch <wk@gnupg.org>
-
- * command.c (option_handler): Fix keep_tty check.
-
-2002-11-06 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): Make sure we have a default ttyname.
- * command.c (option_handler): Check opt.keep_tty here
- * query.c (start_pinentry): but not anymore here.
-
-2002-11-05 Werner Koch <wk@gnupg.org>
-
- * agent.h (opt,server_control_s): Move display and lc_ variables
- to the control struct so that they are per connection.
- * gpg-agent.c (agent_init_default_ctrl): New.
- (main): Assign those command line options to new default_* variables.
- Reset DISPLAY in server mode so that tehre is no implicit default.
- * command.c (start_command_handler): Initialize and deinitialize
- the control values.
- (option_handler): Work on the ctrl values and not on the opt.
- * query.c (start_pinentry): New argument CTRL to set the display
- connection specific. Changed all callers to pass this value.
- (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
- CTRL arg and pass it ot start_pinentry.
- * command.c (cmd_get_passphrase): Pass CTRL argument.
- * trustlist.c (agent_marktrusted): Add CTRL argument
- * command.c (cmd_marktrusted): Pass CTRL argument
- * divert-scd.c (ask_for_card): Add CTRL arg.
- (divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
- (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
- users.
- * findkey.c (unprotect): Add CTRL arg.
- (agent_key_from_file): Ditto.
-
- * query.c (unlock_pinentry): Disconnect the pinentry so that we
- start a new one for each request. This is required to support
- clients with different environments (e.g. X magic cookies).
-
-2002-09-05 Neal H. Walfield <neal@cs.uml.edu>
-
- * gpg-agent.c (main) [USE_GNU_PTH]: No need to call
- assuan_set_io_func as assuan is smart.
-
-2002-09-25 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (handle_signal): Flush cache on SIGHUP.
- * cache.c (agent_flush_cache): New.
-
- * gpg-agent.c, agent.h: Add --keep-display and --keep-tty.
- * query.c (start_pinentry): Implement them. The option passing
- needs more thoughts.
-
-2002-09-09 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (create_private_keys_directory)
- (create_directories): New.
- (main): Try to create a home directory.
-
-2002-09-04 Neal H. Walfield <neal@g10code.de>
-
- * gpg-agent.c (main): Use sigaction, not signal.
-
-2002-09-03 Neal H. Walfield <neal@g10code.de>
-
- * findkey.c: Include <fcntl.h>.
- (agent_write_private_key): Prefer POSIX compatibity, open and
- fdopen, over the simplicity of GNU extensions, fopen(file, "x").
-
-2002-08-22 Werner Koch <wk@gnupg.org>
-
- * query.c (agent_askpin): Provide the default desc text depending
- on the pininfo. Do the basic PIN verification only when
- min_digits is set.
-
-2002-08-21 Werner Koch <wk@gnupg.org>
-
- * query.c (agent_askpin): Hack to show the right default prompt.
- (agent_get_passphrase): Ditto.
-
- * trans.c: Removed and replaced all usages with standard _()
-
- * divert-scd.c (getpin_cb): Pass a more descritive text to the
- pinentry.
-
- * Makefile.am: Renamed the binary protect-tool to gpg-protect-tool.
- * protect-tool.c: Removed the note about internal use only.
-
- * gpg-agent.c (main): New option --daemon so that the program is
- not accidently started in the background.
-
-2002-08-16 Werner Koch <wk@gnupg.org>
-
- * call-scd.c (learn_status_cb): Handle CERTINFO status.
- (agent_card_learn): Add args for certinfo cb.
- * learncard.c (release_certinfo,certinfo_cb): New.
- (send_cert_back): New. With factored out code from ..
- (agent_handle_learn): here. Return certinfo stuff.
-
-2002-07-26 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): New option --ignore-cache-for-signing.
- * command.c (option_handler): New server option
- use-cache-for-signing defaulting to true.
- (cmd_pksign): handle global and per session option.
- * findkey.c (agent_key_from_file, unprotect): New arg
- ignore_cache. Changed all callers.
- * pksign.c (agent_pksign): Likewise.
-
-2002-06-29 Werner Koch <wk@gnupg.org>
-
- * query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY.
- * call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON.
-
-2002-06-28 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c (export_p12_file): New.
- (main): New command --p12-export.
- * minip12.c (create_final,p12_build,compute_tag_length): New.
- (store_tag_length): New.
-
-2002-06-27 Werner Koch <wk@gnupg.org>
-
- * minip12.c (crypt_block): Renamed from decrypt_block, add arg to
- allow encryption.
-
- * Makefile.am (pkglib_PROGRAMS): Put protect-tool there.
-
- * findkey.c (agent_write_private_key,agent_key_from_file)
- (agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant.
- * gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
-
- * protect-tool.c (store_private_key): New.
- (import_p12_file): Store the new file if requested.
- (main): New options --force and --store.
-
- * gpg-agent.c (main): Set a global flag when running detached.
- * query.c (start_pinentry): Pass the list of FD to keep in the
- child when not running detached.
- * call-scd.c (start_scd): Ditto.
-
-2002-06-26 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted)
- (cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase)
- (cmd_learn): Print an error message for a failed operation.
-
- * simple-pwquery.c, simple-pwquery.h: New.
- * protect-tool. (get_passphrase): New, used to get a passphrase
- from the agent if none was given on the command line.
-
-2002-06-25 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c (rsa_key_check): New.
- (import_p12_file): New.
- (main): New command --p12-import.
- * minip12.c, minip12.h: New.
-
-2002-06-24 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c (read_file): New.
- (read_key): Factored most code out to read_file.
-
-2002-06-17 Werner Koch <wk@gnupg.org>
-
- * agent.h: Add a callback function to the pin_entry_info structure.
- * query.c (agent_askpin): Use the callback to check for a correct
- PIN. Removed the start_err_text argument because it is not
- anymore needed; changed callers.
- * findkey.c (unprotect): Replace our own check loop by a callback.
- (try_unprotect_cb): New.
- * genkey.c (reenter_compare_cb): New.
- (agent_genkey): Use this callback here. Fixed setting of the pi2
- variable and a segv in case of an empty PIN.
-
- * divert-scd.c (getpin_cb): Removed some unused stuff and
- explained what we still have to change.
-
-2002-06-12 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): New option --disable-pth.
-
-2002-06-11 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c: Add command --show-keygrip
- (show_keygrip): New.
-
-2002-05-23 Werner Koch <wk@gnupg.org>
-
- * call-scd.c: Seirialized all scdaeom access when using Pth.
-
- * cache.c: Made the cache Pth-thread-safe.
- (agent_unlock_cache_entry): New.
- * findkey.c (unprotect): Unlock the returned cache value.
- * command.c (cmd_get_passphrase): Ditto.
-
- * gpg-agent.c (main): Register pth_read/write with Assuan.
-
-2002-05-22 Werner Koch <wk@gnupg.org>
-
- * query.c: Serialized all pinentry access when using Pth.
-
- * gpg-agent.c (handle_signal,start_connection_thread)
- (handle_connections): New
- (main): Use the new Pth stuff to allow concurrent connections.
- * command.c (start_command_handler): Add new arg FD so that the
- fucntion can also be used for an already connected socket.
- * Makefile.am: Link with Pth.
-
-2002-05-14 Werner Koch <wk@gnupg.org>
-
- * cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
-
-2002-04-26 Werner Koch <wk@gnupg.org>
-
- * cache.c (agent_put_cache): Reinitialize the creation time and
- the ttl when reusing a slot.
-
- * call-scd.c (start_scd): Print debug messages only with debug
- flags set.
- * query.c (start_pinentry): Ditto.
-
-2002-04-25 Marcus Brinkmann <marcus@g10code.de>
-
- * agent.h (agent_get_confirmation): Replace paramter prompt with
- two parameters ok and cancel.
- * query.c (agent_get_confirmation): Likewise. Implement this.
- * trustlist.c (agent_marktrusted): Fix invocation of
- agent_get_confirmation.
- * divert-scd.c (ask_for_card): Likewise.
-
-2002-04-24 Marcus Brinkmann <marcus@g10code.de>
-
- * agent.h (struct opt): Add members display, ttyname, ttytype,
- lc_ctype, and lc_messages.
- * gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname,
- oTTYtype, oLCctype, and LCmessages.
- (main): Handle these options.
- * command.c (option_handler): New function.
- (register_commands): Register option handler.
- * query.c (start_pinentry): Pass the various display and tty
- options to the pinentry.
-
-2002-04-05 Werner Koch <wk@gnupg.org>
-
- * protect-tool.c (show_file): New. Used as default action.
-
-2002-03-28 Werner Koch <wk@gnupg.org>
-
- * divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding,
- the scdaemon should take care of it.
- (ask_for_card): Hack to not display the trailing zero.
-
-2002-03-11 Werner Koch <wk@gnupg.org>
-
- * learncard.c (kpinfo_cb): Remove the content restrictions from
- the keyID.
-
-2002-03-06 Werner Koch <wk@gnupg.org>
-
- * learncard.c: New.
- * divert-scd.c (ask_for_card): The serial number is binary so
- convert it to hex here.
- * findkey.c (agent_write_private_key): New.
- * genkey.c (store_key): And use it here.
-
- * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done.
- * divert-scd.c (divert_pkdecrypt): Changed interface and
- implemented it.
-
-2002-03-05 Werner Koch <wk@gnupg.org>
-
- * call-scd.c (inq_needpin): New.
- (agent_card_pksign): Add getpin_cb args.
- (agent_card_pkdecrypt): New.
-
-2002-03-04 Werner Koch <wk@gnupg.org>
-
- * pksign.c (agent_pksign): Changed how the diversion is done.
- * divert-scd.c (divert_pksign): Changed interface and implemented it.
- (encode_md_for_card): New.
- * call-scd.c (agent_card_pksign): New.
-
-2002-02-28 Werner Koch <wk@gnupg.org>
-
- * pksign.c (agent_pksign): Detect whether a Smartcard is to be
- used and divert the operation in this case.
- * pkdecrypt.c (agent_pkdecrypt): Likewise
- * findkey.c (agent_key_from_file): Add optional arg shadow_info
- and have it return information about a shadowed key.
- * protect.c (agent_get_shadow_info): New.
-
- * protect.c (snext,sskip,smatch): Moved to
- * sexp-parse.h: new file.
- * divert-scd.c: New.
-
-2002-02-27 Werner Koch <wk@gnupg.org>
-
- * protect.c (agent_shadow_key): New.
-
- * command.c (cmd_learn): New command LEARN.
- * gpg-agent.c: New option --scdaemon-program.
- * call-scd.c (start_scd): New. Based on query.c
- * query.c: Add 2 more arguments to all uses of assuan_transact.
-
-2002-02-18 Werner Koch <wk@gnupg.org>
-
- * findkey.c (unprotect): Show an error message for a bad passphrase.
-
- * command.c (cmd_marktrusted): Implemented.
- * trustlist.c (agent_marktrusted): New.
- (open_list): Add APPEND arg.
-
- * query.c (agent_get_confirmation): New.
-
-2002-02-06 Werner Koch <wk@gnupg.org>
-
- * cache.c (housekeeping): Fixed linking in the remove case.
-
-2002-02-01 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c: New option --default-cache-ttl.
- * cache.c (agent_put_cache): Use it.
-
- * cache.c: Add a few debug outputs.
-
- * protect.c (agent_private_key_type): New.
- * agent.h: Add PRIVATE_KEY_ enums.
- * findkey.c (agent_key_from_file): Use it to decide whether we
- have to unprotect a key.
- (unprotect): Cache the passphrase.
-
- * findkey.c (agent_key_from_file,agent_key_available): The key
- files do now require a ".key" suffix to make a script's life
- easier.
- * genkey.c (store_key): Ditto.
-
-2002-01-31 Werner Koch <wk@gnupg.org>
-
- * genkey.c (store_key): Protect the key.
- (agent_genkey): Ask for the passphrase.
- * findkey.c (unprotect): Actually unprotect the key.
- * query.c (agent_askpin): Add an optional start_err_text.
-
-2002-01-30 Werner Koch <wk@gnupg.org>
-
- * protect.c: New.
- (hash_passphrase): Based on the GnuPG 1.0.6 version.
- * protect-tool.c: New
-
-2002-01-29 Werner Koch <wk@gnupg.org>
-
- * findkey.c (agent_key_available): New.
- * command.c (cmd_havekey): New.
- (register_commands): And register new command.
-
-2002-01-20 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_get_passphrase): Remove the plus signs.
-
- * query.c (start_pinentry): Send no-grab option to pinentry
- * gpg-agent.c (main): Move variable grab as no_grab to agent.h.
-
-2002-01-19 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): Disable core dumps.
-
- * cache.c: New.
- * command.c (cmd_get_passphrase): Use the cache.
- (cmd_clear_passphrase): Ditto.
-
- * gpg-agent.c: Removed unused cruft and implement the socket
- based server.
- (my_strusage): Take bug report address from configure.ac.
- * command.c (start_command_handler): Add an argument to start as
- regular server.
- (start_command_handler): Enable Assuan logging.
-
-2002-01-15 Werner Koch <wk@gnupg.org>
-
- * trustlist.c: New.
- * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.
-
-2002-01-07 Werner Koch <wk@gnupg.org>
-
- * genkey.c: Store the secret part and return the public part.
-
-2002-01-03 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_get_passphrase): New.
- (cmd_clear_passphrase): New.
- * query.c (agent_get_passphrase): New.
-
-2002-01-02 Werner Koch <wk@gnupg.org>
-
- * genkey.c: New.
- * command.c (cmd_genkey): New.
-
- * command.c (rc_to_assuan_status): Removed and changed all callers
- to use map_to_assuan_status.
-
-2001-12-19 Werner Koch <wk@gnupg.org>
-
- * keyformat.txt: New.
-
-2001-12-19 Marcus Brinkmann <marcus@g10code.de>
-
- * query.c (start_pinentry): Add new argument to assuan_pipe_connect.
-
-2001-12-18 Werner Koch <wk@gnupg.org>
-
- * Makefile.am: Use LIBGCRYPT macros
-
-2001-12-14 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): New option --batch. New option --debug-wait
- n, so that it is possible to attach gdb when used in server mode.
- * query.c (agent_askpin): Don't ask in batch mode.
-
- * command.c: Removed the conversion macros as they are now in
- ../common/util.h.
-
-2001-12-14 Marcus Brinkmann <marcus@g10code.de>
-
- * query.c (LINELENGTH): Removed.
- (agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH.
-
-2001-11-19 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c: Removed all GUI code, removed code for old
- protocol. New code to use the Assuan protocol as a server and
- also to communicate with a new ask-passphrase utility.
-
-2000-11-22 Werner Koch <wk@gnupg.org>
-
- * gpg-agent.c (main): csh support by Dan Winship, new options --sh
- and --csh and set default by consulting $SHELL.
-
-Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de>
-
- * gpg-agent.c (passphrase_dialog): Cleanup the window and added the
- user supplied text to the window.
- (main): Fixed segv in gtk_init when used without a command to start.
-
- * gpg-agent.c: --flush option.
- (req_flush): New.
- (req_clear_passphrase): Implemented.
-
-Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de>
-
- * gpg-agent.c: New.
- * Makefile.am: New.
-
-
- Copyright 2001, 2002 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/agent/Makefile.am b/agent/Makefile.am
deleted file mode 100644
index 400aa2fd2..000000000
--- a/agent/Makefile.am
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright (C) 2001, 2003 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-## Process this file with automake to produce Makefile.in
-
-localedir = $(datadir)/locale
-INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
-
-bin_PROGRAMS = gpg-agent
-pkglib_PROGRAMS = gpg-protect-tool
-
-AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) \
- $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
-
-gpg_agent_SOURCES = \
- gpg-agent.c agent.h \
- command.c \
- query.c \
- cache.c \
- trans.c \
- findkey.c \
- pksign.c \
- pkdecrypt.c \
- genkey.c \
- protect.c \
- trustlist.c \
- divert-scd.c \
- call-scd.c \
- learncard.c \
- sexp-parse.h
-
-
-gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
- $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \
- -lgpg-error @INTLLIBS@
-
-gpg_protect_tool_SOURCES = \
- protect-tool.c \
- protect.c \
- simple-pwquery.c simple-pwquery.h \
- minip12.c minip12.h
-
-gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \
- ../common/libcommon.a ../common/libsimple-pwquery.a \
- $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@
-
-
diff --git a/agent/agent.h b/agent/agent.h
deleted file mode 100644
index eb4f4e32d..000000000
--- a/agent/agent.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* agent.h - Global definitions for the agent
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef AGENT_H
-#define AGENT_H
-
-#ifdef GPG_ERR_SOURCE_DEFAULT
-#error GPG_ERR_SOURCE_DEFAULT already defined
-#endif
-#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGAGENT
-#include <gpg-error.h>
-#include <errno.h>
-
-#include <gcrypt.h>
-#include "../common/util.h"
-#include "../common/errors.h"
-
-/* Convenience function to be used instead of returning the old
- GNUPG_Out_Of_Core. */
-static __inline__ gpg_error_t
-out_of_core (void)
-{
- return gpg_error (gpg_err_code_from_errno (errno));
-}
-
-#define MAX_DIGEST_LEN 24
-
-/* A large struct name "opt" to keep global flags */
-struct {
- unsigned int debug; /* debug flags (DBG_foo_VALUE) */
- int verbose; /* verbosity level */
- int quiet; /* be as quiet as possible */
- int dry_run; /* don't change any persistent data */
- int batch; /* batch mode */
- const char *homedir; /* configuration directory name */
- const char *pinentry_program;
- const char *scdaemon_program;
- int no_grab; /* don't let the pinentry grab the keyboard */
- unsigned long def_cache_ttl;
-
- int running_detached; /* we are running detached from the tty. */
-
- int ignore_cache_for_signing;
- int keep_tty; /* don't switch the TTY (for pinentry) on request */
- int keep_display; /* don't switch the DISPLAY (for pinentry) on request */
-} opt;
-
-
-#define DBG_COMMAND_VALUE 1 /* debug commands i/o */
-#define DBG_MPI_VALUE 2 /* debug mpi details */
-#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
-#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
-#define DBG_CACHE_VALUE 64 /* debug the caching */
-#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
-#define DBG_HASHING_VALUE 512 /* debug hashing operations */
-#define DBG_ASSUAN_VALUE 1024
-
-#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
-#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
-#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
-#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
-#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
-#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
-
-struct server_local_s;
-
-struct server_control_s {
- struct server_local_s *server_local;
- char *display;
- char *ttyname;
- char *ttytype;
- char *lc_ctype;
- char *lc_messages;
- struct {
- int algo;
- unsigned char value[MAX_DIGEST_LEN];
- int valuelen;
- } digest;
- char keygrip[20];
- int have_keygrip;
-
-};
-typedef struct server_control_s *CTRL;
-
-
-struct pin_entry_info_s {
- int min_digits; /* min. number of digits required or 0 for freeform entry */
- int max_digits; /* max. number of allowed digits allowed*/
- int max_tries;
- int failed_tries;
- int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */
- void *check_cb_arg; /* optional argument which might be of use in the CB */
- const char *cb_errtext; /* used by the cb to displaye a specific error */
- size_t max_length; /* allocated length of the buffer */
- char pin[1];
-};
-
-
-enum {
- PRIVATE_KEY_UNKNOWN = 0,
- PRIVATE_KEY_CLEAR = 1,
- PRIVATE_KEY_PROTECTED = 2,
- PRIVATE_KEY_SHADOWED = 3
-};
-
-/*-- gpg-agent.c --*/
-void agent_exit (int rc); /* also implemented in other tools */
-void agent_init_default_ctrl (struct server_control_s *ctrl);
-
-/*-- command.c --*/
-void start_command_handler (int, int);
-
-/*-- findkey.c --*/
-int agent_write_private_key (const unsigned char *grip,
- const void *buffer, size_t length, int force);
-gcry_sexp_t agent_key_from_file (CTRL ctrl, const unsigned char *grip,
- unsigned char **shadow_info,
- int ignore_cache);
-int agent_key_available (const unsigned char *grip);
-
-/*-- query.c --*/
-int agent_askpin (CTRL ctrl,
- const char *desc_text, struct pin_entry_info_s *pininfo);
-int agent_get_passphrase (CTRL ctrl, char **retpass,
- const char *desc, const char *prompt,
- const char *errtext);
-int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok,
- const char *cancel);
-
-/*-- cache.c --*/
-void agent_flush_cache (void);
-int agent_put_cache (const char *key, const char *data, int ttl);
-const char *agent_get_cache (const char *key, void **cache_id);
-void agent_unlock_cache_entry (void **cache_id);
-
-
-/*-- pksign.c --*/
-int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache);
-
-/*-- pkdecrypt.c --*/
-int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
- FILE *outfp);
-
-/*-- genkey.c --*/
-int agent_genkey (CTRL ctrl,
- const char *keyparam, size_t keyparmlen, FILE *outfp);
-int agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey);
-
-/*-- protect.c --*/
-int agent_protect (const unsigned char *plainkey, const char *passphrase,
- unsigned char **result, size_t *resultlen);
-int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
- unsigned char **result, size_t *resultlen);
-int agent_private_key_type (const unsigned char *privatekey);
-int agent_shadow_key (const unsigned char *pubkey,
- const unsigned char *shadow_info,
- unsigned char **result);
-int agent_get_shadow_info (const unsigned char *shadowkey,
- unsigned char const **shadow_info);
-
-
-/*-- trustlist.c --*/
-int agent_istrusted (const char *fpr);
-int agent_listtrusted (void *assuan_context);
-int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag);
-
-
-/*-- divert-scd.c --*/
-int divert_pksign (CTRL ctrl,
- const unsigned char *digest, size_t digestlen, int algo,
- const unsigned char *shadow_info, unsigned char **r_sig);
-int divert_pkdecrypt (CTRL ctrl,
- const unsigned char *cipher,
- const unsigned char *shadow_info,
- char **r_buf, size_t *r_len);
-int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context);
-
-
-/*-- call-scd.c --*/
-int agent_card_learn (void (*kpinfo_cb)(void*, const char *),
- void *kpinfo_cb_arg,
- void (*certinfo_cb)(void*, const char *),
- void *certinfo_cb_arg,
- void (*sinfo_cb)(void*, const char *,
- size_t, const char *),
- void *sinfo_cb_arg);
-int agent_card_serialno (char **r_serialno);
-int agent_card_pksign (const char *keyid,
- int (*getpin_cb)(void *, const char *, char*, size_t),
- void *getpin_cb_arg,
- const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen);
-int agent_card_pkdecrypt (const char *keyid,
- int (*getpin_cb)(void *, const char *, char*,size_t),
- void *getpin_cb_arg,
- const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen);
-int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen);
-int agent_card_readkey (const char *id, unsigned char **r_buf);
-int agent_card_scd (const char *cmdline,
- int (*getpin_cb)(void *, const char *, char*, size_t),
- void *getpin_cb_arg, void *assuan_context);
-
-
-/*-- learncard.c --*/
-int agent_handle_learn (void *assuan_context);
-
-
-#endif /*AGENT_H*/
diff --git a/agent/cache.c b/agent/cache.c
deleted file mode 100644
index b6ab55085..000000000
--- a/agent/cache.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/* cache.c - keep a cache of passphrases
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <assert.h>
-
-#include "agent.h"
-
-struct secret_data_s {
- int totallen; /* this includes the padding */
- int datalen; /* actual data length */
- char data[1];
-};
-
-typedef struct cache_item_s *ITEM;
-struct cache_item_s {
- ITEM next;
- time_t created;
- time_t accessed;
- int ttl; /* max. lifetime given in seonds */
- int lockcount;
- struct secret_data_s *pw;
- char key[1];
-};
-
-
-static ITEM thecache;
-
-
-static void
-release_data (struct secret_data_s *data)
-{
- xfree (data);
-}
-
-static struct secret_data_s *
-new_data (const void *data, size_t length)
-{
- struct secret_data_s *d;
- int total;
-
- /* we pad the data to 32 bytes so that it get more complicated
- finding something out by watching allocation patterns. This is
- usally not possible but we better assume nothing about our
- secure storage provider*/
- total = length + 32 - (length % 32);
-
- d = gcry_malloc_secure (sizeof *d + total - 1);
- if (d)
- {
- d->totallen = total;
- d->datalen = length;
- memcpy (d->data, data, length);
- }
- return d;
-}
-
-
-/* check whether there are items to expire */
-static void
-housekeeping (void)
-{
- ITEM r, rprev;
- time_t current = gnupg_get_time ();
-
- /* first expire the actual data */
- for (r=thecache; r; r = r->next)
- {
- if (!r->lockcount && r->pw && r->accessed + r->ttl < current)
- {
- if (DBG_CACHE)
- log_debug (" expired `%s' (%ds after last access)\n",
- r->key, r->ttl);
- release_data (r->pw);
- r->pw = NULL;
- r->accessed = current;
- }
- }
-
- /* second, make sure that we also remove them based on the created stamp so
- that the user has to enter it from time to time. We do this every hour */
- for (r=thecache; r; r = r->next)
- {
- if (!r->lockcount && r->pw && r->created + 60*60 < current)
- {
- if (DBG_CACHE)
- log_debug (" expired `%s' (1h after creation)\n", r->key);
- release_data (r->pw);
- r->pw = NULL;
- r->accessed = current;
- }
- }
-
- /* third, make sure that we don't have too many items in the list.
- Expire old and unused entries after 30 minutes */
- for (rprev=NULL, r=thecache; r; )
- {
- if (!r->pw && r->accessed + 60*30 < current)
- {
- if (r->lockcount)
- {
- log_error ("can't remove unused cache entry `%s' due to"
- " lockcount=%d\n",
- r->key, r->lockcount);
- r->accessed += 60*10; /* next error message in 10 minutes */
- rprev = r;
- r = r->next;
- }
- else
- {
- ITEM r2 = r->next;
- if (DBG_CACHE)
- log_debug (" removed `%s' (slot not used for 30m)\n", r->key);
- xfree (r);
- if (!rprev)
- thecache = r2;
- else
- rprev->next = r2;
- r = r2;
- }
- }
- else
- {
- rprev = r;
- r = r->next;
- }
- }
-}
-
-
-void
-agent_flush_cache (void)
-{
- ITEM r;
-
- if (DBG_CACHE)
- log_debug ("agent_flush_cache\n");
-
- for (r=thecache; r; r = r->next)
- {
- if (!r->lockcount && r->pw)
- {
- if (DBG_CACHE)
- log_debug (" flushing `%s'\n", r->key);
- release_data (r->pw);
- r->pw = NULL;
- r->accessed = 0;
- }
- else if (r->lockcount && r->pw)
- {
- if (DBG_CACHE)
- log_debug (" marked `%s' for flushing\n", r->key);
- r->accessed = 0;
- r->ttl = 0;
- }
- }
-}
-
-
-
-/* Store DATA of length DATALEN in the cache under KEY and mark it
- with a maximum lifetime of TTL seconds. If there is already data
- under this key, it will be replaced. Using a DATA of NULL deletes
- the entry */
-int
-agent_put_cache (const char *key, const char *data, int ttl)
-{
- ITEM r;
-
- if (DBG_CACHE)
- log_debug ("agent_put_cache `%s'\n", key);
- housekeeping ();
-
- if (ttl < 1)
- ttl = opt.def_cache_ttl;
- if (!ttl)
- return 0;
-
- for (r=thecache; r; r = r->next)
- {
- if (!r->lockcount && !strcmp (r->key, key))
- break;
- }
- if (r)
- { /* replace */
- if (r->pw)
- {
- release_data (r->pw);
- r->pw = NULL;
- }
- if (data)
- {
- r->created = r->accessed = gnupg_get_time ();
- r->ttl = ttl;
- r->pw = new_data (data, strlen (data)+1);
- if (!r->pw)
- log_error ("out of core while allocating new cache item\n");
- }
- }
- else if (data)
- { /* simply insert */
- r = xtrycalloc (1, sizeof *r + strlen (key));
- if (!r)
- log_error ("out of core while allocating new cache control\n");
- else
- {
- strcpy (r->key, key);
- r->created = r->accessed = gnupg_get_time ();
- r->ttl = ttl;
- r->pw = new_data (data, strlen (data)+1);
- if (!r->pw)
- {
- log_error ("out of core while allocating new cache item\n");
- xfree (r);
- }
- else
- {
- r->next = thecache;
- thecache = r;
- }
- }
- }
- return 0;
-}
-
-
-/* Try to find an item in the cache */
-const char *
-agent_get_cache (const char *key, void **cache_id)
-{
- ITEM r;
-
- if (DBG_CACHE)
- log_debug ("agent_get_cache `%s'...\n", key);
- housekeeping ();
-
- /* first try to find one with no locks - this is an updated cache
- entry: We might have entries with a lockcount and without a
- lockcount. */
- for (r=thecache; r; r = r->next)
- {
- if (!r->lockcount && r->pw && !strcmp (r->key, key))
- {
- /* put_cache does only put strings into the cache, so we
- don't need the lengths */
- r->accessed = gnupg_get_time ();
- if (DBG_CACHE)
- log_debug ("... hit\n");
- r->lockcount++;
- *cache_id = r;
- return r->pw->data;
- }
- }
- /* again, but this time get even one with a lockcount set */
- for (r=thecache; r; r = r->next)
- {
- if (r->pw && !strcmp (r->key, key))
- {
- r->accessed = gnupg_get_time ();
- if (DBG_CACHE)
- log_debug ("... hit (locked)\n");
- r->lockcount++;
- *cache_id = r;
- return r->pw->data;
- }
- }
- if (DBG_CACHE)
- log_debug ("... miss\n");
-
- *cache_id = NULL;
- return NULL;
-}
-
-
-void
-agent_unlock_cache_entry (void **cache_id)
-{
- ITEM r;
-
- for (r=thecache; r; r = r->next)
- {
- if (r == *cache_id)
- {
- if (!r->lockcount)
- log_error ("trying to unlock non-locked cache entry `%s'\n",
- r->key);
- else
- r->lockcount--;
- return;
- }
- }
-}
diff --git a/agent/call-scd.c b/agent/call-scd.c
deleted file mode 100644
index 14487f1e3..000000000
--- a/agent/call-scd.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/* call-scd.c - fork of the scdaemon to do SC operations
- * Copyright (C) 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* Fixme: For now we have serialized all access to the scdaemon which
- make sense becuase the scdaemon can't handle concurrent connections
- right now. We should however keep a list of connections and lock
- just that connection - it migth make sense to implemtn parts of
- this in Assuan.*/
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#ifdef USE_GNU_PTH
-# include <pth.h>
-#endif
-
-#include "agent.h"
-#include <assuan.h>
-
-#ifdef _POSIX_OPEN_MAX
-#define MAX_OPEN_FDS _POSIX_OPEN_MAX
-#else
-#define MAX_OPEN_FDS 20
-#endif
-
-static ASSUAN_CONTEXT scd_ctx = NULL;
-#ifdef USE_GNU_PTH
-static pth_mutex_t scd_lock = PTH_MUTEX_INIT;
-#endif
-
-/* callback parameter for learn card */
-struct learn_parm_s {
- void (*kpinfo_cb)(void*, const char *);
- void *kpinfo_cb_arg;
- void (*certinfo_cb)(void*, const char *);
- void *certinfo_cb_arg;
- void (*sinfo_cb)(void*, const char *, size_t, const char *);
- void *sinfo_cb_arg;
-};
-
-struct inq_needpin_s {
- ASSUAN_CONTEXT ctx;
- int (*getpin_cb)(void *, const char *, char*, size_t);
- void *getpin_cb_arg;
-};
-
-struct membuf {
- size_t len;
- size_t size;
- char *buf;
- int out_of_core;
-};
-
-
-
-/* A simple implementation of a dynamic buffer. Use init_membuf() to
- create a buffer, put_membuf to append bytes and get_membuf to
- release and return the buffer. Allocation errors are detected but
- only returned at the final get_membuf(), this helps not to clutter
- the code with out of core checks. */
-
-static void
-init_membuf (struct membuf *mb, int initiallen)
-{
- mb->len = 0;
- mb->size = initiallen;
- mb->out_of_core = 0;
- mb->buf = xtrymalloc (initiallen);
- if (!mb->buf)
- mb->out_of_core = 1;
-}
-
-static void
-put_membuf (struct membuf *mb, const void *buf, size_t len)
-{
- if (mb->out_of_core)
- return;
-
- if (mb->len + len >= mb->size)
- {
- char *p;
-
- mb->size += len + 1024;
- p = xtryrealloc (mb->buf, mb->size);
- if (!p)
- {
- mb->out_of_core = 1;
- return;
- }
- mb->buf = p;
- }
- memcpy (mb->buf + mb->len, buf, len);
- mb->len += len;
-}
-
-static void *
-get_membuf (struct membuf *mb, size_t *len)
-{
- char *p;
-
- if (mb->out_of_core)
- {
- xfree (mb->buf);
- mb->buf = NULL;
- return NULL;
- }
-
- p = mb->buf;
- *len = mb->len;
- mb->buf = NULL;
- mb->out_of_core = 1; /* don't allow a reuse */
- return p;
-}
-
-
-
-
-static int
-unlock_scd (int rc)
-{
-#ifdef USE_GNU_PTH
- if (!pth_mutex_release (&scd_lock))
- {
- log_error ("failed to release the SCD lock\n");
- if (!rc)
- rc = gpg_error (GPG_ERR_INTERNAL);
- }
-#endif
- return rc;
-}
-
-/* Fork off the SCdaemon if this has not already been done */
-static int
-start_scd (void)
-{
- int rc;
- const char *pgmname;
- ASSUAN_CONTEXT ctx;
- const char *argv[3];
- int no_close_list[3];
- int i;
-
-#ifdef USE_GNU_PTH
- if (!pth_mutex_acquire (&scd_lock, 0, NULL))
- {
- log_error ("failed to acquire the SCD lock\n");
- return gpg_error (GPG_ERR_INTERNAL);
- }
-#endif
-
- if (scd_ctx)
- return 0; /* No need to serialize things because the agent is
- expected to tun as a single-thread (or may be in
- future using libpth) */
-
- if (opt.verbose)
- log_info ("no running SCdaemon - starting it\n");
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return unlock_scd (tmperr);
- }
-
- if (!opt.scdaemon_program || !*opt.scdaemon_program)
- opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON;
- if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
- pgmname = opt.scdaemon_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (!opt.running_detached)
- {
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- }
- no_close_list[i] = -1;
-
- /* connect to the pinentry and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv,
- no_close_list);
- if (rc)
- {
- log_error ("can't connect to the SCdaemon: %s\n",
- assuan_strerror (rc));
- return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON));
- }
- scd_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to SCdaemon established\n");
- return 0;
-}
-
-
-
-static AssuanError
-learn_status_cb (void *opaque, const char *line)
-{
- struct learn_parm_s *parm = opaque;
- const char *keyword = line;
- int keywordlen;
-
- for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
- ;
- while (spacep (line))
- line++;
- if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
- {
- parm->certinfo_cb (parm->certinfo_cb_arg, line);
- }
- else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
- {
- parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
- }
- else if (keywordlen && *line)
- {
- parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
- }
-
- return 0;
-}
-
-/* Perform the learn command and return a list of all private keys
- stored on the card. */
-int
-agent_card_learn (void (*kpinfo_cb)(void*, const char *),
- void *kpinfo_cb_arg,
- void (*certinfo_cb)(void*, const char *),
- void *certinfo_cb_arg,
- void (*sinfo_cb)(void*, const char *, size_t, const char *),
- void *sinfo_cb_arg)
-{
- int rc;
- struct learn_parm_s parm;
-
- rc = start_scd ();
- if (rc)
- return rc;
-
- memset (&parm, 0, sizeof parm);
- parm.kpinfo_cb = kpinfo_cb;
- parm.kpinfo_cb_arg = kpinfo_cb_arg;
- parm.certinfo_cb = certinfo_cb;
- parm.certinfo_cb_arg = certinfo_cb_arg;
- parm.sinfo_cb = sinfo_cb;
- parm.sinfo_cb_arg = sinfo_cb_arg;
- rc = assuan_transact (scd_ctx, "LEARN --force",
- NULL, NULL, NULL, NULL,
- learn_status_cb, &parm);
- if (rc)
- return unlock_scd (map_assuan_err (rc));
-
- return unlock_scd (0);
-}
-
-
-
-static AssuanError
-get_serialno_cb (void *opaque, const char *line)
-{
- char **serialno = opaque;
- const char *keyword = line;
- const char *s;
- int keywordlen, n;
-
- for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
- ;
- while (spacep (line))
- line++;
-
- if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
- {
- if (*serialno)
- return ASSUAN_Unexpected_Status;
- for (n=0,s=line; hexdigitp (s); s++, n++)
- ;
- if (!n || (n&1)|| !(spacep (s) || !*s) )
- return ASSUAN_Invalid_Status;
- *serialno = xtrymalloc (n+1);
- if (!*serialno)
- return ASSUAN_Out_Of_Core;
- memcpy (*serialno, line, n);
- (*serialno)[n] = 0;
- }
-
- return 0;
-}
-
-/* Return the serial number of the card or an appropriate error. The
- serial number is returned as a hexstring. */
-int
-agent_card_serialno (char **r_serialno)
-{
- int rc;
- char *serialno = NULL;
-
- rc = start_scd ();
- if (rc)
- return rc;
-
- /* Hmm, do we really need this reset - scddaemon should do this or
- we can do this if we for some reason figure out that the
- operation might have failed due to a missing RESET. Hmmm, I feel
- this is really SCdaemon's duty */
-/* rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); */
-/* if (rc) */
-/* return unlock_scd (map_assuan_err (rc)); */
-
- rc = assuan_transact (scd_ctx, "SERIALNO",
- NULL, NULL, NULL, NULL,
- get_serialno_cb, &serialno);
- if (rc)
- {
- xfree (serialno);
- return unlock_scd (map_assuan_err (rc));
- }
- *r_serialno = serialno;
- return unlock_scd (0);
-}
-
-
-static AssuanError
-membuf_data_cb (void *opaque, const void *buffer, size_t length)
-{
- struct membuf *data = opaque;
-
- if (buffer)
- put_membuf (data, buffer, length);
- return 0;
-}
-
-/* Handle the NEEDPIN inquiry. */
-static AssuanError
-inq_needpin (void *opaque, const char *line)
-{
- struct inq_needpin_s *parm = opaque;
- char *pin;
- size_t pinlen;
- int rc;
-
- if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
- {
- log_error ("unsupported inquiry `%s'\n", line);
- return ASSUAN_Inquire_Unknown;
- }
- line += 7;
-
- pinlen = 90;
- pin = gcry_malloc_secure (pinlen);
- if (!pin)
- return ASSUAN_Out_Of_Core;
-
- rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
- if (rc)
- rc = ASSUAN_Canceled;
- if (!rc)
- rc = assuan_send_data (parm->ctx, pin, pinlen);
- xfree (pin);
-
- return rc;
-}
-
-
-
-/* Create a signature using the current card */
-int
-agent_card_pksign (const char *keyid,
- int (*getpin_cb)(void *, const char *, char*, size_t),
- void *getpin_cb_arg,
- const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen)
-{
- int rc, i;
- char *p, line[ASSUAN_LINELENGTH];
- struct membuf data;
- struct inq_needpin_s inqparm;
- size_t len;
- unsigned char *sigbuf;
- size_t sigbuflen;
-
- *r_buf = NULL;
- rc = start_scd ();
- if (rc)
- return rc;
-
- if (indatalen*2 + 50 > DIM(line))
- return unlock_scd (gpg_error (GPG_ERR_GENERAL));
-
- sprintf (line, "SETDATA ");
- p = line + strlen (line);
- for (i=0; i < indatalen ; i++, p += 2 )
- sprintf (p, "%02X", indata[i]);
- rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_scd (map_assuan_err (rc));
-
- init_membuf (&data, 1024);
- inqparm.ctx = scd_ctx;
- inqparm.getpin_cb = getpin_cb;
- inqparm.getpin_cb_arg = getpin_cb_arg;
- snprintf (line, DIM(line)-1, "PKSIGN %s", keyid);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (scd_ctx, line,
- membuf_data_cb, &data,
- inq_needpin, &inqparm,
- NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return unlock_scd (map_assuan_err (rc));
- }
- sigbuf = get_membuf (&data, &sigbuflen);
-
- /* create an S-expression from it which is formatted like this:
- "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
- *r_buflen = 21 + 11 + sigbuflen + 4;
- *r_buf = xtrymalloc (*r_buflen);
- if (!*r_buf)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (*r_buf);
- return unlock_scd (tmperr);
- }
- p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
- sprintf (p, "%u:", (unsigned int)sigbuflen);
- p += strlen (p);
- memcpy (p, sigbuf, sigbuflen);
- p += sigbuflen;
- strcpy (p, ")))");
- xfree (sigbuf);
-
- assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
- return unlock_scd (0);
-}
-
-/* Decipher INDATA using the current card. Note that the returned value is */
-int
-agent_card_pkdecrypt (const char *keyid,
- int (*getpin_cb)(void *, const char *, char*, size_t),
- void *getpin_cb_arg,
- const unsigned char *indata, size_t indatalen,
- char **r_buf, size_t *r_buflen)
-{
- int rc, i;
- char *p, line[ASSUAN_LINELENGTH];
- struct membuf data;
- struct inq_needpin_s inqparm;
- size_t len;
-
- *r_buf = NULL;
- rc = start_scd ();
- if (rc)
- return rc;
-
- /* FIXME: use secure memory where appropriate */
- if (indatalen*2 + 50 > DIM(line))
- return unlock_scd (gpg_error (GPG_ERR_GENERAL));
-
- sprintf (line, "SETDATA ");
- p = line + strlen (line);
- for (i=0; i < indatalen ; i++, p += 2 )
- sprintf (p, "%02X", indata[i]);
- rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_scd (map_assuan_err (rc));
-
- init_membuf (&data, 1024);
- inqparm.ctx = scd_ctx;
- inqparm.getpin_cb = getpin_cb;
- inqparm.getpin_cb_arg = getpin_cb_arg;
- snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (scd_ctx, line,
- membuf_data_cb, &data,
- inq_needpin, &inqparm,
- NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return unlock_scd (map_assuan_err (rc));
- }
- *r_buf = get_membuf (&data, r_buflen);
- if (!*r_buf)
- return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
-
- return unlock_scd (0);
-}
-
-
-
-/* Read a certificate with ID into R_BUF and R_BUFLEN. */
-int
-agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
- struct membuf data;
- size_t len;
-
- *r_buf = NULL;
- rc = start_scd ();
- if (rc)
- return rc;
-
- init_membuf (&data, 1024);
- snprintf (line, DIM(line)-1, "READCERT %s", id);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (scd_ctx, line,
- membuf_data_cb, &data,
- NULL, NULL,
- NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return unlock_scd (map_assuan_err (rc));
- }
- *r_buf = get_membuf (&data, r_buflen);
- if (!*r_buf)
- return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
-
- return unlock_scd (0);
-}
-
-
-
-/* Read a key with ID and return it in an allocate buffer pointed to
- by r_BUF as a valid S-expression. */
-int
-agent_card_readkey (const char *id, unsigned char **r_buf)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
- struct membuf data;
- size_t len, buflen;
-
- *r_buf = NULL;
- rc = start_scd ();
- if (rc)
- return rc;
-
- init_membuf (&data, 1024);
- snprintf (line, DIM(line)-1, "READKEY %s", id);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (scd_ctx, line,
- membuf_data_cb, &data,
- NULL, NULL,
- NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return unlock_scd (map_assuan_err (rc));
- }
- *r_buf = get_membuf (&data, &buflen);
- if (!*r_buf)
- return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
-
- if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
- {
- xfree (*r_buf); *r_buf = NULL;
- return unlock_scd (gpg_error (GPG_ERR_INV_VALUE));
- }
-
- return unlock_scd (0);
-}
-
-
-
-
-static AssuanError
-pass_status_thru (void *opaque, const char *line)
-{
- ASSUAN_CONTEXT ctx = opaque;
- char keyword[200];
- int i;
-
- for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
- keyword[i] = *line;
- keyword[i] = 0;
- /* truncate any remaining keyword stuff. */
- for (; *line && !spacep (line); line++)
- ;
- while (spacep (line))
- line++;
-
- assuan_write_status (ctx, keyword, line);
- return 0;
-}
-
-static AssuanError
-pass_data_thru (void *opaque, const void *buffer, size_t length)
-{
- ASSUAN_CONTEXT ctx = opaque;
-
- assuan_send_data (ctx, buffer, length);
- return 0;
-}
-
-
-/* Send the line CMDLINE with command for the SCDdaemon to it and send
- all status messages back. This command is used as a general quoting
- mechanism to pass everything verbatim to SCDAEMOPN. The PIN
- inquirey is handled inside gpg-agent. */
-int
-agent_card_scd (const char *cmdline,
- int (*getpin_cb)(void *, const char *, char*, size_t),
- void *getpin_cb_arg, void *assuan_context)
-{
- int rc;
- struct inq_needpin_s inqparm;
-
- rc = start_scd ();
- if (rc)
- return rc;
-
- inqparm.ctx = scd_ctx;
- inqparm.getpin_cb = getpin_cb;
- inqparm.getpin_cb_arg = getpin_cb_arg;
- rc = assuan_transact (scd_ctx, cmdline,
- pass_data_thru, assuan_context,
- inq_needpin, &inqparm,
- pass_status_thru, assuan_context);
- if (rc)
- {
- return unlock_scd (map_assuan_err (rc));
- }
-
- return unlock_scd (0);
-}
-
-
diff --git a/agent/command.c b/agent/command.c
deleted file mode 100644
index ed4ea6b02..000000000
--- a/agent/command.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/* command.c - gpg-agent command handler
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* FIXME: we should not use the default assuan buffering but setup
- some buffering in secure mempory to protect session keys etc. */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <assuan.h>
-
-#include "agent.h"
-
-/* maximum allowed size of the inquired ciphertext */
-#define MAXLEN_CIPHERTEXT 4096
-/* maximum allowed size of the key parameters */
-#define MAXLEN_KEYPARAM 1024
-
-#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
-
-
-#if MAX_DIGEST_LEN < 20
-#error MAX_DIGEST_LEN shorter than keygrip
-#endif
-
-/* Data used to associate an Assuan context with local server data */
-struct server_local_s {
- ASSUAN_CONTEXT assuan_ctx;
- int message_fd;
- int use_cache_for_signing;
-};
-
-
-
-
-
-static void
-reset_notify (ASSUAN_CONTEXT ctx)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- memset (ctrl->keygrip, 0, 20);
- ctrl->have_keygrip = 0;
- ctrl->digest.valuelen = 0;
-}
-
-
-/* Check whether the option NAME appears in LINE */
-static int
-has_option (const char *line, const char *name)
-{
- const char *s;
- int n = strlen (name);
-
- s = strstr (line, name);
- return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
-
-/* Parse a hex string. Return an Assuan error code or 0 on success and the
- length of the parsed string in LEN. */
-static int
-parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
-{
- const char *p;
- size_t n;
-
- /* parse the hash value */
- for (p=string, n=0; hexdigitp (p); p++, n++)
- ;
- if (*p)
- return set_error (Parameter_Error, "invalid hexstring");
- if ((n&1))
- return set_error (Parameter_Error, "odd number of digits");
- *len = n;
- return 0;
-}
-
-/* Parse the keygrip in STRING into the provided buffer BUF. BUF must
- provide space for 20 bytes. BUF is not changed if the fucntions
- returns an error. */
-static int
-parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
-{
- int rc;
- size_t n;
- const unsigned char *p;
-
- rc = parse_hexstring (ctx, string, &n);
- if (rc)
- return rc;
- n /= 2;
- if (n != 20)
- return set_error (Parameter_Error, "invalid length of keygrip");
-
- for (p=string, n=0; n < 20; p += 2, n++)
- buf[n] = xtoi_2 (p);
-
- return 0;
-}
-
-
-
-
-/* ISTRUSTED <hexstring_with_fingerprint>
-
- Return OK when we have an entry with this fingerprint in our
- trustlist */
-static int
-cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc, n, i;
- char *p;
- char fpr[41];
-
- /* parse the fingerprint value */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (*p || !(n == 40 || n == 32))
- return set_error (Parameter_Error, "invalid fingerprint");
- i = 0;
- if (n==32)
- {
- strcpy (fpr, "00000000");
- i += 8;
- }
- for (p=line; i < 40; p++, i++)
- fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
- fpr[i] = 0;
- rc = agent_istrusted (fpr);
- if (!rc)
- return 0;
- else if (rc == -1)
- return ASSUAN_Not_Trusted;
- else
- {
- log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
- }
-}
-
-/* LISTTRUSTED
-
- List all entries from the trustlist */
-static int
-cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc = agent_listtrusted (ctx);
- if (rc)
- log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-/* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
-
- Store a new key in into the trustlist*/
-static int
-cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc, n, i;
- char *p;
- char fpr[41];
- int flag;
-
- /* parse the fingerprint value */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (!spacep (p) || !(n == 40 || n == 32))
- return set_error (Parameter_Error, "invalid fingerprint");
- i = 0;
- if (n==32)
- {
- strcpy (fpr, "00000000");
- i += 8;
- }
- for (p=line; i < 40; p++, i++)
- fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
- fpr[i] = 0;
-
- while (spacep (p))
- p++;
- flag = *p++;
- if ( (flag != 'S' && flag != 'P') || !spacep (p) )
- return set_error (Parameter_Error, "invalid flag - must be P or S");
- while (spacep (p))
- p++;
-
- rc = agent_marktrusted (ctrl, p, fpr, flag);
- if (rc)
- log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-
-
-/* HAVEKEY <hexstring_with_keygrip>
-
- Return success when the secret key is available */
-static int
-cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- unsigned char buf[20];
-
- rc = parse_keygrip (ctx, line, buf);
- if (rc)
- return rc;
-
- if (agent_key_available (buf))
- return ASSUAN_No_Secret_Key;
-
- return 0;
-}
-
-
-/* SIGKEY <hexstring_with_keygrip>
- SETKEY <hexstring_with_keygrip>
-
- Set the key used for a sign or decrypt operation */
-static int
-cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- CTRL ctrl = assuan_get_pointer (ctx);
-
- rc = parse_keygrip (ctx, line, ctrl->keygrip);
- if (rc)
- return rc;
- ctrl->have_keygrip = 1;
- return 0;
-}
-
-
-/* SETHASH <algonumber> <hexstring>
-
- The client can use this command to tell the server about the data
- (which usually is a hash) to be signed. */
-static int
-cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- size_t n;
- char *p;
- CTRL ctrl = assuan_get_pointer (ctx);
- unsigned char *buf;
- char *endp;
- int algo;
-
- /* parse the algo number and check it */
- algo = (int)strtoul (line, &endp, 10);
- for (line = endp; *line == ' ' || *line == '\t'; line++)
- ;
- if (!algo || gcry_md_test_algo (algo))
- return set_error (Unsupported_Algorithm, NULL);
- ctrl->digest.algo = algo;
-
- /* parse the hash value */
- rc = parse_hexstring (ctx, line, &n);
- if (rc)
- return rc;
- n /= 2;
- if (n != 16 && n != 20 && n != 24 && n != 32)
- return set_error (Parameter_Error, "unsupported length of hash");
- if (n > MAX_DIGEST_LEN)
- return set_error (Parameter_Error, "hash value to long");
-
- buf = ctrl->digest.value;
- ctrl->digest.valuelen = n;
- for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
- buf[n] = xtoi_2 (p);
- for (; n < ctrl->digest.valuelen; n++)
- buf[n] = 0;
- return 0;
-}
-
-
-/* PKSIGN <options>
-
- Perform the actual sign operation. Neither input nor output are
- sensitive to eavesdropping */
-static int
-cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- int ignore_cache = 0;
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (opt.ignore_cache_for_signing)
- ignore_cache = 1;
- else if (!ctrl->server_local->use_cache_for_signing)
- ignore_cache = 1;
-
- rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache);
- if (rc)
- log_error ("command pksign failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-/* PKDECRYPT <options>
-
- Perform the actual decrypt operation. Input is not
- sensitive to eavesdropping */
-static int
-cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- CTRL ctrl = assuan_get_pointer (ctx);
- char *value;
- size_t valuelen;
-
- /* First inquire the data to decrypt */
- rc = assuan_inquire (ctx, "CIPHERTEXT",
- &value, &valuelen, MAXLEN_CIPHERTEXT);
- if (rc)
- return rc;
-
- rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
- xfree (value);
- if (rc)
- log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-/* GENKEY
-
- Generate a new key, store the secret part and return the public
- part. Here is an example transaction:
-
- C: GENKEY
- S: INQUIRE KEYPARM
- C: D (genkey (rsa (nbits 1024)))
- C: END
- S: D (public-key
- S: D (rsa (n 326487324683264) (e 10001)))
- S OK key created
-*/
-
-static int
-cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- char *value;
- size_t valuelen;
-
- /* First inquire the parameters */
- rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
- if (rc)
- return rc;
-
- rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
- xfree (value);
- if (rc)
- log_error ("command genkey failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-static void
-plus_to_blank (char *s)
-{
- for (; *s; s++)
- {
- if (*s == '+')
- *s = ' ';
- }
-}
-
-/* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
-
- This function is usually used to ask for a passphrase to be used
- for conventional encryption, but may also be used by programs which
- need specal handling of passphrases. This command uses a syntax
- which helps clients to use the agent with minimum effort. The
- agent either returns with an error or with a OK followed by the hex
- encoded passphrase. Note that the length of the strings is
- implicitly limited by the maximum length of a command.
-*/
-
-static int
-cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- const char *pw;
- char *response;
- char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
- char *p;
- void *cache_marker;
-
- /* parse the stuff */
- for (p=line; *p == ' '; p++)
- ;
- cacheid = p;
- p = strchr (cacheid, ' ');
- if (p)
- {
- *p++ = 0;
- while (*p == ' ')
- p++;
- errtext = p;
- p = strchr (errtext, ' ');
- if (p)
- {
- *p++ = 0;
- while (*p == ' ')
- p++;
- prompt = p;
- p = strchr (prompt, ' ');
- if (p)
- {
- *p++ = 0;
- while (*p == ' ')
- p++;
- desc = p;
- p = strchr (desc, ' ');
- if (p)
- *p = 0; /* ignore garbage */
- }
- }
- }
- if (!cacheid || !*cacheid || strlen (cacheid) > 50)
- return set_error (Parameter_Error, "invalid length of cacheID");
- if (!desc)
- return set_error (Parameter_Error, "no description given");
-
- if (!strcmp (cacheid, "X"))
- cacheid = NULL;
- if (!strcmp (errtext, "X"))
- errtext = NULL;
- if (!strcmp (prompt, "X"))
- prompt = NULL;
- if (!strcmp (desc, "X"))
- desc = NULL;
-
- /* Note: we store the hexified versions in the cache. */
- pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL;
- if (pw)
- {
- assuan_begin_confidential (ctx);
- rc = assuan_set_okay_line (ctx, pw);
- agent_unlock_cache_entry (&cache_marker);
- }
- else
- {
- /* Note, that we only need to replace the + characters and
- should leave the other escaping in place because the escaped
- string is send verbatim to the pinentry which does the
- unescaping (but not the + replacing) */
- if (errtext)
- plus_to_blank (errtext);
- if (prompt)
- plus_to_blank (prompt);
- if (desc)
- plus_to_blank (desc);
-
- rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
- if (!rc)
- {
- if (cacheid)
- agent_put_cache (cacheid, response, 0);
- assuan_begin_confidential (ctx);
- rc = assuan_set_okay_line (ctx, response);
- xfree (response);
- }
- }
-
- if (rc)
- log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-/* CLEAR_PASSPHRASE <cache_id>
-
- may be used to invalidate the cache entry for a passphrase. The
- function returns with OK even when there is no cached passphrase.
-*/
-
-static int
-cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
-{
- char *cacheid = NULL;
- char *p;
-
- /* parse the stuff */
- for (p=line; *p == ' '; p++)
- ;
- cacheid = p;
- p = strchr (cacheid, ' ');
- if (p)
- *p = 0; /* ignore garbage */
- if (!cacheid || !*cacheid || strlen (cacheid) > 50)
- return set_error (Parameter_Error, "invalid length of cacheID");
-
- agent_put_cache (cacheid, NULL, 0);
- return 0;
-}
-
-
-/* LEARN [--send]
-
- Learn something about the currently inserted smartcard. With
- --send the new certificates are send back. */
-static int
-cmd_learn (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
-
- rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL);
- if (rc)
- log_error ("command learn failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-
-/* PASSWD <hexstring_with_keygrip>
-
- Change the passphrase/PID for the key identified by keygrip in LINE. */
-static int
-cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char grip[20];
- gcry_sexp_t s_skey = NULL;
- unsigned char *shadow_info = NULL;
-
- rc = parse_keygrip (ctx, line, grip);
- if (rc)
- return rc; /* we can't jump to leave because this is already an
- Assuan error code. */
-
- s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1);
- if (!s_skey && !shadow_info)
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- else if (!s_skey)
- {
- log_error ("changing a smartcard PIN is not yet supported\n");
- rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- }
- else
- rc = agent_protect_and_store (ctrl, s_skey);
-
- gcry_sexp_release (s_skey);
- xfree (shadow_info);
- if (rc)
- log_error ("command passwd failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-/* SCD <commands to pass to the scdaemon>
-
- This is a general quote command to redirect everything to the
- SCDAEMON. */
-static int
-cmd_scd (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
-
- rc = divert_generic_cmd (ctrl, line, ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-
-static int
-option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (!strcmp (key, "display"))
- {
- if (ctrl->display)
- free (ctrl->display);
- ctrl->display = strdup (value);
- if (!ctrl->display)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "ttyname"))
- {
- if (!opt.keep_tty)
- {
- if (ctrl->ttyname)
- free (ctrl->ttyname);
- ctrl->ttyname = strdup (value);
- if (!ctrl->ttyname)
- return ASSUAN_Out_Of_Core;
- }
- }
- else if (!strcmp (key, "ttytype"))
- {
- if (!opt.keep_tty)
- {
- if (ctrl->ttytype)
- free (ctrl->ttytype);
- ctrl->ttytype = strdup (value);
- if (!ctrl->ttytype)
- return ASSUAN_Out_Of_Core;
- }
- }
- else if (!strcmp (key, "lc-ctype"))
- {
- if (ctrl->lc_ctype)
- free (ctrl->lc_ctype);
- ctrl->lc_ctype = strdup (value);
- if (!ctrl->lc_ctype)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "lc-messages"))
- {
- if (ctrl->lc_messages)
- free (ctrl->lc_messages);
- ctrl->lc_messages = strdup (value);
- if (!ctrl->lc_messages)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "use-cache-for-signing"))
- ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
- else
- return ASSUAN_Invalid_Option;
-
- return 0;
-}
-
-
-/* Tell the assuan library about our commands */
-static int
-register_commands (ASSUAN_CONTEXT ctx)
-{
- static struct {
- const char *name;
- int (*handler)(ASSUAN_CONTEXT, char *line);
- } table[] = {
- { "ISTRUSTED", cmd_istrusted },
- { "HAVEKEY", cmd_havekey },
- { "SIGKEY", cmd_sigkey },
- { "SETKEY", cmd_sigkey },
- { "SETHASH", cmd_sethash },
- { "PKSIGN", cmd_pksign },
- { "PKDECRYPT", cmd_pkdecrypt },
- { "GENKEY", cmd_genkey },
- { "GET_PASSPHRASE", cmd_get_passphrase },
- { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
- { "LISTTRUSTED", cmd_listtrusted },
- { "MARKTRUSTED", cmd_marktrusted },
- { "LEARN", cmd_learn },
- { "PASSWD", cmd_passwd },
- { "INPUT", NULL },
- { "OUTPUT", NULL },
- { "SCD", cmd_scd },
- { NULL }
- };
- int i, rc;
-
- for (i=0; table[i].name; i++)
- {
- rc = assuan_register_command (ctx, table[i].name, table[i].handler);
- if (rc)
- return rc;
- }
- assuan_register_reset_notify (ctx, reset_notify);
- assuan_register_option_handler (ctx, option_handler);
- return 0;
-}
-
-
-/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple
- piper server, otherwise it is a regular server */
-void
-start_command_handler (int listen_fd, int fd)
-{
- int rc;
- ASSUAN_CONTEXT ctx;
- struct server_control_s ctrl;
-
- memset (&ctrl, 0, sizeof ctrl);
- agent_init_default_ctrl (&ctrl);
-
- if (listen_fd == -1 && fd == -1)
- {
- int filedes[2];
-
- filedes[0] = 0;
- filedes[1] = 1;
- rc = assuan_init_pipe_server (&ctx, filedes);
- }
- else if (listen_fd != -1)
- {
- rc = assuan_init_socket_server (&ctx, listen_fd);
- }
- else
- {
- rc = assuan_init_connected_socket_server (&ctx, fd);
- }
- if (rc)
- {
- log_error ("failed to initialize the server: %s\n",
- assuan_strerror(rc));
- agent_exit (2);
- }
- rc = register_commands (ctx);
- if (rc)
- {
- log_error ("failed to register commands with Assuan: %s\n",
- assuan_strerror(rc));
- agent_exit (2);
- }
-
- assuan_set_pointer (ctx, &ctrl);
- ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
- ctrl.server_local->assuan_ctx = ctx;
- ctrl.server_local->message_fd = -1;
- ctrl.server_local->use_cache_for_signing = 1;
-
- if (DBG_ASSUAN)
- assuan_set_log_stream (ctx, log_get_stream ());
-
- for (;;)
- {
- rc = assuan_accept (ctx);
- if (rc == -1)
- {
- break;
- }
- else if (rc)
- {
- log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
- break;
- }
-
- rc = assuan_process (ctx);
- if (rc)
- {
- log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
- continue;
- }
- }
-
-
- assuan_deinit_server (ctx);
- if (ctrl.display)
- free (ctrl.display);
- if (ctrl.ttyname)
- free (ctrl.ttyname);
- if (ctrl.ttytype)
- free (ctrl.ttytype);
- if (ctrl.lc_ctype)
- free (ctrl.lc_ctype);
- if (ctrl.lc_messages)
- free (ctrl.lc_messages);
-}
-
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
deleted file mode 100644
index 69f184474..000000000
--- a/agent/divert-scd.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/* divert-scd.c - divert operations to the scdaemon
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-#include "sexp-parse.h"
-#include "i18n.h"
-
-
-static int
-ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
-{
- int rc, i;
- const unsigned char *s;
- size_t n;
- char *serialno;
- int no_card = 0;
- char *desc;
- char *want_sn, *want_kid;
- int want_sn_displen;
-
- *r_kid = NULL;
- s = shadow_info;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- want_sn = xtrymalloc (n*2+1);
- if (!want_sn)
- return out_of_core ();
- for (i=0; i < n; i++)
- sprintf (want_sn+2*i, "%02X", s[i]);
- s += n;
- /* We assume that a 20 byte serial number is a standard one which
- seems to have the property to have a zero in the last nibble. We
- don't display this '0' because it may confuse the user */
- want_sn_displen = strlen (want_sn);
- if (want_sn_displen == 20 && want_sn[19] == '0')
- want_sn_displen--;
-
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- want_kid = xtrymalloc (n+1);
- if (!want_kid)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (want_sn);
- return tmperr;
- }
- memcpy (want_kid, s, n);
- want_kid[n] = 0;
-
- for (;;)
- {
- rc = agent_card_serialno (&serialno);
- if (!rc)
- {
- log_debug ("detected card with S/N %s\n", serialno);
- i = strcmp (serialno, want_sn);
- xfree (serialno);
- serialno = NULL;
- if (!i)
- {
- xfree (want_sn);
- *r_kid = want_kid;
- return 0; /* yes, we have the correct card */
- }
- }
- else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
- {
- log_debug ("no card present\n");
- rc = 0;
- no_card = 1;
- }
- else
- {
- log_error ("error accesing card: %s\n", gpg_strerror (rc));
- }
-
- if (!rc)
- {
- if (asprintf (&desc,
- "%s:%%0A%%0A"
- " \"%.*s\"",
- no_card? "Please insert the card with serial number"
- : "Please remove the current card and "
- "insert the one with serial number",
- want_sn_displen, want_sn) < 0)
- {
- rc = out_of_core ();
- }
- else
- {
- rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
- free (desc);
- }
- }
- if (rc)
- {
- xfree (want_sn);
- xfree (want_kid);
- return rc;
- }
- }
-}
-
-
-/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */
-static int
-encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
- unsigned char **r_val, size_t *r_len)
-{
- byte *frame;
- byte asn[100];
- size_t asnlen;
-
- asnlen = DIM(asn);
- if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
- {
- log_error ("no object identifier for algo %d\n", algo);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- frame = xtrymalloc (asnlen + digestlen);
- if (!frame)
- return out_of_core ();
- memcpy (frame, asn, asnlen);
- memcpy (frame+asnlen, digest, digestlen);
- if (DBG_CRYPTO)
- log_printhex ("encoded hash:", frame, asnlen+digestlen);
-
- *r_val = frame;
- *r_len = asnlen+digestlen;
- return 0;
-}
-
-
-/* Callback used to ask for the PIN which should be set into BUF. The
- buf has been allocated by the caller and is of size MAXBUF which
- includes the terminating null. The function should return an UTF-8
- string with the passphrase, the buffer may optionally be padded
- with arbitrary characters */
-static int
-getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
-{
- struct pin_entry_info_s *pi;
- int rc;
- char *desc;
- CTRL ctrl = opaque;
-
- if (maxbuf < 2)
- return gpg_error (GPG_ERR_INV_VALUE);
-
-
- /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole
- mess because we should call the card's verify function from the
- pinentry check pin CB. */
- pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
- pi->max_length = maxbuf-1;
- pi->min_digits = 0; /* we want a real passphrase */
- pi->max_digits = 8;
- pi->max_tries = 3;
-
- if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"),
- info? " (`":"",
- info? info:"",
- info? "')":"") < 0)
- desc = NULL;
- rc = agent_askpin (ctrl, desc?desc:info, pi);
- free (desc);
- if (!rc)
- {
- strncpy (buf, pi->pin, maxbuf-1);
- buf[maxbuf-1] = 0;
- }
- xfree (pi);
- return rc;
-}
-
-
-
-
-int
-divert_pksign (CTRL ctrl,
- const unsigned char *digest, size_t digestlen, int algo,
- const unsigned char *shadow_info, unsigned char **r_sig)
-{
- int rc;
- char *kid;
- size_t siglen;
- char *sigval;
- unsigned char *data;
- size_t ndata;
-
- rc = ask_for_card (ctrl, shadow_info, &kid);
- if (rc)
- return rc;
-
- rc = encode_md_for_card (digest, digestlen, algo,
- &data, &ndata);
- if (rc)
- return rc;
-
- rc = agent_card_pksign (kid, getpin_cb, ctrl,
- data, ndata, &sigval, &siglen);
- if (!rc)
- *r_sig = sigval;
- xfree (data);
- xfree (kid);
-
- return rc;
-}
-
-
-/* Decrypt the the value given asn an S-expression in CIPHER using the
- key identified by SHADOW_INFO and return the plaintext in an
- allocated buffer in R_BUF. */
-int
-divert_pkdecrypt (CTRL ctrl,
- const unsigned char *cipher,
- const unsigned char *shadow_info,
- char **r_buf, size_t *r_len)
-{
- int rc;
- char *kid;
- const unsigned char *s;
- size_t n;
- const unsigned char *ciphertext;
- size_t ciphertextlen;
- char *plaintext;
- size_t plaintextlen;
-
- s = cipher;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "enc-val"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "rsa"))
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "a"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- ciphertext = s;
- ciphertextlen = n;
-
- rc = ask_for_card (ctrl, shadow_info, &kid);
- if (rc)
- return rc;
-
- rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl,
- ciphertext, ciphertextlen,
- &plaintext, &plaintextlen);
- if (!rc)
- {
- *r_buf = plaintext;
- *r_len = plaintextlen;
- }
- xfree (kid);
- return rc;
-}
-
-
-int
-divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context)
-{
- return agent_card_scd (cmdline, getpin_cb, ctrl, assuan_context);
-}
-
-
-
-
-
diff --git a/agent/findkey.c b/agent/findkey.c
deleted file mode 100644
index db36cb1b9..000000000
--- a/agent/findkey.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* findkey.c - locate the secret key
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <assert.h>
-
-#include "agent.h"
-
-/* Helper to pass data to the check callback of the unprotect function. */
-struct try_unprotect_arg_s {
- const unsigned char *protected_key;
- unsigned char *unprotected_key;
-};
-
-
-
-int
-agent_write_private_key (const unsigned char *grip,
- const void *buffer, size_t length, int force)
-{
- int i;
- char *fname;
- FILE *fp;
- char hexgrip[40+4+1];
-
- for (i=0; i < 20; i++)
- sprintf (hexgrip+2*i, "%02X", grip[i]);
- strcpy (hexgrip+40, ".key");
-
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
- if (force)
- fp = fopen (fname, "wb");
- else
- {
- int fd;
-
- if (!access (fname, F_OK))
- {
- log_error ("secret key file `%s' already exists\n", fname);
- xfree (fname);
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- /* We would like to create FNAME but only if it does not already
- exist. We cannot make this guarantee just using POSIX (GNU
- provides the "x" opentype for fopen, however, this is not
- portable). Thus, we use the more flexible open function and
- then use fdopen to obtain a stream.
-
- The mode parameter to open is what fopen uses. It will be
- combined with the process' umask automatically. */
- fd = open (fname, O_CREAT | O_EXCL | O_RDWR,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
- if (fd < 0)
- fp = 0;
- else
- {
- fp = fdopen (fd, "wb");
- if (!fp)
- {
- int save_e = errno;
- close (fd);
- errno = save_e;
- }
- }
- }
-
- if (!fp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("can't create `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- return tmperr;
- }
-
- if (fwrite (buffer, length, 1, fp) != 1)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error writing `%s': %s\n", fname, strerror (errno));
- fclose (fp);
- remove (fname);
- xfree (fname);
- return tmperr;
- }
- if ( fclose (fp) )
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error closing `%s': %s\n", fname, strerror (errno));
- remove (fname);
- xfree (fname);
- return tmperr;
- }
-
- xfree (fname);
- return 0;
-}
-
-
-/* Callback function to try the unprotection from the passpharse query
- code. */
-static int
-try_unprotect_cb (struct pin_entry_info_s *pi)
-{
- struct try_unprotect_arg_s *arg = pi->check_cb_arg;
- size_t dummy;
-
- assert (!arg->unprotected_key);
- return agent_unprotect (arg->protected_key, pi->pin,
- &arg->unprotected_key, &dummy);
-}
-
-
-/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
- should be the hex encoded keygrip of that key to be used with the
- caching mechanism. */
-static int
-unprotect (CTRL ctrl,
- unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
-{
- struct pin_entry_info_s *pi;
- struct try_unprotect_arg_s arg;
- int rc, i;
- unsigned char *result;
- size_t resultlen;
- char hexgrip[40+1];
-
- for (i=0; i < 20; i++)
- sprintf (hexgrip+2*i, "%02X", grip[i]);
- hexgrip[40] = 0;
-
- /* first try to get it from the cache - if there is none or we can't
- unprotect it, we fall back to ask the user */
- if (!ignore_cache)
- {
- void *cache_marker;
- const char *pw = agent_get_cache (hexgrip, &cache_marker);
- if (pw)
- {
- rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
- agent_unlock_cache_entry (&cache_marker);
- if (!rc)
- {
- xfree (*keybuf);
- *keybuf = result;
- return 0;
- }
- rc = 0;
- }
- }
-
- pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
- pi->max_length = 100;
- pi->min_digits = 0; /* we want a real passphrase */
- pi->max_digits = 8;
- pi->max_tries = 3;
- pi->check_cb = try_unprotect_cb;
- arg.protected_key = *keybuf;
- arg.unprotected_key = NULL;
- pi->check_cb_arg = &arg;
-
- rc = agent_askpin (ctrl, NULL, pi);
- if (!rc)
- {
- assert (arg.unprotected_key);
- agent_put_cache (hexgrip, pi->pin, 0);
- xfree (*keybuf);
- *keybuf = arg.unprotected_key;
- }
- xfree (pi);
- return rc;
-}
-
-
-
-/* Return the secret key as an S-Exp after locating it using the grip.
- Returns NULL if key is not available or the operation should be
- diverted to a token. In the latter case shadow_info will point to
- an allocated S-Expression with the shadow_info part from the file.
- With IGNORE_CACHE passed as true the passphrase is not taken from
- the cache.*/
-gcry_sexp_t
-agent_key_from_file (CTRL ctrl,
- const unsigned char *grip, unsigned char **shadow_info,
- int ignore_cache)
-{
- int i, rc;
- char *fname;
- FILE *fp;
- struct stat st;
- unsigned char *buf;
- size_t len, buflen, erroff;
- gcry_sexp_t s_skey;
- char hexgrip[40+4+1];
-
- if (shadow_info)
- *shadow_info = NULL;
-
- for (i=0; i < 20; i++)
- sprintf (hexgrip+2*i, "%02X", grip[i]);
- strcpy (hexgrip+40, ".key");
-
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
- fp = fopen (fname, "rb");
- if (!fp)
- {
- log_error ("can't open `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- return NULL;
- }
-
- if (fstat (fileno(fp), &st))
- {
- log_error ("can't stat `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- fclose (fp);
- return NULL;
- }
-
- buflen = st.st_size;
- buf = xmalloc (buflen+1);
- if (fread (buf, buflen, 1, fp) != 1)
- {
- log_error ("error reading `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- fclose (fp);
- xfree (buf);
- return NULL;
- }
-
- rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
- xfree (fname);
- fclose (fp);
- xfree (buf);
- if (rc)
- {
- log_error ("failed to build S-Exp (off=%u): %s\n",
- (unsigned int)erroff, gpg_strerror (rc));
- return NULL;
- }
- len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xtrymalloc (len);
- if (!buf)
- {
- gcry_sexp_release (s_skey);
- return NULL;
- }
- len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
- gcry_sexp_release (s_skey);
-
- switch (agent_private_key_type (buf))
- {
- case PRIVATE_KEY_CLEAR:
- break; /* no unprotection needed */
- case PRIVATE_KEY_PROTECTED:
- rc = unprotect (ctrl, &buf, grip, ignore_cache);
- if (rc)
- log_error ("failed to unprotect the secret key: %s\n",
- gpg_strerror (rc));
- break;
- case PRIVATE_KEY_SHADOWED:
- if (shadow_info)
- {
- const unsigned char *s;
- size_t n;
-
- rc = agent_get_shadow_info (buf, &s);
- if (!rc)
- {
- n = gcry_sexp_canon_len (s, 0, NULL,NULL);
- assert (n);
- *shadow_info = xtrymalloc (n);
- if (!*shadow_info)
- rc = out_of_core ();
- else
- {
- memcpy (*shadow_info, s, n);
- rc = 0;
- }
- }
- if (rc)
- log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
- }
- rc = -1; /* ugly interface: we return an error but keep a value
- in shadow_info. */
- break;
- default:
- log_error ("invalid private key format\n");
- rc = gpg_error (GPG_ERR_BAD_SECKEY);
- break;
- }
- if (rc)
- {
- xfree (buf);
- return NULL;
- }
-
- /* arggg FIXME: does scan support secure memory? */
- rc = gcry_sexp_sscan (&s_skey, &erroff,
- buf, gcry_sexp_canon_len (buf, 0, NULL, NULL));
- xfree (buf);
- if (rc)
- {
- log_error ("failed to build S-Exp (off=%u): %s\n",
- (unsigned int)erroff, gpg_strerror (rc));
- return NULL;
- }
-
- return s_skey;
-}
-
-/* Return the secret key as an S-Exp after locating it using the grip.
- Returns NULL if key is not available. 0 = key is available */
-int
-agent_key_available (const unsigned char *grip)
-{
- int i;
- char *fname;
- char hexgrip[40+4+1];
-
- for (i=0; i < 20; i++)
- sprintf (hexgrip+2*i, "%02X", grip[i]);
- strcpy (hexgrip+40, ".key");
-
- fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
- i = !access (fname, R_OK)? 0 : -1;
- xfree (fname);
- return i;
-}
-
-
-
diff --git a/agent/genkey.c b/agent/genkey.c
deleted file mode 100644
index 0a0577f17..000000000
--- a/agent/genkey.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* pksign.c - Generate a keypair
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "agent.h"
-#include "i18n.h"
-
-static int
-store_key (gcry_sexp_t private, const char *passphrase, int force)
-{
- int rc;
- char *buf;
- size_t len;
- unsigned char grip[20];
-
- if ( !gcry_pk_get_keygrip (private, grip) )
- {
- log_error ("can't calculate keygrip\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = gcry_malloc_secure (len);
- if (!buf)
- return out_of_core ();
- len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
-
- if (passphrase)
- {
- unsigned char *p;
-
- rc = agent_protect (buf, passphrase, &p, &len);
- if (rc)
- {
- xfree (buf);
- return rc;
- }
- xfree (buf);
- buf = p;
- }
-
- rc = agent_write_private_key (grip, buf, len, force);
- xfree (buf);
- return rc;
-}
-
-/* Callback function to compare the first entered PIN with the one
- currently being entered. */
-static int
-reenter_compare_cb (struct pin_entry_info_s *pi)
-{
- const char *pin1 = pi->check_cb_arg;
-
- if (!strcmp (pin1, pi->pin))
- return 0; /* okay */
- pi->cb_errtext = _("does not match - try again");
- return -1;
-}
-
-
-
-/* Generate a new keypair according to the parameters given in
- KEYPARAM */
-int
-agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
- FILE *outfp)
-{
- gcry_sexp_t s_keyparam, s_key, s_private, s_public;
- struct pin_entry_info_s *pi, *pi2;
- int rc;
- size_t len;
- char *buf;
-
- rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
- if (rc)
- {
- log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc));
- return gpg_error (GPG_ERR_INV_DATA);
- }
-
- /* Get the passphrase now, cause key generation may take a while. */
- {
- const char *text1 = _("Please enter the passphrase to%0A"
- "to protect your new key");
- const char *text2 = _("Please re-enter this passphrase");
-
- pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
- pi2 = pi + (sizeof *pi + 100);
- pi->max_length = 100;
- pi->max_tries = 3;
- pi2->max_length = 100;
- pi2->max_tries = 3;
- pi2->check_cb = reenter_compare_cb;
- pi2->check_cb_arg = pi->pin;
-
- rc = agent_askpin (ctrl, text1, pi);
- if (!rc)
- rc = agent_askpin (ctrl, text2, pi2);
- if (rc)
- return rc;
- if (!*pi->pin)
- {
- xfree (pi);
- pi = NULL; /* User does not want a passphrase. */
- }
- }
-
- rc = gcry_pk_genkey (&s_key, s_keyparam );
- gcry_sexp_release (s_keyparam);
- if (rc)
- {
- log_error ("key generation failed: %s\n", gpg_strerror (rc));
- xfree (pi);
- return map_gcry_err (rc);
- }
-
- /* break out the parts */
- s_private = gcry_sexp_find_token (s_key, "private-key", 0);
- if (!s_private)
- {
- log_error ("key generation failed: invalid return value\n");
- gcry_sexp_release (s_key);
- xfree (pi);
- return gpg_error (GPG_ERR_INV_DATA);
- }
- s_public = gcry_sexp_find_token (s_key, "public-key", 0);
- if (!s_public)
- {
- log_error ("key generation failed: invalid return value\n");
- gcry_sexp_release (s_private);
- gcry_sexp_release (s_key);
- xfree (pi);
- return gpg_error (GPG_ERR_INV_DATA);
- }
- gcry_sexp_release (s_key); s_key = NULL;
-
- /* store the secret key */
- log_debug ("storing private key\n");
- rc = store_key (s_private, pi? pi->pin:NULL, 0);
- xfree (pi); pi = NULL;
- gcry_sexp_release (s_private);
- if (rc)
- {
- gcry_sexp_release (s_public);
- return rc;
- }
-
- /* return the public key */
- log_debug ("returning public key\n");
- len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xtrymalloc (len);
- if (!buf)
- {
- gpg_error_t tmperr = out_of_core ();
- gcry_sexp_release (s_private);
- gcry_sexp_release (s_public);
- return tmperr;
- }
- len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
- if (fwrite (buf, len, 1, outfp) != 1)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error writing public key: %s\n", strerror (errno));
- gcry_sexp_release (s_private);
- gcry_sexp_release (s_public);
- xfree (buf);
- return tmperr;
- }
- gcry_sexp_release (s_public);
- xfree (buf);
-
- return 0;
-}
-
-
-
-/* Apply a new passpahrse to the key S_SKEY and store it. */
-int
-agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey)
-{
- struct pin_entry_info_s *pi, *pi2;
- int rc;
-
- {
- const char *text1 = _("Please enter the new passphrase");
- const char *text2 = _("Please re-enter this passphrase");
-
- pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
- pi2 = pi + (sizeof *pi + 100);
- pi->max_length = 100;
- pi->max_tries = 3;
- pi2->max_length = 100;
- pi2->max_tries = 3;
- pi2->check_cb = reenter_compare_cb;
- pi2->check_cb_arg = pi->pin;
-
- rc = agent_askpin (ctrl, text1, pi);
- if (!rc)
- rc = agent_askpin (ctrl, text2, pi2);
- if (rc)
- return rc;
- if (!*pi->pin)
- {
- xfree (pi);
- pi = NULL; /* User does not want a passphrase. */
- }
- }
-
- rc = store_key (s_skey, pi? pi->pin:NULL, 1);
- xfree (pi);
- return 0;
-}
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
deleted file mode 100644
index 675f2be3f..000000000
--- a/agent/gpg-agent.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/* gpg-agent.c - The GnuPG Agent
- * Copyright (C) 2000, 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <signal.h>
-#ifdef USE_GNU_PTH
-# include <pth.h>
-#endif
-
-#define JNLIB_NEED_LOG_LOGV
-#include "agent.h"
-#include <assuan.h> /* malloc hooks */
-
-#include "i18n.h"
-#include "sysutils.h"
-
-
-enum cmd_and_opt_values
-{ aNull = 0,
- oCsh = 'c',
- oQuiet = 'q',
- oSh = 's',
- oVerbose = 'v',
-
- oNoVerbose = 500,
- oOptions,
- oDebug,
- oDebugAll,
- oDebugWait,
- oNoGreeting,
- oNoOptions,
- oHomedir,
- oNoDetach,
- oNoGrab,
- oLogFile,
- oServer,
- oDaemon,
- oBatch,
-
- oPinentryProgram,
- oDisplay,
- oTTYname,
- oTTYtype,
- oLCctype,
- oLCmessages,
- oScdaemonProgram,
- oDefCacheTTL,
- oDisablePth,
-
- oIgnoreCacheForSigning,
- oKeepTTY,
- oKeepDISPLAY,
-
-aTest };
-
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 301, NULL, 0, N_("@Options:\n ") },
-
- { oServer, "server", 0, N_("run in server mode (foreground)") },
- { oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
- { oVerbose, "verbose", 0, N_("verbose") },
- { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
- { oSh, "sh", 0, N_("sh-style command output") },
- { oCsh, "csh", 0, N_("csh-style command output") },
- { oOptions, "options" , 2, N_("read options from file")},
- { oDebug, "debug" ,4|16, N_("set debugging flags")},
- { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
- { oDebugWait,"debug-wait",1, "@"},
- { oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
- { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
- { oLogFile, "log-file" ,2, N_("use a log file for the server")},
- { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")},
-
- { oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" },
- { oDisplay, "display", 2, "set the display" },
- { oTTYname, "ttyname", 2, "set the tty terminal node name" },
- { oTTYtype, "ttytype", 2, "set the tty terminal type" },
- { oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" },
- { oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" },
-
- { oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" },
- { oDefCacheTTL, "default-cache-ttl", 4,
- "|N|expire cached PINs after N seconds"},
- { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
- "do not use the PIN cache when signing"},
- { oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")},
- { oKeepDISPLAY, "keep-display",
- 0, N_("ignore requests to change the X display")},
- {0}
-};
-
-
-static volatile int caught_fatal_sig = 0;
-
-/* flag to indicate that a shutdown was requested */
-static int shutdown_pending;
-
-
-/* It is possible that we are currently running under setuid permissions */
-static int maybe_setuid = 1;
-
-/* Name of the communication socket */
-static char socket_name[128];
-
-/* Default values for options passed to the pinentry. */
-static char *default_display;
-static char *default_ttyname;
-static char *default_ttytype;
-static char *default_lc_ctype;
-static char *default_lc_messages;
-
-/* Name of a config file, which will be reread on a HUP if it is not NULL. */
-static char *config_filename;
-
-
-/* Local prototypes. */
-static void create_directories (void);
-#ifdef USE_GNU_PTH
-static void handle_connections (int listen_fd);
-#endif
-
-
-
-static const char *
-my_strusage (int level)
-{
- const char *p;
- switch (level)
- {
- case 11: p = "gpg-agent (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: gpg-agent [options] (-h for help)");
- break;
- case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n"
- "Secret key management for GnuPG\n");
- break;
-
- default: p = NULL;
- }
- return p;
-}
-
-
-
-static void
-i18n_init (void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file( PACKAGE );
-#else
-#ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-#endif
-#endif
-}
-
-
-
-/* Used by gcry for logging */
-static void
-my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
-{
- /* translate the log levels */
- switch (level)
- {
- case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
- case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
- case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
- default: level = JNLIB_LOG_ERROR; break;
- }
- log_logv (level, fmt, arg_ptr);
-}
-
-
-static void
-cleanup (void)
-{
- if (*socket_name)
- {
- char *p;
-
- remove (socket_name);
- p = strrchr (socket_name, '/');
- if (p)
- {
- *p = 0;
- rmdir (socket_name);
- *p = '/';
- }
- *socket_name = 0;
- }
-}
-
-
-static RETSIGTYPE
-cleanup_sh (int sig)
-{
- if (caught_fatal_sig)
- raise (sig);
- caught_fatal_sig = 1;
-
- /* gcry_control( GCRYCTL_TERM_SECMEM );*/
- cleanup ();
-
-#ifndef HAVE_DOSISH_SYSTEM
- { /* reset action to default action and raise signal again */
- struct sigaction nact;
- nact.sa_handler = SIG_DFL;
- sigemptyset( &nact.sa_mask );
- nact.sa_flags = 0;
- sigaction( sig, &nact, NULL);
- }
-#endif
- raise( sig );
-}
-
-
-/* Handle options which are allowed to be reset after program start.
- Return true when 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. */
-static int
-parse_rereadable_options (ARGPARSE_ARGS *pargs)
-{
- if (!pargs)
- { /* reset mode */
- opt.quiet = 0;
- opt.verbose = 0;
- opt.debug = 0;
- opt.no_grab = 0;
- opt.pinentry_program = NULL;
- opt.scdaemon_program = NULL;
- opt.def_cache_ttl = 10*60; /* default to 10 minutes */
- opt.ignore_cache_for_signing = 0;
- 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 oNoGrab: opt.no_grab = 1; break;
-
- case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
- case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
-
- case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
-
- case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
-
- default:
- return 0; /* not handled */
- }
- return 1; /* handled */
-}
-
-
-int
-main (int argc, char **argv )
-{
- ARGPARSE_ARGS pargs;
- int orig_argc;
- int may_coredump;
- 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 pipe_server = 0;
- int is_daemon = 0;
- int nodetach = 0;
- int csh_style = 0;
- char *logfile = NULL;
- int debug_wait = 0;
- int disable_pth = 0;
-
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- /* Please note that we may running SUID(ROOT), so be very CAREFUL
- when adding any stuff between here and the call to INIT_SECMEM()
- somewhere after the option parsing */
- log_set_prefix ("gpg-agent", 1|4);
- i18n_init ();
-
- /* We need to initialize Pth before libgcrypt, because the libgcrypt
- initialization done by gcry_check_version internally sets up its
- mutex system. Note that one must not link against pth if
- USE_GNU_PTH is not defined. */
-#ifdef USE_GNU_PTH
- if (!pth_init ())
- {
- log_error ("failed to initialize the Pth library\n");
- exit (1);
- }
-#endif /*USE_GNU_PTH*/
-
- /* check that the libraries are suitable. Do it here because
- the option parsing may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
-
- assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-
- gcry_set_log_handler (my_gcry_logger, NULL);
- gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
-
- may_coredump = disable_core_dumps ();
-
- parse_rereadable_options (NULL); /* Reset them to default values. */
-
- shell = getenv ("SHELL");
- if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
- csh_style = 1;
-
- opt.homedir = getenv("GNUPGHOME");
- if (!opt.homedir || !*opt.homedir)
- opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-
-
- /* check whether we have a config file 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;
- }
-
- /* initialize the secure memory. */
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- maybe_setuid = 0;
-
- /*
- Now we are now working under our real uid
- */
-
-
- if (default_config)
- configname = make_filename (opt.homedir, "gpg-agent.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);
- 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))
- continue; /* Already handled */
- switch (pargs.r_opt)
- {
- case oBatch: opt.batch=1; 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: opt.homedir = pargs.r.ret_str; 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 oServer: pipe_server = 1; break;
- case oDaemon: is_daemon = 1; break;
- case oDisablePth: disable_pth = 1; break;
-
- case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
- case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
- case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
- case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
- case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break;
-
- case oKeepTTY: opt.keep_tty = 1; break;
- case oKeepDISPLAY: opt.keep_display = 1; 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. */
- config_filename = configname;
- configname = NULL;
- goto next_pass;
- }
- xfree (configname);
- configname = NULL;
- if (log_get_errorcount(0))
- exit(2);
- if (nogreeting )
- greeting = 0;
-
- if (greeting)
- {
- fprintf (stderr, "%s %s; %s\n",
- strusage(11), strusage(13), strusage(14) );
- fprintf (stderr, "%s\n", strusage(15) );
- }
-#ifdef IS_DEVELOPMENT_VERSION
- log_info ("NOTE: this is a development version!\n");
-#endif
-
-
- if (atexit (cleanup))
- {
- log_error ("atexit failed\n");
- cleanup ();
- exit (1);
- }
-
- create_directories ();
-
- if (debug_wait && pipe_server)
- {
- log_debug ("waiting for debugger - my pid is %u .....\n",
- (unsigned int)getpid());
- sleep (debug_wait);
- log_debug ("... okay\n");
- }
-
- if (!pipe_server && !is_daemon)
- log_info (_("please use the option `--daemon'"
- " to run the program in the background\n"));
-
-#ifdef ENABLE_NLS
- /* gpg-agent usdually does not ooutput any messages becuase it runs
- in the background. For log files it is acceptable to have
- messages always encoded in utf-8. We switch here to utf-8, so
- that commands like --help still give native messages. It is far
- easier to swicthnonly once instead of for every message and it
- actually helps when more then one thread is active (avoids
- required an extra copy step). */
- bind_textdomain_codeset (PACKAGE, "UTF-8");
-#endif
-
- /* now start with logging to a file if this is desired */
- if (logfile)
- {
- log_set_file (logfile);
- log_set_prefix (NULL, 1|2|4);
- }
-
- /* Make sure that we have a default ttyname. */
- if (!default_ttyname && ttyname (1))
- default_ttyname = xstrdup (ttyname (1));
- if (!default_ttytype && getenv ("TERM"))
- default_ttytype = xstrdup (getenv ("TERM"));
-
- if (pipe_server)
- { /* this is the simple pipe based server */
- start_command_handler (-1, -1);
- }
- else if (!is_daemon)
- ;
- else
- { /* regular server mode */
- int fd;
- pid_t pid;
- int len;
- struct sockaddr_un serv_addr;
- char *p;
-
- /* Remove the DISPLAY variable so that a pinentry does not
- default to a specific display. There is still a default
- display when gpg-agent weas started using --display or a
- client requested this using an OPTION command. */
- if (!opt.keep_display)
- unsetenv ("DISPLAY");
-
- *socket_name = 0;
- snprintf (socket_name, DIM(socket_name)-1,
- "/tmp/gpg-XXXXXX/S.gpg-agent");
- socket_name[DIM(socket_name)-1] = 0;
- p = strrchr (socket_name, '/');
- if (!p)
- BUG ();
- *p = 0;;
- if (!mkdtemp(socket_name))
- {
- log_error ("can't create directory `%s': %s\n",
- socket_name, strerror(errno) );
- exit (1);
- }
- *p = '/';
-
- if (strchr (socket_name, ':') )
- {
- log_error ("colons are not allowed in the socket name\n");
- exit (1);
- }
- if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
- {
- log_error ("name of socket too long\n");
- exit (1);
- }
-
-
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1)
- {
- log_error ("can't create socket: %s\n", strerror(errno) );
- exit (1);
- }
-
- memset (&serv_addr, 0, sizeof serv_addr);
- serv_addr.sun_family = AF_UNIX;
- strcpy (serv_addr.sun_path, socket_name);
- len = (offsetof (struct sockaddr_un, sun_path)
- + strlen(serv_addr.sun_path) + 1);
-
- if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1)
- {
- log_error ("error binding socket to `%s': %s\n",
- serv_addr.sun_path, strerror (errno) );
- close (fd);
- exit (1);
- }
-
- if (listen (fd, 5 ) == -1)
- {
- log_error ("listen() failed: %s\n", strerror (errno));
- close (fd);
- exit (1);
- }
-
- if (opt.verbose)
- log_info ("listening on socket `%s'\n", socket_name );
-
-
- fflush (NULL);
- pid = fork ();
- if (pid == (pid_t)-1)
- {
- log_fatal ("fork failed: %s\n", strerror (errno) );
- exit (1);
- }
- else if (pid)
- { /* we are the parent */
- char *infostr;
-
- close (fd);
-
- /* create the info string: <name>:<pid>:<protocol_version> */
- if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
- socket_name, (ulong)pid ) < 0)
- {
- log_error ("out of core\n");
- kill (pid, SIGTERM);
- exit (1);
- }
- *socket_name = 0; /* don't let cleanup() remove the socket -
- the child should do this from now on */
- if (argc)
- { /* run the program given on the commandline */
- if (putenv (infostr))
- {
- log_error ("failed to set environment: %s\n",
- strerror (errno) );
- kill (pid, SIGTERM );
- exit (1);
- }
- execvp (argv[0], argv);
- log_error ("failed to run the command: %s\n", strerror (errno));
- kill (pid, SIGTERM);
- exit (1);
- }
- else
- {
- /* print the environment string, so that the caller can use
- shell's eval to set it */
- if (csh_style)
- {
- *strchr (infostr, '=') = ' ';
- printf ( "setenv %s\n", infostr);
- }
- else
- {
- printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
- }
- free (infostr);
- exit (0);
- }
- /*NEVER REACHED*/
- } /* end parent */
-
-
- /* this is the child */
-
- /* detach from tty and put process into a new session */
- if (!nodetach )
- {
- int i;
-
- /* close stdin, stdout and stderr unless it is the log stream */
- for (i=0; i <= 2; i++)
- {
- if ( log_get_fd () != i)
- close (i);
- }
- if (setsid() == -1)
- {
- log_error ("setsid() failed: %s\n", strerror(errno) );
- cleanup ();
- exit (1);
- }
- opt.running_detached = 1;
- }
-
- if (chdir("/"))
- {
- log_error ("chdir to / failed: %s\n", strerror (errno));
- exit (1);
- }
-
-
-#ifdef USE_GNU_PTH
- if (!disable_pth)
- {
- struct sigaction sa;
-
- sa.sa_handler = SIG_IGN;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction (SIGPIPE, &sa, NULL);
- handle_connections (fd);
- }
- else
-#endif /*!USE_GNU_PTH*/
- /* setup signals */
- {
- struct sigaction oact, nact;
-
- nact.sa_handler = cleanup_sh;
- sigemptyset (&nact.sa_mask);
- nact.sa_flags = 0;
-
- sigaction (SIGHUP, NULL, &oact);
- if (oact.sa_handler != SIG_IGN)
- sigaction (SIGHUP, &nact, NULL);
- sigaction( SIGTERM, NULL, &oact );
- if (oact.sa_handler != SIG_IGN)
- sigaction (SIGTERM, &nact, NULL);
- nact.sa_handler = SIG_IGN;
- sigaction (SIGPIPE, &nact, NULL);
- sigaction (SIGINT, &nact, NULL);
-
- start_command_handler (fd, -1);
- }
- close (fd);
- }
-
- return 0;
-}
-
-void
-agent_exit (int rc)
-{
- /*FIXME: update_random_seed_file();*/
-#if 1
- /* at this time a bit annoying */
- if (opt.debug & DBG_MEMSTAT_VALUE)
- {
- gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
- gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
- }
- if (opt.debug)
- gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
-#endif
- gcry_control (GCRYCTL_TERM_SECMEM );
- rc = rc? rc : log_get_errorcount(0)? 2 : 0;
- exit (rc);
-}
-
-
-void
-agent_init_default_ctrl (struct server_control_s *ctrl)
-{
- /* Note we ignore malloc errors because we can't do much about it
- and the request will fail anyway shortly after this
- initialization. */
- if (ctrl->display)
- free (ctrl->display);
- ctrl->display = default_display? strdup (default_display) : NULL;
-
- if (ctrl->ttyname)
- free (ctrl->ttyname);
- ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
-
- if (ctrl->ttytype)
- free (ctrl->ttytype);
- ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
-
- if (ctrl->lc_ctype)
- free (ctrl->lc_ctype);
- ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
-
- if (ctrl->lc_messages)
- free (ctrl->lc_messages);
- ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
-}
-
-
-/* Reread parts of the configuration. Note, that this function is
- obviously not thread-safe and should only be called from the PTH
- 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 (!config_filename)
- return; /* No config file. */
-
- fp = fopen (config_filename, "r");
- if (!fp)
- {
- log_error (_("option file `%s': %s\n"),
- config_filename, strerror(errno) );
- return;
- }
-
- parse_rereadable_options (NULL); /* 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, 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);
- }
- fclose (fp);
-}
-
-
-static void
-create_private_keys_directory (const char *home)
-{
- char *fname;
- struct stat statbuf;
-
- fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL);
- if (stat (fname, &statbuf) && errno == ENOENT)
- {
- if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR ))
- log_error (_("can't create directory `%s': %s\n"),
- fname, strerror(errno) );
- else if (!opt.quiet)
- log_info (_("directory `%s' created\n"), fname);
- }
- xfree (fname);
-}
-
-/* Create the directory only if the supplied directory name is the
- same as the default one. This way we avoid to create arbitrary
- directories when a non-default home directory is used. To cope
- with HOME, we compare only the suffix if we see that the default
- homedir does start with a tilde. We don't stop here in case of
- problems because other functions will throw an error anyway.*/
-static void
-create_directories (void)
-{
- struct stat statbuf;
- const char *defhome = GNUPG_DEFAULT_HOMEDIR;
- char *home;
-
- home = make_filename (opt.homedir, NULL);
- if ( stat (home, &statbuf) )
- {
- if (errno == ENOENT)
- {
- if ( (*defhome == '~'
- && (strlen (home) >= strlen (defhome+1)
- && !strcmp (home + strlen(home)
- - strlen (defhome+1), defhome+1)))
- || (*defhome != '~' && !strcmp (home, defhome) )
- )
- {
- if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR ))
- log_error (_("can't create directory `%s': %s\n"),
- home, strerror(errno) );
- else
- {
- if (!opt.quiet)
- log_info (_("directory `%s' created\n"), home);
- create_private_keys_directory (home);
- }
- }
- }
- else
- log_error ("error stat-ing `%s': %s\n", home, strerror (errno));
- }
- else if ( !S_ISDIR(statbuf.st_mode))
- {
- log_error ("can't use `%s' as home directory\n", home);
- }
- else /* exists and is a directory. */
- {
- create_private_keys_directory (home);
- }
- xfree (home);
-}
-
-
-
-#ifdef USE_GNU_PTH
-static void
-handle_signal (int signo)
-{
- switch (signo)
- {
- case SIGHUP:
- log_info ("SIGHUP received - "
- "re-reading configuration and flushing cache\n");
- agent_flush_cache ();
- reread_configuration ();
- break;
-
- case SIGUSR1:
- if (opt.verbose < 5)
- opt.verbose++;
- log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose);
- break;
-
- case SIGUSR2:
- if (opt.verbose)
- opt.verbose--;
- log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose );
- break;
-
- case SIGTERM:
- if (!shutdown_pending)
- log_info ("SIGTERM received - shutting down ...\n");
- else
- log_info ("SIGTERM received - still %ld running threads\n",
- pth_ctrl( PTH_CTRL_GETTHREADS ));
- shutdown_pending++;
- if (shutdown_pending > 2)
- {
- log_info ("shutdown forced\n");
- log_info ("%s %s stopped\n", strusage(11), strusage(13) );
- cleanup ();
- agent_exit (0);
- }
- break;
-
- case SIGINT:
- log_info ("SIGINT received - immediate shutdown\n");
- log_info( "%s %s stopped\n", strusage(11), strusage(13));
- cleanup ();
- agent_exit (0);
- break;
-
- default:
- log_info ("signal %d received - no action defined\n", signo);
- }
-}
-
-
-static void *
-start_connection_thread (void *arg)
-{
- int fd = (int)arg;
-
- if (opt.verbose)
- log_info ("handler for fd %d started\n", fd);
- start_command_handler (-1, fd);
- if (opt.verbose)
- log_info ("handler for fd %d terminated\n", fd);
-
- return NULL;
-}
-
-
-static void
-handle_connections (int listen_fd)
-{
- pth_attr_t tattr;
- pth_event_t ev;
- sigset_t sigs;
- int signo;
- struct sockaddr_un paddr;
- socklen_t plen = sizeof( paddr );
- int fd;
-
- tattr = pth_attr_new();
- pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
- pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024);
- pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent");
-
- sigemptyset (&sigs );
- sigaddset (&sigs, SIGHUP);
- sigaddset (&sigs, SIGUSR1);
- sigaddset (&sigs, SIGUSR2);
- sigaddset (&sigs, SIGINT);
- sigaddset (&sigs, SIGTERM);
- ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
-
- for (;;)
- {
- if (shutdown_pending)
- {
- if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
- break; /* ready */
-
- /* Do not accept anymore connections and wait for existing
- connections to terminate */
- signo = 0;
- pth_wait (ev);
- if (pth_event_occurred (ev) && signo)
- handle_signal (signo);
- continue;
- }
-
- fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
- if (fd == -1)
- {
-#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */
- if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
-#else
- if (pth_event_occurred (ev))
-#endif
- {
- handle_signal (signo);
- continue;
- }
- log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
- pth_sleep(1);
- continue;
- }
-
- if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
- {
- log_error ("error spawning connection handler: %s\n",
- strerror (errno) );
- close (fd);
- }
- }
-
- pth_event_free (ev, PTH_FREE_ALL);
- cleanup ();
- log_info ("%s %s stopped\n", strusage(11), strusage(13));
-}
-#endif /*USE_GNU_PTH*/
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
deleted file mode 100644
index 6c0bd8b83..000000000
--- a/agent/keyformat.txt
+++ /dev/null
@@ -1,163 +0,0 @@
-keyformat.txt (wk 2001-12-18)
------------------------------
-
-
-Some notes on the format of the secret keys used with gpg-agent.
-
-Location of keys
-================
-The secret keys[1] are stored on a per file basis in a directory below
-the ~/.gnupg home directory. This directory is named
-
- private-keys-v1.d
-
-and should have permissions 700.
-
-The secret keys are stored in files with a name matching the
-hexadecimal representation of the keygrip[2].
-
-Unprotected Private Key Format
-==============================
-The content of the file is an S-Expression like the ones used with
-Libgcrypt. Here is an example of an unprotected file:
-
-(private-key
- (rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#)
- )
- (uri http://foo.bar x-foo:whatever_you_want)
-)
-
-Actually this form should not be used for regular purposes and only
-accepted by gpg-agent with the configuration option:
---allow-non-canonical-key-format. The regular way to represent the
-keys is in canonical representation[3]:
-
-(private-key
- (rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#)
- )
- (uri http://foo.bar x-foo:whatever_you_want)
-)
-
-
-Protected Private Key Format
-==============================
-A protected key is like this:
-
-(protected-private-key
- (rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (protected mode (parms) encrypted_octet_string)
- )
- (uri http://foo.bar x-foo:whatever_you_want)
-)
-
-
-In this scheme the encrypted_octet_string is encrypted according to
-the algorithm described after the keyword protected; most protection
-algorithms need some parameters, which are given in a list before the
-encrypted_octet_string. The result of the decryption process is a
-list of the secret key parameters.
-
-The only available protection mode for now is
-
- openpgp-s2k3-sha1-aes-cbc
-
-which describes an algorithm using using AES in CBC mode for
-encryption, SHA-1 for integrity protection and the String to Key
-algorithm 3 from OpenPGP (rfc2440).
-
-Example:
-
-(protected openpgp-s2k3-sha1-aes-cbc
- ((sha1 16byte_salt no_of_iterations) 16byte_iv)
- encrypted_octet_string
-)
-
-The encrypted_octet string should yield this S-Exp (in canonical
-representation) after decryption:
-
-(
- (
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#)
- )
- (hash sha1 #...[hashvalue]...#)
-)
-
-For padding reasons, random bytes are appended to this list - they can
-easily be stripped by looking for the end of the list.
-
-The hash is calculated on the concatenation of the public key and
-secret key parameter lists: i.e it is required to hash the
-concatenation of these 6 canonical encoded lists for RSA, including
-the parenthesis and the algorithm keyword.
-
-(rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#)
-)
-
-After decryption the hash must be recalculated and compared against
-the stored one - If they don't match the integrity of the key is not
-given.
-
-
-Shadowed Private Key Format
-============================
-To keep track of keys stored on IC cards we use a third format for
-private kyes which are called shadow keys as they are only a reference
-to keys stored on a token:
-
-(shadowed-private-key
- (rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (shadowed protocol (info))
- )
- (uri http://foo.bar x-foo:whatever_you_want)
-)
-
-The currently used protocol is "ti-v1" (token info version 1). The
-second list with the information has this layout:
-
-(card_serial_number id_string_of_key)
-
-More items may be added to the list.
-
-
-
-
-
-
-Notes:
-======
-[1] I usually use the terms private and secret key exchangeable but prefer the
-term secret key because it can be visually be better distinguished
-from the term public key.
-
-[2] The keygrip is a unique identifier for a key pair, it is
-independent of any protocol, so that the same key can be ised with
-different protocols. PKCS-15 calls this a subjectKeyHash; it can be
-calculate using Libgcrypt's gcry_pk_get_keygrip().
-
-[3] Even when canonical representation are required we will show the
-S-expression here in a more readable representation.
diff --git a/agent/learncard.c b/agent/learncard.c
deleted file mode 100644
index 28a74f972..000000000
--- a/agent/learncard.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/* learncard.c - Handle the LEARN command
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-#include <assuan.h>
-
-struct keypair_info_s {
- struct keypair_info_s *next;
- int no_cert;
- char *id; /* points into grip */
- char hexgrip[1];
-};
-typedef struct keypair_info_s *KEYPAIR_INFO;
-
-struct kpinfo_cb_parm_s {
- int error;
- KEYPAIR_INFO info;
-};
-
-
-struct certinfo_s {
- struct certinfo_s *next;
- int type;
- int done;
- char id[1];
-};
-typedef struct certinfo_s *CERTINFO;
-
-struct certinfo_cb_parm_s {
- int error;
- CERTINFO info;
-};
-
-
-struct sinfo_s {
- struct sinfo_s *next;
- char *data; /* Points into keyword. */
- char keyword[1];
-};
-typedef struct sinfo_s *SINFO;
-
-struct sinfo_cb_parm_s {
- int error;;
- SINFO info;
-};
-
-
-
-static void
-release_keypair_info (KEYPAIR_INFO info)
-{
- while (info)
- {
- KEYPAIR_INFO tmp = info->next;
- xfree (info);
- info = tmp;
- }
-}
-
-static void
-release_certinfo (CERTINFO info)
-{
- while (info)
- {
- CERTINFO tmp = info->next;
- xfree (info);
- info = tmp;
- }
-}
-
-static void
-release_sinfo (SINFO info)
-{
- while (info)
- {
- SINFO tmp = info->next;
- xfree (info);
- info = tmp;
- }
-}
-
-
-
-/* This callback is used by agent_card_learn and passed the content of
- all KEYPAIRINFO lines. It merely stores this data away */
-static void
-kpinfo_cb (void *opaque, const char *line)
-{
- struct kpinfo_cb_parm_s *parm = opaque;
- KEYPAIR_INFO item;
- char *p;
-
- if (parm->error)
- return; /* no need to gather data after an error coccured */
- item = xtrycalloc (1, sizeof *item + strlen (line));
- if (!item)
- {
- parm->error = out_of_core ();
- return;
- }
- strcpy (item->hexgrip, line);
- for (p = item->hexgrip; hexdigitp (p); p++)
- ;
- if (p == item->hexgrip && *p == 'X' && spacep (p+1))
- {
- item->no_cert = 1;
- p++;
- }
- else if ((p - item->hexgrip) != 40 || !spacep (p))
- { /* not a 20 byte hex keygrip or not followed by a space */
- parm->error = gpg_error (GPG_ERR_INV_RESPONSE);
- xfree (item);
- return;
- }
- *p++ = 0;
- while (spacep (p))
- p++;
- item->id = p;
- while (*p && !spacep (p))
- p++;
- if (p == item->id)
- { /* invalid ID string */
- parm->error = gpg_error (GPG_ERR_INV_RESPONSE);
- xfree (item);
- return;
- }
- *p = 0; /* ignore trailing stuff */
-
- /* store it */
- item->next = parm->info;
- parm->info = item;
-}
-
-
-/* This callback is used by agent_card_learn and passed the content of
- all CERTINFO lines. It merely stores this data away */
-static void
-certinfo_cb (void *opaque, const char *line)
-{
- struct certinfo_cb_parm_s *parm = opaque;
- CERTINFO item;
- int type;
- char *p, *pend;
-
- if (parm->error)
- return; /* no need to gather data after an error coccured */
-
- type = strtol (line, &p, 10);
- while (spacep (p))
- p++;
- for (pend = p; *pend && !spacep (pend); pend++)
- ;
- if (p == pend || !*p)
- {
- parm->error = gpg_error (GPG_ERR_INV_RESPONSE);
- return;
- }
- *pend = 0; /* ignore trailing stuff */
-
- item = xtrycalloc (1, sizeof *item + strlen (p));
- if (!item)
- {
- parm->error = out_of_core ();
- return;
- }
- item->type = type;
- strcpy (item->id, p);
- /* store it */
- item->next = parm->info;
- parm->info = item;
-}
-
-
-/* This callback is used by agent_card_learn and passed the content of
- all SINFO lines. It merely stores this data away */
-static void
-sinfo_cb (void *opaque, const char *keyword, size_t keywordlen,
- const char *data)
-{
- struct sinfo_cb_parm_s *sparm = opaque;
- SINFO item;
-
- if (sparm->error)
- return; /* no need to gather data after an error coccured */
-
- item = xtrycalloc (1, sizeof *item + keywordlen + 1 + strlen (data));
- if (!item)
- {
- sparm->error = out_of_core ();
- return;
- }
- memcpy (item->keyword, keyword, keywordlen);
- item->data = item->keyword + keywordlen;
- *item->data = 0;
- item->data++;
- strcpy (item->data, data);
- /* store it */
- item->next = sparm->info;
- sparm->info = item;
-}
-
-
-/* Create an S-expression with the shadow info. */
-static unsigned char *
-make_shadow_info (const char *serialno, const char *idstring)
-{
- const char *s;
- unsigned char *info, *p;
- char numbuf[21];
- int n;
-
- for (s=serialno, n=0; *s && s[1]; s += 2)
- n++;
-
- info = p = xtrymalloc (1 + 21 + n
- + 21 + strlen (idstring) + 1 + 1);
- *p++ = '(';
- sprintf (numbuf, "%d:", n);
- p = stpcpy (p, numbuf);
- for (s=serialno; *s && s[1]; s += 2)
- *p++ = xtoi_2 (s);
- sprintf (numbuf, "%d:", strlen (idstring));
- p = stpcpy (p, numbuf);
- p = stpcpy (p, idstring);
- *p++ = ')';
- *p = 0;
- return info;
-}
-
-static int
-send_cert_back (const char *id, void *assuan_context)
-{
- int rc;
- char *derbuf;
- size_t derbuflen;
-
- rc = agent_card_readcert (id, &derbuf, &derbuflen);
- if (rc)
- {
- log_error ("error reading certificate: %s\n",
- gpg_strerror (rc));
- return rc;
- }
-
- rc = assuan_send_data (assuan_context, derbuf, derbuflen);
- xfree (derbuf);
- if (!rc)
- rc = assuan_send_data (assuan_context, NULL, 0);
- if (!rc)
- rc = assuan_write_line (assuan_context, "END");
- if (rc)
- {
- log_error ("sending certificate failed: %s\n",
- assuan_strerror (rc));
- return map_assuan_err (rc);
- }
- return 0;
-}
-
-/* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new
- certificates are send via Assuan */
-int
-agent_handle_learn (void *assuan_context)
-{
- int rc;
- struct kpinfo_cb_parm_s parm;
- struct certinfo_cb_parm_s cparm;
- struct sinfo_cb_parm_s sparm;
- char *serialno = NULL;
- KEYPAIR_INFO item;
- SINFO sitem;
- unsigned char grip[20];
- char *p;
- int i;
- static int certtype_list[] = {
- 101, /* trusted */
- 102, /* useful */
- 100, /* regular */
- -1 /* end of list */
- };
-
-
- memset (&parm, 0, sizeof parm);
- memset (&cparm, 0, sizeof cparm);
- memset (&sparm, 0, sizeof sparm);
-
- /* Check whether a card is present and get the serial number */
- rc = agent_card_serialno (&serialno);
- if (rc)
- goto leave;
-
- /* now gather all the available info */
- rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm,
- sinfo_cb, &sparm);
- if (!rc && (parm.error || cparm.error || sparm.error))
- rc = parm.error? parm.error : cparm.error? cparm.error : sparm.error;
- if (rc)
- {
- log_debug ("agent_card_learn failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- log_info ("card has S/N: %s\n", serialno);
-
- /* Pass on all the collected status information. */
- if (assuan_context)
- {
- for (sitem = sparm.info; sitem; sitem = sitem->next)
- {
- assuan_write_status (assuan_context, sitem->keyword, sitem->data);
- }
- }
-
- /* Write out the certificates in a standard order. */
- for (i=0; certtype_list[i] != -1; i++)
- {
- CERTINFO citem;
- for (citem = cparm.info; citem; citem = citem->next)
- {
- if (certtype_list[i] != citem->type)
- continue;
-
- if (opt.verbose)
- log_info (" id: %s (type=%d)\n",
- citem->id, citem->type);
-
- if (assuan_context)
- {
- rc = send_cert_back (citem->id, assuan_context);
- if (rc)
- goto leave;
- citem->done = 1;
- }
- }
- }
-
- for (item = parm.info; item; item = item->next)
- {
- unsigned char *pubkey, *shdkey;
- size_t n;
-
- if (opt.verbose)
- log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip);
-
- if (item->no_cert)
- continue; /* no public key yet available */
-
- for (p=item->hexgrip, i=0; i < 20; p += 2, i++)
- grip[i] = xtoi_2 (p);
-
- if (!agent_key_available (grip))
- continue;
-
- /* unknown - store it */
- rc = agent_card_readkey (item->id, &pubkey);
- if (rc)
- {
- log_debug ("agent_card_readkey failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- {
- unsigned char *shadow_info = make_shadow_info (serialno, item->id);
- if (!shadow_info)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- xfree (pubkey);
- goto leave;
- }
- rc = agent_shadow_key (pubkey, shadow_info, &shdkey);
- xfree (shadow_info);
- }
- xfree (pubkey);
- if (rc)
- {
- log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
- assert (n);
-
- rc = agent_write_private_key (grip, shdkey, n, 0);
- xfree (shdkey);
- if (rc)
- {
- log_error ("error writing key: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (opt.verbose)
- log_info ("stored\n");
-
- if (assuan_context)
- {
- CERTINFO citem;
-
- /* only send the certificate if we have not done so before */
- for (citem = cparm.info; citem; citem = citem->next)
- {
- if (!strcmp (citem->id, item->id))
- break;
- }
- if (!citem)
- {
- rc = send_cert_back (item->id, assuan_context);
- if (rc)
- goto leave;
- }
- }
- }
-
-
- leave:
- xfree (serialno);
- release_keypair_info (parm.info);
- release_certinfo (cparm.info);
- release_sinfo (sparm.info);
- return rc;
-}
-
-
diff --git a/agent/minip12.c b/agent/minip12.c
deleted file mode 100644
index 255fef096..000000000
--- a/agent/minip12.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/* minip12.c - A minimal pkcs-12 implementation.
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <gcrypt.h>
-
-#undef TEST
-
-#ifdef TEST
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#endif
-
-#include "../jnlib/logging.h"
-#include "minip12.h"
-
-#ifndef DIM
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
-#endif
-
-enum
-{
- UNIVERSAL = 0,
- APPLICATION = 1,
- CONTEXT = 2,
- PRIVATE = 3
-};
-
-
-enum
-{
- TAG_NONE = 0,
- TAG_BOOLEAN = 1,
- TAG_INTEGER = 2,
- TAG_BIT_STRING = 3,
- TAG_OCTET_STRING = 4,
- TAG_NULL = 5,
- TAG_OBJECT_ID = 6,
- TAG_OBJECT_DESCRIPTOR = 7,
- TAG_EXTERNAL = 8,
- TAG_REAL = 9,
- TAG_ENUMERATED = 10,
- TAG_EMBEDDED_PDV = 11,
- TAG_UTF8_STRING = 12,
- TAG_REALTIVE_OID = 13,
- TAG_SEQUENCE = 16,
- TAG_SET = 17,
- TAG_NUMERIC_STRING = 18,
- TAG_PRINTABLE_STRING = 19,
- TAG_TELETEX_STRING = 20,
- TAG_VIDEOTEX_STRING = 21,
- TAG_IA5_STRING = 22,
- TAG_UTC_TIME = 23,
- TAG_GENERALIZED_TIME = 24,
- TAG_GRAPHIC_STRING = 25,
- TAG_VISIBLE_STRING = 26,
- TAG_GENERAL_STRING = 27,
- TAG_UNIVERSAL_STRING = 28,
- TAG_CHARACTER_STRING = 29,
- TAG_BMP_STRING = 30
-};
-
-
-static unsigned char const oid_data[9] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
-static unsigned char const oid_encryptedData[9] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 };
-static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 };
-static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 };
-
-static unsigned char const oid_rsaEncryption[9] = {
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
-
-
-static unsigned char const data_3desiter1024[30] = {
- 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86,
- 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E,
- 0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0x02, 0x02, 0x04, 0x00 };
-#define DATA_3DESITER1024_SALT_OFF 18
-
-
-struct buffer_s
-{
- unsigned char *buffer;
- size_t length;
-};
-
-
-struct tag_info
-{
- int class;
- int is_constructed;
- unsigned long tag;
- unsigned long length; /* length part of the TLV */
- int nhdr;
- int ndef; /* It is an indefinite length */
-};
-
-
-/* Parse the buffer at the address BUFFER which is of SIZE and return
- the tag and the length part from the TLV triplet. Update BUFFER
- and SIZE on success. */
-static int
-parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti)
-{
- int c;
- unsigned long tag;
- const unsigned char *buf = *buffer;
- size_t length = *size;
-
- ti->length = 0;
- ti->ndef = 0;
- ti->nhdr = 0;
-
- /* Get the tag */
- if (!length)
- return -1; /* premature eof */
- c = *buf++; length--;
- ti->nhdr++;
-
- ti->class = (c & 0xc0) >> 6;
- ti->is_constructed = !!(c & 0x20);
- tag = c & 0x1f;
-
- if (tag == 0x1f)
- {
- tag = 0;
- do
- {
- tag <<= 7;
- if (!length)
- return -1; /* premature eof */
- c = *buf++; length--;
- ti->nhdr++;
- tag |= c & 0x7f;
- }
- while (c & 0x80);
- }
- ti->tag = tag;
-
- /* Get the length */
- if (!length)
- return -1; /* prematureeof */
- c = *buf++; length--;
- ti->nhdr++;
-
- if ( !(c & 0x80) )
- ti->length = c;
- else if (c == 0x80)
- ti->ndef = 1;
- else if (c == 0xff)
- return -1; /* forbidden length value */
- else
- {
- unsigned long len = 0;
- int count = c & 0x7f;
-
- for (; count; count--)
- {
- len <<= 8;
- if (!length)
- return -1; /* premature_eof */
- c = *buf++; length--;
- ti->nhdr++;
- len |= c & 0xff;
- }
- ti->length = len;
- }
-
- if (ti->class == UNIVERSAL && !ti->tag)
- ti->length = 0;
-
- if (ti->length > length)
- return -1; /* data larger than buffer. */
-
- *buffer = buf;
- *size = length;
- return 0;
-}
-
-
-static int
-string_to_key (int id, char *salt, int iter, const char *pw,
- int req_keylen, unsigned char *keybuf)
-{
- int rc, i, j;
- gcry_md_hd_t md;
- gcry_mpi_t num_b1 = NULL;
- int pwlen;
- unsigned char hash[20], buf_b[64], buf_i[128], *p;
- size_t cur_keylen;
- size_t n;
-
- cur_keylen = 0;
- pwlen = strlen (pw);
- if (pwlen > 63/2)
- {
- log_error ("password too long\n");
- return -1;
- }
-
- /* Store salt and password in BUF_I */
- p = buf_i;
- for(i=0; i < 64; i++)
- *p++ = salt [i%8];
- for(i=j=0; i < 64; i += 2)
- {
- *p++ = 0;
- *p++ = pw[j];
- if (++j > pwlen) /* Note, that we include the trailing zero */
- j = 0;
- }
-
- for (;;)
- {
- rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
- if (rc)
- {
- log_error ( "gcry_md_open failed: %s\n", gpg_strerror (rc));
- return rc;
- }
- for(i=0; i < 64; i++)
- gcry_md_putc (md, id);
- gcry_md_write (md, buf_i, 128);
- memcpy (hash, gcry_md_read (md, 0), 20);
- gcry_md_close (md);
- for (i=1; i < iter; i++)
- gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20);
-
- for (i=0; i < 20 && cur_keylen < req_keylen; i++)
- keybuf[cur_keylen++] = hash[i];
- if (cur_keylen == req_keylen)
- {
- gcry_mpi_release (num_b1);
- return 0; /* ready */
- }
-
- /* need more bytes. */
- for(i=0; i < 64; i++)
- buf_b[i] = hash[i % 20];
- rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, &n);
- if (rc)
- {
- log_error ( "gcry_mpi_scan failed: %s\n", gpg_strerror (rc));
- return -1;
- }
- gcry_mpi_add_ui (num_b1, num_b1, 1);
- for (i=0; i < 128; i += 64)
- {
- gcry_mpi_t num_ij;
-
- rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, &n);
- if (rc)
- {
- log_error ( "gcry_mpi_scan failed: %s\n",
- gpg_strerror (rc));
- return -1;
- }
- gcry_mpi_add (num_ij, num_ij, num_b1);
- gcry_mpi_clear_highbit (num_ij, 64*8);
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, 64, &n, num_ij);
- if (rc)
- {
- log_error ( "gcry_mpi_print failed: %s\n",
- gpg_strerror (rc));
- return -1;
- }
- gcry_mpi_release (num_ij);
- }
- }
-}
-
-
-static int
-set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw)
-{
- unsigned char keybuf[24];
- int rc;
-
- if (string_to_key (1, salt, iter, pw, 24, keybuf))
- return -1;
- rc = gcry_cipher_setkey (chd, keybuf, 24);
- if (rc)
- {
- log_error ( "gcry_cipher_setkey failed: %s\n", gpg_strerror (rc));
- return -1;
- }
-
- if (string_to_key (2, salt, iter, pw, 8, keybuf))
- return -1;
- rc = gcry_cipher_setiv (chd, keybuf, 8);
- if (rc)
- {
- log_error ("gcry_cipher_setiv failed: %s\n", gpg_strerror (rc));
- return -1;
- }
- return 0;
-}
-
-
-static void
-crypt_block (unsigned char *buffer, size_t length, char *salt, int iter,
- const char *pw, int encrypt)
-{
- gcry_cipher_hd_t chd;
- int rc;
-
- rc = gcry_cipher_open (&chd, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
- if (rc)
- {
- log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(-1));
- return;
- }
- if (set_key_iv (chd, salt, iter, pw))
- goto leave;
-
- rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0)
- : gcry_cipher_decrypt (chd, buffer, length, NULL, 0);
-
- if (rc)
- {
- log_error ( "en/de-crytion failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
-/* { */
-/* FILE *fp = fopen("inner.der", "wb"); */
-/* fwrite (buffer, 1, length, fp); */
-/* fclose (fp); */
-/* } */
-
- leave:
- gcry_cipher_close (chd);
-}
-
-
-
-
-static int
-parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
- int startoffset)
-{
- struct tag_info ti;
- const unsigned char *p = buffer;
- size_t n = length;
- const char *where;
-
- where = "start";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != CONTEXT || ti.tag)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_SEQUENCE)
- goto bailout;
-
- where = "bag.encryptedData.version";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 0)
- goto bailout;
- p++; n--;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_SEQUENCE)
- goto bailout;
-
- where = "bag.encryptedData.data";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
- || memcmp (p, oid_data, DIM(oid_data)))
- goto bailout;
- p += DIM(oid_data);
- n -= DIM(oid_data);
-
- /* fixme: continue parsing */
-
- return 0;
- bailout:
- log_error ("encrptedData error at \"%s\", offset %u\n",
- where, (p - buffer)+startoffset);
- return -1;
-}
-
-static gcry_mpi_t *
-parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
- const char *pw)
-{
- int rc;
- struct tag_info ti;
- const unsigned char *p = buffer;
- size_t n = length;
- const char *where;
- char salt[8];
- unsigned int iter;
- int len;
- unsigned char *plain = NULL;
- gcry_mpi_t *result = NULL;
- int result_count, i;
-
- where = "start";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != CONTEXT || ti.tag)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_OCTET_STRING)
- goto bailout;
-
- where = "data.outerseqs";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
-
- where = "data.objectidentifier";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_OBJECT_ID
- || ti.length != DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)
- || memcmp (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
- DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)))
- goto bailout;
- p += DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
- n -= DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
-
- where = "shrouded,outerseqs";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != CONTEXT || ti.tag)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_OBJECT_ID
- || ti.length != DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)
- || memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC,
- DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)))
- goto bailout;
- p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
- n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
-
- where = "3des-params";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 )
- goto bailout;
- memcpy (salt, p, 8);
- p += 8;
- n -= 8;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
- goto bailout;
- for (iter=0; ti.length; ti.length--)
- {
- iter <<= 8;
- iter |= (*p++) & 0xff;
- n--;
- }
-
- where = "3des-ciphertext";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length )
- goto bailout;
-
- log_info ("%lu bytes of 3DES encrypted text\n", ti.length);
-
- plain = gcry_malloc_secure (ti.length);
- if (!plain)
- {
- log_error ("error allocating decryption buffer\n");
- goto bailout;
- }
- memcpy (plain, p, ti.length);
- crypt_block (plain, ti.length, salt, iter, pw, 0);
- n = ti.length;
- startoffset = 0;
- buffer = p = plain;
-
- where = "decrypted-text";
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER
- || ti.length != 1 || *p)
- goto bailout;
- p++; n--;
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- len = ti.length;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (len < ti.nhdr)
- goto bailout;
- len -= ti.nhdr;
- if (ti.class || ti.tag != TAG_OBJECT_ID
- || ti.length != DIM(oid_rsaEncryption)
- || memcmp (p, oid_rsaEncryption,
- DIM(oid_rsaEncryption)))
- goto bailout;
- p += DIM (oid_rsaEncryption);
- n -= DIM (oid_rsaEncryption);
- if (len < ti.length)
- goto bailout;
- len -= ti.length;
- if (n < len)
- goto bailout;
- p += len;
- n -= len;
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_OCTET_STRING)
- goto bailout;
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
- goto bailout;
- len = ti.length;
-
- result = gcry_calloc (10, sizeof *result);
- if (!result)
- {
- log_error ( "error allocating result array\n");
- goto bailout;
- }
- result_count = 0;
-
- where = "reading.key-parameters";
- for (result_count=0; len && result_count < 9;)
- {
- if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER)
- goto bailout;
- if (len < ti.nhdr)
- goto bailout;
- len -= ti.nhdr;
- if (len < ti.length)
- goto bailout;
- len -= ti.length;
- if (!result_count && ti.length == 1 && !*p)
- ; /* ignore the very first one if it is a 0 */
- else
- {
- rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p,
- ti.length, NULL);
- if (rc)
- {
- log_error ("error parsing key parameter: %s\n",
- gpg_strerror (rc));
- goto bailout;
- }
- result_count++;
- }
- p += ti.length;
- n -= ti.length;
- }
- if (len)
- goto bailout;
-
- return result;
-
- bailout:
- gcry_free (plain);
- if (result)
- {
- for (i=0; result[i]; i++)
- gcry_mpi_release (result[i]);
- gcry_free (result);
- }
- log_error ( "data error at \"%s\", offset %u\n",
- where, (p - buffer) + startoffset);
- return NULL;
-}
-
-
-/* Parse a PKCS12 object and return an array of MPI representing the
- secret key parameters. This is a very limited inplementation in
- that it is only able to look for 3DES encoded enctyptedData and
- tries to extract the first private key object it finds. In case of
- an error NULL is returned. */
-gcry_mpi_t *
-p12_parse (const unsigned char *buffer, size_t length, const char *pw)
-{
- struct tag_info ti;
- const unsigned char *p = buffer;
- size_t n = length;
- const char *where;
- int bagseqlength, len;
-
- where = "pfx";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_SEQUENCE)
- goto bailout;
-
- where = "pfxVersion";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 3)
- goto bailout;
- p++; n--;
-
- where = "authSave";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_SEQUENCE)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
- || memcmp (p, oid_data, DIM(oid_data)))
- goto bailout;
- p += DIM(oid_data);
- n -= DIM(oid_data);
-
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != CONTEXT || ti.tag)
- goto bailout;
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING)
- goto bailout;
-
- where = "bags";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
- goto bailout;
- bagseqlength = ti.length;
- while (bagseqlength)
- {
- /*log_debug ( "at offset %u\n", (p - buffer));*/
- where = "bag-sequence";
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
- goto bailout;
-
- if (bagseqlength < ti.nhdr)
- goto bailout;
- bagseqlength -= ti.nhdr;
- if (bagseqlength < ti.length)
- goto bailout;
- bagseqlength -= ti.length;
- len = ti.length;
-
- if (parse_tag (&p, &n, &ti))
- goto bailout;
- len -= ti.nhdr;
- if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData)
- && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData)))
- {
- p += DIM(oid_encryptedData);
- n -= DIM(oid_encryptedData);
- len -= DIM(oid_encryptedData);
- where = "bag.encryptedData";
- if (parse_bag_encrypted_data (p, n, (p - buffer)))
- goto bailout;
- }
- else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
- && !memcmp (p, oid_data, DIM(oid_data)))
- {
- p += DIM(oid_data);
- n -= DIM(oid_data);
- len -= DIM(oid_data);
- return parse_bag_data (p, n, (p-buffer), pw);
- }
- else
- log_info ( "unknown bag type - skipped\n");
-
- if (len < 0 || len > n)
- goto bailout;
- p += len;
- n -= len;
- }
-
- return NULL;
- bailout:
- log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
- return NULL;
-}
-
-
-
-static size_t
-compute_tag_length (size_t n)
-{
- int needed = 0;
-
- if (n < 128)
- needed += 2; /* tag and one length byte */
- else if (n < 256)
- needed += 3; /* tag, number of length bytes, 1 length byte */
- else if (n < 65536)
- needed += 4; /* tag, number of length bytes, 2 length bytes */
- else
- {
- log_error ("object too larger to encode\n");
- return 0;
- }
- return needed;
-}
-
-static unsigned char *
-store_tag_length (unsigned char *p, int tag, size_t n)
-{
- if (tag == TAG_SEQUENCE)
- tag |= 0x20; /* constructed */
-
- *p++ = tag;
- if (n < 128)
- *p++ = n;
- else if (n < 256)
- {
- *p++ = 0x81;
- *p++ = n;
- }
- else if (n < 65536)
- {
- *p++ = 0x82;
- *p++ = n >> 8;
- *p++ = n;
- }
-
- return p;
-}
-
-
-/* Create the final PKCS-12 object from the sequences contained in
- SEQLIST. That array is terminated with an NULL object */
-static unsigned char *
-create_final (struct buffer_s *sequences, size_t *r_length)
-{
- int i;
- size_t needed = 0;
- size_t n, outseqlen, notsooutseqlen, out0taglen, octstrlen, inseqlen;
- unsigned char *result, *p;
- size_t resultlen;
-
- for (i=0; sequences[i].buffer; i++)
- needed += sequences[i].length;
- /* This goes into a sequences. */
- inseqlen = needed;
- n = compute_tag_length (needed);
- needed += n;
- /* And encapsulate all in an octet string. */
- octstrlen = needed;
- n = compute_tag_length (needed);
- needed += n;
- /* And tag it with [0]. */
- out0taglen = needed;
- n = compute_tag_length (needed);
- needed += n;
- /* Prepend an data OID. */
- needed += 2 + DIM (oid_data);
- /* This all into a sequences. */
- notsooutseqlen = needed;
- n = compute_tag_length (needed);
- needed += n;
- /* Prepend the version integer 3. */
- needed += 3;
- /* And the final sequence. */
- outseqlen = needed;
- n = compute_tag_length (needed);
- needed += n;
-
- result = gcry_malloc (needed);
- if (!result)
- {
- log_error ("error allocating buffer\n");
- return NULL;
- }
- p = result;
-
- /* Store the very outer sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
- /* Store the version integer 3. */
- *p++ = TAG_INTEGER;
- *p++ = 1;
- *p++ = 3;
- /* Store another sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, notsooutseqlen);
- /* Store the data OID. */
- p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
- memcpy (p, oid_data, DIM (oid_data));
- p += DIM (oid_data);
- /* Next comes a context tag. */
- p = store_tag_length (p, 0xa0, out0taglen);
- /* And an octet string. */
- p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
- /* And the inner sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
- /* And append all the buffers. */
- for (i=0; sequences[i].buffer; i++)
- {
- memcpy (p, sequences[i].buffer, sequences[i].length);
- p += sequences[i].length;
- }
-
- /* Ready. */
- resultlen = p - result;
- if (needed != resultlen)
- log_debug ("length mismatch: %u, %u\n", needed, resultlen);
-
- *r_length = resultlen;
- return result;
-}
-
-
-/* Expect the RSA key parameters in KPARMS and a password in
- PW. Create a PKCS structure from it and return it as well as the
- length in R_LENGTH; return NULL in case of an error. */
-unsigned char *
-p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length)
-{
- int rc, i;
- size_t needed, n;
- unsigned char *plain, *p, *cipher;
- size_t plainlen, cipherlen;
- size_t outseqlen, oidseqlen, octstrlen, inseqlen;
- size_t out0taglen, in0taglen, outoctstrlen;
- size_t aseq1len, aseq2len, aseq3len;
- char salt[8];
-
- needed = 3; /* The version(?) integer of value 0. */
- for (i=0; kparms[i]; i++)
- {
- n = 0;
- rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
- if (rc)
- {
- log_error ("error formatting parameter: %s\n", gpg_strerror (rc));
- return NULL;
- }
- needed += n;
- n = compute_tag_length (n);
- if (!n)
- return NULL;
- needed += n;
- }
- if (i != 8)
- {
- log_error ("invalid paramters for p12_build\n");
- return NULL;
- }
- /* Now this all goes into a sequence. */
- inseqlen = needed;
- n = compute_tag_length (needed);
- if (!n)
- return NULL;
- needed += n;
- /* Encapsulate all into an octet string. */
- octstrlen = needed;
- n = compute_tag_length (needed);
- if (!n)
- return NULL;
- needed += n;
- /* Prepend the object identifier sequence. */
- oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
- needed += 2 + oidseqlen;
- /* The version number. */
- needed += 3;
- /* And finally put the whole thing into a sequence. */
- outseqlen = needed;
- n = compute_tag_length (needed);
- if (!n)
- return NULL;
- needed += n;
-
- /* allocate 8 extra bytes for padding */
- plain = gcry_malloc_secure (needed+8);
- if (!plain)
- {
- log_error ("error allocating encryption buffer\n");
- return NULL;
- }
-
- /* And now fill the plaintext buffer. */
- p = plain;
- p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
- /* Store version. */
- *p++ = TAG_INTEGER;
- *p++ = 1;
- *p++ = 0;
- /* Store object identifier sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
- p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
- memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption));
- p += DIM (oid_rsaEncryption);
- *p++ = TAG_NULL;
- *p++ = 0;
- /* Start with the octet string. */
- p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
- p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
- /* Store the key parameters. */
- *p++ = TAG_INTEGER;
- *p++ = 1;
- *p++ = 0;
- for (i=0; kparms[i]; i++)
- {
- n = 0;
- rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
- if (rc)
- {
- log_error ("oops: error formatting parameter: %s\n",
- gpg_strerror (rc));
- gcry_free (plain);
- return NULL;
- }
- p = store_tag_length (p, TAG_INTEGER, n);
-
- n = plain + needed - p;
- rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, n, &n, kparms[i]);
- if (rc)
- {
- log_error ("oops: error storing parameter: %s\n",
- gpg_strerror (rc));
- gcry_free (plain);
- return NULL;
- }
- p += n;
- }
-
- plainlen = p - plain;
- assert (needed == plainlen);
- /* Append some pad characters; we already allocated extra space. */
- n = 8 - plainlen % 8;
- for (;(plainlen % 8); plainlen++)
- *p++ = n;
-
- {
- FILE *fp = fopen("inner-out.der", "wb");
- fwrite (plain, 1, plainlen, fp);
- fclose (fp);
- }
-
-
- /* Encrypt it and prepend a lot of stupid things. */
- gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
- crypt_block (plain, plainlen, salt, 1024, pw, 1);
- /* the data goes into an octet string. */
- needed = compute_tag_length (plainlen);
- needed += plainlen;
- /* we prepend the the algorithm identifier (we use a pre-encoded one)*/
- needed += DIM (data_3desiter1024);
- /* we put a sequence around. */
- aseq3len = needed;
- needed += compute_tag_length (needed);
- /* Prepend it with a [0] tag. */
- in0taglen = needed;
- needed += compute_tag_length (needed);
- /* Prepend that shroudedKeyBag OID. */
- needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag);
- /* Put it all into two sequence. */
- aseq2len = needed;
- needed += compute_tag_length ( needed);
- aseq1len = needed;
- needed += compute_tag_length (needed);
- /* This all goes into an octet string. */
- outoctstrlen = needed;
- needed += compute_tag_length (needed);
- /* Prepend it with a [0] tag. */
- out0taglen = needed;
- needed += compute_tag_length (needed);
- /* Prepend the data OID. */
- needed += 2 + DIM (oid_data);
- /* And a sequence. */
- outseqlen = needed;
- needed += compute_tag_length (needed);
-
- cipher = gcry_malloc (needed);
- if (!cipher)
- {
- log_error ("error allocating buffer\n");
- gcry_free (plain);
- return NULL;
- }
- p = cipher;
- /* Store the first sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
- /* Store the data OID. */
- p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
- memcpy (p, oid_data, DIM (oid_data));
- p += DIM (oid_data);
- /* Next comes a context tag. */
- p = store_tag_length (p, 0xa0, out0taglen);
- /* And an octet string. */
- p = store_tag_length (p, TAG_OCTET_STRING, outoctstrlen);
- /* Two sequences. */
- p = store_tag_length (p, TAG_SEQUENCE, aseq1len);
- p = store_tag_length (p, TAG_SEQUENCE, aseq2len);
- /* Store the shroudedKeyBag OID. */
- p = store_tag_length (p, TAG_OBJECT_ID,
- DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag));
- memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
- DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag));
- p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag);
- /* Next comes a context tag. */
- p = store_tag_length (p, 0xa0, in0taglen);
- /* And a sequence. */
- p = store_tag_length (p, TAG_SEQUENCE, aseq3len);
- /* Now for the pre-encoded algorithm indentifier and the salt. */
- memcpy (p, data_3desiter1024, DIM (data_3desiter1024));
- memcpy (p + DATA_3DESITER1024_SALT_OFF, salt, 8);
- p += DIM (data_3desiter1024);
- /* And finally the octet string with the encrypted data. */
- p = store_tag_length (p, TAG_OCTET_STRING, plainlen);
- memcpy (p, plain, plainlen);
- p += plainlen;
- cipherlen = p - cipher;
-
- if (needed != cipherlen)
- log_debug ("length mismatch: %u, %u\n", needed, cipherlen);
- gcry_free (plain);
-
- {
- struct buffer_s seqlist[2];
-
- seqlist[0].buffer = cipher;
- seqlist[0].length = cipherlen;
- seqlist[1].buffer = NULL;
- seqlist[1].length = 0;
-
- cipher = create_final (seqlist, &cipherlen);
- gcry_free (seqlist[0].buffer);
- }
-
- *r_length = cipherlen;
- return cipher;
-}
-
-
-#ifdef TEST
-int
-main (int argc, char **argv)
-{
- FILE *fp;
- struct stat st;
- char *buf;
- size_t buflen;
- GcryMPI *result;
-
- if (argc != 3)
- {
- fprintf (stderr, "usage: testp12 file passphrase\n");
- return 1;
- }
-
- gcry_control (GCRYCTL_DISABLE_SECMEM, NULL);
- gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL);
-
- fp = fopen (argv[1], "rb");
- if (!fp)
- {
- fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno));
- return 1;
- }
-
- if (fstat (fileno(fp), &st))
- {
- fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno));
- return 1;
- }
-
- buflen = st.st_size;
- buf = gcry_malloc (buflen+1);
- if (!buf || fread (buf, buflen, 1, fp) != 1)
- {
- fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno));
- return 1;
- }
- fclose (fp);
-
- result = p12_parse (buf, buflen, argv[2]);
- if (result)
- {
- int i, rc;
- char *buf;
-
- for (i=0; result[i]; i++)
- {
- rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf,
- NULL, result[i]);
- if (rc)
- printf ("%d: [error printing number: %s]\n",
- i, gpg_strerror (rc));
- else
- {
- printf ("%d: %s\n", i, buf);
- gcry_free (buf);
- }
- }
- }
-
- return 0;
-
-}
-#endif /* TEST */
diff --git a/agent/minip12.h b/agent/minip12.h
deleted file mode 100644
index 122215549..000000000
--- a/agent/minip12.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* minip12.h - Global definitions for the minimal pkcs-12 implementation.
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef MINIP12_H
-#define MINIP12_H
-
-#include <gcrypt.h>
-
-gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length,
- const char *pw);
-
-unsigned char *p12_build (gcry_mpi_t *kparms, const char *pw,
- size_t *r_length);
-
-
-#endif /*MINIP12_H*/
diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c
deleted file mode 100644
index 543a82737..000000000
--- a/agent/pkdecrypt.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* pkdecrypt.c - public key decryption (well, acually using a secret key)
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-
-
-/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp.
- Try to get the key from CTRL and write the decoded stuff back to
- OUTFP. */
-int
-agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
- FILE *outfp)
-{
- gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL;
- unsigned char *shadow_info = NULL;
- int rc;
- char *buf = NULL;
- size_t len;
-
- if (!ctrl->have_keygrip)
- {
- log_error ("speculative decryption not yet supported\n");
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- goto leave;
- }
-
- rc = gcry_sexp_sscan (&s_cipher, NULL, ciphertext, ciphertextlen);
- if (rc)
- {
- log_error ("failed to convert ciphertext: %s\n", gpg_strerror (rc));
- rc = gpg_error (GPG_ERR_INV_DATA);
- goto leave;
- }
-
- if (DBG_CRYPTO)
- {
- log_printhex ("keygrip:", ctrl->keygrip, 20);
- log_printhex ("cipher: ", ciphertext, ciphertextlen);
- }
- s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0);
- if (!s_skey && !shadow_info)
- {
- log_error ("failed to read the secret key\n");
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- goto leave;
- }
-
- if (!s_skey)
- { /* divert operation to the smartcard */
-
- if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL))
- {
- rc = gpg_error (GPG_ERR_INV_SEXP);
- goto leave;
- }
-
- rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len );
- if (rc)
- {
- log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- /* FIXME: don't use buffering and change the protocol to return
- a complete S-expression and not just a part. */
- fprintf (outfp, "%u:", (unsigned int)len);
- fwrite (buf, 1, len, outfp);
- putc (0, outfp);
- }
- else
- { /* no smartcard, but a private key */
- if (DBG_CRYPTO)
- {
- log_debug ("skey: ");
- gcry_sexp_dump (s_skey);
- }
-
- rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey);
- if (rc)
- {
- log_error ("decryption failed: %s\n", gpg_strerror (rc));
- rc = map_gcry_err (rc);
- goto leave;
- }
-
- if (DBG_CRYPTO)
- {
- log_debug ("plain: ");
- gcry_sexp_dump (s_plain);
- }
- len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xmalloc (len);
- len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
- /* FIXME: we must make sure that no buffering takes place or we are
- in full control of the buffer memory (easy to do) - should go
- into assuan. */
- fwrite (buf, 1, len, outfp);
- }
-
-
- leave:
- gcry_sexp_release (s_skey);
- gcry_sexp_release (s_plain);
- gcry_sexp_release (s_cipher);
- xfree (buf);
- xfree (shadow_info);
- return rc;
-}
-
-
diff --git a/agent/pksign.c b/agent/pksign.c
deleted file mode 100644
index fba2c652c..000000000
--- a/agent/pksign.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* pksign.c - public key signing (well, acually using a secret key)
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-
-
-static int
-do_encode_md (const unsigned char *digest, size_t digestlen, int algo,
- unsigned int nbits, gcry_mpi_t *r_val)
-{
- int nframe = (nbits+7) / 8;
- byte *frame;
- int i, n;
- byte asn[100];
- size_t asnlen;
-
- asnlen = DIM(asn);
- if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
- {
- log_error ("no object identifier for algo %d\n", algo);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- if (digestlen + asnlen + 4 > nframe )
- {
- log_error ("can't encode a %d bit MD into a %d bits frame\n",
- (int)(digestlen*8), (int)nbits);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- /* We encode the MD in this way:
- *
- * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = xtrymalloc (nframe);
- if (!frame)
- return out_of_core ();
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - digestlen - asnlen -3 ;
- assert ( i > 1 );
- memset ( frame+n, 0xff, i ); n += i;
- frame[n++] = 0;
- memcpy ( frame+n, asn, asnlen ); n += asnlen;
- memcpy ( frame+n, digest, digestlen ); n += digestlen;
- assert ( n == nframe );
- if (DBG_CRYPTO)
- log_printhex ("encoded hash:", frame, nframe);
-
- gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
- xfree (frame);
- return 0;
-}
-
-
-/* SIGN whatever information we have accumulated in CTRL and write it
- back to OUTFP. */
-int
-agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
-{
- gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL;
- gcry_mpi_t frame = NULL;
- unsigned char *shadow_info = NULL;
- int rc;
- char *buf = NULL;
- size_t len;
-
- if (!ctrl->have_keygrip)
- return gpg_error (GPG_ERR_NO_SECKEY);
-
- s_skey = agent_key_from_file (ctrl,
- ctrl->keygrip, &shadow_info, ignore_cache);
- if (!s_skey && !shadow_info)
- {
- log_error ("failed to read the secret key\n");
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- goto leave;
- }
-
- if (!s_skey)
- { /* divert operation to the smartcard */
- unsigned char *sigbuf;
-
- rc = divert_pksign (ctrl,
- ctrl->digest.value,
- ctrl->digest.valuelen,
- ctrl->digest.algo,
- shadow_info, &sigbuf);
- if (rc)
- {
- log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL);
- assert (len);
- buf = sigbuf;
- }
- else
- { /* no smartcard, but a private key */
-
- /* put the hash into a sexp */
- rc = do_encode_md (ctrl->digest.value,
- ctrl->digest.valuelen,
- ctrl->digest.algo,
- gcry_pk_get_nbits (s_skey),
- &frame);
- if (rc)
- goto leave;
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
-
- if (DBG_CRYPTO)
- {
- log_debug ("skey: ");
- gcry_sexp_dump (s_skey);
- }
-
- /* sign */
- rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
- if (rc)
- {
- log_error ("signing failed: %s\n", gpg_strerror (rc));
- rc = map_gcry_err (rc);
- goto leave;
- }
-
- if (DBG_CRYPTO)
- {
- log_debug ("result: ");
- gcry_sexp_dump (s_sig);
- }
-
- len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xmalloc (len);
- len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
- }
-
- /* FIXME: we must make sure that no buffering takes place or we are
- in full control of the buffer memory (easy to do) - should go
- into assuan. */
- fwrite (buf, 1, len, outfp);
-
- leave:
- gcry_sexp_release (s_skey);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_sig);
- gcry_mpi_release (frame);
- xfree (buf);
- xfree (shadow_info);
- return rc;
-}
-
-
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
deleted file mode 100644
index e518c5672..000000000
--- a/agent/protect-tool.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/* protect-tool.c - A tool to test the secret key protection
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 <sys/stat.h>
-#include <unistd.h>
-
-#define JNLIB_NEED_LOG_LOGV
-#include "agent.h"
-#include "minip12.h"
-#include "simple-pwquery.h"
-#include "i18n.h"
-
-enum cmd_and_opt_values
-{ aNull = 0,
- oVerbose = 'v',
- oArmor = 'a',
- oPassphrase = 'P',
-
- oProtect = 'p',
- oUnprotect = 'u',
-
- oNoVerbose = 500,
- oShadow,
- oShowShadowInfo,
- oShowKeygrip,
-
- oP12Import,
- oP12Export,
- oStore,
- oForce,
-
-aTest };
-
-struct rsa_secret_key_s
- {
- gcry_mpi_t n; /* public modulus */
- gcry_mpi_t e; /* public exponent */
- gcry_mpi_t d; /* exponent */
- gcry_mpi_t p; /* prime p. */
- gcry_mpi_t q; /* prime q. */
- gcry_mpi_t u; /* inverse of p mod q. */
- };
-
-
-static int opt_armor;
-static int opt_store;
-static int opt_force;
-static const char *passphrase;
-
-static const char *get_passphrase (void);
-static int store_private_key (const unsigned char *grip,
- const void *buffer, size_t length, int force);
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 301, NULL, 0, N_("@Options:\n ") },
-
- { oVerbose, "verbose", 0, "verbose" },
- { oArmor, "armor", 0, "write output in advanced format" },
- { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" },
- { oProtect, "protect", 256, "protect a private key"},
- { oUnprotect, "unprotect", 256, "unprotect a private key"},
- { oShadow, "shadow", 256, "create a shadow entry for a priblic key"},
- { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
- { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
-
- { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"},
- { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"},
- { oStore, "store", 0, "store the created key in the appropriate place"},
- { oForce, "force", 0, "force overwriting"},
- {0}
-};
-
-static const char *
-my_strusage (int level)
-{
- const char *p;
- switch (level)
- {
- case 11: p = "gpg-protect-tool (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n");
- break;
- case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n"
- "Secret key maintenance tool\n");
- break;
-
- default: p = NULL;
- }
- return p;
-}
-
-
-
-static void
-i18n_init (void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file( PACKAGE );
-#else
-#ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-#endif
-#endif
-}
-
-
-
-/* Used by gcry for logging */
-static void
-my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
-{
- /* translate the log levels */
- switch (level)
- {
- case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
- case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
- case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
- default: level = JNLIB_LOG_ERROR; break; }
- log_logv (level, fmt, arg_ptr);
-}
-
-
-/* static void */
-/* print_mpi (const char *text, gcry_mpi_t a) */
-/* { */
-/* char *buf; */
-/* void *bufaddr = &buf; */
-/* int rc; */
-
-/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
-/* if (rc) */
-/* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */
-/* else */
-/* { */
-/* log_info ("%s: %s\n", text, buf); */
-/* gcry_free (buf); */
-/* } */
-/* } */
-
-
-
-static unsigned char *
-make_canonical (const char *fname, const char *buf, size_t buflen)
-{
- int rc;
- size_t erroff, len;
- gcry_sexp_t sexp;
- unsigned char *result;
-
- rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
- if (rc)
- {
- log_error ("invalid S-Expression in `%s' (off=%u): %s\n",
- fname, (unsigned int)erroff, gpg_strerror (rc));
- return NULL;
- }
- len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- result = xmalloc (len);
- len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
- assert (len);
- gcry_sexp_release (sexp);
- return result;
-}
-
-static char *
-make_advanced (const unsigned char *buf, size_t buflen)
-{
- int rc;
- size_t erroff, len;
- gcry_sexp_t sexp;
- unsigned char *result;
-
- rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
- if (rc)
- {
- log_error ("invalid canonical S-Expression (off=%u): %s\n",
- (unsigned int)erroff, gpg_strerror (rc));
- return NULL;
- }
- len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
- assert (len);
- result = xmalloc (len);
- len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
- assert (len);
- gcry_sexp_release (sexp);
- return result;
-}
-
-
-static char *
-read_file (const char *fname, size_t *r_length)
-{
- FILE *fp;
- struct stat st;
- char *buf;
- size_t buflen;
-
- fp = fopen (fname, "rb");
- if (!fp)
- {
- log_error ("can't open `%s': %s\n", fname, strerror (errno));
- return NULL;
- }
-
- if (fstat (fileno(fp), &st))
- {
- log_error ("can't stat `%s': %s\n", fname, strerror (errno));
- fclose (fp);
- return NULL;
- }
-
- buflen = st.st_size;
- buf = xmalloc (buflen+1);
- if (fread (buf, buflen, 1, fp) != 1)
- {
- log_error ("error reading `%s': %s\n", fname, strerror (errno));
- fclose (fp);
- xfree (buf);
- return NULL;
- }
- fclose (fp);
-
- *r_length = buflen;
- return buf;
-}
-
-
-static unsigned char *
-read_key (const char *fname)
-{
- char *buf;
- size_t buflen;
- unsigned char *key;
-
- buf = read_file (fname, &buflen);
- if (!buf)
- return NULL;
- key = make_canonical (fname, buf, buflen);
- xfree (buf);
- return key;
-}
-
-
-
-static void
-read_and_protect (const char *fname)
-{
- int rc;
- unsigned char *key;
- unsigned char *result;
- size_t resultlen;
-
- key = read_key (fname);
- if (!key)
- return;
-
- rc = agent_protect (key, get_passphrase (), &result, &resultlen);
- xfree (key);
- if (rc)
- {
- log_error ("protecting the key failed: %s\n", gpg_strerror (rc));
- return;
- }
-
- if (opt_armor)
- {
- char *p = make_advanced (result, resultlen);
- xfree (result);
- if (!p)
- return;
- result = p;
- resultlen = strlen (p);
- }
-
- fwrite (result, resultlen, 1, stdout);
- xfree (result);
-}
-
-
-static void
-read_and_unprotect (const char *fname)
-{
- int rc;
- unsigned char *key;
- unsigned char *result;
- size_t resultlen;
-
- key = read_key (fname);
- if (!key)
- return;
-
- rc = agent_unprotect (key, get_passphrase (), &result, &resultlen);
- xfree (key);
- if (rc)
- {
- log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc));
- return;
- }
-
- if (opt_armor)
- {
- char *p = make_advanced (result, resultlen);
- xfree (result);
- if (!p)
- return;
- result = p;
- resultlen = strlen (p);
- }
-
- fwrite (result, resultlen, 1, stdout);
- xfree (result);
-}
-
-
-
-static void
-read_and_shadow (const char *fname)
-{
- int rc;
- unsigned char *key;
- unsigned char *result;
- size_t resultlen;
-
- key = read_key (fname);
- if (!key)
- return;
-
- rc = agent_shadow_key (key, "(8:313233342:43)", &result);
- xfree (key);
- if (rc)
- {
- log_error ("shadowing the key failed: %s\n", gpg_strerror (rc));
- return;
- }
- resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
- assert (resultlen);
-
- if (opt_armor)
- {
- char *p = make_advanced (result, resultlen);
- xfree (result);
- if (!p)
- return;
- result = p;
- resultlen = strlen (p);
- }
-
- fwrite (result, resultlen, 1, stdout);
- xfree (result);
-}
-
-static void
-show_shadow_info (const char *fname)
-{
- int rc;
- unsigned char *key;
- const unsigned char *info;
- size_t infolen;
-
- key = read_key (fname);
- if (!key)
- return;
-
- rc = agent_get_shadow_info (key, &info);
- xfree (key);
- if (rc)
- {
- log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
- return;
- }
- infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
- assert (infolen);
-
- if (opt_armor)
- {
- char *p = make_advanced (info, infolen);
- if (!p)
- return;
- fwrite (p, strlen (p), 1, stdout);
- xfree (p);
- }
- else
- fwrite (info, infolen, 1, stdout);
-}
-
-
-static void
-show_file (const char *fname)
-{
- unsigned char *key;
- size_t keylen;
- char *p;
-
- key = read_key (fname);
- if (!key)
- return;
-
- keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
- assert (keylen);
-
- p = make_advanced (key, keylen);
- xfree (key);
- if (p)
- {
- fwrite (p, strlen (p), 1, stdout);
- xfree (p);
- }
-}
-
-static void
-show_keygrip (const char *fname)
-{
- unsigned char *key;
- gcry_sexp_t private;
- unsigned char grip[20];
- int i;
-
- key = read_key (fname);
- if (!key)
- return;
-
- if (gcry_sexp_new (&private, key, 0, 0))
- {
- log_error ("gcry_sexp_new failed\n");
- return;
- }
- xfree (key);
-
- if (!gcry_pk_get_keygrip (private, grip))
- {
- log_error ("can't calculate keygrip\n");
- return;
- }
- gcry_sexp_release (private);
-
- for (i=0; i < 20; i++)
- printf ("%02X", grip[i]);
- putchar ('\n');
-}
-
-
-static int
-rsa_key_check (struct rsa_secret_key_s *skey)
-{
- int err = 0;
- gcry_mpi_t t = gcry_mpi_snew (0);
- gcry_mpi_t t1 = gcry_mpi_snew (0);
- gcry_mpi_t t2 = gcry_mpi_snew (0);
- gcry_mpi_t phi = gcry_mpi_snew (0);
-
- /* check that n == p * q */
- gcry_mpi_mul (t, skey->p, skey->q);
- if (gcry_mpi_cmp( t, skey->n) )
- {
- log_error ("RSA oops: n != p * q\n");
- err++;
- }
-
- /* check that p is less than q */
- if (gcry_mpi_cmp (skey->p, skey->q) > 0)
- {
- gcry_mpi_t tmp;
-
- log_info ("swapping secret primes\n");
- tmp = gcry_mpi_copy (skey->p);
- gcry_mpi_set (skey->p, skey->q);
- gcry_mpi_set (skey->q, tmp);
- gcry_mpi_release (tmp);
- /* and must recompute u of course */
- gcry_mpi_invm (skey->u, skey->p, skey->q);
- }
-
- /* check that e divides neither p-1 nor q-1 */
- gcry_mpi_sub_ui (t, skey->p, 1 );
- gcry_mpi_div (NULL, t, t, skey->e, 0);
- if (!gcry_mpi_cmp_ui( t, 0) )
- {
- log_error ("RSA oops: e divides p-1\n");
- err++;
- }
- gcry_mpi_sub_ui (t, skey->q, 1);
- gcry_mpi_div (NULL, t, t, skey->e, 0);
- if (!gcry_mpi_cmp_ui( t, 0))
- {
- log_info ( "RSA oops: e divides q-1\n" );
- err++;
- }
-
- /* check that d is correct. */
- gcry_mpi_sub_ui (t1, skey->p, 1);
- gcry_mpi_sub_ui (t2, skey->q, 1);
- gcry_mpi_mul (phi, t1, t2);
- gcry_mpi_invm (t, skey->e, phi);
- if (gcry_mpi_cmp (t, skey->d))
- { /* no: try universal exponent. */
- gcry_mpi_gcd (t, t1, t2);
- gcry_mpi_div (t, NULL, phi, t, 0);
- gcry_mpi_invm (t, skey->e, t);
- if (gcry_mpi_cmp (t, skey->d))
- {
- log_error ("RSA oops: bad secret exponent\n");
- err++;
- }
- }
-
- /* check for correctness of u */
- gcry_mpi_invm (t, skey->p, skey->q);
- if (gcry_mpi_cmp (t, skey->u))
- {
- log_info ( "RSA oops: bad u parameter\n");
- err++;
- }
-
- if (err)
- log_info ("RSA secret key check failed\n");
-
- gcry_mpi_release (t);
- gcry_mpi_release (t1);
- gcry_mpi_release (t2);
- gcry_mpi_release (phi);
-
- return err? -1:0;
-}
-
-
-static void
-import_p12_file (const char *fname)
-{
- char *buf;
- unsigned char *result;
- size_t buflen, resultlen;
- int i;
- int rc;
- gcry_mpi_t *kparms;
- struct rsa_secret_key_s sk;
- gcry_sexp_t s_key;
- unsigned char *key;
- unsigned char grip[20];
-
- /* fixme: we should release some stuff on error */
-
- buf = read_file (fname, &buflen);
- if (!buf)
- return;
-
- kparms = p12_parse (buf, buflen, get_passphrase ());
- xfree (buf);
- if (!kparms)
- {
- log_error ("error parsing or decrypting the PKCS-1 file\n");
- return;
- }
- for (i=0; kparms[i]; i++)
- ;
- if (i != 8)
- {
- log_error ("invalid structure of private key\n");
- return;
- }
-
-
-/* print_mpi (" n", kparms[0]); */
-/* print_mpi (" e", kparms[1]); */
-/* print_mpi (" d", kparms[2]); */
-/* print_mpi (" p", kparms[3]); */
-/* print_mpi (" q", kparms[4]); */
-/* print_mpi ("dmp1", kparms[5]); */
-/* print_mpi ("dmq1", kparms[6]); */
-/* print_mpi (" u", kparms[7]); */
-
- sk.n = kparms[0];
- sk.e = kparms[1];
- sk.d = kparms[2];
- sk.q = kparms[3];
- sk.p = kparms[4];
- sk.u = kparms[7];
- if (rsa_key_check (&sk))
- return;
-/* print_mpi (" n", sk.n); */
-/* print_mpi (" e", sk.e); */
-/* print_mpi (" d", sk.d); */
-/* print_mpi (" p", sk.p); */
-/* print_mpi (" q", sk.q); */
-/* print_mpi (" u", sk.u); */
-
- /* Create an S-expresion from the parameters. */
- rc = gcry_sexp_build (&s_key, NULL,
- "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
- sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL);
- for (i=0; i < 8; i++)
- gcry_mpi_release (kparms[i]);
- gcry_free (kparms);
- if (rc)
- {
- log_error ("failed to created S-expression from key: %s\n",
- gpg_strerror (rc));
- return;
- }
-
- /* Compute the keygrip. */
- if (!gcry_pk_get_keygrip (s_key, grip))
- {
- log_error ("can't calculate keygrip\n");
- return;
- }
- log_info ("keygrip: ");
- for (i=0; i < 20; i++)
- log_printf ("%02X", grip[i]);
- log_printf ("\n");
-
- /* convert to canonical encoding */
- buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (buflen);
- key = gcry_xmalloc_secure (buflen);
- buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, key, buflen);
- assert (buflen);
- gcry_sexp_release (s_key);
-
-
- rc = agent_protect (key, get_passphrase (), &result, &resultlen);
- xfree (key);
- if (rc)
- {
- log_error ("protecting the key failed: %s\n", gpg_strerror (rc));
- return;
- }
-
- if (opt_armor)
- {
- char *p = make_advanced (result, resultlen);
- xfree (result);
- if (!p)
- return;
- result = p;
- resultlen = strlen (p);
- }
-
- if (opt_store)
- store_private_key (grip, result, resultlen, opt_force);
- else
- fwrite (result, resultlen, 1, stdout);
-
- xfree (result);
-}
-
-
-
-static gcry_mpi_t *
-sexp_to_kparms (gcry_sexp_t sexp)
-{
- gcry_sexp_t list, l2;
- const char *name;
- const char *s;
- size_t n;
- int i, idx;
- const char *elems;
- gcry_mpi_t *array;
-
- list = gcry_sexp_find_token (sexp, "private-key", 0 );
- if(!list)
- return NULL;
- l2 = gcry_sexp_cadr (list);
- gcry_sexp_release (list);
- list = l2;
- name = gcry_sexp_nth_data (list, 0, &n);
- if(!name || n != 3 || memcmp (name, "rsa", 3))
- {
- gcry_sexp_release (list);
- return NULL;
- }
-
- /* Parameter names used with RSA. */
- elems = "nedpqu";
- array = xcalloc (strlen(elems) + 1, sizeof *array);
- for (idx=0, s=elems; *s; s++, idx++ )
- {
- l2 = gcry_sexp_find_token (list, s, 1);
- if (!l2)
- {
- for (i=0; i<idx; i++)
- gcry_mpi_release (array[i]);
- xfree (array);
- gcry_sexp_release (list);
- return NULL; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (l2);
- if (!array[idx])
- {
- for (i=0; i<idx; i++)
- gcry_mpi_release (array[i]);
- xfree (array);
- gcry_sexp_release (list);
- return NULL; /* required parameter is invalid */
- }
- }
-
- gcry_sexp_release (list);
- return array;
-}
-
-
-
-
-static void
-export_p12_file (const char *fname)
-{
- gcry_mpi_t kparms[9], *kp;
- unsigned char *key;
- size_t keylen;
- gcry_sexp_t private;
- struct rsa_secret_key_s sk;
- int i;
-
- key = read_key (fname);
- if (!key)
- return;
-
- if (gcry_sexp_new (&private, key, 0, 0))
- {
- log_error ("gcry_sexp_new failed\n");
- return;
- }
- xfree (key);
-
- kp = sexp_to_kparms (private);
- gcry_sexp_release (private);
- if (!kp)
- {
- log_error ("error converting key parameters\n");
- return;
- }
- sk.n = kp[0];
- sk.e = kp[1];
- sk.d = kp[2];
- sk.p = kp[3];
- sk.q = kp[4];
- sk.u = kp[5];
- xfree (kp);
-
-
- kparms[0] = sk.n;
- kparms[1] = sk.e;
- kparms[2] = sk.d;
- kparms[3] = sk.q;
- kparms[4] = sk.p;
- kparms[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */
- gcry_mpi_sub_ui (kparms[5], kparms[3], 1);
- gcry_mpi_mod (kparms[5], sk.d, kparms[5]);
- kparms[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */
- gcry_mpi_sub_ui (kparms[6], kparms[4], 1);
- gcry_mpi_mod (kparms[6], sk.d, kparms[6]);
- kparms[7] = sk.u;
- kparms[8] = NULL;
-
- key = p12_build (kparms, get_passphrase (), &keylen);
- for (i=0; i < 8; i++)
- gcry_mpi_release (kparms[i]);
- if (!key)
- return;
-
- fwrite (key, keylen, 1, stdout);
- xfree (key);
-}
-
-
-int
-main (int argc, char **argv )
-{
- ARGPARSE_ARGS pargs;
- int cmd = 0;
-
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- log_set_prefix ("gpg-protect-tool", 1);
- i18n_init ();
-
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
-
- gcry_set_log_handler (my_gcry_logger, NULL);
-
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
-
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags= 1; /* do not remove the args */
- while (arg_parse (&pargs, opts) )
- {
- switch (pargs.r_opt)
- {
- case oVerbose: opt.verbose++; break;
- case oArmor: opt_armor=1; break;
-
- case oProtect: cmd = oProtect; break;
- case oUnprotect: cmd = oUnprotect; break;
- case oShadow: cmd = oShadow; break;
- case oShowShadowInfo: cmd = oShowShadowInfo; break;
- case oShowKeygrip: cmd = oShowKeygrip; break;
- case oP12Import: cmd = oP12Import; break;
- case oP12Export: cmd = oP12Export; break;
-
- case oPassphrase: passphrase = pargs.r.ret_str; break;
- case oStore: opt_store = 1; break;
- case oForce: opt_force = 1; break;
-
- default : pargs.err = 2; break;
- }
- }
- if (log_get_errorcount(0))
- exit(2);
-
- if (argc != 1)
- usage (1);
-
- if (cmd == oProtect)
- read_and_protect (*argv);
- else if (cmd == oUnprotect)
- read_and_unprotect (*argv);
- else if (cmd == oShadow)
- read_and_shadow (*argv);
- else if (cmd == oShowShadowInfo)
- show_shadow_info (*argv);
- else if (cmd == oShowKeygrip)
- show_keygrip (*argv);
- else if (cmd == oP12Import)
- import_p12_file (*argv);
- else if (cmd == oP12Export)
- export_p12_file (*argv);
- else
- show_file (*argv);
-
- agent_exit (0);
- return 8; /*NOTREACHED*/
-}
-
-void
-agent_exit (int rc)
-{
- rc = rc? rc : log_get_errorcount(0)? 2 : 0;
- exit (rc);
-}
-
-
-/* Return the passphrase string and ask the agent if it has not been
- set from the command line. */
-static const char *
-get_passphrase (void)
-{
- char *pw;
- int err;
-
- if (passphrase)
- return passphrase;
-
- pw = simple_pwquery (NULL,NULL,
- _("Enter passphrase:"),
- _("Please enter the passphrase or the PIN\n"
- "needed to complete this operation."),
- &err);
- if (!pw)
- {
- if (err)
- log_error ("error while asking for the passphrase\n");
- else
- log_info ("cancelled\n");
- agent_exit (0);
- }
- passphrase = pw;
- return passphrase;
-}
-
-
-static int
-store_private_key (const unsigned char *grip,
- const void *buffer, size_t length, int force)
-{
- int i;
- const char *homedir;
- char *fname;
- FILE *fp;
- char hexgrip[40+4+1];
-
- for (i=0; i < 20; i++)
- sprintf (hexgrip+2*i, "%02X", grip[i]);
- strcpy (hexgrip+40, ".key");
-
- homedir = getenv("GNUPGHOME");
- if (!homedir || !*homedir)
- homedir = GNUPG_DEFAULT_HOMEDIR;
-
- fname = make_filename (homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
- if (force)
- fp = fopen (fname, "wb");
- else
- {
- if (!access (fname, F_OK))
- {
- log_error ("secret key file `%s' already exists\n", fname);
- xfree (fname);
- return -1;
- }
- fp = fopen (fname, "wbx"); /* FIXME: the x is a GNU extension - let
- configure check whether this actually
- works */
- }
-
- if (!fp)
- {
- log_error ("can't create `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- return -1;
- }
-
- if (fwrite (buffer, length, 1, fp) != 1)
- {
- log_error ("error writing `%s': %s\n", fname, strerror (errno));
- fclose (fp);
- remove (fname);
- xfree (fname);
- return -1;
- }
- if ( fclose (fp) )
- {
- log_error ("error closing `%s': %s\n", fname, strerror (errno));
- remove (fname);
- xfree (fname);
- return -1;
- }
- log_info ("secret key stored as `%s'\n", fname);
-
- xfree (fname);
- return 0;
-}
diff --git a/agent/protect.c b/agent/protect.c
deleted file mode 100644
index e438d53b4..000000000
--- a/agent/protect.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/* protect.c - Un/Protect a secret key
- * Copyright (C) 1998, 1999, 2000, 2001, 2002,
- * 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-
-#include "sexp-parse.h"
-
-#define PROT_CIPHER GCRY_CIPHER_AES
-#define PROT_CIPHER_STRING "aes"
-#define PROT_CIPHER_KEYLEN (128/8)
-
-
-/* A table containing the information needed to create a protected
- private key */
-static struct {
- const char *algo;
- const char *parmlist;
- int prot_from, prot_to;
-} protect_info[] = {
- { "rsa", "nedpqu", 2, 5 },
- { NULL }
-};
-
-
-static int
-hash_passphrase (const char *passphrase, int hashalgo,
- int s2kmode,
- const unsigned char *s2ksalt, unsigned long s2kcount,
- unsigned char *key, size_t keylen);
-
-
-
-/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to
- a 20 byte buffer. This function is suitable for any algorithms. */
-static int
-calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
-{
- const unsigned char *hash_begin, *hash_end;
- const unsigned char *s;
- size_t n;
-
- s = plainkey;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "private-key"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- hash_begin = s;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n; /* skip over the algorithm name */
-
- while (*s == '(')
- {
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n;
- if ( *s != ')' )
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- }
- if (*s != ')')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- hash_end = s;
-
- gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
- hash_begin, hash_end - hash_begin);
-
- return 0;
-}
-
-
-
-/* Encrypt the parameter block starting at PROTBEGIN with length
- PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
- encrypted block in RESULT or ereturn with an error code. SHA1HASH
- is the 20 byte SHA-1 hash required for the integrity code.
-
- The parameter block is expected to be an incomplete S-Expression of
- the form (example in advanced format):
-
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#)
-
- the returned block is the S-Expression:
-
- (protected mode (parms) encrypted_octet_string)
-
-*/
-static int
-do_encryption (const char *protbegin, size_t protlen,
- const char *passphrase, const unsigned char *sha1hash,
- unsigned char **result, size_t *resultlen)
-{
- gcry_cipher_hd_t hd;
- const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
- int blklen, enclen, outlen;
- char *iv = NULL;
- int rc;
- char *outbuf = NULL;
- char *p;
- int saltpos, ivpos, encpos;
-
- rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
- GCRY_CIPHER_SECURE);
- if (rc)
- return rc;
-
-
- /* We need to work on a copy of the data because this makes it
- easier to add the trailer and the padding and more important we
- have to prefix the text with 2 parenthesis, so we have to
- allocate enough space for:
-
- ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
-
- We always append a full block of random bytes as padding but
- encrypt only what is needed for a full blocksize */
- blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
- outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
- enclen = outlen/blklen * blklen;
- outbuf = gcry_malloc_secure (outlen);
- if (!outbuf)
- rc = out_of_core ();
- if (!rc)
- {
- /* allocate random bytes to be used as IV, padding and s2k salt*/
- iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM);
- if (!iv)
- rc = gpg_error (GPG_ERR_ENOMEM);
- else
- rc = gcry_cipher_setiv (hd, iv, blklen);
- }
- if (!rc)
- {
- unsigned char *key;
- size_t keylen = PROT_CIPHER_KEYLEN;
-
- key = gcry_malloc_secure (keylen);
- if (!key)
- rc = out_of_core ();
- else
- {
- rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
- 3, iv+2*blklen, 96, key, keylen);
- if (!rc)
- rc = gcry_cipher_setkey (hd, key, keylen);
- xfree (key);
- }
- }
- if (!rc)
- {
- p = outbuf;
- *p++ = '(';
- *p++ = '(';
- memcpy (p, protbegin, protlen);
- p += protlen;
- memcpy (p, ")(4:hash4:sha120:", 17);
- p += 17;
- memcpy (p, sha1hash, 20);
- p += 20;
- *p++ = ')';
- *p++ = ')';
- memcpy (p, iv+blklen, blklen);
- p += blklen;
- assert ( p - outbuf == outlen);
- rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
- }
- gcry_cipher_close (hd);
- if (rc)
- {
- xfree (iv);
- xfree (outbuf);
- return rc;
- }
-
- /* Now allocate the buffer we want to return. This is
-
- (protected openpgp-s2k3-sha1-aes-cbc
- ((sha1 salt no_of_iterations) 16byte_iv)
- encrypted_octet_string)
-
- in canoncical format of course. We use asprintf and %n modifier
- and spaces as palceholders. */
- asprintf (&p,
- "(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
- (int)strlen (modestr), modestr,
- &saltpos,
- blklen, &ivpos, blklen, "",
- enclen, &encpos, enclen, "");
- if (p)
- { /* asprintf does not use our malloc system */
- char *psave = p;
- p = xtrymalloc (strlen (psave)+1);
- if (p)
- strcpy (p, psave);
- free (psave);
- }
- if (!p)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (iv);
- xfree (outbuf);
- return tmperr;
- }
- *resultlen = strlen (p);
- *result = p;
- memcpy (p+saltpos, iv+2*blklen, 8);
- memcpy (p+ivpos, iv, blklen);
- memcpy (p+encpos, outbuf, enclen);
- xfree (iv);
- xfree (outbuf);
- return 0;
-}
-
-
-
-/* Protect the key encoded in canonical format in plainkey. We assume
- a valid S-Exp here. */
-int
-agent_protect (const unsigned char *plainkey, const char *passphrase,
- unsigned char **result, size_t *resultlen)
-{
- int rc;
- const unsigned char *s;
- const unsigned char *hash_begin, *hash_end;
- const unsigned char *prot_begin, *prot_end, *real_end;
- size_t n;
- int c, infidx, i;
- unsigned char hashvalue[20];
- unsigned char *protected;
- size_t protectedlen;
- int depth = 0;
- unsigned char *p;
-
- s = plainkey;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "private-key"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- depth++;
- hash_begin = s;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
-
- for (infidx=0; protect_info[infidx].algo
- && !smatch (&s, n, protect_info[infidx].algo); infidx++)
- ;
- if (!protect_info[infidx].algo)
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-
- prot_begin = prot_end = NULL;
- for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
- {
- if (i == protect_info[infidx].prot_from)
- prot_begin = s;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (n != 1 || c != *s)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s +=n; /* skip value */
- if (*s != ')')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth--;
- if (i == protect_info[infidx].prot_to)
- prot_end = s;
- s++;
- }
- if (*s != ')' || !prot_begin || !prot_end )
- return gpg_error (GPG_ERR_INV_SEXP);
- depth--;
- hash_end = s;
- s++;
- /* skip to the end of the S-exp */
- assert (depth == 1);
- rc = sskip (&s, &depth);
- if (rc)
- return rc;
- assert (!depth);
- real_end = s-1;
-
- gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue,
- hash_begin, hash_end - hash_begin + 1);
-
- rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
- passphrase, hashvalue,
- &protected, &protectedlen);
- if (rc)
- return rc;
-
- /* Now create the protected version of the key. Note that the 10
- extra bytes are for for the inserted "protected-" string (the
- beginning of the plaintext reads: "((11:private-key(" ). */
- *resultlen = (10
- + (prot_begin-plainkey)
- + protectedlen
- + (real_end-prot_end));
- *result = p = xtrymalloc (*resultlen);
- if (!p)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (protected);
- return tmperr;
- }
- memcpy (p, "(21:protected-", 14);
- p += 14;
- memcpy (p, plainkey+4, prot_begin - plainkey - 4);
- p += prot_begin - plainkey - 4;
- memcpy (p, protected, protectedlen);
- p += protectedlen;
- memcpy (p, prot_end+1, real_end - prot_end);
- p += real_end - prot_end;
- assert ( p - *result == *resultlen);
- xfree (protected);
- return 0;
-}
-
-
-/* Do the actual decryption and check the return list for consistency. */
-static int
-do_decryption (const unsigned char *protected, size_t protectedlen,
- const char *passphrase,
- const unsigned char *s2ksalt, unsigned long s2kcount,
- const unsigned char *iv, size_t ivlen,
- unsigned char **result)
-{
- int rc = 0;
- int blklen;
- gcry_cipher_hd_t hd;
- unsigned char *outbuf;
- size_t reallen;
-
- blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
- if (protectedlen < 4 || (protectedlen%blklen))
- return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
-
- rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
- GCRY_CIPHER_SECURE);
- if (rc)
- return rc;
-
- outbuf = gcry_malloc_secure (protectedlen);
- if (!outbuf)
- rc = out_of_core ();
- if (!rc)
- rc = gcry_cipher_setiv (hd, iv, ivlen);
- if (!rc)
- {
- unsigned char *key;
- size_t keylen = PROT_CIPHER_KEYLEN;
-
- key = gcry_malloc_secure (keylen);
- if (!key)
- rc = out_of_core ();
- else
- {
- rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
- 3, s2ksalt, s2kcount, key, keylen);
- if (!rc)
- rc = gcry_cipher_setkey (hd, key, keylen);
- xfree (key);
- }
- }
- if (!rc)
- rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
- protected, protectedlen);
- gcry_cipher_close (hd);
- if (rc)
- {
- xfree (outbuf);
- return rc;
- }
- /* do a quick check first */
- if (*outbuf != '(' && outbuf[1] != '(')
- {
- xfree (outbuf);
- return gpg_error (GPG_ERR_BAD_PASSPHRASE);
- }
- /* check that we have a consistent S-Exp */
- reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
- if (!reallen || (reallen + blklen < protectedlen) )
- {
- xfree (outbuf);
- return gpg_error (GPG_ERR_BAD_PASSPHRASE);
- }
- *result = outbuf;
- return 0;
-}
-
-
-/* Merge the parameter list contained in CLEARTEXT with the original
- protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
- Return the new list in RESULT and the MIC value in the 20 byte
- buffer SHA1HASH. */
-static int
-merge_lists (const unsigned char *protectedkey,
- size_t replacepos,
- const unsigned char *cleartext,
- unsigned char *sha1hash, unsigned char **result)
-{
- size_t n, newlistlen;
- unsigned char *newlist, *p;
- const unsigned char *s;
- const unsigned char *startpos, *endpos;
- int i, rc;
-
- if (replacepos < 26)
- return gpg_error (GPG_ERR_BUG);
-
- /* Estimate the required size of the resulting list. We have a large
- safety margin of >20 bytes (MIC hash from CLEARTEXT and the
- removed "protected-" */
- newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
- if (!newlistlen)
- return gpg_error (GPG_ERR_BUG);
- n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
- if (!n)
- return gpg_error (GPG_ERR_BUG);
- newlistlen += n;
- newlist = gcry_malloc_secure (newlistlen);
- if (!newlist)
- return out_of_core ();
-
- /* Copy the initial segment */
- strcpy (newlist, "(11:private-key");
- p = newlist + 15;
- memcpy (p, protectedkey+15+10, replacepos-15-10);
- p += replacepos-15-10;
-
- /* copy the cleartext */
- s = cleartext;
- if (*s != '(' && s[1] != '(')
- return gpg_error (GPG_ERR_BUG); /*we already checked this */
- s += 2;
- startpos = s;
- while ( *s == '(' )
- {
- s++;
- n = snext (&s);
- if (!n)
- goto invalid_sexp;
- s += n;
- n = snext (&s);
- if (!n)
- goto invalid_sexp;
- s += n;
- if ( *s != ')' )
- goto invalid_sexp;
- s++;
- }
- if ( *s != ')' )
- goto invalid_sexp;
- endpos = s;
- s++;
- /* short intermezzo: Get the MIC */
- if (*s != '(')
- goto invalid_sexp;
- s++;
- n = snext (&s);
- if (!smatch (&s, n, "hash"))
- goto invalid_sexp;
- n = snext (&s);
- if (!smatch (&s, n, "sha1"))
- goto invalid_sexp;
- n = snext (&s);
- if (n != 20)
- goto invalid_sexp;
- memcpy (sha1hash, s, 20);
- s += n;
- if (*s != ')')
- goto invalid_sexp;
- /* end intermezzo */
-
- /* append the parameter list */
- memcpy (p, startpos, endpos - startpos);
- p += endpos - startpos;
-
- /* skip overt the protected list element in the original list */
- s = protectedkey + replacepos;
- assert (*s == '(');
- s++;
- i = 1;
- rc = sskip (&s, &i);
- if (rc)
- goto failure;
- startpos = s;
- i = 2; /* we are inside this level */
- rc = sskip (&s, &i);
- if (rc)
- goto failure;
- assert (s[-1] == ')');
- endpos = s; /* one behind the end of the list */
-
- /* append the rest */
- memcpy (p, startpos, endpos - startpos);
- p += endpos - startpos;
-
- /* ready */
- *result = newlist;
- return 0;
-
- failure:
- xfree (newlist);
- return rc;
-
- invalid_sexp:
- xfree (newlist);
- return gpg_error (GPG_ERR_INV_SEXP);
-}
-
-
-
-/* Unprotect the key encoded in canonical format. We assume a valid
- S-Exp here. */
-int
-agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
- unsigned char **result, size_t *resultlen)
-{
- int rc;
- const unsigned char *s;
- size_t n;
- int infidx, i;
- unsigned char sha1hash[20], sha1hash2[20];
- const unsigned char *s2ksalt;
- unsigned long s2kcount;
- const unsigned char *iv;
- const unsigned char *prot_begin;
- unsigned char *cleartext;
- unsigned char *final;
-
- s = protectedkey;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "protected-private-key"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
-
- for (infidx=0; protect_info[infidx].algo
- && !smatch (&s, n, protect_info[infidx].algo); infidx++)
- ;
- if (!protect_info[infidx].algo)
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-
- /* now find the list with the protected information. Here is an
- example for such a list:
- (protected openpgp-s2k3-sha1-aes-cbc
- ((sha1 <salt> <count>) <Initialization_Vector>)
- <encrypted_data>)
- */
- for (;;)
- {
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- prot_begin = s;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (smatch (&s, n, "protected"))
- break;
- s += n;
- i = 1;
- rc = sskip (&s, &i);
- if (rc)
- return rc;
- }
- /* found */
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
- return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
- if (*s != '(' || s[1] != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- s += 2;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "sha1"))
- return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
- n = snext (&s);
- if (n != 8)
- return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- s2ksalt = s;
- s += n;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- /* We expect a list close as next, so we can simply use strtoul()
- here. We might want to check that we only have digits - but this
- is nothing we should worry about */
- if (s[n] != ')' )
- return gpg_error (GPG_ERR_INV_SEXP);
- s2kcount = strtoul (s, NULL, 10);
- if (!s2kcount)
- return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- s += n;
- s++; /* skip list end */
-
- n = snext (&s);
- if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */
- return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- iv = s;
- s += n;
- if (*s != ')' )
- return gpg_error (GPG_ERR_INV_SEXP);
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
-
- rc = do_decryption (s, n,
- passphrase, s2ksalt, s2kcount,
- iv, 16,
- &cleartext);
- if (rc)
- return rc;
-
- rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
- sha1hash, &final);
- xfree (cleartext);
- if (rc)
- return rc;
-
- rc = calculate_mic (final, sha1hash2);
- if (!rc && memcmp (sha1hash, sha1hash2, 20))
- rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- if (rc)
- {
- xfree (final);
- return rc;
- }
-
- *result = final;
- *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
- return 0;
-}
-
-/* Check the type of the private key, this is one of the constants:
- PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
- value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
- PRIVATE_KEY_PROTECTED for an protected private key or
- PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
- elsewhere. */
-int
-agent_private_key_type (const unsigned char *privatekey)
-{
- const unsigned char *s;
- size_t n;
-
- s = privatekey;
- if (*s != '(')
- return PRIVATE_KEY_UNKNOWN;
- s++;
- n = snext (&s);
- if (!n)
- return PRIVATE_KEY_UNKNOWN;
- if (smatch (&s, n, "protected-private-key"))
- return PRIVATE_KEY_PROTECTED;
- if (smatch (&s, n, "shadowed-private-key"))
- return PRIVATE_KEY_SHADOWED;
- if (smatch (&s, n, "private-key"))
- return PRIVATE_KEY_CLEAR;
- return PRIVATE_KEY_UNKNOWN;
-}
-
-
-
-/* Transform a passphrase into a suitable key of length KEYLEN and
- store this key in the caller provided buffer KEY. The caller must
- provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
- that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
- value is 96).
-
- Returns an error code on failure. */
-static int
-hash_passphrase (const char *passphrase, int hashalgo,
- int s2kmode,
- const unsigned char *s2ksalt,
- unsigned long s2kcount,
- unsigned char *key, size_t keylen)
-{
- int rc;
- gcry_md_hd_t md;
- int pass, i;
- int used = 0;
- int pwlen = strlen (passphrase);
-
- if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
- || !hashalgo || !keylen || !key || !passphrase)
- return gpg_error (GPG_ERR_INV_VALUE);
- if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
- if (rc)
- return rc;
-
- for (pass=0; used < keylen; pass++)
- {
- if (pass)
- {
- gcry_md_reset (md);
- for (i=0; i < pass; i++) /* preset the hash context */
- gcry_md_putc (md, 0);
- }
-
- if (s2kmode == 1 || s2kmode == 3)
- {
- int len2 = pwlen + 8;
- unsigned long count = len2;
-
- if (s2kmode == 3)
- {
- count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
- if (count < len2)
- count = len2;
- }
-
- while (count > len2)
- {
- gcry_md_write (md, s2ksalt, 8);
- gcry_md_write (md, passphrase, pwlen);
- count -= len2;
- }
- if (count < 8)
- gcry_md_write (md, s2ksalt, count);
- else
- {
- gcry_md_write (md, s2ksalt, 8);
- count -= 8;
- gcry_md_write (md, passphrase, count);
- }
- }
- else
- gcry_md_write (md, passphrase, pwlen);
-
- gcry_md_final (md);
- i = gcry_md_get_algo_dlen (hashalgo);
- if (i > keylen - used)
- i = keylen - used;
- memcpy (key+used, gcry_md_read (md, hashalgo), i);
- used += i;
- }
- gcry_md_close(md);
- return 0;
-}
-
-
-
-/* Create a shadow key from a public key. We use the shadow protocol
- "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
- S-expression is returned in an allocated buffer RESULT will point
- to. The input parameters are expected to be valid canonilized
- S-expressions */
-int
-agent_shadow_key (const unsigned char *pubkey,
- const unsigned char *shadow_info,
- unsigned char **result)
-{
- const unsigned char *s;
- const unsigned char *point;
- size_t n;
- int depth = 0;
- unsigned char *p;
- size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
- size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
-
- if (!pubkey_len || !shadow_info_len)
- return gpg_error (GPG_ERR_INV_VALUE);
- s = pubkey;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "public-key"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n; /* skip over the algorithm name */
-
- while (*s != ')')
- {
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s +=n; /* skip value */
- if (*s != ')')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth--;
- s++;
- }
- point = s; /* insert right before the point */
- depth--;
- s++;
- assert (depth == 1);
-
- /* calculate required length by taking in account: the "shadowed-"
- prefix, the "shadowed", "t1-v1" as well as some parenthesis */
- n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
- *result = p = xtrymalloc (n);
- if (!p)
- return out_of_core ();
- p = stpcpy (p, "(20:shadowed-private-key");
- /* (10:public-key ...)*/
- memcpy (p, pubkey+14, point - (pubkey+14));
- p += point - (pubkey+14);
- p = stpcpy (p, "(8:shadowed5:t1-v1");
- memcpy (p, shadow_info, shadow_info_len);
- p += shadow_info_len;
- *p++ = ')';
- memcpy (p, point, pubkey_len - (point - pubkey));
- p += pubkey_len - (point - pubkey);
-
- return 0;
-}
-
-/* Parse a canonical encoded shadowed key and return a pointer to the
- inner list with the shadow_info */
-int
-agent_get_shadow_info (const unsigned char *shadowkey,
- unsigned char const **shadow_info)
-{
- const unsigned char *s;
- size_t n;
- int depth = 0;
-
- s = shadowkey;
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "shadowed-private-key"))
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n; /* skip over the algorithm name */
-
- for (;;)
- {
- if (*s == ')')
- return gpg_error (GPG_ERR_UNKNOWN_SEXP);
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth++;
- s++;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (smatch (&s, n, "shadowed"))
- break;
- s += n;
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s +=n; /* skip value */
- if (*s != ')')
- return gpg_error (GPG_ERR_INV_SEXP);
- depth--;
- s++;
- }
- /* found the shadowed list, s points to the protocol */
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- if (smatch (&s, n, "t1-v1"))
- {
- if (*s != '(')
- return gpg_error (GPG_ERR_INV_SEXP);
- *shadow_info = s;
- }
- else
- return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
- return 0;
-}
-
diff --git a/agent/query.c b/agent/query.c
deleted file mode 100644
index 4a051965d..000000000
--- a/agent/query.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* query.c - fork of the pinentry to query stuff from the user
- * Copyright (C) 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#ifdef USE_GNU_PTH
-# include <pth.h>
-#endif
-
-#include "agent.h"
-#include "i18n.h"
-#include <assuan.h>
-
-#ifdef _POSIX_OPEN_MAX
-#define MAX_OPEN_FDS _POSIX_OPEN_MAX
-#else
-#define MAX_OPEN_FDS 20
-#endif
-
-static ASSUAN_CONTEXT entry_ctx = NULL;
-#ifdef USE_GNU_PTH
-static pth_mutex_t entry_lock = PTH_MUTEX_INIT;
-#endif
-
-/* data to be passed to our callbacks */
-struct entry_parm_s {
- int lines;
- size_t size;
- char *buffer;
-};
-
-
-
-
-/* Unlock the pinentry so that another thread can start one and
- disconnect that pinentry - we do this after the unlock so that a
- stalled pinentry does not block other threads. Fixme: We should
- have a timeout in Assuan for the disconnetc operation. */
-static int
-unlock_pinentry (int rc)
-{
- ASSUAN_CONTEXT ctx = entry_ctx;
-
-#ifdef USE_GNU_PTH
- if (!pth_mutex_release (&entry_lock))
- {
- log_error ("failed to release the entry lock\n");
- if (!rc)
- rc = gpg_error (GPG_ERR_INTERNAL);
- }
-#endif
- entry_ctx = NULL;
- assuan_disconnect (ctx);
- return rc;
-}
-
-/* Fork off the pin entry if this has not already been done. Note,
- that this function must always be used to aquire the lock for the
- pinentry - we will serialize _all_ pinentry calls.
- */
-static int
-start_pinentry (CTRL ctrl)
-{
- int rc;
- const char *pgmname;
- ASSUAN_CONTEXT ctx;
- const char *argv[5];
- int no_close_list[3];
- int i;
-
-#ifdef USE_GNU_PTH
- if (!pth_mutex_acquire (&entry_lock, 0, NULL))
- {
- log_error ("failed to acquire the entry lock\n");
- return gpg_error (GPG_ERR_INTERNAL);
- }
-#endif
-
- if (entry_ctx)
- return 0;
-
- if (opt.verbose)
- log_info ("starting a new PIN Entry\n");
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return unlock_pinentry (tmperr);
- }
-
- if (!opt.pinentry_program || !*opt.pinentry_program)
- opt.pinentry_program = GNUPG_DEFAULT_PINENTRY;
- if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
- pgmname = opt.pinentry_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- if (ctrl->display && !opt.keep_display)
- {
- argv[1] = "--display";
- argv[2] = ctrl->display;
- argv[3] = NULL;
- }
- else
- argv[1] = NULL;
-
- i=0;
- if (!opt.running_detached)
- {
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- }
- no_close_list[i] = -1;
-
- /* connect to the pinentry and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.pinentry_program, (char**)argv,
- no_close_list);
- if (rc)
- {
- log_error ("can't connect to the PIN entry module: %s\n",
- assuan_strerror (rc));
- return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
- }
- entry_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to PIN entry established\n");
-
- rc = assuan_transact (entry_ctx,
- opt.no_grab? "OPTION no-grab":"OPTION grab",
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- if (ctrl->ttyname)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
- return unlock_pinentry (out_of_core ());
- rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
- if (ctrl->ttytype)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
- return unlock_pinentry (out_of_core ());
- rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
- if (ctrl->lc_ctype)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
- return unlock_pinentry (out_of_core ());
- rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
- if (ctrl->lc_messages)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
- return unlock_pinentry (out_of_core ());
- rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
- return 0;
-}
-
-
-static AssuanError
-getpin_cb (void *opaque, const void *buffer, size_t length)
-{
- struct entry_parm_s *parm = opaque;
-
- if (!buffer)
- return 0;
-
- /* we expect the pin to fit on one line */
- if (parm->lines || length >= parm->size)
- return ASSUAN_Too_Much_Data;
-
- /* fixme: we should make sure that the assuan buffer is allocated in
- secure memory or read the response byte by byte */
- memcpy (parm->buffer, buffer, length);
- parm->buffer[length] = 0;
- parm->lines++;
- return 0;
-}
-
-
-static int
-all_digitsp( const char *s)
-{
- for (; *s && *s >= '0' && *s <= '9'; s++)
- ;
- return !*s;
-}
-
-
-
-/* Call the Entry and ask for the PIN. We do check for a valid PIN
- number here and repeat it as long as we have invalid formed
- numbers. */
-int
-agent_askpin (CTRL ctrl,
- const char *desc_text, struct pin_entry_info_s *pininfo)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
- struct entry_parm_s parm;
- const char *errtext = NULL;
- int is_pin = 0;
-
- if (opt.batch)
- return 0; /* fixme: we should return BAD PIN */
-
- if (!pininfo || pininfo->max_length < 1)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!desc_text && pininfo->min_digits)
- desc_text = _("Please enter your PIN, so that the secret key "
- "can be unlocked for this session");
- else if (!desc_text)
- desc_text = _("Please enter your passphrase, so that the secret key "
- "can be unlocked for this session");
-
- is_pin = desc_text && strstr (desc_text, "PIN");
-
- rc = start_pinentry (ctrl);
- if (rc)
- return rc;
-
- snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- rc = assuan_transact (entry_ctx,
- is_pin? "SETPROMPT PIN:"
- : "SETPROMPT Passphrase:",
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
- {
- memset (&parm, 0, sizeof parm);
- parm.size = pininfo->max_length;
- parm.buffer = pininfo->pin;
-
- if (errtext)
- {
- /* fixme: should we show the try count? It must be translated */
- snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
- errtext, pininfo->failed_tries+1, pininfo->max_tries);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- errtext = NULL;
- }
-
- rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
- NULL, NULL, NULL, NULL);
- if (rc == ASSUAN_Too_Much_Data)
- errtext = is_pin? _("PIN too long")
- : _("Passphrase too long");
- else if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- if (!errtext && pininfo->min_digits)
- {
- /* do some basic checks on the entered PIN. */
- if (!all_digitsp (pininfo->pin))
- errtext = _("Invalid characters in PIN");
- else if (pininfo->max_digits
- && strlen (pininfo->pin) > pininfo->max_digits)
- errtext = _("PIN too long");
- else if (strlen (pininfo->pin) < pininfo->min_digits)
- errtext = _("PIN too short");
- }
-
- if (!errtext && pininfo->check_cb)
- {
- /* More checks by utilizing the optional callback. */
- pininfo->cb_errtext = NULL;
- rc = pininfo->check_cb (pininfo);
- if (rc == -1 && pininfo->cb_errtext)
- errtext = pininfo->cb_errtext;
- else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
- || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
- errtext = (is_pin? _("Bad PIN")
- : _("Bad Passphrase"));
- else if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
-
- if (!errtext)
- return unlock_pinentry (0); /* okay, got a PIN or passphrase */
- }
-
- return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
- : GPG_ERR_BAD_PASSPHRASE));
-}
-
-
-
-/* Ask for the passphrase using the supplied arguments. The
- passphrase is returned in RETPASS as an hex encoded string to be
- freed by the caller */
-int
-agent_get_passphrase (CTRL ctrl,
- char **retpass, const char *desc, const char *prompt,
- const char *errtext)
-{
-
- int rc;
- char line[ASSUAN_LINELENGTH];
- struct entry_parm_s parm;
- unsigned char *p, *hexstring;
- int i;
-
- *retpass = NULL;
- if (opt.batch)
- return gpg_error (GPG_ERR_BAD_PASSPHRASE);
-
- rc = start_pinentry (ctrl);
- if (rc)
- return rc;
-
- if (!prompt)
- prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
-
-
- if (desc)
- snprintf (line, DIM(line)-1, "SETDESC %s", desc);
- else
- snprintf (line, DIM(line)-1, "RESET");
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- if (errtext)
- {
- snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
-
- memset (&parm, 0, sizeof parm);
- parm.size = ASSUAN_LINELENGTH/2 - 5;
- parm.buffer = gcry_malloc_secure (parm.size+10);
- if (!parm.buffer)
- return unlock_pinentry (out_of_core ());
-
- assuan_begin_confidential (entry_ctx);
- rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
- if (rc)
- {
- xfree (parm.buffer);
- return unlock_pinentry (map_assuan_err (rc));
- }
-
- hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1);
- if (!hexstring)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (parm.buffer);
- return unlock_pinentry (tmperr);
- }
-
- for (i=0, p=parm.buffer; *p; p++, i += 2)
- sprintf (hexstring+i, "%02X", *p);
-
- xfree (parm.buffer);
- *retpass = hexstring;
- return unlock_pinentry (0);
-}
-
-
-
-/* Pop up the PIN-entry, display the text and the prompt and ask the
- user to confirm this. We return 0 for success, ie. the used
- confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
- other error. */
-int
-agent_get_confirmation (CTRL ctrl,
- const char *desc, const char *ok, const char *cancel)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_pinentry (ctrl);
- if (rc)
- return rc;
-
- if (desc)
- snprintf (line, DIM(line)-1, "SETDESC %s", desc);
- else
- snprintf (line, DIM(line)-1, "RESET");
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
-
- if (ok)
- {
- snprintf (line, DIM(line)-1, "SETOK %s", ok);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
- if (cancel)
- {
- snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_pinentry (map_assuan_err (rc));
- }
-
- rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
- return unlock_pinentry (map_assuan_err (rc));
-}
-
-
-
diff --git a/agent/sexp-parse.h b/agent/sexp-parse.h
deleted file mode 100644
index 338321f48..000000000
--- a/agent/sexp-parse.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* sexp-parse.h - S-Exp helper functions
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef SEXP_PARSE_H
-#define SEXP_PARSE_H
-
-#include "../common/util.h"
-
-/* Return the length of the next S-Exp part and update the pointer to
- the first data byte. 0 is return on error */
-static inline size_t
-snext (unsigned char const **buf)
-{
- const unsigned char *s;
- int n;
-
- s = *buf;
- for (n=0; *s && *s != ':' && digitp (s); s++)
- n = n*10 + atoi_1 (s);
- if (!n || *s != ':')
- return 0; /* we don't allow empty lengths */
- *buf = s+1;
- return n;
-}
-
-/* Skip over the S-Expression BUF points to and update BUF to point to
- the chacter right behind. DEPTH gives the initial number of open
- lists and may be passed as a positive number to skip over the
- remainder of an S-Expression if the current position is somewhere
- in an S-Expression. The function may return an error code if it
- encounters an impossible conditions */
-static inline int
-sskip (unsigned char const **buf, int *depth)
-{
- const unsigned char *s = *buf;
- size_t n;
- int d = *depth;
-
- while (d > 0)
- {
- if (*s == '(')
- {
- d++;
- s++;
- }
- else if (*s == ')')
- {
- d--;
- s++;
- }
- else
- {
- if (!d)
- return gpg_error (GPG_ERR_INV_SEXP);
- n = snext (&s);
- if (!n)
- return gpg_error (GPG_ERR_INV_SEXP);
- s += n;
- }
- }
- *buf = s;
- *depth = d;
- return 0;
-}
-
-
-/* Check whether the the string at the address BUF points to matches
- the token. Return true on match and update BUF to point behind the
- token. */
-static inline int
-smatch (unsigned char const **buf, size_t buflen, const char *token)
-{
- size_t toklen = strlen (token);
-
- if (buflen != toklen || memcmp (*buf, token, toklen))
- return 0;
- *buf += toklen;
- return 1;
-}
-
-#endif /*SEXP_PARSE_H*/
diff --git a/agent/simple-pwquery.c b/agent/simple-pwquery.c
deleted file mode 100644
index e870122cb..000000000
--- a/agent/simple-pwquery.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/* simple-pwquery.c - A simple password query client for gpg-agent
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* This module is intended as a standalone client implementation to
- gpg-agent's GET_PASSPHRASE command. In particular it does not use
- the Assuan library and can only cope with an already running
- gpg-agent. Some stuff is configurable in the header file. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#define SIMPLE_PWQUERY_IMPLEMENTATION 1
-#include "simple-pwquery.h"
-
-#if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
-# undef SPWQ_USE_LOGGING
-#endif
-
-#ifndef _
-#define _(a) (a)
-#endif
-
-#if !defined (hexdigitp) && !defined (xtoi_2)
-#define digitp(p) (*(p) >= '0' && *(p) <= '9')
-#define hexdigitp(a) (digitp (a) \
- || (*(a) >= 'A' && *(a) <= 'F') \
- || (*(a) >= 'a' && *(a) <= 'f'))
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-#endif
-
-
-/* Write NBYTES of BUF to file descriptor FD. */
-static int
-writen (int fd, const void *buf, size_t nbytes)
-{
- size_t nleft = nbytes;
- int nwritten;
-
- while (nleft > 0)
- {
- nwritten = write( fd, buf, nleft );
- if (nwritten < 0)
- {
- if (errno == EINTR)
- nwritten = 0;
- else {
-#ifdef SPWQ_USE_LOGGING
- log_error ("write failed: %s\n", strerror (errno));
-#endif
- return SPWQ_IO_ERROR;
- }
- }
- nleft -= nwritten;
- buf = (const char*)buf + nwritten;
- }
-
- return 0;
-}
-
-
-/* Read an entire line and return number of bytes read. */
-static int
-readline (int fd, char *buf, size_t buflen)
-{
- size_t nleft = buflen;
- char *p;
- int nread = 0;
-
- while (nleft > 0)
- {
- int n = read (fd, buf, nleft);
- if (n < 0)
- {
- if (errno == EINTR)
- continue;
- return -(SPWQ_IO_ERROR);
- }
- else if (!n)
- {
- return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
- }
- p = buf;
- nleft -= n;
- buf += n;
- nread += n;
-
- for (; n && *p != '\n'; n--, p++)
- ;
- if (n)
- {
- break; /* at least one full line available - that's enough.
- This function is just a simple implementation, so
- it is okay to forget about pending bytes */
- }
- }
-
- return nread;
-}
-
-
-/* Send an option to the agent */
-static int
-agent_send_option (int fd, const char *name, const char *value)
-{
- char buf[200];
- int nread;
- char *line;
- int i;
-
- line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
- if (!line)
- return SPWQ_OUT_OF_CORE;
- strcpy (stpcpy (stpcpy (stpcpy (
- stpcpy (line, "OPTION "), name), "="), value), "\n");
- i = writen (fd, line, strlen (line));
- spwq_free (line);
- if (i)
- return i;
-
- /* get response */
- nread = readline (fd, buf, DIM(buf)-1);
- if (nread < 0)
- return -nread;
- if (nread < 3)
- return SPWQ_PROTOCOL_ERROR;
-
- if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
- return 0; /* okay */
-
- return SPWQ_ERR_RESPONSE;
-}
-
-
-/* Send all available options to the agent. */
-static int
-agent_send_all_options (int fd)
-{
- char *dft_display = NULL;
- char *dft_ttyname = NULL;
- char *dft_ttytype = NULL;
- int rc = 0;
-
- dft_display = getenv ("DISPLAY");
- if (dft_display)
- {
- if ((rc = agent_send_option (fd, "display", dft_display)))
- return rc;
- }
-
- dft_ttyname = getenv ("GPG_TTY");
- if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
- dft_ttyname = ttyname (0);
- if (dft_ttyname && *dft_ttyname)
- {
- if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
- return rc;
- }
-
- dft_ttytype = getenv ("TERM");
- if (dft_ttyname && dft_ttytype)
- {
- if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
- return rc;
- }
-
-#if defined(HAVE_SETLOCALE)
- {
- char *old_lc = NULL;
- char *dft_lc = NULL;
-
-#if defined(LC_CTYPE)
- old_lc = setlocale (LC_CTYPE, NULL);
- if (old_lc)
- {
- char *p = spwq_malloc (strlen (old_lc)+1);
- if (!p)
- return SPWQ_OUT_OF_CORE;
- strcpy (p, old_lc);
- old_lc = p;
- }
- dft_lc = setlocale (LC_CTYPE, "");
- if (dft_ttyname && dft_lc)
- rc = agent_send_option (fd, "lc-ctype", dft_lc);
- if (old_lc)
- {
- setlocale (LC_CTYPE, old_lc);
- spwq_free (old_lc);
- }
- if (rc)
- return rc;
-#endif
-
-#if defined(LC_MESSAGES)
- old_lc = setlocale (LC_MESSAGES, NULL);
- if (old_lc)
- {
- char *p = spwq_malloc (strlen (old_lc)+1);
- if (!p)
- return SPWQ_OUT_OF_CORE;
- strcpy (p, old_lc);
- old_lc = p;
- }
- dft_lc = setlocale (LC_MESSAGES, "");
- if (dft_ttyname && dft_lc)
- rc = agent_send_option (fd, "lc-messages", dft_lc);
- if (old_lc)
- {
- setlocale (LC_MESSAGES, old_lc);
- spwq_free (old_lc);
- }
- if (rc)
- return rc;
-#endif
- }
-#endif /*HAVE_SETLOCALE*/
-
- return 0;
-}
-
-
-
-/* Try to open a connection to the agent, send all options and return
- the file descriptor for the connection. Return -1 in case of
- error. */
-static int
-agent_open (int *rfd)
-{
- int rc;
- int fd;
- char *infostr, *p;
- struct sockaddr_un client_addr;
- size_t len;
- int prot;
- char line[200];
- int nread;
-
- *rfd = -1;
- infostr = getenv ( "GPG_AGENT_INFO" );
- if ( !infostr )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("gpg-agent is not available in this session\n"));
-#endif
- return SPWQ_NO_AGENT;
- }
-
- if ( !(p = strchr ( infostr, ':')) || p == infostr
- || (p-infostr)+1 >= sizeof client_addr.sun_path )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
-#endif
- return SPWQ_NO_AGENT;
- }
- *p++ = 0;
-
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if ( prot != 1)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
-#endif
- return SPWQ_PROTOCOL_ERROR;
- }
-
- if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ("can't create socket: %s\n", strerror(errno) );
-#endif
- return SPWQ_SYS_ERROR;
- }
-
- memset (&client_addr, 0, sizeof client_addr);
- client_addr.sun_family = AF_UNIX;
- strcpy (client_addr.sun_path, infostr);
- len = (offsetof (struct sockaddr_un, sun_path)
- + strlen(client_addr.sun_path) + 1);
-
- if (connect (fd, (struct sockaddr*)&client_addr, len ) == -1)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno));
-#endif
- close (fd );
- return SPWQ_IO_ERROR;
- }
-
- nread = readline (fd, line, DIM(line));
- if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
- && (line[2] == '\n' || line[2] == ' ')) )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("communication problem with gpg-agent\n"));
-#endif
- close (fd );
- return SPWQ_PROTOCOL_ERROR;
- }
-
- rc = agent_send_all_options (fd);
- if (rc)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("problem setting the gpg-agent options\n"));
-#endif
- close (fd);
- return rc;
- }
-
- *rfd = fd;
- return 0;
-}
-
-
-/* Copy text to BUFFER and escape as required. Return a poiinter to
- the end of the new buffer. NOte that BUFFER must be large enough
- to keep the entire text; allocataing it 3 times the size of TEXT
- is sufficient. */
-static char *
-copy_and_escape (char *buffer, const char *text)
-{
- int i;
- char *p = buffer;
-
- for (i=0; text[i]; i++)
- {
- if (text[i] < ' ' || text[i] == '+')
- {
- sprintf (p, "%%%02X", text[i]);
- p += 3;
- }
- else if (text[i] == ' ')
- *p++ = '+';
- else
- *p++ = text[i];
- }
- return p;
-}
-
-
-/* Ask the gpg-agent for a passphrase and present the user with a
- DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
- If a CACHEID is not NULL it is used to locate the passphrase in in
- the cache and store it under this ID. If ERRORCODE is not NULL it
- should point a variable receiving an errorcode; thsi errocode might
- be 0 if the user canceled the operation. The function returns NULL
- to indicate an error. */
-char *
-simple_pwquery (const char *cacheid,
- const char *tryagain,
- const char *prompt,
- const char *description,
- int *errorcode)
-{
- int fd = -1;
- int nread;
- char *result = NULL;
- char *pw = NULL;
- char *p;
- int rc, i;
-
- rc = agent_open (&fd);
- if (rc)
- goto leave;
-
- if (!cacheid)
- cacheid = "X";
- if (!tryagain)
- tryagain = "X";
- if (!prompt)
- prompt = "X";
- if (!description)
- description = "X";
-
- {
- char *line;
- /* We allocate 3 times the needed space so that there is enough
- space for escaping. */
- line = spwq_malloc (15
- + 3*strlen (cacheid) + 1
- + 3*strlen (tryagain) + 1
- + 3*strlen (prompt) + 1
- + 3*strlen (description) + 1
- + 2);
- if (!line)
- {
- rc = SPWQ_OUT_OF_CORE;
- goto leave;
- }
- strcpy (line, "GET_PASSPHRASE ");
- p = line+15;
- p = copy_and_escape (p, cacheid);
- *p++ = ' ';
- p = copy_and_escape (p, tryagain);
- *p++ = ' ';
- p = copy_and_escape (p, prompt);
- *p++ = ' ';
- p = copy_and_escape (p, description);
- *p++ = '\n';
- rc = writen (fd, line, p - line);
- spwq_free (line);
- if (rc)
- goto leave;
- }
-
- /* get response */
- pw = spwq_secure_malloc (500);
- nread = readline (fd, pw, 499);
- if (nread < 0)
- {
- rc = -nread;
- goto leave;
- }
- if (nread < 3)
- {
- rc = SPWQ_PROTOCOL_ERROR;
- goto leave;
- }
-
- if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
- { /* we got a passphrase - convert it back from hex */
- size_t pwlen = 0;
-
- for (i=3; i < nread && hexdigitp (pw+i); i+=2)
- pw[pwlen++] = xtoi_2 (pw+i);
- pw[pwlen] = 0; /* make a C String */
- result = pw;
- pw = NULL;
- }
- else if (nread > 7 && !memcmp (pw, "ERR 111", 7)
- && (pw[7] == ' ' || pw[7] == '\n') )
- {
-#ifdef SPWQ_USE_LOGGING
- log_info (_("canceled by user\n") );
-#endif
- *errorcode = 0; /* canceled */
- }
- else
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("problem with the agent\n"));
-#endif
- rc = SPWQ_ERR_RESPONSE;
- }
-
- leave:
- if (errorcode)
- *errorcode = rc;
- if (fd != -1)
- close (fd);
- if (pw)
- spwq_free (pw);
- return result;
-}
diff --git a/agent/simple-pwquery.h b/agent/simple-pwquery.h
deleted file mode 100644
index a1b276ff6..000000000
--- a/agent/simple-pwquery.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* simple-pwquery.c - A simple password query cleint for gpg-agent
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef SIMPLE_PWQUERY_H
-#define SIMPLE_PWQUERY_H
-
-#ifdef SIMPLE_PWQUERY_IMPLEMENTATION /* Begin configuration stuff. */
-
-/* Include whatever files you need. */
-#include <gcrypt.h>
-#include "../jnlib/logging.h"
-
-/* Try to write error message using the standard log mechanism. The
- current implementation requires that the HAVE_JNLIB_LOGGING is also
- defined. */
-#define SPWQ_USE_LOGGING 1
-
-/* Memory allocation functions used by the implementation. Note, that
- the returned value is expected to be freed with
- spwq_secure_free. */
-#define spwq_malloc(a) gcry_malloc (a)
-#define spwq_free(a) gcry_free (a)
-#define spwq_secure_malloc(a) gcry_malloc_secure (a)
-#define spwq_secure_free(a) gcry_free (a)
-
-
-#endif /*SIMPLE_PWQUERY_IMPLEMENTATION*/ /* End configuration stuff. */
-
-
-/* Ask the gpg-agent for a passphrase and present the user with a
- DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
- If a CACHEID is not NULL it is used to locate the passphrase in in
- the cache and store it under this ID. If ERRORCODE is not NULL it
- should point a variable receiving an errorcode; thsi errocode might
- be 0 if the user canceled the operation. The function returns NULL
- to indicate an error. */
-char *simple_pwquery (const char *cacheid,
- const char *tryagain,
- const char *prompt,
- const char *description,
- int *errorcode);
-
-
-#define SPWQ_OUT_OF_CORE 1
-#define SPWQ_IO_ERROR 2
-#define SPWQ_PROTOCOL_ERROR 3
-#define SPWQ_ERR_RESPONSE 4
-#define SPWQ_NO_AGENT 5
-#define SPWQ_SYS_ERROR 6
-#define SPWQ_GENERAL_ERROR 7
-
-#endif /*SIMPLE_PWQUERY_H*/
diff --git a/agent/trans.c b/agent/trans.c
deleted file mode 100644
index 7fa5e3d6b..000000000
--- a/agent/trans.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* trans.c - translatable strings
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* To avoid any problems with the gettext implementation (there used
- to be some vulnerabilities in the last years and the use of
- external files is a minor security problem in itself), we use our
- own simple translation stuff */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-
-const char *
-trans (const char *text)
-{
- return text;
-}
diff --git a/agent/trustlist.c b/agent/trustlist.c
deleted file mode 100644
index 8575aedb0..000000000
--- a/agent/trustlist.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* trustlist.c - Maintain the list of trusted keys
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "agent.h"
-#include <assuan.h> /* fixme: need a way to avoid assuan calls here */
-
-static const char headerblurb[] =
-"# This is the list of trusted keys. Comments like this one and empty\n"
-"# lines are allowed but keep in mind that the entire file is integrity\n"
-"# protected by the use of a MAC, so changing the file does not make\n"
-"# much sense without the knowledge of the MAC key. Lines do have a\n"
-"# length limit but this is not serious limitation as the format of the\n"
-"# entries is fixed and checked by gpg-agent: A non-comment line starts\n"
-"# with optional white spaces, followed by exactly 40 hex character,\n"
-"# optioanlly followed by a flag character which my either be 'P', 'S'\n"
-"# or '*'. Additional data delimited with by a white space is ignored.\n"
-"\n";
-
-
-static FILE *trustfp;
-
-
-static int
-open_list (int append)
-{
- char *fname;
-
- fname = make_filename (opt.homedir, "trustlist.txt", NULL);
- trustfp = fopen (fname, append? "a+":"r");
- if (!trustfp && errno == ENOENT)
- {
- trustfp = fopen (fname, "wx");
- if (!trustfp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("can't create `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- return tmperr;
- }
- fputs (headerblurb, trustfp);
- fclose (trustfp);
- trustfp = fopen (fname, append? "a+":"r");
- }
-
- if (!trustfp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("can't open `%s': %s\n", fname, strerror (errno));
- xfree (fname);
- return tmperr;
- }
-
- /*FIXME: check the MAC */
-
- return 0;
-}
-
-
-
-/* Read the trustlist and return entry by entry. KEY must point to a
- buffer of at least 41 characters. KEYFLAG does return either 'P',
- 'S' or '*'.
-
- Reading a valid entry return 0, EOF returns -1 any other error
- returns the appropriate error code. */
-static int
-read_list (char *key, int *keyflag)
-{
- int rc;
- int c, i;
- char *p, line[256];
-
- if (!trustfp)
- {
- rc = open_list (0);
- if (rc)
- return rc;
- }
-
- do
- {
- if (!fgets (line, DIM(line)-1, trustfp) )
- {
- if (feof (trustfp))
- return -1;
- return gpg_error (gpg_err_code_from_errno (errno));
- }
-
- if (!*line || line[strlen(line)-1] != '\n')
- {
- /* eat until end of line */
- while ( (c=getc (trustfp)) != EOF && c != '\n')
- ;
- return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
- : GPG_ERR_INCOMPLETE_LINE);
- }
-
- /* Allow for emty lines and spaces */
- for (p=line; spacep (p); p++)
- ;
- }
- while (!*p || *p == '\n' || *p == '#');
-
- for (i=0; hexdigitp (p+i) && i < 40; i++)
- key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
- key[i] = 0;
- if (i!=40 || !(spacep (p+i) || p[i] == '\n'))
- {
- log_error ("invalid formatted fingerprint in trustlist\n");
- return gpg_error (GPG_ERR_BAD_DATA);
- }
- assert (p[i]);
- if (p[i] == '\n')
- *keyflag = '*';
- else
- {
- i++;
- if ( p[i] == 'P' || p[i] == 'p')
- *keyflag = 'P';
- else if ( p[i] == 'S' || p[i] == 's')
- *keyflag = 'S';
- else if ( p[i] == '*')
- *keyflag = '*';
- else
- {
- log_error ("invalid keyflag in trustlist\n");
- return gpg_error (GPG_ERR_BAD_DATA);
- }
- i++;
- if ( !(spacep (p+i) || p[i] == '\n'))
- {
- log_error ("invalid keyflag in trustlist\n");
- return gpg_error (GPG_ERR_BAD_DATA);
- }
- }
-
- return 0;
-}
-
-/* check whether the given fpr is in our trustdb. We expect FPR to be
- an all uppercase hexstring of 40 characters. */
-int
-agent_istrusted (const char *fpr)
-{
- int rc;
- static char key[41];
- int keyflag;
-
- if (trustfp)
- rewind (trustfp);
- while (!(rc=read_list (key, &keyflag)))
- {
- if (!strcmp (key, fpr))
- return 0;
- }
- if (rc != -1)
- {
- /* error in the trustdb - close it to give the user a chance for
- correction */
- fclose (trustfp);
- trustfp = NULL;
- }
- return rc;
-}
-
-
-/* write all trust entries to FP */
-int
-agent_listtrusted (void *assuan_context)
-{
- int rc;
- static char key[51];
- int keyflag;
-
- if (trustfp)
- rewind (trustfp);
- while (!(rc=read_list (key, &keyflag)))
- {
- key[40] = ' ';
- key[41] = keyflag;
- key[42] = '\n';
- assuan_send_data (assuan_context, key, 43);
- assuan_send_data (assuan_context, NULL, 0); /* flush */
- }
- if (rc == -1)
- rc = 0;
- if (rc)
- {
- /* error in the trustdb - close it to give the user a chance for
- correction */
- fclose (trustfp);
- trustfp = NULL;
- }
- return rc;
-}
-
-
-/* Insert the given fpr into our trustdb. We expect FPR to be an all
- uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
- This function does first check whether that key has alreay ben put
- into the trustdb and returns success in this case. Before a FPR
- actually gets inserted, the user is asked by means of the pin-entry
- whether this is actual wants he want to do.
-*/
-int
-agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
-{
- int rc;
- static char key[41];
- int keyflag;
- char *desc;
-
- if (trustfp)
- rewind (trustfp);
- while (!(rc=read_list (key, &keyflag)))
- {
- if (!strcmp (key, fpr))
- return 0;
- }
- fclose (trustfp);
- trustfp = NULL;
- if (rc != -1)
- return rc; /* error in the trustdb */
-
- /* insert a new one */
- if (asprintf (&desc,
- "Please verify that the certificate identified as:%%0A"
- " \"%s\"%%0A"
- "has the fingerprint:%%0A"
- " %s", name, fpr) < 0 )
- return out_of_core ();
- rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
- free (desc);
- if (rc)
- return rc;
-
- if (asprintf (&desc,
- "Do you ultimately trust%%0A"
- " \"%s\"%%0A"
- "to correctly certify user certificates?",
- name) < 0 )
- return out_of_core ();
- rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
- free (desc);
- if (rc)
- return rc;
-
- /* now check again to avoid duplicates. Also open in append mode now */
- rc = open_list (1);
- if (rc)
- return rc;
- rewind (trustfp);
- while (!(rc=read_list (key, &keyflag)))
- {
- if (!strcmp (key, fpr))
- return 0;
- }
- if (rc != -1)
- {
- fclose (trustfp);
- trustfp = NULL;
- return rc; /* error in the trustdb */
- }
- rc = 0;
-
- /* append the key */
- fflush (trustfp);
- fputs ("\n# ", trustfp);
- print_sanitized_string (trustfp, name, 0);
- fprintf (trustfp, "\n%s %c\n", fpr, flag);
- if (ferror (trustfp))
- rc = gpg_error (gpg_err_code_from_errno (errno));
-
- /* close because we are in append mode */
- if (fclose (trustfp))
- rc = gpg_error (gpg_err_code_from_errno (errno));
- trustfp = NULL;
- return rc;
-}
diff --git a/common/ChangeLog b/common/ChangeLog
deleted file mode 100644
index 4870a4a5d..000000000
--- a/common/ChangeLog
+++ /dev/null
@@ -1,219 +0,0 @@
-2003-07-15 Werner Koch <wk@gnupg.org>
-
- * simple-pwquery.c, simple-pwquery.h: New; moved from ../agent.
- * Makefile.am (libsimple_pwquery_a_LIBADD): New.
-
-2003-06-25 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_to_assuan_status): Directly map 0 to 0.
-
-2003-06-17 Werner Koch <wk@gnupg.org>
-
- * gettime.c (scan_isodatestr,add_days_to_timestamp,strtimevalue)
- (strtimestamp,asctimestamp): New. Code taken from gnupg 1.3.2
- mischelp.c.
-
- * yesno.c: New. Code taken from gnupg 1.3.2 mischelp.c
-
- * miscellaneous.c: New.
-
- * util.h: Include utf8conf.h
-
-2003-06-16 Werner Koch <wk@gnupg.org>
-
- * gettime.c (make_timestamp): New.
-
- * ttyio.c: New. Taken from gnupg 1.2.
- * ttyio.h: Move from ../include.
-
-2003-06-13 Werner Koch <wk@gnupg.org>
-
- * util.h (seterr): Removed macro.
- (xmalloc_secure,xcalloc_secure): New.
-
-2003-06-11 Werner Koch <wk@gnupg.org>
-
- * iobuf.c (iobuf_writebyte,iobuf_write): Return error code from
- iobuf_flush.
- (iobuf_writestr): Ditto.
-
-2003-06-10 Werner Koch <wk@gnupg.org>
-
- * iobuf.c, iobuf.h: New. Taken from current gnupg 1.3 CVS. Run
- indent on it and adjusted error handling to libgpg-error style.
- Replaced IOBUF by iobuf_t. Renamed malloc functions.
-
-2003-06-04 Werner Koch <wk@gnupg.org>
-
- * errors.h: Removed all error codes. We keep the status codes for
- now.
- * Makefile.am: Do not create errors.c anymore; remove it from the
- sources.
-
- * maperror.c: Don't include error.h. Change all error codes to
- libgpg-error style.
- (map_assuan_err): Changed to new Assuan error code convention.
- (map_to_assuan_status): Likewise.
- (map_gcry_err,map_kbx_err): Not needed. For now dummy functions.
-
- * membuf.c, membuf.h: New. Code taken from ../sm/call-agent.h.
- * Makefile.am: Added above.
-
-2003-04-29 Werner Koch <wk@gnupg.org>
-
- * util.h (fopencokokie): Removed prototype and struct.
-
- * fopencookie.c: Removed.
-
- * maperror.c: Use system assuan.h
-
-2002-10-31 Neal H. Walfield <neal@g10code.de>
-
- * isascii.c: New file.
- * putc_unlocked.c: Likewise.
-
-2002-10-28 Neal H. Walfield <neal@g10code.de>
-
- * signal.c (caught_fatal_sig): Remove superfluous zero
- initializer.
- (caught_sigusr1): Likewise.
-
-2002-09-04 Neal H. Walfield <neal@g10code.de>
-
- * vasprintf.c (vasprintf) [va_copy]: Use va_copy.
- [!va_copy && __va_copy]: Use __va_copy.
- [!va_copy && !__va_copy]: Only now fall back to using memcpy.
-
-2002-08-21 Werner Koch <wk@gnupg.org>
-
- * errors.h: Added STATUS_IMPORT_PROBLEM.
-
-2002-08-20 Werner Koch <wk@gnupg.org>
-
- * vasprintf.c: Hack to handle NULL for %s.
-
-2002-08-09 Werner Koch <wk@gnupg.org>
-
- * signal.c: New. Taken from GnuPG 1.1.91.
-
-2002-07-23 Werner Koch <wk@gnupg.org>
-
- * util.h (_IO_cookie_io_functions_t): Fixed typo. Noted by
- Richard Lefebvre.
-
-2002-07-22 Werner Koch <wk@gnupg.org>
-
- * fseeko.c, ftello.c: New.
-
-2002-06-28 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_to_assuan_status): Map more errorcodes to Bad
- Certificate.
-
-2002-06-26 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_to_assuan_status): Map EOF to No_Data_Available.
-
-2002-06-10 Werner Koch <wk@gnupg.org>
-
- * errors.h (gnupg_error_token): Add new prototype.
- (STATUS_ERROR): New.
-
- * mkerrtok: New.
- * Makefile.am: Use it to create the new error token function.
-
-2002-06-04 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_to_assuan_status): Map Bad_CA_Certificate.
-
-2002-05-23 Werner Koch <wk@gnupg.org>
-
- * no-pth.c, Makefile.am: Removed.
-
-2002-05-22 Werner Koch <wk@gnupg.org>
-
- * mkdtemp.c: Replaced byte by unsigned char because it is no longer
- defined in gcrypt.h.
-
-2002-05-21 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_gcry_err): Add libgcrypt's new S-expression errors.
- (map_ksba_err): Add a few mappings.
-
-2002-05-14 Werner Koch <wk@gnupg.org>
-
- * gettime.c: New.
-
-2002-05-03 Werner Koch <wk@gnupg.org>
-
- * errors.h: Added STARUS_EXPSIG and STATUS_EXPKEYSIG.
-
-2002-04-15 Werner Koch <wk@gnupg.org>
-
- * cryptmiss.c: New.
-
-2002-02-14 Werner Koch <wk@gnupg.org>
-
- * maperror.c: Add more assuan<->gnupg mappings.
-
-2002-02-12 Werner Koch <wk@gnupg.org>
-
- * fopencookie.c: Dummy function.
-
- * vasprintf.c: New. Taken from binutils-2.9.1 and dropped all non
- ANSI-C stuff. Merged with asprintf version.
-
- * no-pth.c: New.
-
-2002-01-23 Werner Koch <wk@gnupg.org>
-
- * mkdtemp.c: Copied from gnupg-1.0.6c and changed to use libgcrypt.
-
-2002-01-19 Werner Koch <wk@gnupg.org>
-
- * sysutils.c: New. This is the misc.c file from gnupg 1.0.6 with
- the OpenPGP stuff removed.
- * sysutils.h: New.
-
-2002-01-15 Werner Koch <wk@gnupg.org>
-
- * maperror.c: Add mapping for Not_Trusted.
-
-2002-01-11 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_assuan_err): Codes for CRL
-
-2002-01-08 Werner Koch <wk@gnupg.org>
-
- * util.h (spacep): New.
-
-2002-01-02 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_to_assuan_status): New. Merged from ../agent
- and ../sm.
-
-2001-12-20 Werner Koch <wk@gnupg.org>
-
- * maperror.c (map_gcry_err): Add some mappings.
-
-2001-12-18 Werner Koch <wk@gnupg.org>
-
- * Makefile.am (AM_CPPFLAGS): Include flags for gcrypt and ksba
-
-2001-12-14 Werner Koch <wk@gnupg.org>
-
- * util.h (digitp, hexdigitp): New ctype like macros.
- (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New.
-
-
- Copyright 2001, 2002 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/common/Makefile.am b/common/Makefile.am
deleted file mode 100644
index 2b99a19eb..000000000
--- a/common/Makefile.am
+++ /dev/null
@@ -1,58 +0,0 @@
-# Makefile for common gnupg modules
-# Copyright (C) 2001, 2003 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-## Process this file with automake to produce Makefile.in
-
-EXTRA_DIST = mkerrors mkerrtok
-#INCLUDES =
-
-noinst_LIBRARIES = libcommon.a libsimple-pwquery.a
-
-AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS)
-
-libcommon_a_SOURCES = \
- util.h i18n.h \
- errors.h \
- maperror.c \
- sysutils.c sysutils.h \
- cryptmiss.c \
- gettime.c \
- yesno.c \
- miscellaneous.c \
- membuf.c membuf.h \
- iobuf.c iobuf.h \
- ttyio.c ttyio.h \
- signal.c
-
-
-libcommon_a_LIBADD = @LIBOBJS@
-
-libsimple_pwquery_a_SOURCES = \
- simple-pwquery.c simple-pwquery.h
-
-libsimple_pwquery_a_LIBADD = @LIBOBJS@
-
-
-
-
-
-
-
-
-
diff --git a/common/README b/common/README
deleted file mode 100644
index a90224bab..000000000
--- a/common/README
+++ /dev/null
@@ -1,11 +0,0 @@
-Stuff used by several modules of GnuPG.
-
-These directories use it:
-
-gpg
-sm
-agent
-
-These directories don't use it:
-
-kbx \ No newline at end of file
diff --git a/common/cryptmiss.c b/common/cryptmiss.c
deleted file mode 100644
index ae639db1d..000000000
--- a/common/cryptmiss.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* cryptmiss.c - Missing functions in libgcrypt
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "util.h"
-
-char *
-gcry_strdup (const char *string)
-{
- char *p;
-
- p = gcry_malloc (strlen (string)+1);
- if (p)
- strcpy (p, string);
- return p;
-}
diff --git a/common/errors.h b/common/errors.h
deleted file mode 100644
index a5643f08a..000000000
--- a/common/errors.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* errors.h - Globally used error codes
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_ERRORS_H
-#define GNUPG_COMMON_ERRORS_H
-
-#include "util.h"
-
-/* Status codes - fixme: should go into another file */
-enum {
- STATUS_ENTER,
- STATUS_LEAVE,
- STATUS_ABORT,
- STATUS_GOODSIG,
- STATUS_BADSIG,
- STATUS_ERRSIG,
- STATUS_BADARMOR,
- STATUS_RSA_OR_IDEA,
- STATUS_SIGEXPIRED,
- STATUS_KEYREVOKED,
- STATUS_TRUST_UNDEFINED,
- STATUS_TRUST_NEVER,
- STATUS_TRUST_MARGINAL,
- STATUS_TRUST_FULLY,
- STATUS_TRUST_ULTIMATE,
-
- STATUS_SHM_INFO,
- STATUS_SHM_GET,
- STATUS_SHM_GET_BOOL,
- STATUS_SHM_GET_HIDDEN,
-
- STATUS_NEED_PASSPHRASE,
- STATUS_VALIDSIG,
- STATUS_SIG_ID,
- STATUS_ENC_TO,
- STATUS_NODATA,
- STATUS_BAD_PASSPHRASE,
- STATUS_NO_PUBKEY,
- STATUS_NO_SECKEY,
- STATUS_NEED_PASSPHRASE_SYM,
- STATUS_DECRYPTION_FAILED,
- STATUS_DECRYPTION_OKAY,
- STATUS_MISSING_PASSPHRASE,
- STATUS_GOOD_PASSPHRASE,
- STATUS_GOODMDC,
- STATUS_BADMDC,
- STATUS_ERRMDC,
- STATUS_IMPORTED,
- STATUS_IMPORT_PROBLEM,
- STATUS_IMPORT_RES,
- STATUS_FILE_START,
- STATUS_FILE_DONE,
- STATUS_FILE_ERROR,
-
- STATUS_BEGIN_DECRYPTION,
- STATUS_END_DECRYPTION,
- STATUS_BEGIN_ENCRYPTION,
- STATUS_END_ENCRYPTION,
-
- STATUS_DELETE_PROBLEM,
- STATUS_GET_BOOL,
- STATUS_GET_LINE,
- STATUS_GET_HIDDEN,
- STATUS_GOT_IT,
- STATUS_PROGRESS,
- STATUS_SIG_CREATED,
- STATUS_SESSION_KEY,
- STATUS_NOTATION_NAME,
- STATUS_NOTATION_DATA,
- STATUS_POLICY_URL,
- STATUS_BEGIN_STREAM,
- STATUS_END_STREAM,
- STATUS_KEY_CREATED,
- STATUS_USERID_HIN,
- STATUS_UNEXPECTED,
- STATUS_INV_RECP,
- STATUS_NO_RECP,
- STATUS_ALREADY_SIGNED,
-
- STATUS_EXPSIG,
- STATUS_EXPKEYSIG,
-
- STATUS_TRUNCATED,
- STATUS_ERROR
-};
-
-
-/*-- errors.c (build by mkerror and mkerrtok) --*/
-const char *gnupg_strerror (int err);
-const char *gnupg_error_token (int err);
-
-
-#endif /*GNUPG_COMMON_ERRORS_H*/
diff --git a/common/fopencookie.c b/common/fopencookie.c
deleted file mode 100644
index 7862b9a0d..000000000
--- a/common/fopencookie.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* fopencookie.c - Dummy glibc replacement
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <errno.h>
-
-#include "util.h"
-
-FILE *
-fopencookie (void *cookie, const char *opentype,
- cookie_io_functions_t funclist)
-{
- errno = ENOSYS;
- return NULL;
-}
-
-
diff --git a/common/fseeko.c b/common/fseeko.c
deleted file mode 100644
index f151b09ec..000000000
--- a/common/fseeko.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* fseeko.c - libc replacement function
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-
-int
-fseeko (FILE *stream, off_t off, int whence)
-{
- return fseek (stream, off, whence);
-}
-
-
-
-
-
-
-
-
-
-
diff --git a/common/ftello.c b/common/ftello.c
deleted file mode 100644
index e3141900d..000000000
--- a/common/ftello.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* ftello.c - libc replacement function
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-
-off_t
-ftello (FILE *stream)
-{
- long int off;
-
- off = ftell (stream);
- if (off == -1)
- return (off_t)-1;
- return off;
-}
-
-
-
-
-
-
-
-
-
-
diff --git a/common/gettime.c b/common/gettime.c
deleted file mode 100644
index a7914d348..000000000
--- a/common/gettime.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* gettime.c - Wrapper for time functions
- * Copyright (C) 1998, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <time.h>
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-
-#include "util.h"
-
-static unsigned long timewarp;
-static enum { NORMAL = 0, FROZEN, FUTURE, PAST } timemode;
-
-/* Wrapper for the time(3). We use this here so we can fake the time
- for tests */
-time_t
-gnupg_get_time ()
-{
- time_t current = time (NULL);
- if (timemode == NORMAL)
- return current;
- else if (timemode == FROZEN)
- return timewarp;
- else if (timemode == FUTURE)
- return current + timewarp;
- else
- return current - timewarp;
-}
-
-/* set the time to NEWTIME so that gnupg_get_time returns a time
- starting with this one. With FREEZE set to 1 the returned time
- will never change. Just for completeness, a value of (time_t)-1
- for NEWTIME gets you back to rality. Note that this is obviously
- not thread-safe but this is not required. */
-void
-gnupg_set_time (time_t newtime, int freeze)
-{
- time_t current = time (NULL);
-
- if ( newtime == (time_t)-1 || current == newtime)
- {
- timemode = NORMAL;
- timewarp = 0;
- }
- else if (freeze)
- {
- timemode = FROZEN;
- timewarp = current;
- }
- else if (newtime > current)
- {
- timemode = FUTURE;
- timewarp = newtime - current;
- }
- else
- {
- timemode = PAST;
- timewarp = current - newtime;
- }
-}
-
-/* Returns true when we are in timewarp mode */
-int
-gnupg_faked_time_p (void)
-{
- return timemode;
-}
-
-
-/* This function is used by gpg because OpenPGP defines the timestamp
- as an unsigned 32 bit value. */
-u32
-make_timestamp (void)
-{
- time_t t = gnupg_get_time ();
-
- if (t == (time_t)-1)
- log_fatal ("gnupg_get_time() failed\n");
- return (u32)t;
-}
-
-
-
-/****************
- * Scan a date string and return a timestamp.
- * The only supported format is "yyyy-mm-dd"
- * Returns 0 for an invalid date.
- */
-u32
-scan_isodatestr( const char *string )
-{
- int year, month, day;
- struct tm tmbuf;
- time_t stamp;
- int i;
-
- if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
- return 0;
- for( i=0; i < 4; i++ )
- if( !digitp (string+i) )
- return 0;
- if( !digitp (string+5) || !digitp(string+6) )
- return 0;
- if( !digitp(string+8) || !digitp(string+9) )
- return 0;
- year = atoi(string);
- month = atoi(string+5);
- day = atoi(string+8);
- /* some basic checks */
- if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
- return 0;
- memset( &tmbuf, 0, sizeof tmbuf );
- tmbuf.tm_mday = day;
- tmbuf.tm_mon = month-1;
- tmbuf.tm_year = year - 1900;
- tmbuf.tm_isdst = -1;
- stamp = mktime( &tmbuf );
- if( stamp == (time_t)-1 )
- return 0;
- return stamp;
-}
-
-
-u32
-add_days_to_timestamp( u32 stamp, u16 days )
-{
- return stamp + days*86400L;
-}
-
-
-/****************
- * Return a string with a time value in the form: x Y, n D, n H
- */
-
-const char *
-strtimevalue( u32 value )
-{
- static char buffer[30];
- unsigned int years, days, hours, minutes;
-
- value /= 60;
- minutes = value % 60;
- value /= 60;
- hours = value % 24;
- value /= 24;
- days = value % 365;
- value /= 365;
- years = value;
-
- sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
- if( years )
- return buffer;
- if( days )
- return strchr( buffer, 'y' ) + 1;
- return strchr( buffer, 'd' ) + 1;
-}
-
-
-/****************
- * Note: this function returns GMT
- */
-const char *
-strtimestamp( u32 stamp )
-{
- static char buffer[11+5];
- struct tm *tp;
- time_t atime = stamp;
-
- if (atime < 0) {
- strcpy (buffer, "????" "-??" "-??");
- }
- else {
- tp = gmtime( &atime );
- sprintf(buffer,"%04d-%02d-%02d",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
- }
- return buffer;
-}
-
-/****************
- * Note: this function returns local time
- */
-const char *
-asctimestamp( u32 stamp )
-{
- static char buffer[50];
-#if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
- static char fmt[50];
-#endif
- struct tm *tp;
- time_t atime = stamp;
-
- if (atime < 0) {
- strcpy (buffer, "????" "-??" "-??");
- return buffer;
- }
-
- tp = localtime( &atime );
-#ifdef HAVE_STRFTIME
-#if defined(HAVE_NL_LANGINFO)
- mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 );
- if( strstr( fmt, "%Z" ) == NULL )
- strcat( fmt, " %Z");
- strftime( buffer, DIM(buffer)-1, fmt, tp );
-#else
- /* fixme: we should check whether the locale appends a " %Z"
- * These locales from glibc don't put the " %Z":
- * fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
- */
- strftime( buffer, DIM(buffer)-1, "%c %Z", tp );
-#endif
- buffer[DIM(buffer)-1] = 0;
-#else
- mem2str( buffer, asctime(tp), DIM(buffer) );
-#endif
- return buffer;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/common/i18n.h b/common/i18n.h
deleted file mode 100644
index 0e13dca4d..000000000
--- a/common/i18n.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* i18n.h
- * Copyright (C) 1998, 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_I18N_H
-#define GNUPG_COMMON_I18N_H
-
-#ifdef USE_SIMPLE_GETTEXT
- int set_gettext_file( const char *filename );
- const char *gettext( const char *msgid );
-# define _(a) gettext (a)
-# define N_(a) (a)
-#else
-# ifdef HAVE_LOCALE_H
-# include <locale.h>
-# endif
-# ifdef ENABLE_NLS
-# include <libintl.h>
-# define _(a) gettext (a)
-# ifdef gettext_noop
-# define N_(a) gettext_noop (a)
-# else
-# define N_(a) (a)
-# endif
-# else
-# define _(a) (a)
-# define N_(a) (a)
-# endif
-#endif /*!USE_SIMPLE_GETTEXT*/
-
-#endif /*GNUPG_COMMON_I18N_H*/
diff --git a/common/iobuf.c b/common/iobuf.c
deleted file mode 100644
index 773e2993b..000000000
--- a/common/iobuf.c
+++ /dev/null
@@ -1,2415 +0,0 @@
-/* iobuf.c - file handling
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef HAVE_DOSISH_SYSTEM
-#include <windows.h>
-#endif
-#ifdef __riscos__
-#include <kernel.h>
-#include <swis.h>
-#endif /* __riscos__ */
-
-#include "memory.h"
-#include "util.h"
-#include "iobuf.h"
-
-#undef FILE_FILTER_USES_STDIO
-
-#ifdef HAVE_DOSISH_SYSTEM
-#define USE_SETMODE 1
-#endif
-
-#ifdef FILE_FILTER_USES_STDIO
-#define my_fileno(a) fileno ((a))
-#define my_fopen_ro(a,b) fopen ((a),(b))
-#define my_fopen(a,b) fopen ((a),(b))
-typedef FILE *FILEP_OR_FD;
-#define INVALID_FP NULL
-#define FILEP_OR_FD_FOR_STDIN (stdin)
-#define FILEP_OR_FD_FOR_STDOUT (stdout)
-typedef struct
-{
- FILE *fp; /* open file handle */
- int keep_open;
- int no_cache;
- int print_only_name; /* flags indicating that fname is not a real file */
- char fname[1]; /* name of the file */
-}
-file_filter_ctx_t;
-#else
-#define my_fileno(a) (a)
-#define my_fopen_ro(a,b) fd_cache_open ((a),(b))
-#define my_fopen(a,b) direct_open ((a),(b))
-#ifdef HAVE_DOSISH_SYSTEM
-typedef HANDLE FILEP_OR_FD;
-#define INVALID_FP ((HANDLE)-1)
-#define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE))
-#define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
-#undef USE_SETMODE
-#else
-typedef int FILEP_OR_FD;
-#define INVALID_FP (-1)
-#define FILEP_OR_FD_FOR_STDIN (0)
-#define FILEP_OR_FD_FOR_STDOUT (1)
-#endif
-typedef struct
-{
- FILEP_OR_FD fp; /* open file handle */
- int keep_open;
- int no_cache;
- int eof_seen;
- int print_only_name; /* flags indicating that fname is not a real file */
- char fname[1]; /* name of the file */
-}
-file_filter_ctx_t;
-
-struct close_cache_s
-{
- struct close_cache_s *next;
- FILEP_OR_FD fp;
- char fname[1];
-};
-typedef struct close_cache_s *CLOSE_CACHE;
-static CLOSE_CACHE close_cache;
-#endif
-
-#ifdef __MINGW32__
-typedef struct
-{
- int sock;
- int keep_open;
- int no_cache;
- int eof_seen;
- int print_only_name; /* flags indicating that fname is not a real file */
- char fname[1]; /* name of the file */
-}
-sock_filter_ctx_t;
-#endif /*__MINGW32__*/
-
-/* The first partial length header block must be of size 512
- * to make it easier (and efficienter) we use a min. block size of 512
- * for all chunks (but the last one) */
-#define OP_MIN_PARTIAL_CHUNK 512
-#define OP_MIN_PARTIAL_CHUNK_2POW 9
-
-typedef struct
-{
- int use;
- size_t size;
- size_t count;
- int partial; /* 1 = partial header, 2 in last partial packet */
- char *buffer; /* used for partial header */
- size_t buflen; /* used size of buffer */
- int first_c; /* of partial header (which is > 0) */
- int eof;
-}
-block_filter_ctx_t;
-
-static int special_names_enabled;
-
-static int underflow (iobuf_t a);
-static int translate_file_handle (int fd, int for_write);
-
-#ifndef FILE_FILTER_USES_STDIO
-
-/*
- * Invalidate (i.e. close) a cached iobuf
- */
-static void
-fd_cache_invalidate (const char *fname)
-{
- CLOSE_CACHE cc;
-
- assert (fname);
- if (DBG_IOBUF)
- log_debug ("fd_cache_invalidate (%s)\n", fname);
-
- for (cc = close_cache; cc; cc = cc->next)
- {
- if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
- {
- if (DBG_IOBUF)
- log_debug (" did (%s)\n", cc->fname);
-#ifdef HAVE_DOSISH_SYSTEM
- CloseHandle (cc->fp);
-#else
- close (cc->fp);
-#endif
- cc->fp = INVALID_FP;
- }
- }
-}
-
-
-
-static FILEP_OR_FD
-direct_open (const char *fname, const char *mode)
-{
-#ifdef HAVE_DOSISH_SYSTEM
- unsigned long da, cd, sm;
- HANDLE hfile;
-
- /* Note, that we do not handle all mode combinations */
-
- /* According to the ReactOS source it seems that open() of the
- * standard MSW32 crt does open the file in share mode which is
- * something new for MS applications ;-)
- */
- if (strchr (mode, '+'))
- {
- fd_cache_invalidate (fname);
- da = GENERIC_READ | GENERIC_WRITE;
- cd = OPEN_EXISTING;
- sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
- }
- else if (strchr (mode, 'w'))
- {
- fd_cache_invalidate (fname);
- da = GENERIC_WRITE;
- cd = CREATE_ALWAYS;
- sm = FILE_SHARE_WRITE;
- }
- else
- {
- da = GENERIC_READ;
- cd = OPEN_EXISTING;
- sm = FILE_SHARE_READ;
- }
-
- hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
- return hfile;
-#else
- int oflag;
- int cflag = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-
- /* Note, that we do not handle all mode combinations */
- if (strchr (mode, '+'))
- {
- fd_cache_invalidate (fname);
- oflag = O_RDWR;
- }
- else if (strchr (mode, 'w'))
- {
- fd_cache_invalidate (fname);
- oflag = O_WRONLY | O_CREAT | O_TRUNC;
- }
- else
- {
- oflag = O_RDONLY;
- }
-#ifdef O_BINARY
- if (strchr (mode, 'b'))
- oflag |= O_BINARY;
-#endif
-#ifndef __riscos__
- return open (fname, oflag, cflag);
-#else
- {
- struct stat buf;
- int rc = stat (fname, &buf);
-
- /* Don't allow iobufs on directories */
- if (!rc && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode))
- return __set_errno (EISDIR);
- else
- return open (fname, oflag, cflag);
- }
-#endif
-#endif
-}
-
-
-/*
- * Instead of closing an FD we keep it open and cache it for later reuse
- * Note that this caching strategy only works if the process does not chdir.
- */
-static void
-fd_cache_close (const char *fname, FILEP_OR_FD fp)
-{
- CLOSE_CACHE cc;
-
- assert (fp);
- if (!fname || !*fname)
- {
-#ifdef HAVE_DOSISH_SYSTEM
- CloseHandle (fp);
-#else
- close (fp);
-#endif
- if (DBG_IOBUF)
- log_debug ("fd_cache_close (%p) real\n", (void *) fp);
- return;
- }
- /* try to reuse a slot */
- for (cc = close_cache; cc; cc = cc->next)
- {
- if (cc->fp == INVALID_FP && !strcmp (cc->fname, fname))
- {
- cc->fp = fp;
- if (DBG_IOBUF)
- log_debug ("fd_cache_close (%s) used existing slot\n", fname);
- return;
- }
- }
- /* add a new one */
- if (DBG_IOBUF)
- log_debug ("fd_cache_close (%s) new slot created\n", fname);
- cc = xcalloc (1, sizeof *cc + strlen (fname));
- strcpy (cc->fname, fname);
- cc->fp = fp;
- cc->next = close_cache;
- close_cache = cc;
-}
-
-/*
- * Do an direct_open on FNAME but first try to reuse one from the fd_cache
- */
-static FILEP_OR_FD
-fd_cache_open (const char *fname, const char *mode)
-{
- CLOSE_CACHE cc;
-
- assert (fname);
- for (cc = close_cache; cc; cc = cc->next)
- {
- if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
- {
- FILEP_OR_FD fp = cc->fp;
- cc->fp = INVALID_FP;
- if (DBG_IOBUF)
- log_debug ("fd_cache_open (%s) using cached fp\n", fname);
-#ifdef HAVE_DOSISH_SYSTEM
- if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
- {
- log_error ("rewind file failed on handle %p: ec=%d\n",
- fp, (int) GetLastError ());
- fp = INVALID_FP;
- }
-#else
- if (lseek (fp, 0, SEEK_SET) == (off_t) - 1)
- {
- log_error ("can't rewind fd %d: %s\n", fp, strerror (errno));
- fp = INVALID_FP;
- }
-#endif
- return fp;
- }
- }
- if (DBG_IOBUF)
- log_debug ("fd_cache_open (%s) not cached\n", fname);
- return direct_open (fname, mode);
-}
-
-
-#endif /*FILE_FILTER_USES_STDIO */
-
-
-/****************
- * Read data from a file into buf which has an allocated length of *LEN.
- * return the number of read bytes in *LEN. OPAQUE is the FILE * of
- * the stream. A is not used.
- * control may be:
- * IOBUFCTRL_INIT: called just before the function is linked into the
- * list of function. This can be used to prepare internal
- * data structures of the function.
- * IOBUFCTRL_FREE: called just before the function is removed from the
- * list of functions and can be used to release internal
- * data structures or close a file etc.
- * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
- * with new stuff. *RET_LEN is the available size of the
- * buffer, and should be set to the number of bytes
- * which were put into the buffer. The function
- * returns 0 to indicate success, -1 on EOF and
- * GPG_ERR_xxxxx for other errors.
- *
- * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
- * *RET_LAN is the number of bytes in BUF.
- *
- * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
- * filter may take appropriate action on this message.
- */
-static int
-file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
- size_t * ret_len)
-{
- file_filter_ctx_t *a = opaque;
- FILEP_OR_FD f = a->fp;
- size_t size = *ret_len;
- size_t nbytes = 0;
- int rc = 0;
-
-#ifdef FILE_FILTER_USES_STDIO
- if (control == IOBUFCTRL_UNDERFLOW)
- {
- assert (size); /* need a buffer */
- if (feof (f))
- { /* On terminals you could easiely read as many EOFs as you call */
- rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */
- *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */
- }
- else
- {
- clearerr (f);
- nbytes = fread (buf, 1, size, f);
- if (feof (f) && !nbytes)
- {
- rc = -1; /* okay: we can return EOF now. */
- }
- else if (ferror (f) && errno != EPIPE)
- {
- rc = gpg_error_from_errno (errno);
- log_error ("%s: read error: %s\n", a->fname, strerror (errno));
- }
- *ret_len = nbytes;
- }
- }
- else if (control == IOBUFCTRL_FLUSH)
- {
- if (size)
- {
- clearerr (f);
- nbytes = fwrite (buf, 1, size, f);
- if (ferror (f))
- {
- rc = gpg_error_from_errno (errno);
- log_error ("%s: write error: %s\n", a->fname, strerror (errno));
- }
- }
- *ret_len = nbytes;
- }
- else if (control == IOBUFCTRL_INIT)
- {
- a->keep_open = a->no_cache = 0;
- }
- else if (control == IOBUFCTRL_DESC)
- {
- *(char **) buf = "file_filter";
- }
- else if (control == IOBUFCTRL_FREE)
- {
- if (f != stdin && f != stdout)
- {
- if (DBG_IOBUF)
- log_debug ("%s: close fd %d\n", a->fname, fileno (f));
- if (!a->keep_open)
- fclose (f);
- }
- f = NULL;
- xfree (a); /* we can free our context now */
- }
-#else /* !stdio implementation */
-
- if (control == IOBUFCTRL_UNDERFLOW)
- {
- assert (size); /* need a buffer */
- if (a->eof_seen)
- {
- rc = -1;
- *ret_len = 0;
- }
- else
- {
-#ifdef HAVE_DOSISH_SYSTEM
- unsigned long nread;
-
- nbytes = 0;
- if (!ReadFile (f, buf, size, &nread, NULL))
- {
- int ec = (int) GetLastError ();
- if (ec != ERROR_BROKEN_PIPE)
- {
- rc = gpg_error_from_errno (ec);
- log_error ("%s: read error: ec=%d\n", a->fname, ec);
- }
- }
- else if (!nread)
- {
- a->eof_seen = 1;
- rc = -1;
- }
- else
- {
- nbytes = nread;
- }
-
-#else
-
- int n;
-
- nbytes = 0;
- do
- {
- n = read (f, buf, size);
- }
- while (n == -1 && errno == EINTR);
- if (n == -1)
- { /* error */
- if (errno != EPIPE)
- {
- rc = gpg_error_from_errno (errno);
- log_error ("%s: read error: %s\n",
- a->fname, strerror (errno));
- }
- }
- else if (!n)
- { /* eof */
- a->eof_seen = 1;
- rc = -1;
- }
- else
- {
- nbytes = n;
- }
-#endif
- *ret_len = nbytes;
- }
- }
- else if (control == IOBUFCTRL_FLUSH)
- {
- if (size)
- {
-#ifdef HAVE_DOSISH_SYSTEM
- byte *p = buf;
- unsigned long n;
-
- nbytes = size;
- do
- {
- if (size && !WriteFile (f, p, nbytes, &n, NULL))
- {
- int ec = (int) GetLastError ();
- rc = gpg_error_from_errno (ec);
- log_error ("%s: write error: ec=%d\n", a->fname, ec);
- break;
- }
- p += n;
- nbytes -= n;
- }
- while (nbytes);
- nbytes = p - buf;
-#else
- byte *p = buf;
- int n;
-
- nbytes = size;
- do
- {
- do
- {
- n = write (f, p, nbytes);
- }
- while (n == -1 && errno == EINTR);
- if (n > 0)
- {
- p += n;
- nbytes -= n;
- }
- }
- while (n != -1 && nbytes);
- if (n == -1)
- {
- rc = gpg_error_from_errno (errno);
- log_error ("%s: write error: %s\n", a->fname, strerror (errno));
- }
- nbytes = p - buf;
-#endif
- }
- *ret_len = nbytes;
- }
- else if (control == IOBUFCTRL_INIT)
- {
- a->eof_seen = 0;
- a->keep_open = 0;
- a->no_cache = 0;
- }
- else if (control == IOBUFCTRL_DESC)
- {
- *(char **) buf = "file_filter(fd)";
- }
- else if (control == IOBUFCTRL_FREE)
- {
-#ifdef HAVE_DOSISH_SYSTEM
- if (f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT)
- {
- if (DBG_IOBUF)
- log_debug ("%s: close handle %p\n", a->fname, f);
- if (!a->keep_open)
- fd_cache_close (a->no_cache ? NULL : a->fname, f);
- }
-#else
- if ((int) f != 0 && (int) f != 1)
- {
- if (DBG_IOBUF)
- log_debug ("%s: close fd %d\n", a->fname, f);
- if (!a->keep_open)
- fd_cache_close (a->no_cache ? NULL : a->fname, f);
- }
- f = INVALID_FP;
-#endif
- xfree (a); /* we can free our context now */
- }
-#endif /* !stdio implementation */
- return rc;
-}
-
-#ifdef __MINGW32__
-/* Becuase sockets are an special object under Lose32 we have to
- * use a special filter */
-static int
-sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
- size_t * ret_len)
-{
- sock_filter_ctx_t *a = opaque;
- size_t size = *ret_len;
- size_t nbytes = 0;
- int rc = 0;
-
- if (control == IOBUFCTRL_UNDERFLOW)
- {
- assert (size); /* need a buffer */
- if (a->eof_seen)
- {
- rc = -1;
- *ret_len = 0;
- }
- else
- {
- int nread;
-
- nread = recv (a->sock, buf, size, 0);
- if (nread == SOCKET_ERROR)
- {
- int ec = (int) WSAGetLastError ();
- rc = gpg_error_from_errno (ec);
- log_error ("socket read error: ec=%d\n", ec);
- }
- else if (!nread)
- {
- a->eof_seen = 1;
- rc = -1;
- }
- else
- {
- nbytes = nread;
- }
- *ret_len = nbytes;
- }
- }
- else if (control == IOBUFCTRL_FLUSH)
- {
- if (size)
- {
- byte *p = buf;
- int n;
-
- nbytes = size;
- do
- {
- n = send (a->sock, p, nbytes, 0);
- if (n == SOCKET_ERROR)
- {
- int ec = (int) WSAGetLastError ();
- rc = gpg_error_from_errno (ec);
- log_error ("socket write error: ec=%d\n", ec);
- break;
- }
- p += n;
- nbytes -= n;
- }
- while (nbytes);
- nbytes = p - buf;
- }
- *ret_len = nbytes;
- }
- else if (control == IOBUFCTRL_INIT)
- {
- a->eof_seen = 0;
- a->keep_open = 0;
- a->no_cache = 0;
- }
- else if (control == IOBUFCTRL_DESC)
- {
- *(char **) buf = "sock_filter";
- }
- else if (control == IOBUFCTRL_FREE)
- {
- if (!a->keep_open)
- closesocket (a->sock);
- xfree (a); /* we can free our context now */
- }
- return rc;
-}
-#endif /*__MINGW32__*/
-
-/****************
- * This is used to implement the block write mode.
- * Block reading is done on a byte by byte basis in readbyte(),
- * without a filter
- */
-static int
-block_filter (void *opaque, int control, iobuf_t chain, byte * buf,
- size_t * ret_len)
-{
- block_filter_ctx_t *a = opaque;
- size_t size = *ret_len;
- int c, needed, rc = 0;
- char *p;
-
- if (control == IOBUFCTRL_UNDERFLOW)
- {
- size_t n = 0;
-
- p = buf;
- assert (size); /* need a buffer */
- if (a->eof) /* don't read any further */
- rc = -1;
- while (!rc && size)
- {
- if (!a->size)
- { /* get the length bytes */
- if (a->partial == 2)
- {
- a->eof = 1;
- if (!n)
- rc = -1;
- break;
- }
- else if (a->partial)
- {
- /* These OpenPGP introduced huffman like encoded length
- * bytes are really a mess :-( */
- if (a->first_c)
- {
- c = a->first_c;
- a->first_c = 0;
- }
- else if ((c = iobuf_get (chain)) == -1)
- {
- log_error ("block_filter: 1st length byte missing\n");
- rc = GPG_ERR_BAD_DATA;
- break;
- }
- if (c < 192)
- {
- a->size = c;
- a->partial = 2;
- if (!a->size)
- {
- a->eof = 1;
- if (!n)
- rc = -1;
- break;
- }
- }
- else if (c < 224)
- {
- a->size = (c - 192) * 256;
- if ((c = iobuf_get (chain)) == -1)
- {
- log_error
- ("block_filter: 2nd length byte missing\n");
- rc = GPG_ERR_BAD_DATA;
- break;
- }
- a->size += c + 192;
- a->partial = 2;
- if (!a->size)
- {
- a->eof = 1;
- if (!n)
- rc = -1;
- break;
- }
- }
- else if (c == 255)
- {
- a->size = iobuf_get (chain) << 24;
- a->size |= iobuf_get (chain) << 16;
- a->size |= iobuf_get (chain) << 8;
- if ((c = iobuf_get (chain)) == -1)
- {
- log_error ("block_filter: invalid 4 byte length\n");
- rc = GPG_ERR_BAD_DATA;
- break;
- }
- a->size |= c;
- }
- else
- { /* next partial body length */
- a->size = 1 << (c & 0x1f);
- }
- /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */
- }
- else
- { /* the gnupg partial length scheme - much better :-) */
- c = iobuf_get (chain);
- a->size = c << 8;
- c = iobuf_get (chain);
- a->size |= c;
- if (c == -1)
- {
- log_error ("block_filter: error reading length info\n");
- rc = GPG_ERR_BAD_DATA;
- }
- if (!a->size)
- {
- a->eof = 1;
- if (!n)
- rc = -1;
- break;
- }
- }
- }
-
- while (!rc && size && a->size)
- {
- needed = size < a->size ? size : a->size;
- c = iobuf_read (chain, p, needed);
- if (c < needed)
- {
- if (c == -1)
- c = 0;
- log_error
- ("block_filter %p: read error (size=%lu,a->size=%lu)\n",
- a, (ulong) size + c, (ulong) a->size + c);
- rc = GPG_ERR_BAD_DATA;
- }
- else
- {
- size -= c;
- a->size -= c;
- p += c;
- n += c;
- }
- }
- }
- *ret_len = n;
- }
- else if (control == IOBUFCTRL_FLUSH)
- {
- if (a->partial)
- { /* the complicated openpgp scheme */
- size_t blen, n, nbytes = size + a->buflen;
-
- assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
- if (nbytes < OP_MIN_PARTIAL_CHUNK)
- {
- /* not enough to write a partial block out; so we store it */
- if (!a->buffer)
- a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
- memcpy (a->buffer + a->buflen, buf, size);
- a->buflen += size;
- }
- else
- { /* okay, we can write out something */
- /* do this in a loop to use the most efficient block lengths */
- p = buf;
- do
- {
- /* find the best matching block length - this is limited
- * by the size of the internal buffering */
- for (blen = OP_MIN_PARTIAL_CHUNK * 2,
- c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes;
- blen *= 2, c++)
- ;
- blen /= 2;
- c--;
- /* write the partial length header */
- assert (c <= 0x1f); /*;-) */
- c |= 0xe0;
- iobuf_put (chain, c);
- if ((n = a->buflen))
- { /* write stuff from the buffer */
- assert (n == OP_MIN_PARTIAL_CHUNK);
- if (iobuf_write (chain, a->buffer, n))
- rc = gpg_error_from_errno (errno);
- a->buflen = 0;
- nbytes -= n;
- }
- if ((n = nbytes) > blen)
- n = blen;
- if (n && iobuf_write (chain, p, n))
- rc = gpg_error_from_errno (errno);
- p += n;
- nbytes -= n;
- }
- while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK);
- /* store the rest in the buffer */
- if (!rc && nbytes)
- {
- assert (!a->buflen);
- assert (nbytes < OP_MIN_PARTIAL_CHUNK);
- if (!a->buffer)
- a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
- memcpy (a->buffer, p, nbytes);
- a->buflen = nbytes;
- }
- }
- }
- else
- { /* the gnupg scheme (which is not openpgp compliant) */
- size_t avail, n;
-
- for (p = buf; !rc && size;)
- {
- n = size;
- avail = a->size - a->count;
- if (!avail)
- {
- if (n > a->size)
- {
- iobuf_put (chain, (a->size >> 8) & 0xff);
- iobuf_put (chain, a->size & 0xff);
- avail = a->size;
- a->count = 0;
- }
- else
- {
- iobuf_put (chain, (n >> 8) & 0xff);
- iobuf_put (chain, n & 0xff);
- avail = n;
- a->count = a->size - n;
- }
- }
- if (n > avail)
- n = avail;
- if (iobuf_write (chain, p, n))
- rc = gpg_error_from_errno (errno);
- a->count += n;
- p += n;
- size -= n;
- }
- }
- }
- else if (control == IOBUFCTRL_INIT)
- {
- if (DBG_IOBUF)
- log_debug ("init block_filter %p\n", a);
- if (a->partial)
- a->count = 0;
- else if (a->use == 1)
- a->count = a->size = 0;
- else
- a->count = a->size; /* force first length bytes */
- a->eof = 0;
- a->buffer = NULL;
- a->buflen = 0;
- }
- else if (control == IOBUFCTRL_DESC)
- {
- *(char **) buf = "block_filter";
- }
- else if (control == IOBUFCTRL_FREE)
- {
- if (a->use == 2)
- { /* write the end markers */
- if (a->partial)
- {
- u32 len;
- /* write out the remaining bytes without a partial header
- * the length of this header may be 0 - but if it is
- * the first block we are not allowed to use a partial header
- * and frankly we can't do so, because this length must be
- * a power of 2. This is _really_ complicated because we
- * have to check the possible length of a packet prior
- * to it's creation: a chain of filters becomes complicated
- * and we need a lot of code to handle compressed packets etc.
- * :-(((((((
- */
- /* construct header */
- len = a->buflen;
- /*log_debug("partial: remaining length=%u\n", len ); */
- if (len < 192)
- rc = iobuf_put (chain, len);
- else if (len < 8384)
- {
- if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192)))
- rc = iobuf_put (chain, ((len - 192) % 256));
- }
- else
- { /* use a 4 byte header */
- if (!(rc = iobuf_put (chain, 0xff)))
- if (!(rc = iobuf_put (chain, (len >> 24) & 0xff)))
- if (!(rc = iobuf_put (chain, (len >> 16) & 0xff)))
- if (!(rc = iobuf_put (chain, (len >> 8) & 0xff)))
- rc = iobuf_put (chain, len & 0xff);
- }
- if (!rc && len)
- rc = iobuf_write (chain, a->buffer, len);
- if (rc)
- {
- log_error ("block_filter: write error: %s\n",
- strerror (errno));
- rc = gpg_error_from_errno (errno);
- }
- xfree (a->buffer);
- a->buffer = NULL;
- a->buflen = 0;
- }
- else
- {
- iobuf_writebyte (chain, 0);
- iobuf_writebyte (chain, 0);
- }
- }
- else if (a->size)
- {
- log_error ("block_filter: pending bytes!\n");
- }
- if (DBG_IOBUF)
- log_debug ("free block_filter %p\n", a);
- xfree (a); /* we can free our context now */
- }
-
- return rc;
-}
-
-
-static void
-print_chain (iobuf_t a)
-{
- if (!DBG_IOBUF)
- return;
- for (; a; a = a->chain)
- {
- size_t dummy_len = 0;
- const char *desc = "[none]";
-
- if (a->filter)
- a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL,
- (byte *) & desc, &dummy_len);
-
- log_debug ("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
- a->no, a->subno, desc, a->filter_eof,
- (int) a->d.start, (int) a->d.len);
- }
-}
-
-int
-iobuf_print_chain (iobuf_t a)
-{
- print_chain (a);
- return 0;
-}
-
-/****************
- * Allocate a new io buffer, with no function assigned.
- * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
- * BUFSIZE is a suggested buffer size.
- */
-iobuf_t
-iobuf_alloc (int use, size_t bufsize)
-{
- iobuf_t a;
- static int number = 0;
-
- a = xcalloc (1, sizeof *a);
- a->use = use;
- a->d.buf = xmalloc (bufsize);
- a->d.size = bufsize;
- a->no = ++number;
- a->subno = 0;
- a->opaque = NULL;
- a->real_fname = NULL;
- return a;
-}
-
-int
-iobuf_close (iobuf_t a)
-{
- iobuf_t a2;
- size_t dummy_len = 0;
- int rc = 0;
-
- if (a && a->directfp)
- {
- fclose (a->directfp);
- xfree (a->real_fname);
- if (DBG_IOBUF)
- log_debug ("iobuf_close -> %p\n", a->directfp);
- return 0;
- }
-
- for (; a && !rc; a = a2)
- {
- a2 = a->chain;
- if (a->use == 2 && (rc = iobuf_flush (a)))
- log_error ("iobuf_flush failed on close: %s\n", gpg_strerror (rc));
-
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc);
- if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_FREE,
- a->chain, NULL, &dummy_len)))
- log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc));
- xfree (a->real_fname);
- if (a->d.buf)
- {
- memset (a->d.buf, 0, a->d.size); /* erase the buffer */
- xfree (a->d.buf);
- }
- xfree (a);
- }
- return rc;
-}
-
-int
-iobuf_cancel (iobuf_t a)
-{
- const char *s;
- iobuf_t a2;
- int rc;
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- char *remove_name = NULL;
-#endif
-
- if (a && a->use == 2)
- {
- s = iobuf_get_real_fname (a);
- if (s && *s)
- {
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- remove_name = m_strdup (s);
-#else
- remove (s);
-#endif
- }
- }
-
- /* send a cancel message to all filters */
- for (a2 = a; a2; a2 = a2->chain)
- {
- size_t dummy;
- if (a2->filter)
- a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy);
- }
-
- rc = iobuf_close (a);
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- if (remove_name)
- {
- /* Argg, MSDOS does not allow to remove open files. So
- * we have to do it here */
- remove (remove_name);
- xfree (remove_name);
- }
-#endif
- return rc;
-}
-
-
-/****************
- * create a temporary iobuf, which can be used to collect stuff
- * in an iobuf and later be written by iobuf_write_temp() to another
- * iobuf.
- */
-iobuf_t
-iobuf_temp ()
-{
- iobuf_t a;
-
- a = iobuf_alloc (3, 8192);
-
- return a;
-}
-
-iobuf_t
-iobuf_temp_with_content (const char *buffer, size_t length)
-{
- iobuf_t a;
-
- a = iobuf_alloc (3, length);
- memcpy (a->d.buf, buffer, length);
- a->d.len = length;
-
- return a;
-}
-
-void
-iobuf_enable_special_filenames (int yes)
-{
- special_names_enabled = yes;
-}
-
-/*
- * see whether the filename has the for "-&nnnn", where n is a
- * non-zero number.
- * Returns this number or -1 if it is not the case.
- */
-static int
-check_special_filename (const char *fname)
-{
- if (special_names_enabled && fname && *fname == '-' && fname[1] == '&')
- {
- int i;
-
- fname += 2;
- for (i = 0; isdigit (fname[i]); i++)
- ;
- if (!fname[i])
- return atoi (fname);
- }
- return -1;
-}
-
-/****************
- * Create a head iobuf for reading from a file
- * returns: NULL if an error occures and sets errno
- */
-iobuf_t
-iobuf_open (const char *fname)
-{
- iobuf_t a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
- int print_only = 0;
- int fd;
-
- if (!fname || (*fname == '-' && !fname[1]))
- {
- fp = FILEP_OR_FD_FOR_STDIN;
-#ifdef USE_SETMODE
- setmode (my_fileno (fp), O_BINARY);
-#endif
- fname = "[stdin]";
- print_only = 1;
- }
- else if ((fd = check_special_filename (fname)) != -1)
- return iobuf_fdopen (translate_file_handle (fd, 0), "rb");
- else if ((fp = my_fopen_ro (fname, "rb")) == INVALID_FP)
- return NULL;
- a = iobuf_alloc (1, 8192);
- fcx = xmalloc (sizeof *fcx + strlen (fname));
- fcx->fp = fp;
- fcx->print_only_name = print_only;
- strcpy (fcx->fname, fname);
- if (!print_only)
- a->real_fname = xstrdup (fname);
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: open `%s' fd=%d\n",
- a->no, a->subno, fname, (int) my_fileno (fcx->fp));
-
- return a;
-}
-
-/****************
- * Create a head iobuf for reading from a file
- * returns: NULL if an error occures and sets errno
- */
-iobuf_t
-iobuf_fdopen (int fd, const char *mode)
-{
- iobuf_t a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
-#ifdef FILE_FILTER_USES_STDIO
- if (!(fp = fdopen (fd, mode)))
- return NULL;
-#else
- fp = (FILEP_OR_FD) fd;
-#endif
- a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192);
- fcx = xmalloc (sizeof *fcx + 20);
- fcx->fp = fp;
- fcx->print_only_name = 1;
- sprintf (fcx->fname, "[fd %d]", fd);
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname);
- iobuf_ioctl (a, 3, 1, NULL); /* disable fd caching */
- return a;
-}
-
-
-iobuf_t
-iobuf_sockopen (int fd, const char *mode)
-{
- iobuf_t a;
-#ifdef __MINGW32__
- sock_filter_ctx_t *scx;
- size_t len;
-
- a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192);
- scx = m_alloc (sizeof *scx + 25);
- scx->sock = fd;
- scx->print_only_name = 1;
- sprintf (scx->fname, "[sock %d]", fd);
- a->filter = sock_filter;
- a->filter_ov = scx;
- sock_filter (scx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
- iobuf_ioctl (a, 3, 1, NULL); /* disable fd caching */
-#else
- a = iobuf_fdopen (fd, mode);
-#endif
- return a;
-}
-
-/****************
- * create an iobuf for writing to a file; the file will be created.
- */
-iobuf_t
-iobuf_create (const char *fname)
-{
- iobuf_t a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
- int print_only = 0;
- int fd;
-
- if (!fname || (*fname == '-' && !fname[1]))
- {
- fp = FILEP_OR_FD_FOR_STDOUT;
-#ifdef USE_SETMODE
- setmode (my_fileno (fp), O_BINARY);
-#endif
- fname = "[stdout]";
- print_only = 1;
- }
- else if ((fd = check_special_filename (fname)) != -1)
- return iobuf_fdopen (translate_file_handle (fd, 1), "wb");
- else if ((fp = my_fopen (fname, "wb")) == INVALID_FP)
- return NULL;
- a = iobuf_alloc (2, 8192);
- fcx = xmalloc (sizeof *fcx + strlen (fname));
- fcx->fp = fp;
- fcx->print_only_name = print_only;
- strcpy (fcx->fname, fname);
- if (!print_only)
- a->real_fname = xstrdup (fname);
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc);
-
- return a;
-}
-
-/****************
- * append to an iobuf; if the file does not exist, create it.
- * cannot be used for stdout.
- * Note: This is not used.
- */
-#if 0 /* not used */
-iobuf_t
-iobuf_append (const char *fname)
-{
- iobuf_t a;
- FILE *fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
- if (!fname)
- return NULL;
- else if (!(fp = my_fopen (fname, "ab")))
- return NULL;
- a = iobuf_alloc (2, 8192);
- fcx = m_alloc (sizeof *fcx + strlen (fname));
- fcx->fp = fp;
- strcpy (fcx->fname, fname);
- a->real_fname = m_strdup (fname);
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc);
-
- return a;
-}
-#endif
-
-iobuf_t
-iobuf_openrw (const char *fname)
-{
- iobuf_t a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
- if (!fname)
- return NULL;
- else if ((fp = my_fopen (fname, "r+b")) == INVALID_FP)
- return NULL;
- a = iobuf_alloc (2, 8192);
- fcx = xmalloc (sizeof *fcx + strlen (fname));
- fcx->fp = fp;
- strcpy (fcx->fname, fname);
- a->real_fname = xstrdup (fname);
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
- file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc);
-
- return a;
-}
-
-
-int
-iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval)
-{
- if (cmd == 1)
- { /* keep system filepointer/descriptor open */
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: ioctl `%s' keep=%d\n",
- a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?",
- intval);
- for (; a; a = a->chain)
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- b->keep_open = intval;
- return 0;
- }
-#ifdef __MINGW32__
- else if (!a->chain && a->filter == sock_filter)
- {
- sock_filter_ctx_t *b = a->filter_ov;
- b->keep_open = intval;
- return 0;
- }
-#endif
- }
- else if (cmd == 2)
- { /* invalidate cache */
- if (DBG_IOBUF)
- log_debug ("iobuf-*.*: ioctl `%s' invalidate\n",
- ptrval ? (char *) ptrval : "?");
- if (!a && !intval && ptrval)
- {
-#ifndef FILE_FILTER_USES_STDIO
- fd_cache_invalidate (ptrval);
-#endif
- return 0;
- }
- }
- else if (cmd == 3)
- { /* disallow/allow caching */
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
- a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?",
- intval);
- for (; a; a = a->chain)
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- b->no_cache = intval;
- return 0;
- }
-#ifdef __MINGW32__
- else if (!a->chain && a->filter == sock_filter)
- {
- sock_filter_ctx_t *b = a->filter_ov;
- b->no_cache = intval;
- return 0;
- }
-#endif
- }
-
- return -1;
-}
-
-
-/****************
- * Register an i/o filter.
- */
-int
-iobuf_push_filter (iobuf_t a,
- int (*f) (void *opaque, int control,
- iobuf_t chain, byte * buf, size_t * len),
- void *ov)
-{
- return iobuf_push_filter2 (a, f, ov, 0);
-}
-
-int
-iobuf_push_filter2 (iobuf_t a,
- int (*f) (void *opaque, int control,
- iobuf_t chain, byte * buf, size_t * len),
- void *ov, int rel_ov)
-{
- iobuf_t b;
- size_t dummy_len = 0;
- int rc = 0;
-
- if (a->directfp)
- BUG ();
-
- if (a->use == 2 && (rc = iobuf_flush (a)))
- return rc;
- /* make a copy of the current stream, so that
- * A is the new stream and B the original one.
- * The contents of the buffers are transferred to the
- * new stream.
- */
- b = xmalloc (sizeof *b);
- memcpy (b, a, sizeof *b);
- /* fixme: it is stupid to keep a copy of the name at every level
- * but we need the name somewhere because the name known by file_filter
- * may have been released when we need the name of the file */
- b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL;
- /* remove the filter stuff from the new stream */
- a->filter = NULL;
- a->filter_ov = NULL;
- a->filter_ov_owner = 0;
- a->filter_eof = 0;
- if (a->use == 3)
- a->use = 2; /* make a write stream from a temp stream */
-
- if (a->use == 2)
- { /* allocate a fresh buffer for the
- original stream */
- b->d.buf = xmalloc (a->d.size);
- b->d.len = 0;
- b->d.start = 0;
- }
- else
- { /* allocate a fresh buffer for the new
- stream */
- a->d.buf = xmalloc (a->d.size);
- a->d.len = 0;
- a->d.start = 0;
- }
- /* disable nlimit for the new stream */
- a->ntotal = b->ntotal + b->nbytes;
- a->nlimit = a->nbytes = 0;
- a->nofast &= ~1;
- /* make a link from the new stream to the original stream */
- a->chain = b;
- a->opaque = b->opaque;
-
- /* setup the function on the new stream */
- a->filter = f;
- a->filter_ov = ov;
- a->filter_ov_owner = rel_ov;
-
- a->subno = b->subno + 1;
- f (ov, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &dummy_len);
-
- if (DBG_IOBUF)
- {
- log_debug ("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc);
- print_chain (a);
- }
-
- /* now we can initialize the new function if we have one */
- if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain,
- NULL, &dummy_len)))
- log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-/****************
- * Remove an i/o filter.
- */
-int
-pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
- iobuf_t chain, byte * buf, size_t * len),
- void *ov)
-{
- iobuf_t b;
- size_t dummy_len = 0;
- int rc = 0;
-
- if (a->directfp)
- BUG ();
-
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc);
- if (!a->filter)
- { /* this is simple */
- b = a->chain;
- assert (b);
- xfree (a->d.buf);
- xfree (a->real_fname);
- memcpy (a, b, sizeof *a);
- xfree (b);
- return 0;
- }
- for (b = a; b; b = b->chain)
- if (b->filter == f && (!ov || b->filter_ov == ov))
- break;
- if (!b)
- log_bug ("pop_filter(): filter function not found\n");
-
- /* flush this stream if it is an output stream */
- if (a->use == 2 && (rc = iobuf_flush (b)))
- {
- log_error ("iobuf_flush failed in pop_filter: %s\n", gpg_strerror (rc));
- return rc;
- }
- /* and tell the filter to free it self */
- if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain,
- NULL, &dummy_len)))
- {
- log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
- return rc;
- }
- if (b->filter_ov && b->filter_ov_owner)
- {
- xfree (b->filter_ov);
- b->filter_ov = NULL;
- }
-
-
- /* and see how to remove it */
- if (a == b && !b->chain)
- log_bug ("can't remove the last filter from the chain\n");
- else if (a == b)
- { /* remove the first iobuf from the chain */
- /* everything from b is copied to a. This is save because
- * a flush has been done on the to be removed entry
- */
- b = a->chain;
- xfree (a->d.buf);
- xfree (a->real_fname);
- memcpy (a, b, sizeof *a);
- xfree (b);
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno);
- }
- else if (!b->chain)
- { /* remove the last iobuf from the chain */
- log_bug ("Ohh jeee, trying to remove a head filter\n");
- }
- else
- { /* remove an intermediate iobuf from the chain */
- log_bug ("Ohh jeee, trying to remove an intermediate filter\n");
- }
-
- return rc;
-}
-
-
-/****************
- * read underflow: read more bytes into the buffer and return
- * the first byte or -1 on EOF.
- */
-static int
-underflow (iobuf_t a)
-{
- size_t len;
- int rc;
-
- assert (a->d.start == a->d.len);
- if (a->use == 3)
- return -1; /* EOF because a temp buffer can't do an underflow */
-
- if (a->filter_eof)
- {
- if (a->chain)
- {
- iobuf_t b = a->chain;
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: pop `%s' in underflow\n",
- a->no, a->subno, a->desc);
- xfree (a->d.buf);
- xfree (a->real_fname);
- memcpy (a, b, sizeof *a);
- xfree (b);
- print_chain (a);
- }
- else
- a->filter_eof = 0; /* for the top level filter */
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
- a->no, a->subno);
- return -1; /* return one(!) EOF */
- }
- if (a->error)
- {
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: error\n", a->no, a->subno);
- return -1;
- }
-
- if (a->directfp)
- {
- FILE *fp = a->directfp;
-
- len = fread (a->d.buf, 1, a->d.size, fp);
- if (len < a->d.size)
- {
- if (ferror (fp))
- a->error = gpg_error_from_errno (errno);
- }
- a->d.len = len;
- a->d.start = 0;
- return len ? a->d.buf[a->d.start++] : -1;
- }
-
-
- if (a->filter)
- {
- len = a->d.size;
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: underflow: req=%lu\n",
- a->no, a->subno, (ulong) len);
- rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
- a->d.buf, &len);
- if (DBG_IOBUF)
- {
- log_debug ("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
- a->no, a->subno, (ulong) len, rc);
-/* if( a->no == 1 ) */
-/* log_hexdump (" data:", a->d.buf, len); */
- }
- if (a->use == 1 && rc == -1)
- { /* EOF: we can remove the filter */
- size_t dummy_len = 0;
-
- /* and tell the filter to free itself */
- if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain,
- NULL, &dummy_len)))
- log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
- if (a->filter_ov && a->filter_ov_owner)
- {
- xfree (a->filter_ov);
- a->filter_ov = NULL;
- }
- a->filter = NULL;
- a->desc = NULL;
- a->filter_ov = NULL;
- a->filter_eof = 1;
- if (!len && a->chain)
- {
- iobuf_t b = a->chain;
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
- a->no, a->subno, a->desc);
- xfree (a->d.buf);
- xfree (a->real_fname);
- memcpy (a, b, sizeof *a);
- xfree (b);
- print_chain (a);
- }
- }
- else if (rc)
- a->error = rc;
-
- if (!len)
- {
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: underflow: eof\n", a->no, a->subno);
- return -1;
- }
- a->d.len = len;
- a->d.start = 0;
- return a->d.buf[a->d.start++];
- }
- else
- {
- if (DBG_IOBUF)
- log_debug ("iobuf-%d.%d: underflow: eof (no filter)\n",
- a->no, a->subno);
- return -1; /* no filter; return EOF */
- }
-}
-
-
-int
-iobuf_flush (iobuf_t a)
-{
- size_t len;
- int rc;
-
- if (a->directfp)
- return 0;
-
- if (a->use == 3)
- { /* increase the temp buffer */
- char *newbuf;
- size_t newsize = a->d.size + 8192;
-
- if (DBG_IOBUF)
- log_debug ("increasing temp iobuf from %lu to %lu\n",
- (ulong) a->d.size, (ulong) newsize);
- newbuf = xmalloc (newsize);
- memcpy (newbuf, a->d.buf, a->d.len);
- xfree (a->d.buf);
- a->d.buf = newbuf;
- a->d.size = newsize;
- return 0;
- }
- else if (a->use != 2)
- log_bug ("flush on non-output iobuf\n");
- else if (!a->filter)
- log_bug ("iobuf_flush: no filter\n");
- len = a->d.len;
- rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len);
- if (!rc && len != a->d.len)
- {
- log_info ("iobuf_flush did not write all!\n");
- rc = GPG_ERR_INTERNAL;
- }
- else if (rc)
- a->error = rc;
- a->d.len = 0;
-
- return rc;
-}
-
-
-/****************
- * Read a byte from the iobuf; returns -1 on EOF
- */
-int
-iobuf_readbyte (iobuf_t a)
-{
- int c;
-
- /* nlimit does not work together with unget */
- /* nbytes is also not valid! */
- if (a->unget.buf)
- {
- if (a->unget.start < a->unget.len)
- return a->unget.buf[a->unget.start++];
- xfree (a->unget.buf);
- a->unget.buf = NULL;
- a->nofast &= ~2;
- }
-
- if (a->nlimit && a->nbytes >= a->nlimit)
- return -1; /* forced EOF */
-
- if (a->d.start < a->d.len)
- {
- c = a->d.buf[a->d.start++];
- }
- else if ((c = underflow (a)) == -1)
- return -1; /* EOF */
-
- a->nbytes++;
- return c;
-}
-
-
-int
-iobuf_read (iobuf_t a, byte * buf, unsigned buflen)
-{
- int c, n;
-
- if (a->unget.buf || a->nlimit)
- {
- /* handle special cases */
- for (n = 0; n < buflen; n++)
- {
- if ((c = iobuf_readbyte (a)) == -1)
- {
- if (!n)
- return -1; /* eof */
- break;
- }
- else if (buf)
- *buf = c;
- if (buf)
- buf++;
- }
- return n;
- }
-
- n = 0;
- do
- {
- if (n < buflen && a->d.start < a->d.len)
- {
- unsigned size = a->d.len - a->d.start;
- if (size > buflen - n)
- size = buflen - n;
- if (buf)
- memcpy (buf, a->d.buf + a->d.start, size);
- n += size;
- a->d.start += size;
- if (buf)
- buf += size;
- }
- if (n < buflen)
- {
- if ((c = underflow (a)) == -1)
- {
- a->nbytes += n;
- return n ? n : -1 /*EOF*/;
- }
- if (buf)
- *buf++ = c;
- n++;
- }
- }
- while (n < buflen);
- a->nbytes += n;
- return n;
-}
-
-
-/****************
- * Have a look at the iobuf.
- * NOTE: This only works in special cases.
- */
-int
-iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
-{
- int n = 0;
-
- if (a->filter_eof)
- return -1;
-
- if (!(a->d.start < a->d.len))
- {
- if (underflow (a) == -1)
- return -1;
- /* and unget this character */
- assert (a->d.start == 1);
- a->d.start = 0;
- }
-
- for (n = 0; n < buflen && (a->d.start + n) < a->d.len; n++, buf++)
- *buf = a->d.buf[n];
- return n;
-}
-
-
-
-
-int
-iobuf_writebyte (iobuf_t a, unsigned c)
-{
- int rc;
-
- if (a->directfp)
- BUG ();
-
- if (a->d.len == a->d.size)
- if ((rc=iobuf_flush (a)))
- return rc;
-
- assert (a->d.len < a->d.size);
- a->d.buf[a->d.len++] = c;
- return 0;
-}
-
-
-int
-iobuf_write (iobuf_t a, byte * buf, unsigned buflen)
-{
- int rc;
-
- if (a->directfp)
- BUG ();
-
- do
- {
- if (buflen && a->d.len < a->d.size)
- {
- unsigned size = a->d.size - a->d.len;
- if (size > buflen)
- size = buflen;
- memcpy (a->d.buf + a->d.len, buf, size);
- buflen -= size;
- buf += size;
- a->d.len += size;
- }
- if (buflen)
- {
- rc = iobuf_flush (a);
- if (rc)
- return rc;
- }
- }
- while (buflen);
- return 0;
-}
-
-
-int
-iobuf_writestr (iobuf_t a, const char *buf)
-{
- int rc;
-
- for (; *buf; buf++)
- if ((rc=iobuf_writebyte (a, *buf)))
- return rc;
- return 0;
-}
-
-
-
-/****************
- * copy the contents of TEMP to A.
- */
-int
-iobuf_write_temp (iobuf_t a, iobuf_t temp)
-{
- while (temp->chain)
- pop_filter (temp, temp->filter, NULL);
- return iobuf_write (a, temp->d.buf, temp->d.len);
-}
-
-/****************
- * copy the contents of the temp io stream to BUFFER.
- */
-size_t
-iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
-{
- size_t n = a->d.len;
-
- if (n > buflen)
- n = buflen;
- memcpy (buffer, a->d.buf, n);
- return n;
-}
-
-
-/****************
- * Call this function to terminate processing of the temp stream
- * without closing it. This removes all filters from the stream
- * makes sure that iobuf_get_temp_{buffer,length}() returns correct
- * values.
- */
-void
-iobuf_flush_temp (iobuf_t temp)
-{
- while (temp->chain)
- pop_filter (temp, temp->filter, NULL);
-}
-
-
-/****************
- * Set a limit on how many bytes may be read from the input stream A.
- * Setting the limit to 0 disables this feature.
- */
-void
-iobuf_set_limit (iobuf_t a, off_t nlimit)
-{
- if (nlimit)
- a->nofast |= 1;
- else
- a->nofast &= ~1;
- a->nlimit = nlimit;
- a->ntotal += a->nbytes;
- a->nbytes = 0;
-}
-
-
-
-/****************
- * Return the length of an open file
- */
-off_t
-iobuf_get_filelength (iobuf_t a)
-{
- struct stat st;
-
- if (a->directfp)
- {
- FILE *fp = a->directfp;
-
- if (!fstat (fileno (fp), &st))
- return st.st_size;
- log_error ("fstat() failed: %s\n", strerror (errno));
- return 0;
- }
-
- /* Hmmm: file_filter may have already been removed */
- for (; a; a = a->chain)
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- FILEP_OR_FD fp = b->fp;
-
-#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
- ulong size;
-
- if ((size = GetFileSize (fp, NULL)) != 0xffffffff)
- return size;
- log_error ("GetFileSize for handle %p failed: ec=%d\n",
- fp, (int) GetLastError ());
-#else
- if (!fstat (my_fileno (fp), &st))
- return st.st_size;
- log_error ("fstat() failed: %s\n", strerror (errno));
-#endif
- break;
- }
-
- return 0;
-}
-
-/****************
- * Tell the file position, where the next read will take place
- */
-off_t
-iobuf_tell (iobuf_t a)
-{
- return a->ntotal + a->nbytes;
-}
-
-
-#if !defined(HAVE_FSEEKO) && !defined(fseeko)
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-#ifndef LONG_MAX
-# define LONG_MAX ((long) ((unsigned long) -1 >> 1))
-#endif
-#ifndef LONG_MIN
-# define LONG_MIN (-1 - LONG_MAX)
-#endif
-
-/****************
- * A substitute for fseeko, for hosts that don't have it.
- */
-static int
-fseeko (FILE * stream, off_t newpos, int whence)
-{
- while (newpos != (long) newpos)
- {
- long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
- if (fseek (stream, pos, whence) != 0)
- return -1;
- newpos -= pos;
- whence = SEEK_CUR;
- }
- return fseek (stream, (long) newpos, whence);
-}
-#endif
-
-/****************
- * This is a very limited implementation. It simply discards all internal
- * buffering and removes all filters but the first one.
- */
-int
-iobuf_seek (iobuf_t a, off_t newpos)
-{
- file_filter_ctx_t *b = NULL;
-
- if (a->directfp)
- {
- FILE *fp = a->directfp;
- if (fseeko (fp, newpos, SEEK_SET))
- {
- log_error ("can't seek: %s\n", strerror (errno));
- return -1;
- }
- clearerr (fp);
- }
- else
- {
- for (; a; a = a->chain)
- {
- if (!a->chain && a->filter == file_filter)
- {
- b = a->filter_ov;
- break;
- }
- }
- if (!a)
- return -1;
-#ifdef FILE_FILTER_USES_STDIO
- if (fseeko (b->fp, newpos, SEEK_SET))
- {
- log_error ("can't fseek: %s\n", strerror (errno));
- return -1;
- }
-#else
-#ifdef HAVE_DOSISH_SYSTEM
- if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff)
- {
- log_error ("SetFilePointer failed on handle %p: ec=%d\n",
- b->fp, (int) GetLastError ());
- return -1;
- }
-#else
- if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1)
- {
- log_error ("can't lseek: %s\n", strerror (errno));
- return -1;
- }
-#endif
-#endif
- }
- a->d.len = 0; /* discard buffer */
- a->d.start = 0;
- a->nbytes = 0;
- a->nlimit = 0;
- a->nofast &= ~1;
- a->ntotal = newpos;
- a->error = 0;
- /* remove filters, but the last */
- if (a->chain)
- log_debug ("pop_filter called in iobuf_seek - please report\n");
- while (a->chain)
- pop_filter (a, a->filter, NULL);
-
- return 0;
-}
-
-
-
-
-
-
-/****************
- * Retrieve the real filename
- */
-const char *
-iobuf_get_real_fname (iobuf_t a)
-{
- if (a->real_fname)
- return a->real_fname;
-
- /* the old solution */
- for (; a; a = a->chain)
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- return b->print_only_name ? NULL : b->fname;
- }
-
- return NULL;
-}
-
-
-/****************
- * Retrieve the filename
- */
-const char *
-iobuf_get_fname (iobuf_t a)
-{
- for (; a; a = a->chain)
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- return b->fname;
- }
-
- return NULL;
-}
-
-/****************
- * Start the block write mode, see rfc1991.new for details.
- * A value of 0 for N stops this mode (flushes and writes
- * the end marker)
- */
-void
-iobuf_set_block_mode (iobuf_t a, size_t n)
-{
- block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
-
- assert (a->use == 1 || a->use == 2);
- ctx->use = a->use;
- if (!n)
- {
- if (a->use == 1)
- log_debug ("pop_filter called in set_block_mode - please report\n");
- pop_filter (a, block_filter, NULL);
- }
- else
- {
- ctx->size = n; /* only needed for use 2 */
- iobuf_push_filter (a, block_filter, ctx);
- }
-}
-
-/****************
- * enable partial block mode as described in the OpenPGP draft.
- * LEN is the first length byte on read, but ignored on writes.
- */
-void
-iobuf_set_partial_block_mode (iobuf_t a, size_t len)
-{
- block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
-
- assert (a->use == 1 || a->use == 2);
- ctx->use = a->use;
- if (!len)
- {
- if (a->use == 1)
- log_debug ("pop_filter called in set_partial_block_mode"
- " - please report\n");
- pop_filter (a, block_filter, NULL);
- }
- else
- {
- ctx->partial = 1;
- ctx->size = 0;
- ctx->first_c = len;
- iobuf_push_filter (a, block_filter, ctx);
- }
-}
-
-
-/****************
- * Checks whether the stream is in block mode
- * Note: This does not work if other filters are pushed on the stream.
- */
-int
-iobuf_in_block_mode (iobuf_t a)
-{
- if (a && a->filter == block_filter)
- return 1; /* yes */
- return 0; /* no */
-}
-
-
-/****************
- * Same as fgets() but if the buffer is too short a larger one will
- * be allocated up to some limit *max_length.
- * A line is considered a byte stream ending in a LF.
- * Returns the length of the line. EOF is indicated by a line of
- * length zero. The last LF may be missing due to an EOF.
- * is max_length is zero on return, the line has been truncated.
- *
- * Note: The buffer is allocated with enough space to append a CR,LF,EOL
- */
-unsigned int
-iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
- unsigned *length_of_buffer, unsigned *max_length)
-{
- int c;
- char *buffer = *addr_of_buffer;
- unsigned length = *length_of_buffer;
- unsigned nbytes = 0;
- unsigned maxlen = *max_length;
- char *p;
-
- if (!buffer)
- { /* must allocate a new buffer */
- length = 256;
- buffer = xmalloc (length);
- *addr_of_buffer = buffer;
- *length_of_buffer = length;
- }
-
- length -= 3; /* reserve 3 bytes (cr,lf,eol) */
- p = buffer;
- while ((c = iobuf_get (a)) != -1)
- {
- if (nbytes == length)
- { /* increase the buffer */
- if (length > maxlen)
- { /* this is out limit */
- /* skip the rest of the line */
- while (c != '\n' && (c = iobuf_get (a)) != -1)
- ;
- *p++ = '\n'; /* always append a LF (we have reserved space) */
- nbytes++;
- *max_length = 0; /* indicate truncation */
- break;
- }
- length += 3; /* correct for the reserved byte */
- length += length < 1024 ? 256 : 1024;
- buffer = xrealloc (buffer, length);
- *addr_of_buffer = buffer;
- *length_of_buffer = length;
- length -= 3; /* and reserve again */
- p = buffer + nbytes;
- }
- *p++ = c;
- nbytes++;
- if (c == '\n')
- break;
- }
- *p = 0; /* make sure the line is a string */
-
- return nbytes;
-}
-
-/* This is the non iobuf specific function */
-int
-iobuf_translate_file_handle (int fd, int for_write)
-{
-#ifdef __MINGW32__
- {
- int x;
-
- if (fd <= 2)
- return fd; /* do not do this for error, stdin, stdout, stderr */
-
- x = _open_osfhandle (fd, for_write ? 1 : 0);
- if (x == -1)
- log_error ("failed to translate osfhandle %p\n", (void *) fd);
- else
- {
- /*log_info ("_open_osfhandle %p yields %d%s\n",
- (void*)fd, x, for_write? " for writing":"" ); */
- fd = x;
- }
- }
-#endif
- return fd;
-}
-
-static int
-translate_file_handle (int fd, int for_write)
-{
-#ifdef __MINGW32__
-#ifdef FILE_FILTER_USES_STDIO
- fd = iobuf_translate_file_handle (fd, for_write);
-#else
- {
- int x;
-
- if (fd == 0)
- x = (int) GetStdHandle (STD_INPUT_HANDLE);
- else if (fd == 1)
- x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
- else if (fd == 2)
- x = (int) GetStdHandle (STD_ERROR_HANDLE);
- else
- x = fd;
-
- if (x == -1)
- log_debug ("GetStdHandle(%d) failed: ec=%d\n",
- fd, (int) GetLastError ());
-
- fd = x;
- }
-#endif
-#endif
- return fd;
-}
diff --git a/common/iobuf.h b/common/iobuf.h
deleted file mode 100644
index 0af94e22d..000000000
--- a/common/iobuf.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* iobuf.h - I/O buffer
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_IOBUF_H
-#define GNUPG_COMMON_IOBUF_H
-
-#include "../include/types.h" /* fixme: should be moved elsewhere. */
-
-
-#define DBG_IOBUF iobuf_debug_mode
-
-
-#define IOBUFCTRL_INIT 1
-#define IOBUFCTRL_FREE 2
-#define IOBUFCTRL_UNDERFLOW 3
-#define IOBUFCTRL_FLUSH 4
-#define IOBUFCTRL_DESC 5
-#define IOBUFCTRL_CANCEL 6
-#define IOBUFCTRL_USER 16
-
-typedef struct iobuf_struct *iobuf_t;
-
-/* fixme: we should hide most of this stuff */
-struct iobuf_struct
-{
- int use; /* 1 input , 2 output, 3 temp */
- off_t nlimit;
- off_t nbytes; /* used together with nlimit */
- off_t ntotal; /* total bytes read (position of stream) */
- int nofast; /* used by the iobuf_get() */
- void *directfp;
- struct
- {
- size_t size; /* allocated size */
- size_t start; /* number of invalid bytes at the begin of the buffer */
- size_t len; /* currently filled to this size */
- byte *buf;
- }
- d;
- int filter_eof;
- int error;
- int (*filter) (void *opaque, int control,
- iobuf_t chain, byte * buf, size_t * len);
- void *filter_ov; /* value for opaque */
- int filter_ov_owner;
- char *real_fname;
- iobuf_t chain; /* next iobuf used for i/o if any
- (passed to filter) */
- int no, subno;
- const char *desc;
- void *opaque; /* can be used to hold any information
- this value is copied to all
- instances */
- struct
- {
- size_t size; /* allocated size */
- size_t start; /* number of invalid bytes at the
- begin of the buffer */
- size_t len; /* currently filled to this size */
- byte *buf;
- }
- unget;
-};
-
-#ifndef EXTERN_UNLESS_MAIN_MODULE
-#if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE)
-#define EXTERN_UNLESS_MAIN_MODULE extern
-#else
-#define EXTERN_UNLESS_MAIN_MODULE
-#endif
-#endif
-EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode;
-
-void iobuf_enable_special_filenames (int yes);
-iobuf_t iobuf_alloc (int use, size_t bufsize);
-iobuf_t iobuf_temp (void);
-iobuf_t iobuf_temp_with_content (const char *buffer, size_t length);
-iobuf_t iobuf_open (const char *fname);
-iobuf_t iobuf_fdopen (int fd, const char *mode);
-iobuf_t iobuf_sockopen (int fd, const char *mode);
-iobuf_t iobuf_create (const char *fname);
-iobuf_t iobuf_append (const char *fname);
-iobuf_t iobuf_openrw (const char *fname);
-int iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval);
-int iobuf_close (iobuf_t iobuf);
-int iobuf_cancel (iobuf_t iobuf);
-
-int iobuf_push_filter (iobuf_t a, int (*f) (void *opaque, int control,
- iobuf_t chain, byte * buf,
- size_t * len), void *ov);
-int iobuf_push_filter2 (iobuf_t a,
- int (*f) (void *opaque, int control, iobuf_t chain,
- byte * buf, size_t * len), void *ov,
- int rel_ov);
-int iobuf_flush (iobuf_t a);
-void iobuf_clear_eof (iobuf_t a);
-#define iobuf_set_error(a) do { (a)->error = 1; } while(0)
-#define iobuf_error(a) ((a)->error)
-
-void iobuf_set_limit (iobuf_t a, off_t nlimit);
-
-off_t iobuf_tell (iobuf_t a);
-int iobuf_seek (iobuf_t a, off_t newpos);
-
-int iobuf_readbyte (iobuf_t a);
-int iobuf_read (iobuf_t a, byte * buf, unsigned buflen);
-unsigned iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
- unsigned *length_of_buffer, unsigned *max_length);
-int iobuf_peek (iobuf_t a, byte * buf, unsigned buflen);
-int iobuf_writebyte (iobuf_t a, unsigned c);
-int iobuf_write (iobuf_t a, byte * buf, unsigned buflen);
-int iobuf_writestr (iobuf_t a, const char *buf);
-
-void iobuf_flush_temp (iobuf_t temp);
-int iobuf_write_temp (iobuf_t a, iobuf_t temp);
-size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
-void iobuf_unget_and_close_temp (iobuf_t a, iobuf_t temp);
-
-off_t iobuf_get_filelength (iobuf_t a);
-#define IOBUF_FILELENGTH_LIMIT 0xffffffff
-const char *iobuf_get_real_fname (iobuf_t a);
-const char *iobuf_get_fname (iobuf_t a);
-
-void iobuf_set_block_mode (iobuf_t a, size_t n);
-void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
-int iobuf_in_block_mode (iobuf_t a);
-
-int iobuf_translate_file_handle (int fd, int for_write);
-
-
-/* get a byte form the iobuf; must check for eof prior to this function
- * this function returns values in the range 0 .. 255 or -1 to indicate EOF
- * iobuf_get_noeof() does not return -1 to indicate EOF, but masks the
- * returned value to be in the range 0 ..255.
- */
-#define iobuf_get(a) \
- ( ((a)->nofast || (a)->d.start >= (a)->d.len )? \
- iobuf_readbyte((a)) : ( (a)->nbytes++, (a)->d.buf[(a)->d.start++] ) )
-#define iobuf_get_noeof(a) (iobuf_get((a))&0xff)
-
-/* write a byte to the iobuf and return true on write error
- * This macro does only write the low order byte
- */
-#define iobuf_put(a,c) iobuf_writebyte(a,c)
-
-#define iobuf_where(a) "[don't know]"
-#define iobuf_id(a) ((a)->no)
-
-#define iobuf_get_temp_buffer(a) ( (a)->d.buf )
-#define iobuf_get_temp_length(a) ( (a)->d.len )
-#define iobuf_is_temp(a) ( (a)->use == 3 )
-
-#endif /*GNUPG_COMMON_IOBUF_H*/
diff --git a/common/isascii.c b/common/isascii.c
deleted file mode 100644
index 565c71664..000000000
--- a/common/isascii.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* isascii.c - Replacement for isascii.
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-int
-isascii (int c)
-{
- return (((c) & ~0x7f) == 0);
-}
diff --git a/common/maperror.c b/common/maperror.c
deleted file mode 100644
index 13657bece..000000000
--- a/common/maperror.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* maperror.c - Error mapping
- * Copyright (C) 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <ksba.h>
-#include <assuan.h>
-
-#include "util.h"
-#include "errors.h"
-
-/* Note: we might want to wrap this in a macro to get our hands on
- the line and file where the error occured */
-int
-map_ksba_err (int err)
-{
- switch (err)
- {
- case -1:
- case 0:
- break;
-
- case KSBA_Out_Of_Core: err = GPG_ERR_ENOMEM; break;
- case KSBA_Invalid_Value: err = GPG_ERR_INV_VALUE; break;
- case KSBA_Not_Implemented: err = GPG_ERR_NOT_IMPLEMENTED; break;
- case KSBA_Conflict: err = GPG_ERR_CONFLICT; break;
- case KSBA_Read_Error: err = GPG_ERR_EIO; break;
- case KSBA_Write_Error: err = GPG_ERR_EIO; break;
- case KSBA_No_Data: err = GPG_ERR_NO_DATA; break;
- case KSBA_Bug: err = GPG_ERR_BUG; break;
- case KSBA_Unsupported_Algorithm: err = GPG_ERR_UNSUPPORTED_ALGORITHM; break;
- case KSBA_Invalid_Index: err = GPG_ERR_INV_INDEX; break;
- case KSBA_Invalid_Sexp: err = GPG_ERR_INV_SEXP; break;
- case KSBA_Unknown_Sexp: err = GPG_ERR_UNKNOWN_SEXP; break;
-
- default:
- err = GPG_ERR_GENERAL;
- break;
- }
- return err;
-}
-
-
-int
-map_gcry_err (int err)
-{
- return err;
-}
-
-int
-map_kbx_err (int err)
-{
- return err;
-}
-
-/* Map Assuan error code ERR to an GPG_ERR_ code. We need to
- distinguish between genuine (and legacy) Assuan error codes and
- application error codes shared with all GnuPG modules. The rule is
- simple: All errors with a gpg_err_source of UNKNOWN are genuine
- Assuan codes all others are passed verbatim through. */
-gpg_error_t
-map_assuan_err (int err)
-{
- gpg_err_code_t ec;
-
- if (gpg_err_source (err))
- return err;
-
- switch (err)
- {
- case -1: ec = GPG_ERR_EOF; break;
- case 0: ec = 0; break;
-
- case ASSUAN_Canceled: ec = GPG_ERR_CANCELED; break;
- case ASSUAN_Invalid_Index: ec = GPG_ERR_INV_INDEX; break;
-
- case ASSUAN_Not_Implemented: ec = GPG_ERR_NOT_IMPLEMENTED; break;
- case ASSUAN_Server_Fault: ec = GPG_ERR_ASSUAN_SERVER_FAULT; break;
- case ASSUAN_No_Public_Key: ec = GPG_ERR_NO_PUBKEY; break;
- case ASSUAN_No_Secret_Key: ec = GPG_ERR_NO_SECKEY; break;
-
- case ASSUAN_Cert_Revoked: ec = GPG_ERR_CERT_REVOKED; break;
- case ASSUAN_No_CRL_For_Cert: ec = GPG_ERR_NO_CRL_KNOWN; break;
- case ASSUAN_CRL_Too_Old: ec = GPG_ERR_CRL_TOO_OLD; break;
-
- case ASSUAN_Not_Trusted: ec = GPG_ERR_NOT_TRUSTED; break;
-
- case ASSUAN_Card_Error: ec = GPG_ERR_CARD; break;
- case ASSUAN_Invalid_Card: ec = GPG_ERR_INV_CARD; break;
- case ASSUAN_No_PKCS15_App: ec = GPG_ERR_NO_PKCS15_APP; break;
- case ASSUAN_Card_Not_Present: ec= GPG_ERR_CARD_NOT_PRESENT; break;
- case ASSUAN_Not_Confirmed: ec = GPG_ERR_NOT_CONFIRMED; break;
- case ASSUAN_Invalid_Id: ec = GPG_ERR_INV_ID; break;
-
- default:
- ec = err < 100? GPG_ERR_ASSUAN_SERVER_FAULT : GPG_ERR_ASSUAN;
- break;
- }
- return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, ec);
-}
-
-/* Map GPG_xERR_xx error codes to Assuan status codes */
-int
-map_to_assuan_status (int rc)
-{
- gpg_err_code_t ec = gpg_err_code (rc);
- gpg_err_source_t es = gpg_err_source (rc);
-
- if (!rc)
- return 0;
- if (!es)
- {
- es = GPG_ERR_SOURCE_USER_4; /* This should not happen, but we
- need to make sure to pass a new
- Assuan errorcode along. */
- log_debug ("map_to_assuan_status called with no error source\n");
- }
-
- if (ec == -1)
- ec = GPG_ERR_NO_DATA; /* That used to be ASSUAN_No_Data_Available. */
-
- return gpg_err_make (es, ec);
-}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/common/membuf.c b/common/membuf.c
deleted file mode 100644
index 69e4ab908..000000000
--- a/common/membuf.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* membuf.c - A simple implementation of a dynamic buffer
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "membuf.h"
-
-#include "util.h"
-
-
-/* A simple implementation of a dynamic buffer. Use init_membuf() to
- create a buffer, put_membuf to append bytes and get_membuf to
- release and return the buffer. Allocation errors are detected but
- only returned at the final get_membuf(), this helps not to clutter
- the code with out of core checks. */
-
-void
-init_membuf (membuf_t *mb, int initiallen)
-{
- mb->len = 0;
- mb->size = initiallen;
- mb->out_of_core = 0;
- mb->buf = xtrymalloc (initiallen);
- if (!mb->buf)
- mb->out_of_core = errno;
-}
-
-
-void
-put_membuf (membuf_t *mb, const void *buf, size_t len)
-{
- if (mb->out_of_core)
- return;
-
- if (mb->len + len >= mb->size)
- {
- char *p;
-
- mb->size += len + 1024;
- p = xtryrealloc (mb->buf, mb->size);
- if (!p)
- {
- mb->out_of_core = errno;
- return;
- }
- mb->buf = p;
- }
- memcpy (mb->buf + mb->len, buf, len);
- mb->len += len;
-}
-
-
-void *
-get_membuf (membuf_t *mb, size_t *len)
-{
- char *p;
-
- if (mb->out_of_core)
- {
- xfree (mb->buf);
- mb->buf = NULL;
- return NULL;
- }
-
- p = mb->buf;
- *len = mb->len;
- mb->buf = NULL;
- mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
- return p;
-}
diff --git a/common/membuf.h b/common/membuf.h
deleted file mode 100644
index c199363cc..000000000
--- a/common/membuf.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* membuf.h - A simple implementation of a dynamic buffer
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_MEMBUF_H
-#define GNUPG_COMMON_MEMBUF_H
-
-/* The definition of the structure is private, we only need it here,
- so it can be allocated on the stack. */
-struct private_membuf_s {
- size_t len;
- size_t size;
- char *buf;
- int out_of_core;
-};
-
-typedef struct private_membuf_s membuf_t;
-
-
-void init_membuf (membuf_t *mb, int initiallen);
-void put_membuf (membuf_t *mb, const void *buf, size_t len);
-void *get_membuf (membuf_t *mb, size_t *len);
-
-
-#endif /*GNUPG_COMMON_MEMBUF_H*/
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
deleted file mode 100644
index bdb12c574..000000000
--- a/common/miscellaneous.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* miscellaneous.c - Stuff not fitting elsewhere
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "util.h"
-#include "iobuf.h"
-
-/* Decide whether the filename is stdout or a real filename and return
- * an appropriate string. */
-const char *
-print_fname_stdout (const char *s)
-{
- if( !s || (*s == '-' && !s[1]) )
- return "[stdout]";
- return s;
-}
-
-
-/* Decide whether the filename is stdin or a real filename and return
- * an appropriate string. */
-const char *
-print_fname_stdin (const char *s)
-{
- if( !s || (*s == '-' && !s[1]) )
- return "[stdin]";
- return s;
-}
-
-void
-print_string( FILE *fp, const byte *p, size_t n, int delim )
-{
- print_sanitized_buffer (fp, p, n, delim);
-}
-
-void
-print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
-{
- print_sanitized_utf8_buffer (fp, p, n, delim);
-}
-
-void
-print_utf8_string( FILE *fp, const byte *p, size_t n )
-{
- print_utf8_string2 (fp, p, n, 0);
-}
-
-char *
-make_printable_string( const byte *p, size_t n, int delim )
-{
- return sanitize_buffer (p, n, delim);
-}
-
-
-/*
- * Check if the file is compressed.
- */
-int
-is_file_compressed (const char *s, int *ret_rc)
-{
- iobuf_t a;
- byte buf[4];
- int i, rc = 0;
-
- struct magic_compress_s {
- size_t len;
- byte magic[4];
- } magic[] = {
- { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
- { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
- { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
- };
-
- if ( !s || (*s == '-' && !s[1]) || !ret_rc )
- return 0; /* We can't check stdin or no file was given */
-
- a = iobuf_open( s );
- if ( a == NULL ) {
- *ret_rc = gpg_error_from_errno (errno);
- return 0;
- }
-
- if ( iobuf_get_filelength( a ) < 4 ) {
- *ret_rc = 0;
- goto leave;
- }
-
- if ( iobuf_read( a, buf, 4 ) == -1 ) {
- *ret_rc = a->error;
- goto leave;
- }
-
- for ( i = 0; i < DIM( magic ); i++ ) {
- if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
- *ret_rc = 0;
- rc = 1;
- break;
- }
- }
-
-leave:
- iobuf_close( a );
- return rc;
-}
-
-
-
diff --git a/common/mkdtemp.c b/common/mkdtemp.c
deleted file mode 100644
index 5347b9cb4..000000000
--- a/common/mkdtemp.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* mkdtemp.c - libc replacement function
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* This is a replacement function for mkdtemp in case the platform
- we're building on (like mine!) doesn't have it. */
-
-#include <config.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <gcrypt.h>
-
-#ifdef MKDIR_TAKES_ONE_ARG
-# undef mkdir
-# define mkdir(a,b) mkdir(a)
-#endif
-
-char *mkdtemp(char *template)
-{
- int attempts,idx,count=0;
- unsigned char *ch;
-
- idx=strlen(template);
-
- /* Walk backwards to count all the Xes */
- while(idx>0 && template[idx-1]=='X')
- {
- count++;
- idx--;
- }
-
- if(count==0)
- {
- errno=EINVAL;
- return NULL;
- }
-
- ch=&template[idx];
-
- /* Try 4 times to make the temp directory */
- for(attempts=0;attempts<4;attempts++)
- {
- int remaining=count;
- char *marker=ch;
- unsigned char *randombits;
-
- idx=0;
-
- /* Using really random bits is probably overkill here. The
- worst thing that can happen with a directory name collision
- is that the function will return an error. */
-
- randombits = gcry_random_bytes (4*remaining, GCRY_WEAK_RANDOM);
-
- while(remaining>1)
- {
- sprintf(marker,"%02X",randombits[idx++]);
- marker+=2;
- remaining-=2;
- }
-
- /* Any leftover Xes? get_random_bits rounds up to full bytes,
- so this is safe. */
- if(remaining>0)
- sprintf(marker,"%X",randombits[idx]&0xF);
-
- gcry_free (randombits);
-
- if(mkdir(template,0700)==0)
- break;
- }
-
- if(attempts==4)
- return NULL; /* keeps the errno from mkdir, whatever it is */
-
- return template;
-}
-
-
diff --git a/common/mkerrors b/common/mkerrors
deleted file mode 100755
index 5a1ef33da..000000000
--- a/common/mkerrors
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/sh
-# mkerrors - Extract error strings from errors.h
-# and create C source for gnupg_strerror
-# Copyright (C) 2001 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-cat <<EOF
-/* Generated automatically by mkerrors */
-/* Do not edit! */
-
-#include <config.h>
-#include <stdio.h>
-#include "errors.h"
-
-/**
- * gnupg_strerror:
- * @err: Error code
- *
- * This function returns a textual representaion of the given
- * errorcode. If this is an unknown value, a string with the value
- * is returned (Beware: it is hold in a static buffer).
- *
- * Return value: String with the error description.
- **/
-const char *
-gnupg_strerror (int err)
-{
- const char *s;
- static char buf[25];
-
- switch (err)
- {
-EOF
-
-awk '
-/GNUPG_No_Error/ { okay=1 }
-!okay {next}
-/}/ { exit 0 }
-/GNUPG_[A-Za-z_]*/ { print_code($1) }
-
-
-function print_code( s )
-{
-printf " case %s: s=\"", s ;
-gsub(/_/, " ", s );
-printf "%s\"; break;\n", tolower(substr(s,7));
-}
-'
-
-cat <<EOF
- default: sprintf (buf, "ec=%d", err ); s=buf; break;
- }
-
- return s;
-}
-
-EOF \ No newline at end of file
diff --git a/common/mkerrtok b/common/mkerrtok
deleted file mode 100755
index 1029614af..000000000
--- a/common/mkerrtok
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/sh
-# mkerrtok - Create error tokens from errors.h
-# and the C source for gnupg_errortoken
-# Copyright (C) 2001, 2002 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-cat <<EOF
-/* Generated automatically by mkerrtok */
-/* Do not edit! */
-
-/**
- * gnupg_error_token:
- * @err: Error code
- *
- * This function returns a textual representaion of the given
- * errorcode. If this is an unknown value, a static string is returned.
- * This function differs from gnupg_strerror that it yields the string
- * representation of the macro which is never subject to i18n.
- *
- * Return value: String with the error token.
- **/
-const char *
-gnupg_error_token (int err)
-{
- const char *s;
-
- switch (err)
- {
-EOF
-
-awk '
-/GNUPG_No_Error/ { okay=1 }
-!okay {next}
-/}/ { exit 0 }
-/GNUPG_[A-Za-z_]*/ { print_code($1) }
-
-
-function print_code( s )
-{
-printf " case %s: s=\"", s ;
-printf "%s\"; break;\n", substr(s,7);
-}
-'
-
-cat <<EOF
- default: s = "Unknown_Error"; break;
- }
-
- return s;
-}
-
-EOF
diff --git a/common/putc_unlocked.c b/common/putc_unlocked.c
deleted file mode 100644
index 02c646130..000000000
--- a/common/putc_unlocked.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* putc_unlocked.c - Replacement for putc_unlocked.
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-int
-putc_unlocked (int c, FILE *stream)
-{
- return putc (c, stream);
-}
diff --git a/common/signal.c b/common/signal.c
deleted file mode 100644
index dc026c10f..000000000
--- a/common/signal.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* signal.c - signal handling
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "util.h"
-
-
-static volatile int caught_fatal_sig;
-static volatile int caught_sigusr1;
-static void (*cleanup_fnc)(void);
-
-
-static void
-init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign )
-{
-#ifndef HAVE_DOSISH_SYSTEM
-# ifdef HAVE_SIGACTION
- struct sigaction oact, nact;
-
- if (check_ign)
- {
- /* we don't want to change an IGN handler */
- sigaction (sig, NULL, &oact );
- if (oact.sa_handler == SIG_IGN )
- return;
- }
-
- nact.sa_handler = handler;
- sigemptyset (&nact.sa_mask);
- nact.sa_flags = 0;
- sigaction ( sig, &nact, NULL);
-# else
- RETSIGTYPE (*ohandler)(int);
-
- ohandler = signal (sig, handler);
- if (check_ign && ohandler == SIG_IGN)
- {
- /* Change it back if it was already set to IGN */
- signal (sig, SIG_IGN);
- }
-# endif
-#endif /*!HAVE_DOSISH_SYSTEM*/
-}
-
-static const char *
-get_signal_name( int signum )
-{
-#if defined(SYS_SIGLIST_DECLARED) && defined(NSIG)
- return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?";
-#else
- return "some signal";
-#endif
-}
-
-static RETSIGTYPE
-got_fatal_signal (int sig)
-{
- const char *s;
-
- if (caught_fatal_sig)
- raise (sig);
- caught_fatal_sig = 1;
-
- if (cleanup_fnc)
- cleanup_fnc ();
- /* better don't translate these messages */
- write (2, "\n", 1 );
- s = log_get_prefix (NULL);
- if (s)
- write(2, s, strlen (s));
- write (2, ": ", 2 );
- s = get_signal_name(sig);
- write (2, s, strlen(s) );
- write (2, " caught ... exiting\n", 20);
-
- /* reset action to default action and raise signal again */
- init_one_signal (sig, SIG_DFL, 0);
- /* fixme: remove_lockfiles ();*/
-#ifdef __riscos__
- close_fds ();
-#endif /* __riscos__ */
- raise( sig );
-}
-
-
-static RETSIGTYPE
-got_usr_signal (int sig)
-{
- caught_sigusr1 = 1;
-}
-
-
-void
-gnupg_init_signals (int mode, void (*fast_cleanup)(void))
-{
- assert (!mode);
-
- cleanup_fnc = fast_cleanup;
-#ifndef HAVE_DOSISH_SYSTEM
- init_one_signal (SIGINT, got_fatal_signal, 1 );
- init_one_signal (SIGHUP, got_fatal_signal, 1 );
- init_one_signal (SIGTERM, got_fatal_signal, 1 );
- init_one_signal (SIGQUIT, got_fatal_signal, 1 );
- init_one_signal (SIGSEGV, got_fatal_signal, 1 );
- init_one_signal (SIGUSR1, got_usr_signal, 0 );
- init_one_signal (SIGPIPE, SIG_IGN, 0 );
-#endif
-}
-
-void
-gnupg_pause_on_sigusr (int which)
-{
-#ifndef HAVE_DOSISH_SYSTEM
-# ifdef HAVE_SIGPROCMASK
- sigset_t mask, oldmask;
-
- assert (which == 1);
- sigemptyset( &mask );
- sigaddset( &mask, SIGUSR1 );
-
- sigprocmask( SIG_BLOCK, &mask, &oldmask );
- while (!caught_sigusr1)
- sigsuspend (&oldmask);
- caught_sigusr1 = 0;
- sigprocmask (SIG_UNBLOCK, &mask, NULL);
-# else
- assert (which == 1);
- sighold (SIGUSR1);
- while (!caught_sigusr1)
- sigpause(SIGUSR1);
- caught_sigusr1 = 0;
- sigrelease(SIGUSR1);
-# endif /*!HAVE_SIGPROCMASK*/
-#endif
-}
-
-
-static void
-do_block( int block )
-{
-#ifndef HAVE_DOSISH_SYSTEM
- static int is_blocked;
-#ifdef HAVE_SIGPROCMASK
- static sigset_t oldmask;
-
- if (block)
- {
- sigset_t newmask;
-
- if (is_blocked)
- log_bug ("signals are already blocked\n");
- sigfillset( &newmask );
- sigprocmask( SIG_BLOCK, &newmask, &oldmask );
- is_blocked = 1;
- }
- else
- {
- if (!is_blocked)
- log_bug("signals are not blocked\n");
- sigprocmask (SIG_SETMASK, &oldmask, NULL);
- is_blocked = 0;
- }
-#else /*!HAVE_SIGPROCMASK*/
- static void (*disposition[MAXSIG])();
- int sig;
-
- if (block)
- {
- if (is_blocked)
- log_bug("signals are already blocked\n");
- for (sig=1; sig < MAXSIG; sig++)
- {
- disposition[sig] = sigset (sig, SIG_HOLD);
- }
- is_blocked = 1;
- }
- else
- {
- if (!is_blocked)
- log_bug ("signals are not blocked\n");
- for (sig=1; sig < MAXSIG; sig++) {
- sigset (sig, disposition[sig]);
- }
- is_blocked = 0;
- }
-#endif /*!HAVE_SIGPROCMASK*/
-#endif /*HAVE_DOSISH_SYSTEM*/
-}
-
-
-void
-gnupg_block_all_signals ()
-{
- do_block(1);
-}
-
-void
-gnupg_unblock_all_signals ()
-{
- do_block(0);
-}
diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c
deleted file mode 100644
index afdc4e2a4..000000000
--- a/common/simple-pwquery.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/* simple-pwquery.c - A simple password query cleint for gpg-agent
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* This module is intended as a standalone client implementation to
- gpg-agent's GET_PASSPHRASE command. In particular it does not use
- the Assuan library and can only cope with an already running
- gpg-agent. Some stuff is configurable in the header file. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#define SIMPLE_PWQUERY_IMPLEMENTATION 1
-#include "simple-pwquery.h"
-
-#if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
-# undef SPWQ_USE_LOGGING
-#endif
-
-#ifndef _
-#define _(a) (a)
-#endif
-
-#if !defined (hexdigitp) && !defined (xtoi_2)
-#define digitp(p) (*(p) >= '0' && *(p) <= '9')
-#define hexdigitp(a) (digitp (a) \
- || (*(a) >= 'A' && *(a) <= 'F') \
- || (*(a) >= 'a' && *(a) <= 'f'))
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-#endif
-
-
-/* Write NBYTES of BUF to file descriptor FD. */
-static int
-writen (int fd, const void *buf, size_t nbytes)
-{
- size_t nleft = nbytes;
- int nwritten;
-
- while (nleft > 0)
- {
- nwritten = write( fd, buf, nleft );
- if (nwritten < 0)
- {
- if (errno == EINTR)
- nwritten = 0;
- else {
-#ifdef SPWQ_USE_LOGGING
- log_error ("write failed: %s\n", strerror (errno));
-#endif
- return SPWQ_IO_ERROR;
- }
- }
- nleft -= nwritten;
- buf = (const char*)buf + nwritten;
- }
-
- return 0;
-}
-
-
-/* Read an entire line and return number of bytes read. */
-static int
-readline (int fd, char *buf, size_t buflen)
-{
- size_t nleft = buflen;
- char *p;
- int nread = 0;
-
- while (nleft > 0)
- {
- int n = read (fd, buf, nleft);
- if (n < 0)
- {
- if (errno == EINTR)
- continue;
- return -(SPWQ_IO_ERROR);
- }
- else if (!n)
- {
- return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
- }
- p = buf;
- nleft -= n;
- buf += n;
- nread += n;
-
- for (; n && *p != '\n'; n--, p++)
- ;
- if (n)
- {
- break; /* at least one full line available - that's enough.
- This function is just a simple implementation, so
- it is okay to forget about pending bytes */
- }
- }
-
- return nread;
-}
-
-
-/* Send an option to the agent */
-static int
-agent_send_option (int fd, const char *name, const char *value)
-{
- char buf[200];
- int nread;
- char *line;
- int i;
-
- line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
- if (!line)
- return SPWQ_OUT_OF_CORE;
- strcpy (stpcpy (stpcpy (stpcpy (
- stpcpy (line, "OPTION "), name), "="), value), "\n");
- i = writen (fd, line, strlen (line));
- spwq_free (line);
- if (i)
- return i;
-
- /* get response */
- nread = readline (fd, buf, DIM(buf)-1);
- if (nread < 0)
- return -nread;
- if (nread < 3)
- return SPWQ_PROTOCOL_ERROR;
-
- if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
- return 0; /* okay */
-
- return SPWQ_ERR_RESPONSE;
-}
-
-
-/* Send all available options to the agent. */
-static int
-agent_send_all_options (int fd)
-{
- char *dft_display = NULL;
- char *dft_ttyname = NULL;
- char *dft_ttytype = NULL;
- int rc = 0;
-
- dft_display = getenv ("DISPLAY");
- if (dft_display)
- {
- if ((rc = agent_send_option (fd, "display", dft_display)))
- return rc;
- }
-
- dft_ttyname = getenv ("GPG_TTY");
- if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
- dft_ttyname = ttyname (0);
- if (dft_ttyname && *dft_ttyname)
- {
- if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
- return rc;
- }
-
- dft_ttytype = getenv ("TERM");
- if (dft_ttyname && dft_ttytype)
- {
- if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
- return rc;
- }
-
-#if defined(HAVE_SETLOCALE)
- {
- char *old_lc = NULL;
- char *dft_lc = NULL;
-
-#if defined(LC_CTYPE)
- old_lc = setlocale (LC_CTYPE, NULL);
- if (old_lc)
- {
- char *p = spwq_malloc (strlen (old_lc)+1);
- if (!p)
- return SPWQ_OUT_OF_CORE;
- strcpy (p, old_lc);
- old_lc = p;
- }
- dft_lc = setlocale (LC_CTYPE, "");
- if (dft_ttyname && dft_lc)
- rc = agent_send_option (fd, "lc-ctype", dft_lc);
- if (old_lc)
- {
- setlocale (LC_CTYPE, old_lc);
- spwq_free (old_lc);
- }
- if (rc)
- return rc;
-#endif
-
-#if defined(LC_MESSAGES)
- old_lc = setlocale (LC_MESSAGES, NULL);
- if (old_lc)
- {
- char *p = spwq_malloc (strlen (old_lc)+1);
- if (!p)
- return SPWQ_OUT_OF_CORE;
- strcpy (p, old_lc);
- old_lc = p;
- }
- dft_lc = setlocale (LC_MESSAGES, "");
- if (dft_ttyname && dft_lc)
- rc = agent_send_option (fd, "lc-messages", dft_lc);
- if (old_lc)
- {
- setlocale (LC_MESSAGES, old_lc);
- spwq_free (old_lc);
- }
- if (rc)
- return rc;
-#endif
- }
-#endif /*HAVE_SETLOCALE*/
-
- return 0;
-}
-
-
-
-/* Try to open a connection to the agent, send all options and return
- the file descriptor for the connection. Return -1 in case of
- error. */
-static int
-agent_open (int *rfd)
-{
- int rc;
- int fd;
- char *infostr, *p;
- struct sockaddr_un client_addr;
- size_t len;
- int prot;
- char line[200];
- int nread;
-
- *rfd = -1;
- infostr = getenv ( "GPG_AGENT_INFO" );
- if ( !infostr )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("gpg-agent is not available in this session\n"));
-#endif
- return SPWQ_NO_AGENT;
- }
-
- if ( !(p = strchr ( infostr, ':')) || p == infostr
- || (p-infostr)+1 >= sizeof client_addr.sun_path )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
-#endif
- return SPWQ_NO_AGENT;
- }
- *p++ = 0;
-
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if ( prot != 1)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
-#endif
- return SPWQ_PROTOCOL_ERROR;
- }
-
- if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ("can't create socket: %s\n", strerror(errno) );
-#endif
- return SPWQ_SYS_ERROR;
- }
-
- memset (&client_addr, 0, sizeof client_addr);
- client_addr.sun_family = AF_UNIX;
- strcpy (client_addr.sun_path, infostr);
- len = (offsetof (struct sockaddr_un, sun_path)
- + strlen(client_addr.sun_path) + 1);
-
- if (connect (fd, (struct sockaddr*)&client_addr, len ) == -1)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno));
-#endif
- close (fd );
- return SPWQ_IO_ERROR;
- }
-
- nread = readline (fd, line, DIM(line));
- if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
- && (line[2] == '\n' || line[2] == ' ')) )
- {
-#ifdef SPWQ_USE_LOGGING
- log_error ( _("communication problem with gpg-agent\n"));
-#endif
- close (fd );
- return SPWQ_PROTOCOL_ERROR;
- }
-
- rc = agent_send_all_options (fd);
- if (rc)
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("problem setting the gpg-agent options\n"));
-#endif
- close (fd);
- return rc;
- }
-
- *rfd = fd;
- return 0;
-}
-
-
-/* Copy text to BUFFER and escape as required. Return a poiinter to
- the end of the new buffer. NOte that BUFFER must be large enough
- to keep the entire text; allocataing it 3 times the size of TEXT
- is sufficient. */
-static char *
-copy_and_escape (char *buffer, const char *text)
-{
- int i;
- char *p = buffer;
-
- for (i=0; text[i]; i++)
- {
- if (text[i] < ' ' || text[i] == '+')
- {
- sprintf (p, "%%%02X", text[i]);
- p += 3;
- }
- else if (text[i] == ' ')
- *p++ = '+';
- else
- *p++ = text[i];
- }
- return p;
-}
-
-
-/* Ask the gpg-agent for a passphrase and present the user with a
- DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
- If a CACHEID is not NULL it is used to locate the passphrase in in
- the cache and store it under this ID. If ERRORCODE is not NULL it
- should point a variable receiving an errorcode; thsi errocode might
- be 0 if the user canceled the operation. The function returns NULL
- to indicate an error. */
-char *
-simple_pwquery (const char *cacheid,
- const char *tryagain,
- const char *prompt,
- const char *description,
- int *errorcode)
-{
- int fd = -1;
- int nread;
- char *result = NULL;
- char *pw = NULL;
- char *p;
- int rc, i;
-
- rc = agent_open (&fd);
- if (rc)
- goto leave;
-
- if (!cacheid)
- cacheid = "X";
- if (!tryagain)
- tryagain = "X";
- if (!prompt)
- prompt = "X";
- if (!description)
- description = "X";
-
- {
- char *line;
- /* We allocate 3 times the needed space so that there is enough
- space for escaping. */
- line = spwq_malloc (15
- + 3*strlen (cacheid) + 1
- + 3*strlen (tryagain) + 1
- + 3*strlen (prompt) + 1
- + 3*strlen (description) + 1
- + 2);
- if (!line)
- {
- rc = SPWQ_OUT_OF_CORE;
- goto leave;
- }
- strcpy (line, "GET_PASSPHRASE ");
- p = line+15;
- p = copy_and_escape (p, cacheid);
- *p++ = ' ';
- p = copy_and_escape (p, tryagain);
- *p++ = ' ';
- p = copy_and_escape (p, prompt);
- *p++ = ' ';
- p = copy_and_escape (p, description);
- *p++ = '\n';
- rc = writen (fd, line, p - line);
- spwq_free (line);
- if (rc)
- goto leave;
- }
-
- /* get response */
- pw = spwq_secure_malloc (500);
- nread = readline (fd, pw, 499);
- if (nread < 0)
- {
- rc = -nread;
- goto leave;
- }
- if (nread < 3)
- {
- rc = SPWQ_PROTOCOL_ERROR;
- goto leave;
- }
-
- if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
- { /* we got a passphrase - convert it back from hex */
- size_t pwlen = 0;
-
- for (i=3; i < nread && hexdigitp (pw+i); i+=2)
- pw[pwlen++] = xtoi_2 (pw+i);
- pw[pwlen] = 0; /* make a C String */
- result = pw;
- pw = NULL;
- }
- else if (nread > 7 && !memcmp (pw, "ERR 111", 7)
- && (pw[7] == ' ' || pw[7] == '\n') )
- {
-#ifdef SPWQ_USE_LOGGING
- log_info (_("canceled by user\n") );
-#endif
- *errorcode = 0; /* canceled */
- }
- else
- {
-#ifdef SPWQ_USE_LOGGING
- log_error (_("problem with the agent\n"));
-#endif
- rc = SPWQ_ERR_RESPONSE;
- }
-
- leave:
- if (errorcode)
- *errorcode = rc;
- if (fd != -1)
- close (fd);
- if (pw)
- spwq_free (pw);
- return result;
-}
diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h
deleted file mode 100644
index 5947c42b5..000000000
--- a/common/simple-pwquery.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* simple-pwquery.c - A simple password query cleint for gpg-agent
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef SIMPLE_PWQUERY_H
-#define SIMPLE_PWQUERY_H
-
-#ifdef SIMPLE_PWQUERY_IMPLEMENTATION /* Begin configuration stuff. */
-
-/* Include whatever files you need. */
-#include <gcrypt.h>
-#include "../jnlib/logging.h"
-
-/* Try to write error message using the standard log mechanism. The
- current implementation requires that the HAVE_JNLIB_LOGGING is also
- defined. */
-#define SPWQ_USE_LOGGING 1
-
-/* Memory allocation functions used by the implementation. Note, that
- the returned value is expected to be freed with
- spwq_secure_free. */
-#define spwq_malloc(a) gcry_malloc (a)
-#define spwq_free(a) gcry_free (a)
-#define spwq_secure_malloc(a) gcry_malloc_secure (a)
-#define spwq_secure_free(a) gcry_free (a)
-
-
-#endif /*SIMPLE_PWQUERY_IMPLEMENTATION*/ /* End configuration stuff. */
-
-
-/* Ask the gpg-agent for a passphrase and present the user with a
- DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
- If a CACHEID is not NULL it is used to locate the passphrase in in
- the cache and store it under this ID. If ERRORCODE is not NULL it
- should point a variable receiving an errorcode; this errocode might
- be 0 if the user canceled the operation. The function returns NULL
- to indicate an error. */
-char *simple_pwquery (const char *cacheid,
- const char *tryagain,
- const char *prompt,
- const char *description,
- int *errorcode);
-
-
-#define SPWQ_OUT_OF_CORE 1
-#define SPWQ_IO_ERROR 2
-#define SPWQ_PROTOCOL_ERROR 3
-#define SPWQ_ERR_RESPONSE 4
-#define SPWQ_NO_AGENT 5
-#define SPWQ_SYS_ERROR 6
-#define SPWQ_GENERAL_ERROR 7
-
-#endif /*SIMPLE_PWQUERY_H*/
diff --git a/common/sysutils.c b/common/sysutils.c
deleted file mode 100644
index 6eb40b125..000000000
--- a/common/sysutils.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/* sysutils.c - system helpers
- * Copyright (C) 1998, 1999, 2000, 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef HAVE_STAT
-#include <sys/stat.h>
-#endif
-#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
- #include <asm/sysinfo.h>
- #include <asm/unistd.h>
-#endif
-#ifdef HAVE_SETRLIMIT
- #include <time.h>
- #include <sys/time.h>
- #include <sys/resource.h>
-#endif
-#include "util.h"
-#include "i18n.h"
-
-#include "sysutils.h"
-
-#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
-#warning using trap_unaligned
-static int
-setsysinfo(unsigned long op, void *buffer, unsigned long size,
- int *start, void *arg, unsigned long flag)
-{
- return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
-}
-
-void
-trap_unaligned(void)
-{
- unsigned int buf[2];
-
- buf[0] = SSIN_UACPROC;
- buf[1] = UAC_SIGBUS | UAC_NOPRINT;
- setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
-}
-#else
-void
-trap_unaligned(void)
-{ /* dummy */
-}
-#endif
-
-
-int
-disable_core_dumps (void)
-{
- #ifdef HAVE_DOSISH_SYSTEM
- return 0;
- #else
- #ifdef HAVE_SETRLIMIT
- struct rlimit limit;
-
- limit.rlim_cur = 0;
- limit.rlim_max = 0;
- if( !setrlimit( RLIMIT_CORE, &limit ) )
- return 0;
- if( errno != EINVAL && errno != ENOSYS )
- log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
- #endif
- return 1;
- #endif
-}
-
-
-
-/* Return a string which is used as a kind of process ID */
-const byte *
-get_session_marker( size_t *rlen )
-{
- static byte marker[SIZEOF_UNSIGNED_LONG*2];
- static int initialized;
-
- if ( !initialized ) {
- volatile ulong aa, bb; /* we really want the uninitialized value */
- ulong a, b;
-
- initialized = 1;
- /* also this marker is guessable it is not easy to use this
- * for a faked control packet because an attacker does not
- * have enough control about the time the verification does
- * take place. Of course, we can add just more random but
- * than we need the random generator even for verification
- * tasks - which does not make sense. */
- a = aa ^ (ulong)getpid();
- b = bb ^ (ulong)time(NULL);
- memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
- memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
- }
- *rlen = sizeof(marker);
- return marker;
-}
-
-
-#if 0 /* not yet needed */
-int
-check_permissions(const char *path,int extension,int checkonly)
-{
-#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
- char *tmppath;
- struct stat statbuf;
- int ret=1;
- int isdir=0;
-
- if(opt.no_perm_warn)
- return 0;
-
- if(extension && path[0]!=DIRSEP_C)
- {
- if(strchr(path,DIRSEP_C))
- tmppath=make_filename(path,NULL);
- else
- tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
- }
- else
- tmppath=m_strdup(path);
-
- /* It's okay if the file doesn't exist */
- if(stat(tmppath,&statbuf)!=0)
- {
- ret=0;
- goto end;
- }
-
- isdir=S_ISDIR(statbuf.st_mode);
-
- /* Per-user files must be owned by the user. Extensions must be
- owned by the user or root. */
- if((!extension && statbuf.st_uid != getuid()) ||
- (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
- {
- if(!checkonly)
- log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
- isdir?"directory":extension?"extension":"file",path);
- goto end;
- }
-
- /* This works for both directories and files - basically, we don't
- care what the owner permissions are, so long as the group and
- other permissions are 0 for per-user files, and non-writable for
- extensions. */
- if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
- (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
- {
- char *dir;
-
- /* However, if the directory the directory/file is in is owned
- by the user and is 700, then this is not a problem.
- Theoretically, we could walk this test up to the root
- directory /, but for the sake of sanity, I'm stopping at one
- level down. */
-
- dir= make_dirname (tmppath);
- if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
- S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
- {
- xfree (dir);
- ret=0;
- goto end;
- }
-
- m_free(dir);
-
- if(!checkonly)
- log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
- isdir?"directory":extension?"extension":"file",path);
- goto end;
- }
-
- ret=0;
-
- end:
- m_free(tmppath);
-
- return ret;
-
-#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
-
- return 0;
-}
-#endif
diff --git a/common/sysutils.h b/common/sysutils.h
deleted file mode 100644
index f2054d468..000000000
--- a/common/sysutils.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* sysutils.h - System utility functions for Gnupg
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_SYSUTILS_H
-#define GNUPG_COMMON_SYSUTILS_H
-
-void trap_unaligned (void);
-int disable_core_dumps (void);
-const unsigned char *get_session_marker (size_t *rlen);
-int check_permissions (const char *path,int extension,int checkonly);
-
-
-#endif /*GNUPG_COMMON_SYSUTILS_H*/
diff --git a/common/ttyio.c b/common/ttyio.c
deleted file mode 100644
index fd748009e..000000000
--- a/common/ttyio.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/* ttyio.c - tty i/O functions
- * Copyright (C) 1998,1999,2000,2001,2002,2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#ifdef HAVE_TCGETATTR
-#include <termios.h>
-#else
-#ifdef HAVE_TERMIO_H
-/* simulate termios with termio */
-#include <termio.h>
-#define termios termio
-#define tcsetattr ioctl
-#define TCSAFLUSH TCSETAF
-#define tcgetattr(A,B) ioctl(A,TCGETA,B)
-#define HAVE_TCGETATTR
-#endif
-#endif
-#ifdef __MINGW32__ /* use the odd Win32 functions */
-#include <windows.h>
-#ifdef HAVE_TCGETATTR
-#error mingw32 and termios
-#endif
-#endif
-#include <errno.h>
-#include <ctype.h>
-#include "util.h"
-#include "memory.h"
-#include "ttyio.h"
-
-#define CONTROL_D ('D' - 'A' + 1)
-
-#ifdef __MINGW32__ /* use the odd Win32 functions */
-static struct {
- HANDLE in, out;
-} con;
-#define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
- |ENABLE_PROCESSED_INPUT )
-#define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
-#define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
-
-#else /* yeah, we have a real OS */
-static FILE *ttyfp = NULL;
-#endif
-
-static int initialized;
-static int last_prompt_len;
-static int batchmode;
-static int no_terminal;
-
-#ifdef HAVE_TCGETATTR
- static struct termios termsave;
- static int restore_termios;
-#endif
-
-
-
-/* This is a wrapper around ttyname so that we can use it even when
- the standard streams are redirected. It figures the name out the
- first time and returns it in a statically allocated buffer. */
-const char *
-tty_get_ttyname (void)
-{
- static char *name;
-
- /* On a GNU system ctermid() always return /dev/tty, so this does
- not make much sense - however if it is ever changed we do the
- Right Thing now. */
-#ifdef HAVE_CTERMID
- static int got_name;
-
- if (!got_name)
- {
- const char *s;
- s = ctermid (NULL);
- if (s)
- name = strdup (s);
- got_name = 1;
- }
-#endif
- /* Assume the staandrd tty on memory error or when tehre is no
- certmid. */
- return name? name : "/dev/tty";
-}
-
-
-
-#ifdef HAVE_TCGETATTR
-static void
-cleanup(void)
-{
- if( restore_termios ) {
- restore_termios = 0; /* do it prios in case it is interrupted again */
- if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
- log_error("tcsetattr() failed: %s\n", strerror(errno) );
- }
-}
-#endif
-
-static void
-init_ttyfp(void)
-{
- if( initialized )
- return;
-
-#if defined(__MINGW32__)
- {
- SECURITY_ATTRIBUTES sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- &sa, OPEN_EXISTING, 0, 0 );
- if( con.out == INVALID_HANDLE_VALUE )
- log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
- memset(&sa, 0, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- &sa, OPEN_EXISTING, 0, 0 );
- if( con.in == INVALID_HANDLE_VALUE )
- log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
- }
- SetConsoleMode(con.in, DEF_INPMODE );
- SetConsoleMode(con.out, DEF_OUTMODE );
-
-#elif defined(__EMX__)
- ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
-#else
- ttyfp = batchmode? stderr : fopen (tty_get_ttyname (), "r+");
- if( !ttyfp ) {
- log_error("cannot open `%s': %s\n", tty_get_ttyname (),
- strerror(errno) );
- exit(2);
- }
-#endif
-#ifdef HAVE_TCGETATTR
- atexit( cleanup );
-#endif
- initialized = 1;
-}
-
-
-int
-tty_batchmode( int onoff )
-{
- int old = batchmode;
- if( onoff != -1 )
- batchmode = onoff;
- return old;
-}
-
-int
-tty_no_terminal(int onoff)
-{
- int old = no_terminal;
- no_terminal = onoff ? 1 : 0;
- return old;
-}
-
-void
-tty_printf( const char *fmt, ... )
-{
- va_list arg_ptr;
-
- if (no_terminal)
- return;
-
- if( !initialized )
- init_ttyfp();
-
- va_start( arg_ptr, fmt ) ;
-#ifdef __MINGW32__
- {
- char *buf = NULL;
- int n;
- DWORD nwritten;
-
- n = vasprintf(&buf, fmt, arg_ptr);
- if( !buf )
- log_bug("vasprintf() failed\n");
-
- if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
- log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
- if( n != nwritten )
- log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten );
- last_prompt_len += n;
- xfree (buf);
- }
-#else
- last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
- fflush(ttyfp);
-#endif
- va_end(arg_ptr);
-}
-
-
-/****************
- * Print a string, but filter all control characters out.
- */
-void
-tty_print_string( byte *p, size_t n )
-{
- if (no_terminal)
- return;
-
- if( !initialized )
- init_ttyfp();
-
-#ifdef __MINGW32__
- /* not so effective, change it if you want */
- for( ; n; n--, p++ )
- if( iscntrl( *p ) ) {
- if( *p == '\n' )
- tty_printf("\\n");
- else if( !*p )
- tty_printf("\\0");
- else
- tty_printf("\\x%02x", *p);
- }
- else
- tty_printf("%c", *p);
-#else
- for( ; n; n--, p++ )
- if( iscntrl( *p ) ) {
- putc('\\', ttyfp);
- if( *p == '\n' )
- putc('n', ttyfp);
- else if( !*p )
- putc('0', ttyfp);
- else
- fprintf(ttyfp, "x%02x", *p );
- }
- else
- putc(*p, ttyfp);
-#endif
-}
-
-void
-tty_print_utf8_string2( byte *p, size_t n, size_t max_n )
-{
- size_t i;
- char *buf;
-
- if (no_terminal)
- return;
-
- /* we can handle plain ascii simpler, so check for it first */
- for(i=0; i < n; i++ ) {
- if( p[i] & 0x80 )
- break;
- }
- if( i < n ) {
- buf = utf8_to_native( p, n, 0 );
- if( max_n && (strlen( buf ) > max_n )) {
- buf[max_n] = 0;
- }
- /*(utf8 conversion already does the control character quoting)*/
- tty_printf("%s", buf );
- xfree( buf );
- }
- else {
- if( max_n && (n > max_n) ) {
- n = max_n;
- }
- tty_print_string( p, n );
- }
-}
-
-void
-tty_print_utf8_string( byte *p, size_t n )
-{
- tty_print_utf8_string2( p, n, 0 );
-}
-
-
-static char *
-do_get( const char *prompt, int hidden )
-{
- char *buf;
-#ifndef __riscos__
- byte cbuf[1];
-#endif
- int c, n, i;
-
- if( batchmode ) {
- log_error("Sorry, we are in batchmode - can't get input\n");
- exit(2);
- }
-
- if (no_terminal) {
- log_error("Sorry, no terminal at all requested - can't get input\n");
- exit(2);
- }
-
- if( !initialized )
- init_ttyfp();
-
- last_prompt_len = 0;
- tty_printf( "%s", prompt );
- buf = xmalloc((n=50));
- i = 0;
-
-#ifdef __MINGW32__ /* windoze version */
- if( hidden )
- SetConsoleMode(con.in, HID_INPMODE );
-
- for(;;) {
- DWORD nread;
-
- if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
- log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
- if( !nread )
- continue;
- if( *cbuf == '\n' )
- break;
-
- if( !hidden )
- last_prompt_len++;
- c = *cbuf;
- if( c == '\t' )
- c = ' ';
- else if( c > 0xa0 )
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- else if( iscntrl(c) )
- continue;
- if( !(i < n-1) ) {
- n += 50;
- buf = xrealloc (buf, n);
- }
- buf[i++] = c;
- }
-
- if( hidden )
- SetConsoleMode(con.in, DEF_INPMODE );
-
-#elif defined(__riscos__)
- do {
- c = riscos_getchar();
- if (c == 0xa || c == 0xd) { /* Return || Enter */
- c = (int) '\n';
- } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
- if (i>0) {
- i--;
- if (!hidden) {
- last_prompt_len--;
- fputc(8, ttyfp);
- fputc(32, ttyfp);
- fputc(8, ttyfp);
- fflush(ttyfp);
- }
- } else {
- fputc(7, ttyfp);
- fflush(ttyfp);
- }
- continue;
- } else if (c == (int) '\t') { /* Tab */
- c = ' ';
- } else if (c > 0xa0) {
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- } else if (iscntrl(c)) {
- continue;
- }
- if(!(i < n-1)) {
- n += 50;
- buf = xrealloc (buf, n);
- }
- buf[i++] = c;
- if (!hidden) {
- last_prompt_len++;
- fputc(c, ttyfp);
- fflush(ttyfp);
- }
- } while (c != '\n');
- i = (i>0) ? i-1 : 0;
-#else /* unix version */
- if( hidden ) {
-#ifdef HAVE_TCGETATTR
- struct termios term;
-
- if( tcgetattr(fileno(ttyfp), &termsave) )
- log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
- restore_termios = 1;
- term = termsave;
- term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
- if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
- log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
-#endif
- }
-
- /* fixme: How can we avoid that the \n is echoed w/o disabling
- * canonical mode - w/o this kill_prompt can't work */
- while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
- if( !hidden )
- last_prompt_len++;
- c = *cbuf;
- if( c == CONTROL_D )
- log_info("control d found\n");
- if( c == '\t' )
- c = ' ';
- else if( c > 0xa0 )
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- else if( iscntrl(c) )
- continue;
- if( !(i < n-1) ) {
- n += 50;
- buf = xrealloc (buf, n );
- }
- buf[i++] = c;
- }
- if( *cbuf != '\n' ) {
- buf[0] = CONTROL_D;
- i = 1;
- }
-
-
- if( hidden ) {
-#ifdef HAVE_TCGETATTR
- if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
- log_error("tcsetattr() failed: %s\n", strerror(errno) );
- restore_termios = 0;
-#endif
- }
-#endif /* end unix version */
- buf[i] = 0;
- return buf;
-}
-
-
-char *
-tty_get( const char *prompt )
-{
- return do_get( prompt, 0 );
-}
-
-char *
-tty_get_hidden( const char *prompt )
-{
- return do_get( prompt, 1 );
-}
-
-
-void
-tty_kill_prompt()
-{
- if ( no_terminal )
- return;
-
- if( !initialized )
- init_ttyfp();
-
- if( batchmode )
- last_prompt_len = 0;
- if( !last_prompt_len )
- return;
-#ifdef __MINGW32__
- tty_printf("\r%*s\r", last_prompt_len, "");
-#else
- {
- int i;
- putc('\r', ttyfp);
- for(i=0; i < last_prompt_len; i ++ )
- putc(' ', ttyfp);
- putc('\r', ttyfp);
- fflush(ttyfp);
- }
-#endif
- last_prompt_len = 0;
-}
-
-
-int
-tty_get_answer_is_yes( const char *prompt )
-{
- int yes;
- char *p = tty_get( prompt );
- tty_kill_prompt();
- yes = answer_is_yes(p);
- xfree(p);
- return yes;
-}
diff --git a/common/ttyio.h b/common/ttyio.h
deleted file mode 100644
index b3ca7dcaf..000000000
--- a/common/ttyio.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* ttyio.h
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-#ifndef GNUPG_COMMON_TTYIO_H
-#define GNUPG_COMMON_TTYIO_H
-
-const char *tty_get_ttyname (void);
-int tty_batchmode (int onoff);
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
-void tty_printf (const char *fmt, ... ) __attribute__ ((format (printf,1,2)));
-#else
-void tty_printf (const char *fmt, ... );
-#endif
-void tty_print_string (unsigned char *p, size_t n);
-void tty_print_utf8_string (unsigned char *p, size_t n);
-void tty_print_utf8_string2 (unsigned char *p, size_t n, size_t max_n);
-char *tty_get (const char *prompt);
-char *tty_get_hidden (const char *prompt);
-void tty_kill_prompt (void);
-int tty_get_answer_is_yes (const char *prompt);
-int tty_no_terminal (int onoff);
-
-
-#endif /*GNUPG_COMMON_TTYIO_H*/
diff --git a/common/util.h b/common/util.h
deleted file mode 100644
index 045851481..000000000
--- a/common/util.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* util.h - Utility functions for Gnupg
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_COMMON_UTIL_H
-#define GNUPG_COMMON_UTIL_H
-
-#include <gcrypt.h> /* We need this for the memory function protos. */
-#include <time.h> /* We need time_t. */
-#include <gpg-error.h> /* we need gpg-error_t. */
-
-/* to pass hash functions to libksba we need to cast it */
-#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
-
-/* get all the stuff from jnlib */
-#include "../jnlib/logging.h"
-#include "../jnlib/argparse.h"
-#include "../jnlib/stringhelp.h"
-#include "../jnlib/mischelp.h"
-#include "../jnlib/strlist.h"
-#include "../jnlib/dotlock.h"
-#include "../jnlib/utf8conv.h"
-
-/* handy malloc macros - use only them */
-#define xtrymalloc(a) gcry_malloc ((a))
-#define xtrycalloc(a,b) gcry_calloc ((a),(b))
-#define xtryrealloc(a,b) gcry_realloc ((a),(b))
-#define xtrystrdup(a) gcry_strdup ((a))
-#define xfree(a) gcry_free ((a))
-
-#define xmalloc(a) gcry_xmalloc ((a))
-#define xmalloc_secure(a) gcry_xmalloc_secure ((a))
-#define xcalloc(a,b) gcry_xcalloc ((a),(b))
-#define xcalloc_secure(a,b) gcry_xcalloc_secure ((a),(b))
-#define xrealloc(a,b) gcry_xrealloc ((a),(b))
-#define xstrdup(a) gcry_xstrdup ((a))
-
-/*-- maperror.c --*/
-int map_ksba_err (int err);
-int map_gcry_err (int err);
-int map_kbx_err (int err);
-gpg_error_t map_assuan_err (int err);
-int map_to_assuan_status (int rc);
-
-/*-- gettime.c --*/
-time_t gnupg_get_time (void);
-void gnupg_set_time (time_t newtime, int freeze);
-int gnupg_faked_time_p (void);
-u32 make_timestamp (void);
-u32 scan_isodatestr (const char *string);
-u32 add_days_to_timestamp (u32 stamp, u16 days);
-const char *strtimevalue (u32 stamp);
-const char *strtimestamp (u32 stamp); /* GMT */
-const char *asctimestamp (u32 stamp); /* localized */
-
-/*-- signal.c --*/
-void gnupg_init_signals (int mode, void (*fast_cleanup)(void));
-void gnupg_pause_on_sigusr (int which);
-void gnupg_block_all_signals (void);
-void gnupg_unblock_all_signals (void);
-
-/*-- yesno.c --*/
-int answer_is_yes (const char *s);
-int answer_is_yes_no_default (const char *s, int def_answer);
-int answer_is_yes_no_quit (const char *s);
-
-
-/*-- miscellaneous.c --*/
-const char *print_fname_stdout (const char *s);
-const char *print_fname_stdin (const char *s);
-void print_string (FILE *fp, const byte *p, size_t n, int delim);
-void print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim);
-void print_utf8_string (FILE *fp, const byte *p, size_t n);
-char *make_printable_string (const byte *p, size_t n, int delim);
-
-int is_file_compressed (const char *s, int *ret_rc);
-
-
-/*-- replacement functions from funcname.c --*/
-#if !HAVE_VASPRINTF
-#include <stdarg.h>
-int vasprintf (char **result, const char *format, va_list *args);
-int asprintf (char **result, const char *format, ...);
-#endif
-
-
-
-/*-- some macros to replace ctype ones and avoid locale problems --*/
-#define spacep(p) (*(p) == ' ' || *(p) == '\t')
-#define digitp(p) (*(p) >= '0' && *(p) <= '9')
-#define hexdigitp(a) (digitp (a) \
- || (*(a) >= 'A' && *(a) <= 'F') \
- || (*(a) >= 'a' && *(a) <= 'f'))
-/* the atoi macros assume that the buffer has only valid digits */
-#define atoi_1(p) (*(p) - '0' )
-#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
-#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-
-
-
-#endif /*GNUPG_COMMON_UTIL_H*/
diff --git a/common/vasprintf.c b/common/vasprintf.c
deleted file mode 100644
index 2af2d3a20..000000000
--- a/common/vasprintf.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Like vsprintf but provides a pointer to malloc'd storage, which must
- be freed by the caller.
- Copyright (C) 1994, 2002 Free Software Foundation, Inc.
-
-This file is part of the libiberty library.
-Libiberty is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-Libiberty 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
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with libiberty; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#ifdef TEST
-int global_total_width;
-#endif
-
-int
-vasprintf (char **result, const char *format, va_list *args)
-{
- const char *p = format;
- /* Add one to make sure that it is never zero, which might cause malloc
- to return NULL. */
- int total_width = strlen (format) + 1;
- va_list ap;
-
-#ifdef va_copy
- va_copy (ap, args);
-#else
-#ifdef __va_copy
- __va_copy (ap, args);
-#else
- memcpy (&ap, args, sizeof (va_list));
-#endif /* __va_copy */
-#endif /* va_copy */
-
- while (*p != '\0')
- {
- if (*p++ == '%')
- {
- while (strchr ("-+ #0", *p))
- ++p;
- if (*p == '*')
- {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else
- total_width += strtoul (p, (char**)&p, 10);
- if (*p == '.')
- {
- ++p;
- if (*p == '*')
- {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else
- total_width += strtoul (p, (char**)&p, 10);
- }
- while (strchr ("hlL", *p))
- ++p;
- /* Should be big enough for any format specifier except %s
- and floats. */
- total_width += 30;
- switch (*p)
- {
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- case 'c':
- (void) va_arg (ap, int);
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- (void) va_arg (ap, double);
- /* Since an ieee double can have an exponent of 307, we'll
- make the buffer wide enough to cover the gross case. */
- total_width += 307;
- break;
- case 's':
- {
- char *tmp = va_arg (ap, char *);
- if (tmp)
- total_width += strlen (tmp);
- else /* in case the vsprintf does prints a text */
- total_width += 25; /* e.g. "(null pointer reference)" */
- }
- break;
- case 'p':
- case 'n':
- (void) va_arg (ap, char *);
- break;
- }
- }
- }
-#ifdef TEST
- global_total_width = total_width;
-#endif
- *result = malloc (total_width);
- if (*result != NULL)
- return vsprintf (*result, format, *args);
- else
- return 0;
-}
-
-
-int
-asprintf (char **buf, const char *fmt, ...)
-{
- int status;
- va_list ap;
-
- va_start (ap, fmt);
- status = vasprintf (buf, fmt, ap);
- va_end (ap);
- return status;
-}
-
-
-#ifdef TEST
-void
-checkit (const char* format, ...)
-{
- va_list args;
- char *result;
-
- va_start (args, format);
- vasprintf (&result, format, args);
- if (strlen (result) < global_total_width)
- printf ("PASS: ");
- else
- printf ("FAIL: ");
- printf ("%d %s\n", global_total_width, result);
-}
-
-int
-main (void)
-{
- checkit ("%d", 0x12345678);
- checkit ("%200d", 5);
- checkit ("%.300d", 6);
- checkit ("%100.150d", 7);
- checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
-777777777777777777333333333333366666666666622222222222777777777777733333");
- checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
-}
-#endif /* TEST */
diff --git a/common/yesno.c b/common/yesno.c
deleted file mode 100644
index 2a96b4e5d..000000000
--- a/common/yesno.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* yesno.c - Yes/No questions
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "i18n.h"
-#include "util.h"
-
-int
-answer_is_yes_no_default( const char *s, int def_answer )
-{
- const char *long_yes = _("yes");
- const char *short_yes = _("yY");
- const char *long_no = _("no");
- const char *short_no = _("nN");
-
- /* Note: we have to use the local dependent strcasecmp here */
- if( !strcasecmp(s, long_yes ) )
- return 1;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- /* test for no strings to catch ambiguities for the next test */
- if( !strcasecmp(s, long_no ) )
- return 0;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- /* test for the english version (for those who are used to type yes) */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- return def_answer;
-}
-
-int
-answer_is_yes( const char *s )
-{
- return answer_is_yes_no_default(s,0);
-}
-
-/****************
- * Return 1 for yes, -1 for quit, or 0 for no
- */
-int
-answer_is_yes_no_quit( const char *s )
-{
- const char *long_yes = _("yes");
- const char *long_no = _("no");
- const char *long_quit = _("quit");
- const char *short_yes = _("yY");
- const char *short_no = _("nN");
- const char *short_quit = _("qQ");
-
- /* Note: We have to use the locale dependent strcasecmp */
- if( !strcasecmp(s, long_no ) )
- return 0;
- if( !strcasecmp(s, long_yes ) )
- return 1;
- if( !strcasecmp(s, long_quit ) )
- return -1;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- if( *s && strchr( short_quit, *s ) && !s[1] )
- return -1;
- /* but not here */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( !ascii_strcasecmp(s, "quit" ) )
- return -1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- if( *s && strchr( "qQ", *s ) && !s[1] )
- return -1;
- return 0;
-}
diff --git a/scd/ChangeLog b/scd/ChangeLog
deleted file mode 100644
index ad4b0518c..000000000
--- a/scd/ChangeLog
+++ /dev/null
@@ -1,242 +0,0 @@
-2003-07-31 Werner Koch <wk@gnupg.org>
-
- * Makefile.am (scdaemon_LDADD): Added INTLLIBS.
-
-2003-07-28 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (do_setattr): Change implementation. Allow all
- useful DOs.
-
-2003-07-27 Werner Koch <wk@gnupg.org>
-
- Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
-
-2003-07-24 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (do_learn_status): Print more status information.
- (app_select_openpgp): Store the card version.
- (store_fpr): Add argument card_version and fix DOs for old cards.
- (app_openpgp_storekey): Likewise.
-
-2003-07-23 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_pkauth): New.
- (cmd_setdata): Check whether data was given at all to avoid
- passing 0 to malloc.
-
- * app.c (app_auth): New.
- * app-openpgp.c (do_auth): New.
-
-2003-07-22 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_passwd): New.
- * app.c (app_change_pin): New.
- * app-openpgp.c (do_change_pin): New.
- * iso7816.c (iso7816_reset_retry_counter): Implemented.
-
- * sc-investigate.c (main): New option --gen-random.
- * iso7816.c (iso7816_get_challenge): Don't create APDUs with a
- length larger than 255.
-
-2003-07-17 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_random): New command RANDOM.
-
- * iso7816.c (map_sw): New. Use it in this file to return
- meaningful error messages. Changed all public fucntions to return
- a gpg_error_t.
- (iso7816_change_reference_data): New.
- * apdu.c (apdu_open_reader): Use faked status words for soem
- system errors.
-
-2003-07-16 Werner Koch <wk@gnupg.org>
-
- * apdu.c (apdu_send_simple): Use apdu_send_le so that we can
- specify not to send Le as it should be.
-
-2003-07-15 Werner Koch <wk@gnupg.org>
-
- * Makefile.am: Add sc-copykeys program.
- * sc-copykeys.c: New.
- * app-openpgp.c (app_openpgp_storekey): New.
- (app_openpgp_cardinfo): New.
- (count_bits): New.
- (store_fpr): And use it here to get the actual length in bit.
-
-2003-07-03 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (do_setattr): Add setting of the URL.
- (app_select_openpgp): Dump card data only in very verbose mode.
- (do_decipher): New.
-
-2003-07-02 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (get_sig_counter): New.
- (do_sign): Print the signature counter and enable the PIN callback.
- (do_genkey): Implement the PIN callback.
-
-2003-07-01 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (store_fpr): Fixed fingerprint calculation.
-
-2003-06-26 Werner Koch <wk@gnupg.org>
-
- * app-openpgp.c (find_tlv): Fixed length header parsing.
-
- * app.c (app_genkey): New.
- * command.c (cmd_genkey): New.
-
-2003-06-25 Werner Koch <wk@gnupg.org>
-
- * command.c (percent_plus_unescape): New.
- (cmd_setattr): New.
-
-2003-06-24 Werner Koch <wk@gnupg.org>
-
- * command.c (send_status_info): New.
-
- * app-openpgp.c (app_select_openpgp): Replace SLOT arg by APP arg
- and setup the function pointers in APP on success. Changed callers.
- * app.c: New.
- * app-common.h: New.
- * scdaemon.h (APP): New type to handle applications.
- (server_control_s): Add an APP context field.
-
- * command.c (cmd_serialno): Handle applications.
- (cmd_pksign): Ditto.
- (cmd_pkdecrypt): Ditto.
- (reset_notify): Ditto.
- (cmd_learn): For now return error for application contexts.
- (cmd_readcert): Ditto.
- (cmd_readkey): Ditto.
-
-2003-06-04 Werner Koch <wk@gnupg.org>
-
- * card.c (map_sc_err): Renamed gpg_make_err to gpg_err_make.
-
- Renamed error codes from INVALID to INV and removed _ERROR suffixes.
-
-2003-06-03 Werner Koch <wk@gnupg.org>
-
- Changed all error codes in all files to the new libgpg-error scheme.
-
- * scdaemon.h: Include gpg-error.h and errno.h
- * card.c (map_sc_err): Use unknown for the error source.
- * Makefile.am: Link with libgpg-error
-
-2003-05-14 Werner Koch <wk@gnupg.org>
-
- * atr.c, atr.h: New.
- * sc-investigate.c: Dump the ATR in a human readable format.
-
-2003-05-08 Werner Koch <wk@gnupg.org>
-
- * scdaemon.h (DBG_CARD_IO_VALUE): New.
-
- * sc-investigate.c: New.
- * scdaemon.c (main): Removed --print-atr option.
-
- * iso7816.c, iso7816.h, app-openpgp.c: New.
-
-2003-04-29 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c: New options --print-atr and --reader-port
- * apdu.c, apdu.h: New
-
- * card.c, card-p15.c, card-dinsig.c: Allow build without OpenSC.
-
- * Makefile.am (LDFLAGS): Removed.
-
- * command.c (register_commands): Adjusted for new Assuan semantics.
-
-2002-08-21 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c (main): New option --daemon so that the program is
- not accidently started in the background.
-
-2002-08-16 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c: Include i18n.h.
-
- * card-common.h (struct p15_private_s): Forward declaration. Add
- it to card_ctx_s.
- * card.c (card_close): Make sure private data is released.
- (card_enum_certs): New.
- * card-p15.c (p15_release_private_data): New.
- (init_private_data): New to work around an OpenSC weirdness.
- (p15_enum_keypairs): Do an OpenSC get_objects only once.
- (p15_enum_certs): New.
- (card_p15_bind): Bind new function.
- * command.c (cmd_learn): Return information about the certificates.
-
-2002-08-09 Werner Koch <wk@gnupg.org>
-
- * card.c (card_get_serial_and_stamp): Use the tokeinfo serial
- number as a fallback. Add a special prefix for serial numbers.
-
-2002-07-30 Werner Koch <wk@gnupg.org>
-
- Changes to cope with OpenSC 0.7.0:
-
- * card.c: Removed the check for the packed opensc version.
- Changed include file names of opensc.
- (map_sc_err): Adjusted error codes for new opensc version.
- * card-p15.c: Changed include filename of opensc.
- * card-dinsig.c: Ditto.
-
- * card-p15.c (p15_decipher): Add flags argument to OpenSC call.
-
-2002-07-24 Werner Koch <wk@gnupg.org>
-
- * card.c (find_simple_tlv, find_iccsn): New.
- (card_get_serial_and_stamp): Improved serial number parser.
-
-2002-06-27 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
-
-2002-06-15 Werner Koch <wk@gnupg.org>
-
- * card-dinsig.c: Documented some stuff from the DIN norm.
-
-2002-04-15 Werner Koch <wk@gnupg.org>
-
- * command.c (cmd_pksign, cmd_pkdecrypt): Use a copy of the key ID.
-
-2002-04-12 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c: New option --debug-sc N.
- * card.c (card_open): set it here.
-
- * card-p15.c (p15_prepare_key): Factored out common code from ...
- (p15_sign, p15_decipher): here and made the decryption work the
- regular way.
-
-2002-04-10 Werner Koch <wk@gnupg.org>
-
- * card.c (card_open): Return immediately when no reader is available.
-
-2002-03-27 Werner Koch <wk@gnupg.org>
-
- * card.c (card_open, card_close): Adjusted for changes in OpenSC.
-
-2002-03-10 Werner Koch <wk@gnupg.org>
-
- * card-p15.c, card-dinsig.c, card-common.h: New.
- * card.c: Factored most code out to the new modules, so that we
- can better support different types of card applications.
-
-2002-01-26 Werner Koch <wk@gnupg.org>
-
- * scdaemon.c scdaemon.h, command.c: New. Based on the code from
- the gpg-agent.
-
- Copyright 2002 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/scd/Makefile.am b/scd/Makefile.am
deleted file mode 100644
index 0771beb60..000000000
--- a/scd/Makefile.am
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright (C) 2002, 2003 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-## Process this file with automake to produce Makefile.in
-
-localedir = $(datadir)/locale
-INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
-
-bin_PROGRAMS = scdaemon sc-investigate sc-copykeys
-
-AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \
- $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS)
-
-scdaemon_SOURCES = \
- scdaemon.c scdaemon.h \
- command.c card.c \
- card-common.h \
- card-p15.c card-dinsig.c \
- apdu.c apdu.h \
- iso7816.c iso7816.h \
- app.c app-common.h \
- app-openpgp.c
-
-scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
- $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \
- -lgpg-error @INTLLIBS@ -ldl
-
-sc_investigate_SOURCES = \
- sc-investigate.c scdaemon.h \
- apdu.c apdu.h \
- iso7816.c iso7816.h \
- app.c app-common.h \
- app-openpgp.c \
- atr.c atr.h
-
-sc_investigate_LDADD = \
- ../jnlib/libjnlib.a ../common/libcommon.a \
- $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl
-
-
-sc_copykeys_SOURCES = \
- sc-copykeys.c scdaemon.h \
- apdu.c apdu.h \
- iso7816.c iso7816.h \
- app.c app-common.h \
- app-openpgp.c \
- atr.c atr.h
-
-sc_copykeys_LDADD = \
- ../jnlib/libjnlib.a ../common/libcommon.a \
- ../common/libsimple-pwquery.a \
- $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl
-
-
-
-
-
diff --git a/scd/apdu.c b/scd/apdu.c
deleted file mode 100644
index 6fec584b9..000000000
--- a/scd/apdu.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* apdu.c - ISO 7816 APDU functions and low level I/O
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <assert.h>
-
-#include "scdaemon.h"
-#include "apdu.h"
-
-#define HAVE_CTAPI 1
-
-#define MAX_READER 4 /* Number of readers we support concurrently. */
-#define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for
- insertion of the card (1 = don't wait). */
-
-
-
-/* A global table to keep track of active readers. */
-static struct {
- int used; /* True if slot is used. */
- unsigned short port; /* port number0 = unused, 1 - dev/tty */
- int status;
- unsigned char atr[33];
- size_t atrlen;
-} reader_table[MAX_READER];
-
-
-/* ct API function pointer. */
-static char (*CT_init) (unsigned short ctn, unsigned short Pn);
-static char (*CT_data) (unsigned short ctn, unsigned char *dad,
- unsigned char *sad, unsigned short lc,
- unsigned char *cmd, unsigned short *lr,
- unsigned char *rsp);
-static char (*CT_close) (unsigned short ctn);
-
-
-
-
-
-/*
- Helper
- */
-
-
-/* Find an unused reader slot for PORT and put it into the reader
- table. Return -1 on error or the index into the reader table. */
-static int
-new_reader_slot (int port)
-{
- int i, reader = -1;
-
- if (port < 0 || port > 0xffff)
- {
- log_error ("new_reader_slot: invalid port %d requested\n", port);
- return -1;
- }
-
- for (i=0; i < MAX_READER; i++)
- {
- if (reader_table[i].used && reader_table[i].port == port)
- {
- log_error ("new_reader_slot: requested port %d already in use\n",
- reader);
- return -1;
- }
- else if (!reader_table[i].used && reader == -1)
- reader = i;
- }
- if (reader == -1)
- {
- log_error ("new_reader_slot: out of slots\n");
- return -1;
- }
- reader_table[reader].used = 1;
- reader_table[reader].port = port;
- return reader;
-}
-
-
-static void
-dump_reader_status (int reader)
-{
- log_info ("reader %d: %s\n", reader,
- reader_table[reader].status == 1? "Processor ICC present" :
- reader_table[reader].status == 0? "Memory ICC present" :
- "ICC not present" );
-
- if (reader_table[reader].status != -1)
- {
- log_info ("reader %d: ATR=", reader);
- log_printhex ("", reader_table[reader].atr,
- reader_table[reader].atrlen);
- }
-}
-
-
-
-#ifdef HAVE_CTAPI
-/*
- ct API Interface
- */
-
-static const char *
-ct_error_string (int err)
-{
- switch (err)
- {
- case 0: return "okay";
- case -1: return "invalid data";
- case -8: return "ct error";
- case -10: return "transmission error";
- case -11: return "memory allocation error";
- case -128: return "HTSI error";
- default: return "unknown CT-API error";
- }
-}
-
-/* Wait for the card in READER and activate it. Return -1 on error or
- 0 on success. */
-static int
-ct_activate_card (int reader)
-{
- int rc, count;
-
- for (count = 0; count < CARD_CONNECT_TIMEOUT; count++)
- {
- unsigned char dad[1], sad[1], cmd[11], buf[256];
- unsigned short buflen;
-
- if (count)
- sleep (1); /* FIXME: we should use a more reliable timer. */
-
- /* Check whether card has been inserted. */
- dad[0] = 1; /* Destination address: CT. */
- sad[0] = 2; /* Source address: Host. */
-
- cmd[0] = 0x20; /* Class byte. */
- cmd[1] = 0x13; /* Request status. */
- cmd[2] = 0x00; /* From kernel. */
- cmd[3] = 0x80; /* Return card's DO. */
- cmd[4] = 0x00;
-
- buflen = DIM(buf);
-
- rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf);
- if (rc || buflen < 2 || buf[buflen-2] != 0x90)
- {
- log_error ("ct_activate_card: can't get status of reader %d: %s\n",
- reader, ct_error_string (rc));
- return -1;
- }
-
- if (buf[0] == 0x05)
- { /* Connected, now activate the card. */
- dad[0] = 1; /* Destination address: CT. */
- sad[0] = 2; /* Source address: Host. */
-
- cmd[0] = 0x20; /* Class byte. */
- cmd[1] = 0x12; /* Request ICC. */
- cmd[2] = 0x01; /* From first interface. */
- cmd[3] = 0x01; /* Return card's ATR. */
- cmd[4] = 0x00;
-
- buflen = DIM(buf);
-
- rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf);
- if (rc || buflen < 2 || buf[buflen-2] != 0x90)
- {
- log_error ("ct_activate_card(%d): activation failed: %s\n",
- reader, ct_error_string (rc));
- return -1;
- }
-
- /* Store the type and the ATR. */
- if (buflen - 2 > DIM (reader_table[0].atr))
- {
- log_error ("ct_activate_card(%d): ATR too long\n", reader);
- return -1;
- }
-
- reader_table[reader].status = buf[buflen - 1];
- memcpy (reader_table[reader].atr, buf, buflen - 2);
- reader_table[reader].atrlen = buflen - 2;
- return 0;
- }
-
- }
-
- log_info ("ct_activate_card(%d): timeout waiting for card\n", reader);
- return -1;
-}
-
-
-/* Open a reader and return an internal handle for it. PORT is a
- non-negative value with the port number of the reader. USB readers
- do have port numbers starting at 32769. */
-static int
-open_ct_reader (int port)
-{
- int rc, reader;
-
- reader = new_reader_slot (port);
- if (reader == -1)
- return reader;
-
- rc = CT_init (reader, (unsigned short)port);
- if (rc)
- {
- log_error ("apdu_open_ct_reader failed on port %d: %s\n",
- port, ct_error_string (rc));
- reader_table[reader].used = 0;
- return -1;
- }
-
- rc = ct_activate_card (reader);
- if (rc)
- {
- reader_table[reader].used = 0;
- return -1;
- }
-
- dump_reader_status (reader);
- return reader;
-}
-
-
-/* Actually send the APDU of length APDULEN to SLOT and return a
- maximum of *BUFLEN data in BUFFER, the actual retruned size will be
- set to BUFLEN. Returns: CT API error code. */
-static int
-ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
- unsigned char *buffer, size_t *buflen)
-{
- int rc;
- unsigned char dad[1], sad[1];
- unsigned short ctbuflen;
-
- dad[0] = 0; /* Destination address: Card. */
- sad[0] = 2; /* Source address: Host. */
- ctbuflen = *buflen;
- if (DBG_CARD_IO)
- log_printhex (" CT_data:", apdu, apdulen);
- rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer);
- *buflen = ctbuflen;
-
- /* FIXME: map the errorcodes to GNUPG ones, so that they can be
- shared between CTAPI and PCSC. */
- return rc;
-}
-
-
-#endif /*HAVE_CTAPI*/
-
-
-#ifdef HAVE_PCSC
-/*
- PC/SC Interface
- */
-
-
-#endif /*HAVE_PCSC*/
-
-
-/*
- Driver Access
- */
-
-/* Open the reader and return an internal slot number or -1 on
- error. */
-int
-apdu_open_reader (int port)
-{
- static int ct_api_loaded;
-
- if (!ct_api_loaded)
- {
- void *handle;
-
- handle = dlopen ("libtowitoko.so", RTLD_LAZY);
- if (!handle)
- {
- log_error ("apdu_open_reader: failed to open driver: %s",
- dlerror ());
- return -1;
- }
- CT_init = dlsym (handle, "CT_init");
- CT_data = dlsym (handle, "CT_data");
- CT_close = dlsym (handle, "CT_close");
- if (!CT_init || !CT_data || !CT_close)
- {
- log_error ("apdu_open_reader: invalid driver\n");
- dlclose (handle);
- return -1;
- }
- ct_api_loaded = 1;
- }
- return open_ct_reader (port);
-}
-
-
-unsigned char *
-apdu_get_atr (int slot, size_t *atrlen)
-{
- char *buf;
-
- if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
- return NULL;
-
- buf = xtrymalloc (reader_table[slot].atrlen);
- if (!buf)
- return NULL;
- memcpy (buf, reader_table[slot].atr, reader_table[slot].atrlen);
- *atrlen = reader_table[slot].atrlen;
- return buf;
-}
-
-
-static const char *
-error_string (int slot, int rc)
-{
-#ifdef HAVE_CTAPI
- return ct_error_string (rc);
-#elif defined(HAVE_PCSC)
- return "?";
-#else
- return "?";
-#endif
-}
-
-
-/* Dispatcher for the actual send_apdu fucntion. */
-static int
-send_apdu (int slot, unsigned char *apdu, size_t apdulen,
- unsigned char *buffer, size_t *buflen)
-{
-#ifdef HAVE_CTAPI
- return ct_send_apdu (slot, apdu, apdulen, buffer, buflen);
-#elif defined(HAVE_PCSC)
- return SW_HOST_NO_DRIVER;
-#else
- return SW_HOST_NO_DRIVER;
-#endif
-}
-
-/* Send an APDU to the card in SLOT. The APDU is created from all
- given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1
- for LC won't sent this field and the data field; in this case DATA
- must also be passed as NULL. The return value is the status word
- or -1 for an invalid SLOT or other non card related error. If
- RETBUF is not NULL, it will receive an allocated buffer with the
- returned data. The length of that data will be put into
- *RETBUFLEN. The caller is reponsible for releasing the buffer even
- in case of errors. */
-int
-apdu_send_le(int slot, int class, int ins, int p0, int p1,
- int lc, const char *data, int le,
- unsigned char **retbuf, size_t *retbuflen)
-{
- unsigned char result[256+10]; /* 10 extra in case of bugs in the driver. */
- size_t resultlen = 256;
- unsigned char apdu[5+256+1];
- size_t apdulen;
- int rc, sw;
-
- if (DBG_CARD_IO)
- log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n",
- class, ins, p0, p1, lc, le);
-
- if (lc != -1 && (lc > 255 || lc < 0))
- return SW_WRONG_LENGTH;
- if (le != -1 && (le > 256 || le < 1))
- return SW_WRONG_LENGTH;
- if ((!data && lc != -1) || (data && lc == -1))
- return SW_HOST_INV_VALUE;
-
- apdulen = 0;
- apdu[apdulen++] = class;
- apdu[apdulen++] = ins;
- apdu[apdulen++] = p0;
- apdu[apdulen++] = p1;
- if (lc != -1)
- {
- apdu[apdulen++] = lc;
- memcpy (apdu+apdulen, data, lc);
- apdulen += lc;
- }
- if (le != -1)
- apdu[apdulen++] = le; /* Truncation is okay becuase 0 means 256. */
- assert (sizeof (apdu) >= apdulen);
- /* As safeguard don't pass any garbage from the stack to the driver. */
- memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
- rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
- if (rc || resultlen < 2)
- {
- log_error ("apdu_send_simple(%d) failed: %s\n",
- slot, error_string (slot, rc));
- return SW_HOST_INCOMPLETE_CARD_RESPONSE;
- }
- sw = (result[resultlen-2] << 8) | result[resultlen-1];
- /* store away the returned data but strip the statusword. */
- resultlen -= 2;
- if (DBG_CARD_IO)
- {
- log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen);
- if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
- }
-
- if (sw == SW_SUCCESS)
- {
- if (retbuf)
- {
- *retbuf = xtrymalloc (resultlen? resultlen : 1);
- if (!*retbuf)
- return SW_HOST_OUT_OF_CORE;
- *retbuflen = resultlen;
- memcpy (*retbuf, result, resultlen);
- }
- }
- else if ((sw & 0xff00) == SW_MORE_DATA)
- {
- unsigned char *p = NULL, *tmp;
- size_t bufsize = 4096;
-
- /* It is likely that we need to return much more data, so we
- start off with a large buffer. */
- if (retbuf)
- {
- *retbuf = p = xtrymalloc (bufsize);
- if (!*retbuf)
- return SW_HOST_OUT_OF_CORE;
- assert (resultlen < bufsize);
- memcpy (p, result, resultlen);
- p += resultlen;
- }
-
- do
- {
- int len = (sw & 0x00ff);
-
- log_debug ("apdu_send_simple(%d): %d more bytes available\n",
- slot, len);
- apdulen = 0;
- apdu[apdulen++] = class;
- apdu[apdulen++] = 0xC0;
- apdu[apdulen++] = 0;
- apdu[apdulen++] = 0;
- apdu[apdulen++] = 64; /* that is 256 bytes for Le */
- memset (apdu+apdulen, 0, sizeof (apdu) - apdulen);
- rc = send_apdu (slot, apdu, apdulen, result, &resultlen);
- if (rc || resultlen < 2)
- {
- log_error ("apdu_send_simple(%d) for get response failed: %s\n",
- slot, error_string (slot, rc));
- return SW_HOST_INCOMPLETE_CARD_RESPONSE;
- }
- sw = (result[resultlen-2] << 8) | result[resultlen-1];
- resultlen -= 2;
- if (DBG_CARD_IO)
- {
- log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen);
- if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA))
- log_printhex (" dump: ", result, resultlen);
- }
-
- if ((sw & 0xff00) == SW_MORE_DATA || sw == SW_SUCCESS)
- {
- if (retbuf)
- {
- if (p - *retbuf + resultlen > bufsize)
- {
- bufsize += resultlen > 4096? resultlen: 4096;
- tmp = xtryrealloc (*retbuf, bufsize);
- if (!tmp)
- return SW_HOST_OUT_OF_CORE;
- p = tmp + (p - *retbuf);
- *retbuf = tmp;
- }
- memcpy (p, result, resultlen);
- p += resultlen;
- }
- }
- else
- log_info ("apdu_send_simple(%d) "
- "got unexpected status %04X from get response\n",
- slot, sw);
- }
- while ((sw & 0xff00) == SW_MORE_DATA);
-
- if (retbuf)
- {
- *retbuflen = p - *retbuf;
- tmp = xtryrealloc (*retbuf, *retbuflen);
- if (tmp)
- *retbuf = tmp;
- }
- }
- if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS)
- log_printhex (" dump: ", *retbuf, *retbuflen);
-
- return sw;
-}
-
-/* Send an APDU to the card in SLOT. The APDU is created from all
- given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
- LC won't sent this field and the data field; in this case DATA must
- also be passed as NULL. The return value is the status word or -1
- for an invalid SLOT or other non card related error. If RETBUF is
- not NULL, it will receive an allocated buffer with the returned
- data. The length of that data will be put into *RETBUFLEN. The
- caller is reponsible for releasing the buffer even in case of
- errors. */
-int
-apdu_send (int slot, int class, int ins, int p0, int p1,
- int lc, const char *data, unsigned char **retbuf, size_t *retbuflen)
-{
- return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256,
- retbuf, retbuflen);
-}
-
-/* Send an APDU to the card in SLOT. The APDU is created from all
- given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for
- LC won't sent this field and the data field; in this case DATA must
- also be passed as NULL. The return value is the status word or -1
- for an invalid SLOT or other non card related error. No data will be
- returned. */
-int
-apdu_send_simple (int slot, int class, int ins, int p0, int p1,
- int lc, const char *data)
-{
- return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL);
-}
-
-
-
-
diff --git a/scd/apdu.h b/scd/apdu.h
deleted file mode 100644
index 44166a3fe..000000000
--- a/scd/apdu.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* apdu.h - ISO 7816 APDU functions and low level I/O
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef APDU_H
-#define APDU_H
-
-/* ISO 7816 values for the statusword are defined here because they
- should not be visible to the users of the actual ISO command
- API. */
-enum {
- SW_MORE_DATA = 0x6100, /* Note: that the low byte must be
- masked of.*/
- SW_EEPROM_FAILURE = 0x6581,
- SW_WRONG_LENGTH = 0x6700,
- SW_CHV_WRONG = 0x6982,
- SW_CHV_BLOCKED = 0x6983,
- SW_USE_CONDITIONS = 0x6985,
- SW_NOT_SUPPORTED = 0x6a81,
- SW_BAD_PARAMETER = 0x6a80, /* (in the data field) */
- SW_REF_NOT_FOUND = 0x6a88,
- SW_BAD_P0_P1 = 0x6b00,
- SW_INS_NOT_SUP = 0x6d00,
- SW_CLA_NOT_SUP = 0x6e00,
- SW_SUCCESS = 0x9000,
-
- /* The follwoing statuswords are no real ones but used to map host
- OS errors into status words. A status word is 16 bit so that
- those values can't be issued by a card. */
- SW_HOST_OUT_OF_CORE = 0x10001, /* No way yet to differentiate
- between errnos on a failed malloc. */
- SW_HOST_INV_VALUE = 0x10002,
- SW_HOST_INCOMPLETE_CARD_RESPONSE = 0x10003,
-};
-
-
-
-/* Note , that apdu_open_reader returns no status word but -1 on error. */
-int apdu_open_reader (int port);
-unsigned char *apdu_get_atr (int slot, size_t *atrlen);
-
-
-/* The apdu send functions do return status words. */
-int apdu_send_simple (int slot, int class, int ins, int p0, int p1,
- int lc, const char *data);
-int apdu_send (int slot, int class, int ins, int p0, int p1,
- int lc, const char *data,
- unsigned char **retbuf, size_t *retbuflen);
-int apdu_send_le (int slot, int class, int ins, int p0, int p1,
- int lc, const char *data, int le,
- unsigned char **retbuf, size_t *retbuflen);
-
-
-#endif /*APDU_H*/
-
-
-
diff --git a/scd/app-common.h b/scd/app-common.h
deleted file mode 100644
index 282f82715..000000000
--- a/scd/app-common.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* app-common.h - Common declarations for all card applications
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_SCD_APP_COMMON_H
-#define GNUPG_SCD_APP_COMMON_H
-
-struct app_ctx_s {
- int initialized; /* The application has been initialied and the
- function pointers may be used. Note that for
- unsupported operations the particular
- function pointer is set to NULL */
- int slot; /* Used reader. */
- unsigned char *serialno; /* Serialnumber in raw form, allocated. */
- size_t serialnolen; /* Length in octets of serialnumber. */
- unsigned int card_version;
- int did_chv1;
- int did_chv2;
- int did_chv3;
- struct {
- int (*learn_status) (APP app, CTRL ctrl);
- int (*setattr) (APP app, const char *name,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const unsigned char *value, size_t valuelen);
- int (*sign) (APP app,
- const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
- int (*auth) (APP app, const char *keyidstr,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
- int (*decipher) (APP app, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
- int (*genkey) (APP app, CTRL ctrl,
- const char *keynostr, unsigned int flags,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg);
- int (*change_pin) (APP app, CTRL ctrl,
- const char *chvnostr, int reset_mode,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg);
- } fnc;
-
-
-};
-
-/*-- app.c --*/
-APP select_application (void);
-int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp);
-int app_write_learn_status (APP app, CTRL ctrl);
-int app_setattr (APP app, const char *name,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const unsigned char *value, size_t valuelen);
-int app_sign (APP app, const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
-int app_auth (APP app, const char *keyidstr,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
-int app_decipher (APP app, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
-int app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg);
-int app_get_challenge (APP app, size_t nbytes, unsigned char *buffer);
-int app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg);
-
-
-/*-- app-openpgp.c --*/
-int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen);
-
-int app_openpgp_cardinfo (APP app,
- char **serialno,
- char **disp_name,
- char **pubkey_url,
- unsigned char **fpr1,
- unsigned char **fpr2,
- unsigned char **fpr3);
-int app_openpgp_storekey (APP app, int keyno,
- unsigned char *template, size_t template_len,
- time_t created_at,
- const unsigned char *m, size_t mlen,
- const unsigned char *e, size_t elen,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg);
-int app_openpgp_readkey (APP app, int keyno,
- unsigned char **m, size_t *mlen,
- unsigned char **e, size_t *elen);
-
-
-#endif /*GNUPG_SCD_APP_COMMON_H*/
-
-
-
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
deleted file mode 100644
index 09a19699d..000000000
--- a/scd/app-openpgp.c
+++ /dev/null
@@ -1,1482 +0,0 @@
-/* app-openpgp.c - The OpenPGP card application.
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "scdaemon.h"
-#include "app-common.h"
-#include "iso7816.h"
-
-
-
-static struct {
- int tag;
- int constructed;
- int get_from; /* Constructed DO with this DO or 0 for direct access. */
- int binary;
- char *desc;
-} data_objects[] = {
- { 0x005E, 0, 0, 1, "Login Data" },
- { 0x5F50, 0, 0, 0, "URL" },
- { 0x0065, 1, 0, 1, "Cardholder Related Data"},
- { 0x005B, 0, 0x65, 0, "Name" },
- { 0x5F2D, 0, 0x65, 0, "Language preferences" },
- { 0x5F35, 0, 0x65, 0, "Sex" },
- { 0x006E, 1, 0, 1, "Application Related Data" },
- { 0x004F, 0, 0x6E, 1, "AID" },
- { 0x0073, 1, 0, 1, "Discretionary Data Objects" },
- { 0x0047, 0, 0x6E, 1, "Card Capabilities" },
- { 0x00C0, 0, 0x6E, 1, "Extended Card Capabilities" },
- { 0x00C1, 0, 0x6E, 1, "Algorithm Attributes Signature" },
- { 0x00C2, 0, 0x6E, 1, "Algorithm Attributes Decryption" },
- { 0x00C3, 0, 0x6E, 1, "Algorithm Attributes Authentication" },
- { 0x00C4, 0, 0x6E, 1, "CHV Status Bytes" },
- { 0x00C5, 0, 0x6E, 1, "Fingerprints" },
- { 0x00C6, 0, 0x6E, 1, "CA Fingerprints" },
- { 0x007A, 1, 0, 1, "Security Support Template" },
- { 0x0093, 0, 0x7A, 1, "Digital Signature Counter" },
- { 0 }
-};
-
-
-static unsigned long get_sig_counter (APP app);
-
-
-/* Locate a TLV encoded data object in BUFFER of LENGTH and
- return a pointer to value as well as its length in NBYTES. Return
- NULL if it was not found. Note, that the function does not check
- whether the value fits into the provided buffer.
-
- FIXME: Move this to an extra file, it is mostly duplicated from card.c.
-*/
-static const unsigned char *
-find_tlv (const unsigned char *buffer, size_t length,
- int tag, size_t *nbytes, int nestlevel)
-{
- const unsigned char *s = buffer;
- size_t n = length;
- size_t len;
- int this_tag;
- int composite;
-
- for (;;)
- {
- buffer = s;
- if (n < 2)
- return NULL; /* buffer definitely too short for tag and length. */
- if (!*s || *s == 0xff)
- { /* Skip optional filler between TLV objects. */
- s++;
- n--;
- continue;
- }
- composite = !!(*s & 0x20);
- if ((*s & 0x1f) == 0x1f)
- { /* more tag bytes to follow */
- s++;
- n--;
- if (n < 2)
- return NULL; /* buffer definitely too short for tag and length. */
- if ((*s & 0x1f) == 0x1f)
- return NULL; /* We support only up to 2 bytes. */
- this_tag = (s[-1] << 8) | (s[0] & 0x7f);
- }
- else
- this_tag = s[0];
- len = s[1];
- s += 2; n -= 2;
- if (len < 0x80)
- ;
- else if (len == 0x81)
- { /* One byte length follows. */
- if (!n)
- return NULL; /* we expected 1 more bytes with the length. */
- len = s[0];
- s++; n--;
- }
- else if (len == 0x82)
- { /* Two byte length follows. */
- if (n < 2)
- return NULL; /* we expected 2 more bytes with the length. */
- len = (s[0] << 8) | s[1];
- s += 2; n -= 2;
- }
- else
- return NULL; /* APDU limit is 65535, thus it does not make
- sense to assume longer length fields. */
-
- if (composite && nestlevel < 100)
- { /* Dive into this composite DO after checking for too deep
- nesting. */
- const unsigned char *tmp_s;
- size_t tmp_len;
-
- tmp_s = find_tlv (s, len, tag, &tmp_len, nestlevel+1);
- if (tmp_s)
- {
- *nbytes = tmp_len;
- return tmp_s;
- }
- }
-
- if (this_tag == tag)
- {
- *nbytes = len;
- return s;
- }
- if (len > n)
- return NULL; /* buffer too short to skip to the next tag. */
- s += len; n -= len;
- }
-}
-
-
-/* Get the DO identified by TAG from the card in SLOT and return a
- buffer with its content in RESULT and NBYTES. The return value is
- NULL if not found or a pointer which must be used to release the
- buffer holding value. */
-static void *
-get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes)
-{
- int rc, i;
- unsigned char *buffer;
- size_t buflen;
- unsigned char *value;
- size_t valuelen;
-
- *result = NULL;
- *nbytes = 0;
- for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
- ;
-
- value = NULL;
- rc = -1;
- if (data_objects[i].tag && data_objects[i].get_from)
- {
- rc = iso7816_get_data (slot, data_objects[i].get_from,
- &buffer, &buflen);
- if (!rc)
- {
- const unsigned char *s;
-
- s = find_tlv (buffer, buflen, tag, &valuelen, 0);
- if (!s)
- value = NULL; /* not found */
- else if (valuelen > buflen - (s - buffer))
- {
- log_error ("warning: constructed DO too short\n");
- value = NULL;
- xfree (buffer); buffer = NULL;
- }
- else
- value = buffer + (s - buffer);
- }
- }
-
- if (!value) /* Not in a constructed DO, try simple. */
- {
- rc = iso7816_get_data (slot, tag, &buffer, &buflen);
- if (!rc)
- {
- value = buffer;
- valuelen = buflen;
- }
- }
-
- if (!rc)
- {
- *nbytes = valuelen;
- *result = value;
- return buffer;
- }
- return NULL;
-}
-
-#if 0 /* not used */
-static void
-dump_one_do (int slot, int tag)
-{
- int rc, i;
- unsigned char *buffer;
- size_t buflen;
- const char *desc;
- int binary;
- const unsigned char *value;
- size_t valuelen;
-
- for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
- ;
- desc = data_objects[i].tag? data_objects[i].desc : "?";
- binary = data_objects[i].tag? data_objects[i].binary : 1;
-
- value = NULL;
- rc = -1;
- if (data_objects[i].tag && data_objects[i].get_from)
- {
- rc = iso7816_get_data (slot, data_objects[i].get_from,
- &buffer, &buflen);
- if (!rc)
- {
- value = find_tlv (buffer, buflen, tag, &valuelen, 0);
- if (!value)
- ; /* not found */
- else if (valuelen > buflen - (value - buffer))
- {
- log_error ("warning: constructed DO too short\n");
- value = NULL;
- xfree (buffer); buffer = NULL;
- }
- }
- }
-
- if (!value) /* Not in a constructed DO, try simple. */
- {
- rc = iso7816_get_data (slot, tag, &buffer, &buflen);
- if (!rc)
- {
- value = buffer;
- valuelen = buflen;
- }
- }
- if (rc == 0x6a88)
- log_info ("DO `%s' not available\n", desc);
- else if (rc)
- log_info ("DO `%s' not available (rc=%04X)\n", desc, rc);
- else
- {
- if (binary)
- {
- log_info ("DO `%s': ", desc);
- log_printhex ("", value, valuelen);
- }
- else
- log_info ("DO `%s': `%.*s'\n",
- desc, (int)valuelen, value); /* FIXME: sanitize */
- xfree (buffer);
- }
-}
-#endif /*not used*/
-
-
-static void
-dump_all_do (int slot)
-{
- int rc, i, j;
- unsigned char *buffer;
- size_t buflen;
-
- for (i=0; data_objects[i].tag; i++)
- {
- if (data_objects[i].get_from)
- continue;
-
- rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen);
- if (rc == 0x6a88)
- ;
- else if (rc)
- log_info ("DO `%s' not available (rc=%04X)\n",
- data_objects[i].desc, rc);
- else
- {
- if (data_objects[i].binary)
- {
- log_info ("DO `%s': ", data_objects[i].desc);
- log_printhex ("", buffer, buflen);
- }
- else
- log_info ("DO `%s': `%.*s'\n",
- data_objects[i].desc,
- (int)buflen, buffer); /* FIXME: sanitize */
- }
-
- if (data_objects[i].constructed)
- {
- for (j=0; data_objects[j].tag; j++)
- {
- const unsigned char *value;
- size_t valuelen;
-
- if (j==i || data_objects[i].tag != data_objects[j].get_from)
- continue;
- value = find_tlv (buffer, buflen,
- data_objects[j].tag, &valuelen, 0);
- if (!value)
- ; /* not found */
- else if (valuelen > buflen - (value - buffer))
- log_error ("warning: constructed DO too short\n");
- else
- {
- if (data_objects[j].binary)
- {
- log_info ("DO `%s': ", data_objects[j].desc);
- log_printhex ("", value, valuelen);
- }
- else
- log_info ("DO `%s': `%.*s'\n",
- data_objects[j].desc,
- (int)valuelen, value); /* FIXME: sanitize */
- }
- }
- }
- xfree (buffer); buffer = NULL;
- }
-}
-
-
-/* Count the number of bits, assuming the A represents an unsigned big
- integer of length LEN bytes. */
-static unsigned int
-count_bits (const unsigned char *a, size_t len)
-{
- unsigned int n = len * 8;
- int i;
-
- for (; len && !*a; len--, a++, n -=8)
- ;
- if (len)
- {
- for (i=7; i && !(*a & (1<<i)); i--)
- n--;
- }
- return n;
-}
-
-/* Note, that FPR must be at least 20 bytes. */
-static int
-store_fpr (int slot, int keynumber, u32 timestamp,
- const unsigned char *m, size_t mlen,
- const unsigned char *e, size_t elen,
- unsigned char *fpr, unsigned int card_version)
-{
- unsigned int n, nbits;
- unsigned char *buffer, *p;
- int rc;
-
- for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
- ;
- for (; elen && !*e; elen--, e++) /* strip leading zeroes */
- ;
-
- n = 6 + 2 + mlen + 2 + elen;
- p = buffer = xtrymalloc (3 + n);
- if (!buffer)
- return out_of_core ();
-
- *p++ = 0x99; /* ctb */
- *p++ = n >> 8; /* 2 byte length header */
- *p++ = n;
- *p++ = 4; /* key packet version */
- *p++ = timestamp >> 24;
- *p++ = timestamp >> 16;
- *p++ = timestamp >> 8;
- *p++ = timestamp;
- *p++ = 1; /* RSA */
- nbits = count_bits (m, mlen);
- *p++ = nbits >> 8;
- *p++ = nbits;
- memcpy (p, m, mlen); p += mlen;
- nbits = count_bits (e, elen);
- *p++ = nbits >> 8;
- *p++ = nbits;
- memcpy (p, e, elen); p += elen;
-
- log_printhex ("fprbuf:", buffer, n+3);
- gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3);
-
- xfree (buffer);
-
- rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6)
- + keynumber, fpr, 20);
- if (rc)
- log_error ("failed to store the fingerprint: rc=%04X\n", rc);
-
- return rc;
-}
-
-
-static void
-send_fpr_if_not_null (CTRL ctrl, const char *keyword,
- int number, const unsigned char *fpr)
-{
- int i;
- char buf[41];
- char numbuf[25];
-
- for (i=0; i < 20 && !fpr[i]; i++)
- ;
- if (i==20)
- return; /* All zero. */
- for (i=0; i< 20; i++)
- sprintf (buf+2*i, "%02X", fpr[i]);
- if (number == -1)
- *numbuf = 0; /* Don't print the key number */
- else
- sprintf (numbuf, "%d", number);
- send_status_info (ctrl, keyword,
- numbuf, (size_t)strlen(numbuf),
- buf, (size_t)strlen (buf), NULL, 0);
-}
-
-static void
-send_key_data (CTRL ctrl, const char *name,
- const unsigned char *a, size_t alen)
-{
- char *p, *buf = xmalloc (alen*2+1);
-
- for (p=buf; alen; a++, alen--, p += 2)
- sprintf (p, "%02X", *a);
-
- send_status_info (ctrl, "KEY-DATA",
- name, (size_t)strlen(name),
- buf, (size_t)strlen (buf),
- NULL, 0);
- xfree (buf);
-}
-
-
-
-static int
-do_learn_status (APP app, CTRL ctrl)
-{
- void *relptr;
- unsigned char *value;
- size_t valuelen;
- int i;
-
- relptr = get_one_do (app->slot, 0x005B, &value, &valuelen);
- if (relptr)
- {
- send_status_info (ctrl, "DISP-NAME", value, valuelen, NULL, 0);
- xfree (relptr);
- }
- relptr = get_one_do (app->slot, 0x5F2D, &value, &valuelen);
- if (relptr)
- {
- send_status_info (ctrl, "DISP-LANG", value, valuelen, NULL, 0);
- xfree (relptr);
- }
- relptr = get_one_do (app->slot, 0x5F35, &value, &valuelen);
- if (relptr)
- {
- send_status_info (ctrl, "DISP-SEX", value, valuelen, NULL, 0);
- xfree (relptr);
- }
- relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen);
- if (relptr)
- {
- send_status_info (ctrl, "PUBKEY-URL", value, valuelen, NULL, 0);
- xfree (relptr);
- }
- relptr = get_one_do (app->slot, 0x005E, &value, &valuelen);
- if (relptr)
- {
- send_status_info (ctrl, "LOGIN-DATA", value, valuelen, NULL, 0);
- xfree (relptr);
- }
-
- relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen);
- if (relptr && valuelen >= 60)
- {
- for (i=0; i < 3; i++)
- send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20);
- }
- xfree (relptr);
- relptr = get_one_do (app->slot, 0x00C6, &value, &valuelen);
- if (relptr && valuelen >= 60)
- {
- for (i=0; i < 3; i++)
- send_fpr_if_not_null (ctrl, "CA-FPR", i+1, value+i*20);
- }
- xfree (relptr);
- relptr = get_one_do (app->slot, 0x00C4, &value, &valuelen);
- if (relptr)
- {
- char numbuf[7*23];
-
- for (i=0,*numbuf=0; i < valuelen && i < 7; i++)
- sprintf (numbuf+strlen (numbuf), " %d", value[i]);
- send_status_info (ctrl, "CHV-STATUS", numbuf, strlen (numbuf), NULL, 0);
- xfree (relptr);
- }
-
- {
- unsigned long ul = get_sig_counter (app);
- char numbuf[23];
-
- sprintf (numbuf, "%lu", ul);
- send_status_info (ctrl, "SIG-COUNTER", numbuf, strlen (numbuf), NULL, 0);
- }
- return 0;
-}
-
-
-/* Handle the SETATTR operation. All arguments are already basically
- checked. */
-static int
-do_setattr (APP app, const char *name,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const unsigned char *value, size_t valuelen)
-{
- gpg_error_t rc;
- int idx;
- static struct {
- const char *name;
- int tag;
- } table[] = {
- { "DISP-NAME", 0x005B },
- { "LOGIN-DATA", 0x005E },
- { "DISP-LANG", 0x5F2D },
- { "DISP-SEX", 0x5F35 },
- { "PUBKEY-URL", 0x5F50 },
- { "CHV-STATUS-1", 0x00C4 },
- { "CA-FPR-1", 0x00CA },
- { "CA-FPR-2", 0x00CB },
- { "CA-FPR-3", 0x00CC },
- { NULL, 0 }
- };
-
-
- for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++)
- ;
- if (!table[idx].name)
- return gpg_error (GPG_ERR_INV_NAME);
-
- if (!app->did_chv3)
- {
- char *pinvalue;
-
- rc = pincb (pincb_arg, "Admin PIN (CHV3)",
- &pinvalue);
-/* pinvalue = xstrdup ("12345678"); */
-/* rc = 0; */
- if (rc)
- {
- log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV3 failed\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- return rc;
- }
- app->did_chv3 = 1;
- }
-
- rc = iso7816_put_data (app->slot, table[idx].tag, value, valuelen);
- if (rc)
- log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc));
- /* FIXME: If this fails we should *once* try again after
- doing a verify command, so that in case of a problem with
- tracking the verify operation we have a fallback. */
-
- return rc;
-}
-
-/* Handle the PASSWD command. */
-static int
-do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc = 0;
- int chvno = atoi (chvnostr);
- char *pinvalue;
-
- if (reset_mode && chvno == 3)
- {
- rc = gpg_error (GPG_ERR_INV_ID);
- goto leave;
- }
- else if (reset_mode || chvno == 3)
- {
- rc = pincb (pincb_arg, "Admin PIN", &pinvalue);
- if (rc)
- {
- log_error ("error getting PIN: %s\n", gpg_strerror (rc));
- goto leave;
- }
- rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV3 failed: rc=%04X\n", rc);
- goto leave;
- }
- }
- else if (chvno == 1)
- {
- rc = pincb (pincb_arg, "Signature PIN", &pinvalue);
- if (rc)
- {
- log_error ("error getting PIN: %s\n", gpg_strerror (rc));
- goto leave;
- }
- rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV1 failed: rc=%04X\n", rc);
- goto leave;
- }
- }
- else if (chvno == 2)
- {
- rc = pincb (pincb_arg, "Decryption PIN", &pinvalue);
- if (rc)
- {
- log_error ("error getting PIN: %s\n", gpg_strerror (rc));
- goto leave;
- }
- rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV2 failed: rc=%04X\n", rc);
- goto leave;
- }
- }
- else
- {
- rc = gpg_error (GPG_ERR_INV_ID);
- goto leave;
- }
-
-
- rc = pincb (pincb_arg, chvno == 1? "New Signature PIN" :
- chvno == 2? "New Decryption PIN" :
- chvno == 3? "New Admin PIN" : "?", &pinvalue);
- if (rc)
- {
- log_error ("error getting new PIN: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (reset_mode)
- rc = iso7816_reset_retry_counter (app->slot, 0x80 + chvno,
- pinvalue, strlen (pinvalue));
- else
- rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
- NULL, 0,
- pinvalue, strlen (pinvalue));
- xfree (pinvalue);
-
-
- leave:
- return rc;
-}
-
-
-
-/* Handle the GENKEY command. */
-static int
-do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
- int i;
- char numbuf[30];
- unsigned char fprbuf[20];
- const unsigned char *fpr;
- const unsigned char *keydata, *m, *e;
- unsigned char *buffer;
- size_t buflen, keydatalen, n, mlen, elen;
- time_t created_at;
- int keyno = atoi (keynostr);
- int force = (flags & 1);
- time_t start_at;
-
- if (keyno < 1 || keyno > 3)
- return gpg_error (GPG_ERR_INV_ID);
- keyno--;
-
- rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
- if (rc)
- {
- log_error ("error reading application data\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
- fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0);
- if (!fpr || n != 60)
- {
- rc = gpg_error (GPG_ERR_GENERAL);
- log_error ("error reading fingerprint DO\n");
- goto leave;
- }
- fpr += 20*keyno;
- for (i=0; i < 20 && !fpr[i]; i++)
- ;
- if (i!=20 && !force)
- {
- rc = gpg_error (GPG_ERR_EEXIST);
- log_error ("key already exists\n");
- goto leave;
- }
- else if (i!=20)
- log_info ("existing key will be replaced\n");
- else
- log_info ("generating new key\n");
-
- {
- char *pinvalue;
- rc = pincb (pincb_arg, "Admin PIN", &pinvalue);
- if (rc)
- {
- log_error ("error getting PIN: %s\n", gpg_strerror (rc));
- return rc;
- }
- rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- }
- if (rc)
- {
- log_error ("verify CHV3 failed: rc=%04X\n", rc);
- goto leave;
- }
-
- xfree (buffer); buffer = NULL;
-#if 1
- log_info ("please wait while key is being generated ...\n");
- start_at = time (NULL);
- rc = iso7816_generate_keypair
-#else
-#warning key generation temporary replaced by reading an existing key.
- rc = iso7816_read_public_key
-#endif
- (app->slot,
- keyno == 0? "\xB6" :
- keyno == 1? "\xB8" : "\xA4",
- 2,
- &buffer, &buflen);
- if (rc)
- {
- rc = gpg_error (GPG_ERR_CARD);
- log_error ("generating key failed\n");
- goto leave;
- }
- log_info ("key generation completed (%d seconds)\n",
- (int)(time (NULL) - start_at));
- keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0);
- if (!keydata)
- {
- rc = gpg_error (GPG_ERR_CARD);
- log_error ("response does not contain the public key data\n");
- goto leave;
- }
-
- m = find_tlv (keydata, keydatalen, 0x0081, &mlen, 0);
- if (!m)
- {
- rc = gpg_error (GPG_ERR_CARD);
- log_error ("response does not contain the RSA modulus\n");
- goto leave;
- }
-/* log_printhex ("RSA n:", m, mlen); */
- send_key_data (ctrl, "n", m, mlen);
-
- e = find_tlv (keydata, keydatalen, 0x0082, &elen, 0);
- if (!e)
- {
- rc = gpg_error (GPG_ERR_CARD);
- log_error ("response does not contain the RSA public exponent\n");
- goto leave;
- }
-/* log_printhex ("RSA e:", e, elen); */
- send_key_data (ctrl, "e", e, elen);
-
- created_at = gnupg_get_time ();
- sprintf (numbuf, "%lu", (unsigned long)created_at);
- send_status_info (ctrl, "KEY-CREATED-AT",
- numbuf, (size_t)strlen(numbuf), NULL, 0);
-
- rc = store_fpr (app->slot, keyno, (u32)created_at,
- m, mlen, e, elen, fprbuf, app->card_version);
- if (rc)
- goto leave;
- send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
-
-
- leave:
- xfree (buffer);
- return rc;
-}
-
-
-static unsigned long
-get_sig_counter (APP app)
-{
- void *relptr;
- unsigned char *value;
- size_t valuelen;
- unsigned long ul;
-
- relptr = get_one_do (app->slot, 0x0093, &value, &valuelen);
- if (!relptr)
- return 0;
- if (valuelen == 3 )
- ul = (value[0] << 16) | (value[1] << 8) | value[2];
- else
- {
- log_error ("invalid structure of OpenPGP card (DO 0x93)\n");
- ul = 0;
- }
- xfree (relptr);
- return ul;
-}
-
-static int
-compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr)
-{
- const unsigned char *fpr;
- unsigned char *buffer;
- size_t buflen, n;
- int rc, i;
-
- assert (keyno >= 1 && keyno <= 3);
-
- rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
- if (rc)
- {
- log_error ("error reading application data\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
- fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0);
- if (!fpr || n != 60)
- {
- xfree (buffer);
- log_error ("error reading fingerprint DO\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
- fpr += (keyno-1)*20;
- for (i=0; i < 20; i++)
- if (sha1fpr[i] != fpr[i])
- {
- xfree (buffer);
- return gpg_error (GPG_ERR_WRONG_SECKEY);
- }
- xfree (buffer);
- return 0;
-}
-
-
-
-/* Compute a digital signature on INDATA which is expected to be the
- raw message digest. For this application the KEYIDSTR consists of
- the serialnumber and the fingerprint delimited by a slash.
-
- Note that this fucntion may return the error code
- GPG_ERR_WRONG_CARD to indicate that the card currently present does
- not match the one required for the requested action (e.g. the
- serial number does not match). */
-static int
-do_sign (APP app, const char *keyidstr, int hashalgo,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
- { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
- 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
- static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
- { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
- 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
- int rc;
- unsigned char data[35];
- unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
- const char *s;
- int n;
- const char *fpr = NULL;
- unsigned long sigcount;
-
- if (!keyidstr || !*keyidstr)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (indatalen != 20)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- /* Check whether an OpenPGP card of any version has been requested. */
- if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 32)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* no fingerprint given: we allow this for now. */
- else if (*s == '/')
- fpr = s + 1;
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; n < 16; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
-
- if (app->serialnolen != 16)
- return gpg_error (GPG_ERR_INV_CARD);
- if (memcmp (app->serialno, tmp_sn, 16))
- return gpg_error (GPG_ERR_WRONG_CARD);
-
- /* If a fingerprint has been specified check it against the one on
- the card. This is allows for a meaningful error message in case
- the key on the card has been replaced but the shadow information
- known to gpg was not updated. If there is no fingerprint, gpg
- will detect a bogus signature anyway due to the
- verify-after-signing feature. */
- if (fpr)
- {
- for (s=fpr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 40)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* okay */
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=fpr, n=0; n < 20; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
- rc = compare_fingerprint (app, 1, tmp_sn);
- if (rc)
- return rc;
- }
-
- if (hashalgo == GCRY_MD_SHA1)
- memcpy (data, sha1_prefix, 15);
- else if (hashalgo == GCRY_MD_RMD160)
- memcpy (data, rmd160_prefix, 15);
- else
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- memcpy (data+15, indata, indatalen);
-
- sigcount = get_sig_counter (app);
- log_info ("signatures created so far: %lu\n", sigcount);
-
- /* FIXME: Check whether we are really required to enter the PIN for
- each signature. There is a DO for this. */
- if (!app->did_chv1 || 1)
- {
- char *pinvalue;
-
- {
- char *prompt;
- if (asprintf (&prompt, "Signature PIN [sigs done: %lu]", sigcount) < 0)
- return gpg_error_from_errno (errno);
- rc = pincb (pincb_arg, prompt, &pinvalue);
- free (prompt);
- }
-/* pinvalue = xstrdup ("123456"); */
-/* rc = 0; */
- if (rc)
- {
- log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV1 failed\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- return rc;
- }
- app->did_chv1 = 1;
- }
-
- rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
- return rc;
-}
-
-/* Compute a digital signature using the INTERNAL AUTHENTICATE command
- on INDATA which is expected to be the raw message digest. For this
- application the KEYIDSTR consists of the serialnumber and the
- fingerprint delimited by a slash.
-
- Note that this fucntion may return the error code
- GPG_ERR_WRONG_CARD to indicate that the card currently present does
- not match the one required for the requested action (e.g. the
- serial number does not match). */
-static int
-do_auth (APP app, const char *keyidstr,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
- unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
- const char *s;
- int n;
- const char *fpr = NULL;
-
- if (!keyidstr || !*keyidstr)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (indatalen > 50) /* For a 1024 bit key. */
- return gpg_error (GPG_ERR_INV_VALUE);
-
- /* Check whether an OpenPGP card of any version has been requested. */
- if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 32)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* no fingerprint given: we allow this for now. */
- else if (*s == '/')
- fpr = s + 1;
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; n < 16; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
-
- if (app->serialnolen != 16)
- return gpg_error (GPG_ERR_INV_CARD);
- if (memcmp (app->serialno, tmp_sn, 16))
- return gpg_error (GPG_ERR_WRONG_CARD);
-
- /* If a fingerprint has been specified check it against the one on
- the card. This is allows for a meaningful error message in case
- the key on the card has been replaced but the shadow information
- known to gpg was not updated. If there is no fingerprint, gpg
- will detect a bogus signature anyway due to the
- verify-after-signing feature. */
- if (fpr)
- {
- for (s=fpr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 40)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* okay */
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=fpr, n=0; n < 20; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
- rc = compare_fingerprint (app, 3, tmp_sn);
- if (rc)
- return rc;
- }
-
- if (!app->did_chv2)
- {
- char *pinvalue;
-
- rc = pincb (pincb_arg, "Authentication/Decryption PIN", &pinvalue);
- if (rc)
- {
- log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV2 failed\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- return rc;
- }
- app->did_chv2 = 1;
- }
-
- rc = iso7816_internal_authenticate (app->slot, indata, indatalen,
- outdata, outdatalen);
- return rc;
-}
-
-
-static int
-do_decipher (APP app, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
- unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
- const char *s;
- int n;
- const char *fpr = NULL;
-
- if (!keyidstr || !*keyidstr || !indatalen)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- /* Check whether an OpenPGP card of any version has been requested. */
- if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 32)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* no fingerprint given: we allow this for now. */
- else if (*s == '/')
- fpr = s + 1;
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=keyidstr, n=0; n < 16; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
-
- if (app->serialnolen != 16)
- return gpg_error (GPG_ERR_INV_CARD);
- if (memcmp (app->serialno, tmp_sn, 16))
- return gpg_error (GPG_ERR_WRONG_CARD);
-
- /* If a fingerprint has been specified check it against the one on
- the card. This is allows for a meaningful error message in case
- the key on the card has been replaced but the shadow information
- known to gpg was not updated. If there is no fingerprint, the
- decryption will won't produce the right plaintext anyway. */
- if (fpr)
- {
- for (s=fpr, n=0; hexdigitp (s); s++, n++)
- ;
- if (n != 40)
- return gpg_error (GPG_ERR_INV_ID);
- else if (!*s)
- ; /* okay */
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- for (s=fpr, n=0; n < 20; s += 2, n++)
- tmp_sn[n] = xtoi_2 (s);
- rc = compare_fingerprint (app, 2, tmp_sn);
- if (rc)
- return rc;
- }
-
- if (!app->did_chv2)
- {
- char *pinvalue;
-
- rc = pincb (pincb_arg, "Decryption PIN", &pinvalue);
-/* pinvalue = xstrdup ("123456"); */
-/* rc = 0; */
- if (rc)
- {
- log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_error ("verify CHV2 failed\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- return rc;
- }
- app->did_chv2 = 1;
- }
-
- rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen);
- return rc;
-}
-
-
-
-
-/* Select the OpenPGP application on the card in SLOT. This function
- must be used before any other OpenPGP application functions. */
-int
-app_select_openpgp (APP app, unsigned char **sn, size_t *snlen)
-{
- static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
- int slot = app->slot;
- int rc;
- unsigned char *buffer;
- size_t buflen;
-
- rc = iso7816_select_application (slot, aid, sizeof aid);
- if (!rc)
- {
- /* fixme: get the full AID and check that the version is okay
- with us. */
- rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen);
- if (rc)
- goto leave;
- if (opt.verbose)
- {
- log_info ("got AID: ");
- log_printhex ("", buffer, buflen);
- }
-
- if (sn)
- {
- *sn = buffer;
- *snlen = buflen;
- app->card_version = buffer[6] << 8;
- app->card_version |= buffer[7];
- }
- else
- xfree (buffer);
-
- if (opt.verbose > 1)
- dump_all_do (slot);
-
- app->fnc.learn_status = do_learn_status;
- app->fnc.setattr = do_setattr;
- app->fnc.genkey = do_genkey;
- app->fnc.sign = do_sign;
- app->fnc.auth = do_auth;
- app->fnc.decipher = do_decipher;
- app->fnc.change_pin = do_change_pin;
- }
-
-leave:
- return rc;
-}
-
-
-
-/* This function is a hack to retrieve essential information about the
- card to be displayed by simple tools. It mostly resembles what the
- LEARN command returns. All parameters return allocated strings or
- buffers or NULL if the data object is not available. All returned
- values are sanitized. */
-int
-app_openpgp_cardinfo (APP app,
- char **serialno,
- char **disp_name,
- char **pubkey_url,
- unsigned char **fpr1,
- unsigned char **fpr2,
- unsigned char **fpr3)
-{
- int rc;
- void *relptr;
- unsigned char *value;
- size_t valuelen;
-
- if (serialno)
- {
- time_t dummy;
-
- *serialno = NULL;
- rc = app_get_serial_and_stamp (app, serialno, &dummy);
- if (rc)
- {
- log_error ("error getting serial number: %s\n", gpg_strerror (rc));
- return rc;
- }
- }
-
- if (disp_name)
- {
- *disp_name = NULL;
- relptr = get_one_do (app->slot, 0x005B, &value, &valuelen);
- if (relptr)
- {
- *disp_name = make_printable_string (value, valuelen, 0);
- xfree (relptr);
- }
- }
-
- if (pubkey_url)
- {
- *pubkey_url = NULL;
- relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen);
- if (relptr)
- {
- *pubkey_url = make_printable_string (value, valuelen, 0);
- xfree (relptr);
- }
- }
-
- if (fpr1)
- *fpr1 = NULL;
- if (fpr2)
- *fpr2 = NULL;
- if (fpr3)
- *fpr3 = NULL;
- relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen);
- if (relptr && valuelen >= 60)
- {
- if (fpr1)
- {
- *fpr1 = xmalloc (20);
- memcpy (*fpr1, value + 0, 20);
- }
- if (fpr2)
- {
- *fpr2 = xmalloc (20);
- memcpy (*fpr2, value + 20, 20);
- }
- if (fpr3)
- {
- *fpr3 = xmalloc (20);
- memcpy (*fpr3, value + 40, 20);
- }
- }
- xfree (relptr);
-
- return 0;
-}
-
-
-
-/* This function is currently only used by the sc-copykeys program to
- store a key on the smartcard. APP ist the application handle,
- KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask
- for the SO PIN. TEMPLATE and TEMPLATE_LEN describe a buffer with
- the key template to store. CREATED_AT is the timestamp used to
- create the fingerprint. M, MLEN is the RSA modulus and E, ELEN the
- RSA public exponent. This function silently overwrites an existing
- key.*/
-int
-app_openpgp_storekey (APP app, int keyno,
- unsigned char *template, size_t template_len,
- time_t created_at,
- const unsigned char *m, size_t mlen,
- const unsigned char *e, size_t elen,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
- unsigned char fprbuf[20];
-
- if (keyno < 1 || keyno > 3)
- return gpg_error (GPG_ERR_INV_ID);
- keyno--;
-
- {
- char *pinvalue;
- rc = pincb (pincb_arg, "Admin PIN", &pinvalue);
- if (rc)
- {
- log_error ("error getting PIN: %s\n", gpg_strerror (rc));
- return rc;
- }
- rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- }
- if (rc)
- {
- log_error ("verify CHV3 failed: rc=%04X\n", rc);
- goto leave;
- }
-
- rc = iso7816_put_data (app->slot,
- (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno,
- template, template_len);
- if (rc)
- {
- log_error ("failed to store the key: rc=%04X\n", rc);
- rc = gpg_error (GPG_ERR_CARD);
- goto leave;
- }
-
-/* log_printhex ("RSA n:", m, mlen); */
-/* log_printhex ("RSA e:", e, elen); */
-
- rc = store_fpr (app->slot, keyno, (u32)created_at,
- m, mlen, e, elen, fprbuf, app->card_version);
-
- leave:
- return rc;
-}
-
-
-/* Utility function for external tools: Read the public RSA key at
- KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */
-int
-app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
- unsigned char **e, size_t *elen)
-{
- int rc;
- const unsigned char *keydata, *a;
- unsigned char *buffer;
- size_t buflen, keydatalen, alen;
-
- *m = NULL;
- *e = NULL;
-
- if (keyno < 1 || keyno > 3)
- return gpg_error (GPG_ERR_INV_ID);
- keyno--;
-
- rc = iso7816_read_public_key(app->slot,
- keyno == 0? "\xB6" :
- keyno == 1? "\xB8" : "\xA4",
- 2,
- &buffer, &buflen);
- if (rc)
- {
- rc = gpg_error (GPG_ERR_CARD);
- log_error ("reading key failed\n");
- goto leave;
- }
-
- keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0);
- if (!keydata)
- {
- log_error ("response does not contain the public key data\n");
- rc = gpg_error (GPG_ERR_CARD);
- goto leave;
- }
-
- a = find_tlv (keydata, keydatalen, 0x0081, &alen, 0);
- if (!a)
- {
- log_error ("response does not contain the RSA modulus\n");
- rc = gpg_error (GPG_ERR_CARD);
- goto leave;
- }
- *mlen = alen;
- *m = xmalloc (alen);
- memcpy (*m, a, alen);
-
- a = find_tlv (keydata, keydatalen, 0x0082, &alen, 0);
- if (!e)
- {
- log_error ("response does not contain the RSA public exponent\n");
- rc = gpg_error (GPG_ERR_CARD);
- goto leave;
- }
- *elen = alen;
- *e = xmalloc (alen);
- memcpy (*e, a, alen);
-
- leave:
- xfree (buffer);
- if (rc)
- {
- xfree (*m); *m = NULL;
- xfree (*e); *e = NULL;
- }
- return rc;
-}
diff --git a/scd/app.c b/scd/app.c
deleted file mode 100644
index 7a85df336..000000000
--- a/scd/app.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* app.c - Application selection.
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-
-#include "scdaemon.h"
-#include "app-common.h"
-#include "apdu.h"
-#include "iso7816.h"
-
-/* The select the best fitting application and return a context.
- Returns NULL if no application was found or no card is present. */
-APP
-select_application (void)
-{
- int reader_port = 32768; /* First USB reader. */
- int slot;
- int rc;
- APP app;
-
- slot = apdu_open_reader (reader_port);
- if (slot == -1)
- {
- log_error ("card reader not available\n");
- return NULL;
- }
-
- app = xtrycalloc (1, sizeof *app);
- if (!app)
- {
- rc = out_of_core ();
- log_info ("error allocating context: %s\n", gpg_strerror (rc));
- /*apdu_close_reader (slot);*/
- return NULL;
- }
-
- app->slot = slot;
- rc = app_select_openpgp (app, &app->serialno, &app->serialnolen);
- if (rc)
- {
-/* apdu_close_reader (slot); */
- log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
- xfree (app);
- return NULL;
- }
-
- app->initialized = 1;
- return app;
-}
-
-
-
-/* Retrieve the serial number and the time of the last update of the
- card. The serial number is returned as a malloced string (hex
- encoded) in SERIAL and the time of update is returned in STAMP. If
- no update time is available the returned value is 0. Caller must
- free SERIAL unless the function returns an error. */
-int
-app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
-{
- unsigned char *buf, *p;
- int i;
-
- if (!app || !serial || !stamp)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- *serial = NULL;
- *stamp = 0; /* not available */
-
- buf = xtrymalloc (app->serialnolen * 2 + 1);
- if (!buf)
- return gpg_error_from_errno (errno);
- for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
- sprintf (p, "%02X", app->serialno[i]);
- *p = 0;
- *serial = buf;
- return 0;
-}
-
-
-/* Write out the application specifig status lines for the LEARN
- command. */
-int
-app_write_learn_status (APP app, CTRL ctrl)
-{
- if (!app)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.learn_status)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- return app->fnc.learn_status (app, ctrl);
-}
-
-
-/* Perform a SETATTR operation. */
-int
-app_setattr (APP app, const char *name,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg,
- const unsigned char *value, size_t valuelen)
-{
- if (!app || !name || !*name || !value)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.setattr)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
-}
-
-/* Create the signature and return the allocated result in OUTDATA.
- If a PIN is required the PINCB will be used to ask for the PIN; it
- should return the PIN in an allocated buffer and put it into PIN. */
-int
-app_sign (APP app, const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
-
- if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.sign)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.sign (app, keyidstr, hashalgo,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation sign result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-/* Create the signature using the INTERNAL AUTHENTICATE command and
- return the allocated result in OUTDATA. If a PIN is required the
- PINCB will be used to ask for the PIN; it should return the PIN in
- an allocated buffer and put it into PIN. */
-int
-app_auth (APP app, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
-
- if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.auth)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.auth (app, keyidstr,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation auth result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Decrypt the data in INDATA and return the allocated result in OUTDATA.
- If a PIN is required the PINCB will be used to ask for the PIN; it
- should return the PIN in an allocated buffer and put it into PIN. */
-int
-app_decipher (APP app, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
-
- if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.decipher)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.decipher (app, keyidstr,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("operation decipher result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Perform a SETATTR operation. */
-int
-app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
-
- if (!app || !keynostr || !*keynostr || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.genkey)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg);
- if (opt.verbose)
- log_info ("operation genkey result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Perform a GET CHALLENGE operation. This fucntion is special as it
- directly accesses the card without any application specific
- wrapper. */
-int
-app_get_challenge (APP app, size_t nbytes, unsigned char *buffer)
-{
- if (!app || !nbytes || !buffer)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- return iso7816_get_challenge (app->slot, nbytes, buffer);
-}
-
-
-
-/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
-int
-app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
- int (*pincb)(void*, const char *, char **),
- void *pincb_arg)
-{
- int rc;
-
- if (!app || !chvnostr || !*chvnostr || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!app->initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!app->fnc.change_pin)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg);
- if (opt.verbose)
- log_info ("operation change_pin result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-
-
-
-
diff --git a/scd/atr.c b/scd/atr.c
deleted file mode 100644
index 4e15aad50..000000000
--- a/scd/atr.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* atr.c - ISO 7816 ATR fucntions
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <assert.h>
-
-#include "scdaemon.h"
-#include "apdu.h"
-#include "atr.h"
-
-static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1,
- -1, 512, 768, 1024, 1536, 2048, -1, -1 };
-static int const di_table[16] = { -1, 1, 2, 4, 8, 16, -1, -1,
- 0, -1, -2, -4, -8, -16, -32, -64};
-
-
-/* Dump the ATR of the card at SLOT in a human readable format to
- stream FP. */
-int
-atr_dump (int slot, FILE *fp)
-{
- unsigned char *atrbuffer, *atr;
- size_t atrlen;
- int have_ta, have_tb, have_tc, have_td;
- int n_historical;
- int idx, val;
- unsigned char chksum;
-
- atr = atrbuffer = apdu_get_atr (slot, &atrlen);
- if (!atr)
- return gpg_error (GPG_ERR_GENERAL);
-
- fprintf (fp, "Info on ATR of length %u at slot %d\n",
- (unsigned int)atrlen, slot);
- if (!atrlen)
- {
- fprintf (fp, "error: empty ATR\n");
- goto bailout;
- }
-
-
- if (*atr == 0x3b)
- fputs ("direct convention\n", fp);
- else if (*atr == 0x3f)
- fputs ("inverse convention\n", fp);
- else
- fprintf (fp,"error: invalid TS character 0x%02x\n", *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
-
- chksum = *atr;
- for (idx=1; idx < atrlen-1; idx++)
- chksum ^= atr[idx];
-
- have_ta = !!(*atr & 0x10);
- have_tb = !!(*atr & 0x20);
- have_tc = !!(*atr & 0x40);
- have_td = !!(*atr & 0x80);
- n_historical = (*atr & 0x0f);
- fprintf (fp, "%d historical characters indicated\n", n_historical);
-
- if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
- fputs ("error: ATR shorter than indicated by format character\n", fp);
- if (!--atrlen)
- goto bailout;
- atr++;
-
- if (have_ta)
- {
- fputs ("TA1: F=", fp);
- val = fi_table[(*atr >> 4) & 0x0f];
- if (!val)
- fputs ("internal clock", fp);
- else if (val == -1)
- fputs ("RFU", fp);
- else
- fprintf (fp, "%d", val);
- fputs (" D=", fp);
- val = di_table[*atr & 0x0f];
- if (!val)
- fputs ("[impossible value]\n", fp);
- else if (val == -1)
- fputs ("RFU\n", fp);
- else if (val < 0 )
- fprintf (fp, "1/%d\n", val);
- else
- fprintf (fp, "%d\n", val);
-
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tb)
- {
- fprintf (fp, "TB1: II=%d PI1=%d%s\n", (*atr >> 5) & 3, *atr & 0x1f,
- (*atr & 0x80)? " [high bit not cleared]":"");
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tc)
- {
- if (*atr == 255)
- fputs ("TC1: guard time shortened to 1 etu\n", fp);
- else
- fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr);
-
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_td)
- {
- have_ta = !!(*atr & 0x10);
- have_tb = !!(*atr & 0x20);
- have_tc = !!(*atr & 0x40);
- have_td = !!(*atr & 0x80);
- fprintf (fp, "TD1: protocol T%d supported\n", *atr & 0x0f);
-
- if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
- fputs ("error: ATR shorter than indicated by format character\n", fp);
-
- if (!--atrlen)
- goto bailout;
- atr++;
- }
- else
- have_ta = have_tb = have_tc = have_td = 0;
-
- if (have_ta)
- {
- fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n",
- (*atr & 0x80)? "no-":"",
- (*atr & 0x10)? "im": "ex",
- (*atr & 0x0f));
- if ((*atr & 0x60))
- fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tb)
- {
- fprintf (fp, "TB2: PI2=%d\n", *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tc)
- {
- fprintf (fp, "TC2: PWI=%d\n", *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_td)
- {
- have_ta = !!(*atr & 0x10);
- have_tb = !!(*atr & 0x20);
- have_tc = !!(*atr & 0x40);
- have_td = !!(*atr & 0x80);
- fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f);
-
- if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
- fputs ("error: ATR shorter than indicated by format character\n", fp);
-
- if (!--atrlen)
- goto bailout;
- atr++;
- }
- else
- have_ta = have_tb = have_tc = have_td = 0;
-
- for (idx = 3; have_ta || have_tb || have_tc || have_td; idx++)
- {
- if (have_ta)
- {
- fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tb)
- {
- fprintf (fp, "TB%d: BWI=%d CWI=%d\n",
- idx, (*atr >> 4) & 0x0f, *atr & 0x0f);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_tc)
- {
- fprintf (fp, "TC%d: 0x%02X\n", idx, *atr);
- if (!--atrlen)
- goto bailout;
- atr++;
- }
-
- if (have_td)
- {
- have_ta = !!(*atr & 0x10);
- have_tb = !!(*atr & 0x20);
- have_tc = !!(*atr & 0x40);
- have_td = !!(*atr & 0x80);
- fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f);
-
- if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
- fputs ("error: ATR shorter than indicated by format character\n",
- fp);
-
- if (!--atrlen)
- goto bailout;
- atr++;
- }
- else
- have_ta = have_tb = have_tc = have_td = 0;
- }
-
- if (n_historical + 1 > atrlen)
- fputs ("error: ATR shorter than required for historical bytes "
- "and checksum\n", fp);
-
- if (n_historical)
- {
- fputs ("Historical:", fp);
- for (; n_historical && atrlen ; n_historical--, atrlen--, atr++)
- fprintf (fp, " %02X", *atr);
- putchar ('\n');
- }
-
- if (!atrlen)
- fputs ("error: checksum missing\n", fp);
- else if (*atr == chksum)
- fprintf (fp, "TCK: %02X (good)\n", *atr);
- else
- fprintf (fp, "TCK: %02X (bad; calculated %02X)\n", *atr, chksum);
-
- atrlen--;
- if (atrlen)
- fprintf (fp, "error: %u bytes garbage at end of ATR\n",
- (unsigned int)atrlen );
-
- bailout:
- xfree (atrbuffer);
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
diff --git a/scd/atr.h b/scd/atr.h
deleted file mode 100644
index 5fdd57457..000000000
--- a/scd/atr.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* atr.h - ISO 7816 ATR functions
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef ATR_H
-#define ATR_H
-
-int atr_dump (int slot, FILE *fp);
-
-
-
-#endif /*ATR_H*/
diff --git a/scd/card-common.h b/scd/card-common.h
deleted file mode 100644
index 31f0dfe8f..000000000
--- a/scd/card-common.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* card-common.h - Common declarations for all card types
- * Copyright (C) 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef CARD_COMMON_H
-#define CARD_COMMON_H
-
-/* Declaration of private data structure used by card-p15.c */
-struct p15private_s;
-
-
-struct card_ctx_s {
- int reader; /* used reader */
- struct sc_context *ctx;
- struct sc_card *scard;
- struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */
- struct p15private_s *p15priv; /* private data used by card-p15.c */
-
- struct {
- int initialized; /* the card has been initialied and the function
- pointers may be used. However for
- unsupported operations the particular
- function pointer is set to NULL */
-
- int (*enum_keypairs) (CARD card, int idx,
- unsigned char *keygrip, char **keyid);
- int (*enum_certs) (CARD card, int idx, char **certid, int *certtype);
- int (*read_cert) (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert);
- int (*sign) (CARD card,
- const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
- int (*decipher) (CARD card, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
- } fnc;
-
-};
-
-/*-- card.c --*/
-gpg_error_t map_sc_err (int rc);
-int card_help_get_keygrip (KsbaCert cert, unsigned char *array);
-
-/*-- card-15.c --*/
-void p15_release_private_data (CARD card);
-
-/* constructors */
-void card_p15_bind (CARD card);
-void card_dinsig_bind (CARD card);
-
-
-#endif /*CARD_COMMON_H*/
diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c
deleted file mode 100644
index 391a51da8..000000000
--- a/scd/card-dinsig.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* card-dinsig.c - German signature law (DINSIG) functions
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/* The German signature law and its bylaw (SigG and SigV) is currently
- used with an interface specification described in DIN V 66291-1.
- The AID to be used is: 'D27600006601'.
-
- The file IDs for certificates utilize the generic format:
- Cxyz
- C being the hex digit 'C' (12).
- x being the service indicator:
- '0' := SigG conform digital signature.
- '1' := entity authentication.
- '2' := key encipherment.
- '3' := data encipherment.
- '4' := key agreement.
- other values are reserved for future use.
- y being the security environment number using '0' for cards
- not supporting a SE number.
- z being the certificate type:
- '0' := C.CH (base certificate of ard holder) or C.ICC.
- '1' .. '7' := C.CH (business or professional certificate
- of card holder.
- '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA).
- 'E' := C.RCA (self certified certificate of the Root-CA).
- 'F' := reserved.
-
- The file IDs used by default are:
- '1F00' EF.SSD (security service descriptor). [o,o]
- '2F02' EF.GDO (global data objects) [m,m]
- 'A000' EF.PROT (signature log). Cyclic file with 20 records of 53 byte.
- Read and update after user authentication. [o,o]
- 'B000' EF.PK.RCA.DS (public keys of Root-CA). Size is 512b or size
- of keys. [m (unless a 'C00E' is present),m]
- 'B001' EF.PK.CA.DS (public keys of CAs). Size is 512b or size
- of keys. [o,o]
- 'C00n' EF.C.CH.DS (digital signature certificate of card holder)
- with n := 0 .. 7. Size is 2k or size of cert. Read and
- update allowed after user authentication. [m,m]
- 'C00m' EF.C.CA.DS (digital signature certificate of CA)
- with m := 8 .. E. Size is 1k or size of cert. Read always
- allowed, update after uder authentication. [o,o]
- 'C100' EF.C.ICC.AUT (AUT certificate of ICC) [o,m]
- 'C108' EF.C.CA.AUT (AUT certificate of CA) [o,m]
- 'D000' EF.DM (display message) [-,m]
-
- The letters in brackets indicate optional or mandatory files: The
- first for card terminals under full control and the second for
- "business" card terminals.
-
- FIXME: Needs a lot more explanation.
-
-*/
-
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-#include <ksba.h>
-
-#include "scdaemon.h"
-#include "card-common.h"
-
-static int dinsig_read_cert (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert);
-
-
-
-/* See card.c for interface description. Frankly we don't do any real
- enumeration but just check whether the well know files are
- available. */
-static int
-dinsig_enum_keypairs (CARD card, int idx,
- unsigned char *keygrip, char **keyid)
-{
- int rc;
- unsigned char *buf;
- size_t buflen;
- KsbaError krc;
- KsbaCert cert;
-
- /* fixme: We should locate the application via the EF(DIR) and not
- assume a Netkey card */
- if (!idx)
- rc = dinsig_read_cert (card, "DINSIG-DF01.C000", &buf, &buflen);
- else if (idx == 1)
- rc = dinsig_read_cert (card, "DINSIG-DF01.C200", &buf, &buflen);
- else
- rc = -1;
- if (rc)
- return rc;
-
- cert = ksba_cert_new ();
- if (!cert)
- {
- gpg_error_t tmperr = out_of_core ();
- xfree (buf);
- return tmperr;
- }
-
- krc = ksba_cert_init_from_mem (cert, buf, buflen);
- xfree (buf);
- if (krc)
- {
- log_error ("failed to parse the certificate at idx %d: %s\n",
- idx, ksba_strerror (krc));
- ksba_cert_release (cert);
- return gpg_error (GPG_ERR_CARD);
- }
- if (card_help_get_keygrip (cert, keygrip))
- {
- log_error ("failed to calculate the keygrip at index %d\n", idx);
- ksba_cert_release (cert);
- return gpg_error (GPG_ERR_CARD);
- }
- ksba_cert_release (cert);
-
- /* return the iD */
- if (keyid)
- {
- *keyid = xtrymalloc (17);
- if (!*keyid)
- return out_of_core ();
- if (!idx)
- strcpy (*keyid, "DINSIG-DF01.C000");
- else
- strcpy (*keyid, "DINSIG-DF01.C200");
- }
-
- return 0;
-}
-
-
-
-/* See card.c for interface description */
-static int
-dinsig_read_cert (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert)
-{
- int rc;
- struct sc_path path;
- struct sc_file *file;
- unsigned char *buf;
- int buflen;
-
- if (!strcmp (certidstr, "DINSIG-DF01.C000"))
- sc_format_path ("3F00DF01C000", &path);
- else if (!strcmp (certidstr, "DINSIG-DF01.C200"))
- sc_format_path ("3F00DF01C200", &path);
- else
- return gpg_error (GPG_ERR_INV_ID);
-
- rc = sc_select_file (card->scard, &path, &file);
- if (rc)
- {
- log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
- return map_sc_err (rc);
- }
- if (file->type != SC_FILE_TYPE_WORKING_EF
- || file->ef_structure != SC_FILE_EF_TRANSPARENT)
- {
- log_error ("wrong type or structure of certificate EF\n");
- sc_file_free (file);
- return gpg_error (GPG_ERR_CARD);
- }
- if (file->size < 20) /* check against a somewhat arbitrary length */
- {
- log_error ("certificate EF too short\n");
- sc_file_free (file);
- return gpg_error (GPG_ERR_CARD);
- }
- buf = xtrymalloc (file->size);
- if (!buf)
- {
- gpg_error_t tmperr = out_of_core ();
- sc_file_free (file);
- return tmperr;
- }
-
- rc = sc_read_binary (card->scard, 0, buf, file->size, 0);
- if (rc >= 0 && rc != file->size)
- {
- log_error ("short read on certificate EF\n");
- sc_file_free (file);
- xfree (buf);
- return gpg_error (GPG_ERR_CARD);
- }
- sc_file_free (file);
- if (rc < 0)
- {
- log_error ("error reading certificate EF: %s\n", sc_strerror (rc));
- xfree (buf);
- return map_sc_err (rc);
- }
- buflen = rc;
-
- /* The object is not a plain certificate but wrapped into id-at
- userCertificate - fixme: we should check the specs and decided
- whether libksba should support it */
- if (buflen > 9 && buf[0] == 0x30 && buf[4] == 6 && buf[5] == 3
- && buf[6] == 0x55 && buf[7] == 4 && buf[8] == 0x24)
- {
- /* We have to strip the padding. Although this is a good idea
- anyway, we have to do it due to a KSBA problem; KSBA does not
- work correct when the buffer is larger than the ASN.1
- structure and the certificates here are padded with FF. So
- as a workaround we look at the outer structure to get the
- size of the entire thing and adjust the buflen. We can only
- do this when there is a 2 byte length field */
- size_t seqlen;
- if (buf[1] == 0x82)
- {
- seqlen = ((buf[2] << 8) | buf[3]) + 4;
- if (seqlen < buflen)
- buflen = seqlen;
- }
- memmove (buf, buf+9, buflen-9);
- buflen -= 9;
- }
-
- *cert = buf;
- *ncert = buflen;
- return 0;
-}
-
-
-
-
-/* Bind our operations to the card */
-void
-card_dinsig_bind (CARD card)
-{
- card->fnc.enum_keypairs = dinsig_enum_keypairs;
- card->fnc.read_cert = dinsig_read_cert;
-
-}
-#endif /*HAVE_OPENSC*/
diff --git a/scd/card-p15.c b/scd/card-p15.c
deleted file mode 100644
index 3cf4ba519..000000000
--- a/scd/card-p15.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/* card-p15.c - PKCS-15 based card access
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-#include <ksba.h>
-
-#include "scdaemon.h"
-#include "card-common.h"
-
-
-struct p15private_s {
- int n_prkey_rsa_objs;
- struct sc_pkcs15_object *prkey_rsa_objs[32];
- int n_cert_objs;
- struct sc_pkcs15_object *cert_objs[32];
-};
-
-
-/* Allocate private data. */
-static int
-init_private_data (CARD card)
-{
- struct p15private_s *priv;
- int rc;
-
- if (card->p15priv)
- return 0; /* already done. */
-
- priv = xtrycalloc (1, sizeof *priv);
- if (!priv)
- return out_of_core ();
-
- /* OpenSC (0.7.0) is a bit strange in that the get_objects functions
- tries to be a bit too clever and implicitly does an enumeration
- which eventually leads to the fact that every call to this
- fucntion returns one more macthing object. The old code in
- p15_enum_keypairs assume that it would alwyas return the same
- numer of objects and used this to figure out what the last object
- enumerated is. We now do an enum_objects just once and keep it
- in the private data. */
- rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA,
- priv->prkey_rsa_objs,
- DIM (priv->prkey_rsa_objs));
- if (rc < 0)
- {
- log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
- xfree (priv);
- return gpg_error (GPG_ERR_CARD);
- }
- priv->n_prkey_rsa_objs = rc;
-
- /* Read all certificate objects. */
- rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509,
- priv->cert_objs,
- DIM (priv->cert_objs));
- if (rc < 0)
- {
- log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
- xfree (priv);
- return gpg_error (GPG_ERR_CARD);
- }
- priv->n_cert_objs = rc;
-
- card->p15priv = priv;
- return 0;
-}
-
-
-/* Release private data used in this module. */
-void
-p15_release_private_data (CARD card)
-{
- if (!card->p15priv)
- return;
- xfree (card->p15priv);
- card->p15priv = NULL;
-}
-
-
-
-/* See card.c for interface description */
-static int
-p15_enum_keypairs (CARD card, int idx,
- unsigned char *keygrip, char **keyid)
-{
- int rc;
- KsbaError krc;
- struct p15private_s *priv;
- struct sc_pkcs15_object *tmpobj;
- int nobjs;
- struct sc_pkcs15_prkey_info *pinfo;
- struct sc_pkcs15_cert_info *certinfo;
- struct sc_pkcs15_cert *certder;
- KsbaCert cert;
-
- rc = init_private_data (card);
- if (rc)
- return rc;
- priv = card->p15priv;
- nobjs = priv->n_prkey_rsa_objs;
- rc = 0;
- if (idx >= nobjs)
- return -1;
- pinfo = priv->prkey_rsa_objs[idx]->data;
-
- /* now we need to read the certificate so that we can calculate the
- keygrip */
- rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
- if (rc)
- {
- log_info ("certificate for private key %d not found: %s\n",
- idx, sc_strerror (rc));
- /* note, that we return the ID anyway */
- rc = gpg_error (GPG_ERR_MISSING_CERTIFICATE);
- goto return_keyid;
- }
- certinfo = tmpobj->data;
- rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
- if (rc)
- {
- log_info ("failed to read certificate for private key %d: %s\n",
- idx, sc_strerror (rc));
- return gpg_error (GPG_ERR_CARD);
- }
-
- cert = ksba_cert_new ();
- if (!cert)
- {
- gpg_error_t tmperr = out_of_core ();
- sc_pkcs15_free_certificate (certder);
- return tmperr;
- }
- krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
- sc_pkcs15_free_certificate (certder);
- if (krc)
- {
- log_error ("failed to parse the certificate for private key %d: %s\n",
- idx, ksba_strerror (krc));
- ksba_cert_release (cert);
- return gpg_error (GPG_ERR_CARD);
- }
- if (card_help_get_keygrip (cert, keygrip))
- {
- log_error ("failed to calculate the keygrip of private key %d\n", idx);
- ksba_cert_release (cert);
- return gpg_error (GPG_ERR_CARD);
- }
- ksba_cert_release (cert);
-
- rc = 0;
- return_keyid:
- if (keyid)
- {
- char *p;
- int i;
-
- *keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
- if (!*keyid)
- return out_of_core ();
- p = stpcpy (p, "P15-5015.");
- for (i=0; i < pinfo->id.len; i++, p += 2)
- sprintf (p, "%02X", pinfo->id.value[i]);
- *p = 0;
- }
-
- return rc;
-}
-
-/* See card.c for interface description */
-static int
-p15_enum_certs (CARD card, int idx, char **certid, int *type)
-{
- int rc;
- struct p15private_s *priv;
- struct sc_pkcs15_object *obj;
- struct sc_pkcs15_cert_info *cinfo;
- int nobjs;
-
- rc = init_private_data (card);
- if (rc)
- return rc;
- priv = card->p15priv;
- nobjs = priv->n_cert_objs;
- rc = 0;
- if (idx >= nobjs)
- return -1;
- obj = priv->cert_objs[idx];
- cinfo = obj->data;
-
- if (certid)
- {
- char *p;
- int i;
-
- *certid = p = xtrymalloc (9+cinfo->id.len*2+1);
- if (!*certid)
- return out_of_core ();
- p = stpcpy (p, "P15-5015.");
- for (i=0; i < cinfo->id.len; i++, p += 2)
- sprintf (p, "%02X", cinfo->id.value[i]);
- *p = 0;
- }
- if (type)
- {
- if (!obj->df)
- *type = 0; /* unknown */
- else if (obj->df->type == SC_PKCS15_CDF)
- *type = 100;
- else if (obj->df->type == SC_PKCS15_CDF_TRUSTED)
- *type = 101;
- else if (obj->df->type == SC_PKCS15_CDF_USEFUL)
- *type = 102;
- else
- *type = 0; /* error -> unknown */
- }
-
- return rc;
-}
-
-
-
-static int
-idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
-{
- const char *s;
- int n;
-
- /* For now we only support the standard DF */
- if (strncmp (idstr, "P15-5015.", 9) )
- return gpg_error (GPG_ERR_INV_ID);
- for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
- ;
- if (*s || (n&1))
- return gpg_error (GPG_ERR_INV_ID); /*invalid or odd number of digits*/
- n /= 2;
- if (!n || n > SC_PKCS15_MAX_ID_SIZE)
- return gpg_error (GPG_ERR_INV_ID); /* empty or too large */
- for (s=idstr+9, n=0; *s; s += 2, n++)
- id->value[n] = xtoi_2 (s);
- id->len = n;
- return 0;
-}
-
-
-/* See card.c for interface description */
-static int
-p15_read_cert (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert)
-{
- struct sc_pkcs15_object *tmpobj;
- struct sc_pkcs15_id certid;
- struct sc_pkcs15_cert_info *certinfo;
- struct sc_pkcs15_cert *certder;
- int rc;
-
- if (!card || !certidstr || !cert || !ncert)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!card->p15card)
- return gpg_error (GPG_ERR_NO_PKCS15_APP);
-
- rc = idstr_to_id (certidstr, &certid);
- if (rc)
- return rc;
-
- rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
- if (rc)
- {
- log_info ("certificate '%s' not found: %s\n",
- certidstr, sc_strerror (rc));
- return -1;
- }
- certinfo = tmpobj->data;
- rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
- if (rc)
- {
- log_info ("failed to read certificate '%s': %s\n",
- certidstr, sc_strerror (rc));
- return gpg_error (GPG_ERR_CARD);
- }
-
- *cert = xtrymalloc (certder->data_len);
- if (!*cert)
- {
- gpg_error_t tmperr = out_of_core ();
- sc_pkcs15_free_certificate (certder);
- return tmperr;
- }
- memcpy (*cert, certder->data, certder->data_len);
- *ncert = certder->data_len;
- sc_pkcs15_free_certificate (certder);
- return 0;
-}
-
-
-
-
-
-static int
-p15_prepare_key (CARD card, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg, struct sc_pkcs15_object **r_keyobj)
-{
- struct sc_pkcs15_id keyid;
- struct sc_pkcs15_pin_info *pin;
- struct sc_pkcs15_object *keyobj, *pinobj;
- char *pinvalue;
- int rc;
-
- rc = idstr_to_id (keyidstr, &keyid);
- if (rc)
- return rc;
-
- rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
- if (rc < 0)
- {
- log_error ("private key not found: %s\n", sc_strerror(rc));
- return gpg_error (GPG_ERR_NO_SECRET_KEY);
- }
-
- rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
- &keyobj->auth_id, &pinobj);
- if (rc)
- {
- log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
- return gpg_error (GPG_ERR_BAD_PIN_METHOD);
- }
- pin = pinobj->data;
-
- /* Fixme: pack this into a verification loop */
- /* Fixme: we might want to pass pin->min_length and
- pin->stored_length */
- rc = pincb (pincb_arg, pinobj->label, &pinvalue);
- if (rc)
- {
- log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
- return rc;
- }
-
- rc = sc_pkcs15_verify_pin (card->p15card, pin,
- pinvalue, strlen (pinvalue));
- xfree (pinvalue);
- if (rc)
- {
- log_info ("PIN verification failed: %s\n", sc_strerror (rc));
- return gpg_error (GPG_ERR_BAD_PIN);
- }
-
- /* fixme: check wheter we need to release KEYOBJ in case of an error */
- *r_keyobj = keyobj;
- return 0;
-}
-
-
-/* See card.c for interface description */
-static int
-p15_sign (CARD card, const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- unsigned int cryptflags;
- struct sc_pkcs15_object *keyobj;
- int rc;
- unsigned char *outbuf = NULL;
- size_t outbuflen;
-
- if (hashalgo != GCRY_MD_SHA1)
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
-
- rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
- if (rc)
- return rc;
-
- cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1;
-
- outbuflen = 1024;
- outbuf = xtrymalloc (outbuflen);
- if (!outbuf)
- return out_of_core ();
-
- rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
- cryptflags,
- indata, indatalen,
- outbuf, outbuflen );
- if (rc < 0)
- {
- log_error ("failed to create signature: %s\n", sc_strerror (rc));
- rc = gpg_error (GPG_ERR_CARD);
- }
- else
- {
- *outdatalen = rc;
- *outdata = outbuf;
- outbuf = NULL;
- rc = 0;
- }
-
- xfree (outbuf);
- return rc;
-}
-
-
-/* See card.c for description */
-static int
-p15_decipher (CARD card, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- struct sc_pkcs15_object *keyobj;
- int rc;
- unsigned char *outbuf = NULL;
- size_t outbuflen;
-
- rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj);
- if (rc)
- return rc;
-
- if (card && card->scard && card->scard->driver
- && !strcasecmp (card->scard->driver->short_name, "tcos"))
- {
- /* very ugly hack to force the use of a local key. We need this
- until we have fixed the initialization code for TCOS cards */
- struct sc_pkcs15_prkey_info *prkey = keyobj->data;
- if ( !(prkey->key_reference & 0x80))
- {
- prkey->key_reference |= 0x80;
- log_debug ("using TCOS hack to force the use of local keys\n");
- }
- if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6')
- {
- prkey->key_reference |= 1;
- log_debug ("warning: using even more TCOS hacks\n");
- }
- }
-
- outbuflen = indatalen < 256? 256 : indatalen;
- outbuf = xtrymalloc (outbuflen);
- if (!outbuf)
- return out_of_core ();
-
- rc = sc_pkcs15_decipher (card->p15card, keyobj,
- 0,
- indata, indatalen,
- outbuf, outbuflen);
- if (rc < 0)
- {
- log_error ("failed to decipher the data: %s\n", sc_strerror (rc));
- rc = gpg_error (GPG_ERR_CARD);
- }
- else
- {
- *outdatalen = rc;
- *outdata = outbuf;
- outbuf = NULL;
- rc = 0;
- }
-
- xfree (outbuf);
- return rc;
-}
-
-
-
-/* Bind our operations to the card */
-void
-card_p15_bind (CARD card)
-{
- card->fnc.enum_keypairs = p15_enum_keypairs;
- card->fnc.enum_certs = p15_enum_certs;
- card->fnc.read_cert = p15_read_cert;
- card->fnc.sign = p15_sign;
- card->fnc.decipher = p15_decipher;
-}
-#endif /*HAVE_OPENSC*/
diff --git a/scd/card.c b/scd/card.c
deleted file mode 100644
index 02b7bfdbf..000000000
--- a/scd/card.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/* card.c - SCdaemon card functions
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifdef HAVE_OPENSC
-#include <opensc/pkcs15.h>
-#endif
-#include <ksba.h>
-
-#include "scdaemon.h"
-#include "card-common.h"
-
-/* Map the SC error codes to the GNUPG ones */
-gpg_error_t
-map_sc_err (int rc)
-{
- gpg_err_code_t e;
-
- switch (rc)
- {
- case 0: e = 0; break;
-#ifdef HAVE_OPENSC
- case SC_ERROR_NOT_SUPPORTED: e = GPG_ERR_NOT_SUPPORTED; break;
- case SC_ERROR_PKCS15_APP_NOT_FOUND: e = GPG_ERR_NO_PKCS15_APP; break;
- case SC_ERROR_OUT_OF_MEMORY: e = GPG_ERR_ENOMEM; break;
- case SC_ERROR_CARD_NOT_PRESENT: e = GPG_ERR_CARD_NOT_PRESENT; break;
- case SC_ERROR_CARD_REMOVED: e = GPG_ERR_CARD_REMOVED; break;
- case SC_ERROR_INVALID_CARD: e = GPG_ERR_INV_CARD; break;
-#endif
- default: e = GPG_ERR_CARD; break;
- }
- return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, e);
-}
-
-/* Get the keygrip from CERT, return 0 on success */
-int
-card_help_get_keygrip (KsbaCert cert, unsigned char *array)
-{
- gcry_sexp_t s_pkey;
- int rc;
- KsbaSexp p;
- size_t n;
-
- p = ksba_cert_get_public_key (cert);
- if (!p)
- return -1; /* oops */
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- return -1; /* libksba did not return a proper S-expression */
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- xfree (p);
- if (rc)
- return -1; /* can't parse that S-expression */
- array = gcry_pk_get_keygrip (s_pkey, array);
- gcry_sexp_release (s_pkey);
- if (!array)
- return -1; /* failed to calculate the keygrip */
- return 0;
-}
-
-
-
-
-
-
-
-/* Create a new context for the card and figures out some basic
- information of the card. Detects whgether a PKCS_15 application is
- stored.
-
- Common errors: GPG_ERR_CARD_NOT_PRESENT */
-int
-card_open (CARD *rcard)
-{
-#ifdef HAVE_OPENSC
- CARD card;
- int rc;
-
- card = xtrycalloc (1, sizeof *card);
- if (!card)
- return out_of_core ();
- card->reader = 0;
-
- rc = sc_establish_context (&card->ctx, "scdaemon");
- if (rc)
- {
- log_error ("failed to establish SC context: %s\n", sc_strerror (rc));
- rc = map_sc_err (rc);
- goto leave;
- }
- if (card->reader >= card->ctx->reader_count)
- {
- log_error ("no card reader available\n");
- rc = gpg_error (GPG_ERR_CARD);
- goto leave;
- }
- card->ctx->error_file = log_get_stream ();
- card->ctx->debug = opt.debug_sc;
- card->ctx->debug_file = log_get_stream ();
-
- if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1)
- {
- rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
- goto leave;
- }
-
- rc = sc_connect_card (card->ctx->reader[card->reader], 0, &card->scard);
- if (rc)
- {
- log_error ("failed to connect card in reader %d: %s\n",
- card->reader, sc_strerror (rc));
- rc = map_sc_err (rc);
- goto leave;
- }
- if (opt.verbose)
- log_info ("connected to card in reader %d using driver `%s'\n",
- card->reader, card->scard->driver->name);
-
- rc = sc_lock (card->scard);
- if (rc)
- {
- log_error ("can't lock card in reader %d: %s\n",
- card->reader, sc_strerror (rc));
- rc = map_sc_err (rc);
- goto leave;
- }
-
-
- leave:
- if (rc)
- card_close (card);
- else
- *rcard = card;
-
- return rc;
-#else
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-#endif
-}
-
-
-/* Close a card and release all resources */
-void
-card_close (CARD card)
-{
- if (card)
- {
-#ifdef HAVE_OPENSC
- if (card->p15card)
- {
- sc_pkcs15_unbind (card->p15card);
- card->p15card = NULL;
- }
- if (card->p15priv)
- p15_release_private_data (card);
- if (card->scard)
- {
- sc_unlock (card->scard);
- sc_disconnect_card (card->scard, 0);
- card->scard = NULL;
- }
- if (card->ctx)
- {
- sc_release_context (card->ctx);
- card->ctx = NULL;
- }
-#endif
- xfree (card);
- }
-}
-
-/* Locate a simple TLV encoded data object in BUFFER of LENGTH and
- return a pointer to value as well as its length in NBYTES. Return
- NULL if it was not found. Note, that the function does not check
- whether the value fits into the provided buffer. */
-#ifdef HAVE_OPENSC
-static const char *
-find_simple_tlv (const unsigned char *buffer, size_t length,
- int tag, size_t *nbytes)
-{
- const char *s = buffer;
- size_t n = length;
- size_t len;
-
- for (;;)
- {
- buffer = s;
- if (n < 2)
- return NULL; /* buffer too short for tag and length. */
- len = s[1];
- s += 2; n -= 2;
- if (len == 255)
- {
- if (n < 2)
- return NULL; /* we expected 2 more bytes with the length. */
- len = (s[0] << 8) | s[1];
- s += 2; n -= 2;
- }
- if (*buffer == tag)
- {
- *nbytes = len;
- return s;
- }
- if (len > n)
- return NULL; /* buffer too short to skip to the next tag. */
- s += len; n -= len;
- }
-}
-#endif /*HAVE_OPENSC*/
-
-/* Find the ICC Serial Number within the provided BUFFER of LENGTH
- (which should contain the GDO file) and return it as a hex encoded
- string and allocated string in SERIAL. Return an error code when
- the ICCSN was not found. */
-#ifdef HAVE_OPENSC
-static int
-find_iccsn (const unsigned char *buffer, size_t length, char **serial)
-{
- size_t n;
- const unsigned char *s;
- char *p;
-
- s = find_simple_tlv (buffer, length, 0x5A, &n);
- if (!s)
- return gpg_error (GPG_ERR_CARD);
- length -= s - buffer;
- if (n > length)
- {
- /* Oops, it does not fit into the buffer. This is an invalid
- encoding (or the buffer is too short. However, I have some
- test cards with such an invalid encoding and therefore I use
- this ugly workaround to return something I can further
- experiment with. */
- if (n == 0x0D && length+1 == n)
- {
- log_debug ("enabling BMI testcard workaround\n");
- n--;
- }
- else
- return gpg_error (GPG_ERR_CARD); /* Bad encoding; does
- not fit into buffer. */
- }
- if (!n)
- return gpg_error (GPG_ERR_CARD); /* Well, that is too short. */
-
- *serial = p = xtrymalloc (2*n+1);
- if (!*serial)
- return out_of_core ();
- for (; n; n--, p += 2, s++)
- sprintf (p, "%02X", *s);
- *p = 0;
- return 0;
-}
-#endif /*HAVE_OPENSC*/
-
-/* Retrieve the serial number and the time of the last update of the
- card. The serial number is returned as a malloced string (hex
- encoded) in SERIAL and the time of update is returned in STAMP.
- If no update time is available the returned value is 0. The serial
- is mandatory for a PKCS_15 application and an error will be
- returned if this value is not availbale. For non-PKCS-15 cards a
- serial number is constructed by other means. Caller must free
- SERIAL unless the function returns an error. */
-int
-card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
-{
-#ifdef HAVE_OPENSC
- int rc;
- struct sc_path path;
- struct sc_file *file;
- unsigned char buf[256];
- int buflen;
-#endif
-
- if (!card || !serial || !stamp)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- *serial = NULL;
- *stamp = 0; /* not available */
-
-#ifdef HAVE_OPENSC
- if (!card->fnc.initialized)
- {
- card->fnc.initialized = 1;
- /* The first use of this card tries to figure out the type of the card
- and sets up the function pointers. */
- rc = sc_pkcs15_bind (card->scard, &card->p15card);
- if (rc)
- {
- if (rc != SC_ERROR_PKCS15_APP_NOT_FOUND)
- log_error ("binding of existing PKCS-15 failed in reader %d: %s\n",
- card->reader, sc_strerror (rc));
- card->p15card = NULL;
- rc = 0;
- }
- if (card->p15card)
- card_p15_bind (card);
- else
- card_dinsig_bind (card);
- card->fnc.initialized = 1;
- }
-
-
- /* We should lookup the iso 7812-1 and 8583-3 - argh ISO
- practice is suppressing innovation - IETF rules! So we
- always get the serialnumber from the 2F02 GDO file. */
- /* FIXME: in case we can't parse the 2F02 EF and we have a P15 card,
- we should get the serial number from the respective P15 file */
- sc_format_path ("3F002F02", &path);
- rc = sc_select_file (card->scard, &path, &file);
- if (rc)
- {
- log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
- return gpg_error (GPG_ERR_CARD);
- }
- if (file->type != SC_FILE_TYPE_WORKING_EF
- || file->ef_structure != SC_FILE_EF_TRANSPARENT)
- {
- log_error ("wrong type or structure of GDO file\n");
- sc_file_free (file);
- return gpg_error (GPG_ERR_CARD);
- }
-
- if (!file->size || file->size >= DIM(buf) )
- { /* FIXME: Use a real parser */
- log_error ("unsupported size of GDO file (%d)\n", file->size);
- sc_file_free (file);
- return gpg_error (GPG_ERR_CARD);
- }
- buflen = file->size;
-
- rc = sc_read_binary (card->scard, 0, buf, buflen, 0);
- sc_file_free (file);
- if (rc < 0)
- {
- log_error ("error reading GDO file: %s\n", sc_strerror (rc));
- return gpg_error (GPG_ERR_CARD);
- }
- if (rc != buflen)
- {
- log_error ("short read on GDO file\n");
- return gpg_error (GPG_ERR_CARD);
- }
-
- rc = find_iccsn (buf, buflen, serial);
- if (gpg_err_code (rc) == GPG_ERR_CARD)
- log_error ("invalid structure of GDO file\n");
- if (!rc && card->p15card && !strcmp (*serial, "D27600000000000000000000"))
- { /* This is a German card with a silly serial number. Try to get
- the serial number from the EF(TokenInfo). We indicate such a
- serial number by the using the prefix: "FF0100". */
- const char *efser = card->p15card->serial_number;
- char *p;
-
- if (!efser)
- efser = "";
-
- xfree (*serial);
- *serial = NULL;
- p = xtrymalloc (strlen (efser) + 7);
- if (!p)
- rc = out_of_core ();
- else
- {
- strcpy (p, "FF0100");
- strcpy (p+6, efser);
- *serial = p;
- }
- }
- else if (!rc && **serial == 'F' && (*serial)[1] == 'F')
- { /* The serial number starts with our special prefix. This
- requires that we put our default prefix "FF0000" in front. */
- char *p = xtrymalloc (strlen (*serial) + 7);
- if (!p)
- {
- xfree (*serial);
- *serial = NULL;
- rc = out_of_core ();
- }
- else
- {
- strcpy (p, "FF0000");
- strcpy (p+6, *serial);
- xfree (*serial);
- *serial = p;
- }
- }
- return rc;
-#else
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-#endif
-}
-
-
-/* Enumerate all keypairs on the card and return the Keygrip as well
- as the internal identification of the key. KEYGRIP must be a
- caller provided buffer with a size of 20 bytes which will receive
- the KEYGRIP of the keypair. If KEYID is not NULL, it returns the
- ID field of the key in allocated memory; this is a string without
- spaces. The function returns -1 when all keys have been
- enumerated. Note that the error GPG_ERR_MISSING_CERTIFICATE may be
- returned if there is just the private key but no public key (ie.e a
- certificate) available. Applications might want to continue
- enumerating after this error.*/
-int
-card_enum_keypairs (CARD card, int idx,
- unsigned char *keygrip,
- char **keyid)
-{
- int rc;
-
- if (keyid)
- *keyid = NULL;
-
- if (!card || !keygrip)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (idx < 0)
- return gpg_error (GPG_ERR_INV_INDEX);
- if (!card->fnc.initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!card->fnc.enum_keypairs)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = card->fnc.enum_keypairs (card, idx, keygrip, keyid);
- if (opt.verbose)
- log_info ("card operation enum_keypairs result: %s\n",
- gpg_strerror (rc));
- return rc;
-}
-
-
-/* Enumerate all trusted certificates available on the card, return
- their ID in CERT and the type in CERTTYPE. Types of certificates
- are:
- 0 := Unknown
- 100 := Regular X.509 cert
- 101 := Trusted X.509 cert
- 102 := Useful X.509 cert
- */
-int
-card_enum_certs (CARD card, int idx, char **certid, int *certtype)
-{
- int rc;
-
- if (certid)
- *certid = NULL;
-
- if (!card)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (idx < 0)
- return gpg_error (GPG_ERR_INV_INDEX);
- if (!card->fnc.initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!card->fnc.enum_certs)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = card->fnc.enum_certs (card, idx, certid, certtype);
- if (opt.verbose)
- log_info ("card operation enum_certs result: %s\n",
- gpg_strerror (rc));
- return rc;
-}
-
-
-
-/* Read the certificate identified by CERTIDSTR which is the
- hexadecimal encoded ID of the certificate, prefixed with the string
- "3F005015.". The certificate is return in DER encoded form in CERT
- and NCERT. */
-int
-card_read_cert (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert)
-{
- int rc;
-
- if (!card || !certidstr || !cert || !ncert)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!card->fnc.initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!card->fnc.read_cert)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = card->fnc.read_cert (card, certidstr, cert, ncert);
- if (opt.verbose)
- log_info ("card operation read_cert result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Create the signature and return the allocated result in OUTDATA.
- If a PIN is required the PINCB will be used to ask for the PIN; it
- should return the PIN in an allocated buffer and put it into PIN. */
-int
-card_sign (CARD card, const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
-
- if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!card->fnc.initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!card->fnc.sign)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = card->fnc.sign (card, keyidstr, hashalgo,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("card operation sign result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
-
-/* Create the signature and return the allocated result in OUTDATA.
- If a PIN is required the PINCB will be used to ask for the PIN; it
- should return the PIN in an allocated buffer and put it into PIN. */
-int
-card_decipher (CARD card, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen )
-{
- int rc;
-
- if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb)
- return gpg_error (GPG_ERR_INV_VALUE);
- if (!card->fnc.initialized)
- return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (!card->fnc.decipher)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
- rc = card->fnc.decipher (card, keyidstr,
- pincb, pincb_arg,
- indata, indatalen,
- outdata, outdatalen);
- if (opt.verbose)
- log_info ("card operation decipher result: %s\n", gpg_strerror (rc));
- return rc;
-}
-
diff --git a/scd/command.c b/scd/command.c
deleted file mode 100644
index c53af84f9..000000000
--- a/scd/command.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/* command.c - SCdaemon command handler
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <ksba.h>
-
-#include <assuan.h>
-
-#include "scdaemon.h"
-#include "app-common.h"
-
-/* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */
-#define MAXLEN_PIN 100
-
-#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
-
-/* Data used to associate an Assuan context with local server data */
-struct server_local_s {
- ASSUAN_CONTEXT assuan_ctx;
-};
-
-
-/* Check whether the option NAME appears in LINE */
-static int
-has_option (const char *line, const char *name)
-{
- const char *s;
- int n = strlen (name);
-
- s = strstr (line, name);
- return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
-
-
-
-
-/* Note, that this reset_notify is also used for cleanup purposes. */
-static void
-reset_notify (ASSUAN_CONTEXT ctx)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (ctrl->card_ctx)
- {
- card_close (ctrl->card_ctx);
- ctrl->card_ctx = NULL;
- xfree (ctrl->in_data.value);
- ctrl->in_data.value = NULL;
- }
- if (ctrl->app_ctx)
- {
- /* FIXME: close the application. */
- xfree (ctrl->app_ctx);
- ctrl->app_ctx = NULL;
- }
-}
-
-
-static int
-option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
-{
- return 0;
-}
-
-
-/* If the card has not yet been opened, do it. Note that this
- function returns an Assuan error, so don't map the error a second
- time */
-static AssuanError
-open_card (CTRL ctrl)
-{
- if (ctrl->app_ctx)
- return 0; /* Already initialized for one specific application. */
- if (ctrl->card_ctx)
- return 0; /* Already initialized using a card context. */
-
- ctrl->app_ctx = select_application ();
- if (!ctrl->app_ctx)
- { /* No application found - fall back to old mode. */
- int rc = card_open (&ctrl->card_ctx);
- if (rc)
- return map_to_assuan_status (rc);
- }
- return 0;
-}
-
-
-/* Do the percent and plus/space unescaping in place and return tghe
- length of the valid buffer. */
-static size_t
-percent_plus_unescape (unsigned char *string)
-{
- unsigned char *p = string;
- size_t n = 0;
-
- while (*string)
- {
- if (*string == '%' && string[1] && string[2])
- {
- string++;
- *p++ = xtoi_2 (string);
- n++;
- string+= 2;
- }
- else if (*string == '+')
- {
- *p++ = ' ';
- n++;
- string++;
- }
- else
- {
- *p++ = *string++;
- n++;
- }
- }
-
- return n;
-}
-
-
-
-/* SERIALNO
-
- Return the serial number of the card using a status reponse. This
- functon should be used to check for the presence of a card.
-
- This function is special in that it can be used to reset the card.
- Most other functions will return an error when a card change has
- been detected and the use of this function is therefore required.
-
- Background: We want to keep the client clear of handling card
- changes between operations; i.e. the client can assume that all
- operations are done on the same card unless he calls this function.
- */
-static int
-cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc = 0;
- char *serial_and_stamp;
- char *serial;
- time_t stamp;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (ctrl->app_ctx)
- rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
- else
- rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
- if (rc)
- return map_to_assuan_status (rc);
- rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
- xfree (serial);
- if (rc < 0)
- return ASSUAN_Out_Of_Core;
- rc = 0;
- assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
- free (serial_and_stamp);
- return 0;
-}
-
-
-
-
-/* LEARN [--force]
-
- Learn all useful information of the currently inserted card. When
- used without the force options, the command might do an INQUIRE
- like this:
-
- INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
-
- The client should just send an "END" if the processing should go on
- or a "CANCEL" to force the function to terminate with a Cancel
- error message. The response of this command is a list of status
- lines formatted as this:
-
- S APPTYPE <apptype>
-
- This returns the type of the application, currently the strings:
-
- P15 = PKCS-15 structure used
- DINSIG = DIN SIG
- OPENPGP = OpenPGP card
-
- are implemented. These strings are aliases for the AID
-
- S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
-
- If there is no certificate yet stored on the card a single "X" is
- returned as the keygrip. In addition to the keypair info, information
- about all certificates stored on the card is also returned:
-
- S CERTINFO <certtype> <hexstring_with_id>
-
- Where CERTTYPE is a number indicating the type of certificate:
- 0 := Unknown
- 100 := Regular X.509 cert
- 101 := Trusted X.509 cert
- 102 := Useful X.509 cert
-
- For certain cards, more information will be returned:
-
- S KEY-FPR <no> <hexstring>
-
- For OpenPGP cards this returns the stored fingerprints of the
- keys. This can be used check whether a key is available on the
- card. NO may be 1, 2 or 3.
-
- S CA-FPR <no> <hexstring>
-
- Similar to above, these are the fingerprints of keys assumed to be
- ultimately trusted.
-
- S DISP-NAME <name_of_card_holder>
-
- The name of the card holder as stored on the card; percent
- aescaping takes place, spaces are encoded as '+'
-
- S PUBKEY-URL <url>
-
- The URL to be used for locating the entire public key.
-
-*/
-static int
-cmd_learn (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc = 0;
- int idx;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- /* Unless the force option is used we try a shortcut by identifying
- the card using a serial number and inquiring the client with
- that. The client may choose to cancel the operation if he already
- knows about this card */
- {
- char *serial_and_stamp;
- char *serial;
- time_t stamp;
-
- if (ctrl->app_ctx)
- rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
- else
- rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
- if (rc)
- return map_to_assuan_status (rc);
- rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
- xfree (serial);
- if (rc < 0)
- return ASSUAN_Out_Of_Core;
- rc = 0;
- assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
-
- if (!has_option (line, "--force"))
- {
- char *command;
-
- rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
- if (rc < 0)
- {
- free (serial_and_stamp);
- return ASSUAN_Out_Of_Core;
- }
- rc = 0;
- rc = assuan_inquire (ctx, command, NULL, NULL, 0);
- free (command); /* (must use standard free here) */
- if (rc)
- {
- if (rc != ASSUAN_Canceled)
- log_error ("inquire KNOWNCARDP failed: %s\n",
- assuan_strerror (rc));
- free (serial_and_stamp);
- return rc;
- }
- /* not canceled, so we have to proceeed */
- }
- free (serial_and_stamp);
- }
-
- /* Return information about the certificates. */
- if (ctrl->app_ctx)
- rc = -1; /* This information is not yet available for applications. */
- for (idx=0; !rc; idx++)
- {
- char *certid;
- int certtype;
-
- rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype);
- if (!rc)
- {
- char *buf;
-
- buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
- if (!buf)
- rc = out_of_core ();
- else
- {
- sprintf (buf, "%d %s", certtype, certid);
- assuan_write_status (ctx, "CERTINFO", buf);
- xfree (buf);
- }
- }
- xfree (certid);
- }
- if (rc == -1)
- rc = 0;
-
-
- /* Return information about the keys. */
- if (ctrl->app_ctx)
- rc = -1; /* This information is not yet available for applications. */
- for (idx=0; !rc; idx++)
- {
- unsigned char keygrip[20];
- char *keyid;
- int no_cert = 0;
-
- rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
- if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
- {
- /* this does happen with an incomplete personalized
- card; i.e. during the time we have stored the key on the
- card but not stored the certificate; probably becuase it
- has not yet been received back from the CA. Note that we
- must release KEYID in this case. */
- rc = 0;
- no_cert = 1;
- }
- if (!rc)
- {
- char *buf, *p;
-
- buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
- if (!buf)
- rc = out_of_core ();
- else
- {
- int i;
-
- if (no_cert)
- *p++ = 'X';
- else
- {
- for (i=0; i < 20; i++, p += 2)
- sprintf (p, "%02X", keygrip[i]);
- }
- *p++ = ' ';
- strcpy (p, keyid);
- assuan_write_status (ctx, "KEYPAIRINFO", buf);
- xfree (buf);
- }
- }
- xfree (keyid);
- }
- if (rc == -1)
- rc = 0;
-
- if (!rc && ctrl->app_ctx)
- rc = app_write_learn_status (ctrl->app_ctx, ctrl);
-
-
- return map_to_assuan_status (rc);
-}
-
-
-
-/* READCERT <hexified_certid>
-
- */
-static int
-cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char *cert;
- size_t ncert;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
- if (rc)
- {
- log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
- }
- if (!rc)
- {
- rc = assuan_send_data (ctx, cert, ncert);
- xfree (cert);
- if (rc)
- return rc;
- }
-
- return map_to_assuan_status (rc);
-}
-
-
-/* READKEY <hexified_certid>
-
- Return the public key for the given cert or key ID as an standard
- S-Expression. */
-static int
-cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char *cert = NULL;
- size_t ncert, n;
- KsbaCert kc = NULL;
- KsbaSexp p;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
- if (rc)
- {
- log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- kc = ksba_cert_new ();
- if (!kc)
- {
- rc = out_of_core ();
- xfree (cert);
- goto leave;
- }
- rc = ksba_cert_init_from_mem (kc, cert, ncert);
- if (rc)
- {
- log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc));
- rc = map_ksba_err (rc);
- goto leave;
- }
-
- p = ksba_cert_get_public_key (kc);
- if (!p)
- {
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- goto leave;
- }
-
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- rc = assuan_send_data (ctx, p, n);
- rc = map_assuan_err (rc);
- xfree (p);
-
-
- leave:
- ksba_cert_release (kc);
- xfree (cert);
- return map_to_assuan_status (rc);
-}
-
-
-
-
-/* SETDATA <hexstring>
-
- The client should use this command to tell us the data he want to
- sign. */
-static int
-cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int n;
- char *p;
- unsigned char *buf;
-
- /* parse the hexstring */
- for (p=line,n=0; hexdigitp (p); p++, n++)
- ;
- if (*p)
- return set_error (Parameter_Error, "invalid hexstring");
- if (!n)
- return set_error (Parameter_Error, "no data given");
- if ((n&1))
- return set_error (Parameter_Error, "odd number of digits");
- n /= 2;
- buf = xtrymalloc (n);
- if (!buf)
- return ASSUAN_Out_Of_Core;
-
- ctrl->in_data.value = buf;
- ctrl->in_data.valuelen = n;
- for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
- buf[n] = xtoi_2 (p);
- return 0;
-}
-
-
-
-static int
-pin_cb (void *opaque, const char *info, char **retstr)
-{
- ASSUAN_CONTEXT ctx = opaque;
- char *command;
- int rc;
- char *value;
- size_t valuelen;
-
- *retstr = NULL;
- log_debug ("asking for PIN '%s'\n", info);
-
- rc = asprintf (&command, "NEEDPIN %s", info);
- if (rc < 0)
- return out_of_core ();
-
- /* FIXME: Write an inquire function which returns the result in
- secure memory */
- rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
- free (command);
- if (rc)
- return map_assuan_err (rc);
-
- if (!valuelen || value[valuelen-1])
- {
- /* We require that the returned value is an UTF-8 string */
- xfree (value);
- return gpg_error (GPG_ERR_INV_RESPONSE);
- }
- *retstr = value;
- return 0;
-}
-
-
-/* PKSIGN <hexified_id>
-
- */
-static int
-cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char *outdata;
- size_t outdatalen;
- char *keyidstr;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- /* We have to use a copy of the key ID because the function may use
- the pin_cb which in turn uses the assuan line buffer and thus
- overwriting the original line with the keyid */
- keyidstr = strdup (line);
- if (!keyidstr)
- return ASSUAN_Out_Of_Core;
-
- if (ctrl->app_ctx)
- rc = app_sign (ctrl->app_ctx,
- keyidstr, GCRY_MD_SHA1,
- pin_cb, ctx,
- ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
- else
- rc = card_sign (ctrl->card_ctx,
- keyidstr, GCRY_MD_SHA1,
- pin_cb, ctx,
- ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
- free (keyidstr);
- if (rc)
- {
- log_error ("card_sign failed: %s\n", gpg_strerror (rc));
- }
- else
- {
- rc = assuan_send_data (ctx, outdata, outdatalen);
- xfree (outdata);
- if (rc)
- return rc; /* that is already an assuan error code */
- }
-
- return map_to_assuan_status (rc);
-}
-
-/* PKAUTH <hexified_id>
-
- */
-static int
-cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char *outdata;
- size_t outdatalen;
- char *keyidstr;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (!ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- /* We have to use a copy of the key ID because the function may use
- the pin_cb which in turn uses the assuan line buffer and thus
- overwriting the original line with the keyid */
- keyidstr = strdup (line);
- if (!keyidstr)
- return ASSUAN_Out_Of_Core;
-
- rc = app_auth (ctrl->app_ctx,
- keyidstr,
- pin_cb, ctx,
- ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
- free (keyidstr);
- if (rc)
- {
- log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc));
- }
- else
- {
- rc = assuan_send_data (ctx, outdata, outdatalen);
- xfree (outdata);
- if (rc)
- return rc; /* that is already an assuan error code */
- }
-
- return map_to_assuan_status (rc);
-}
-
-/* PKDECRYPT <hexified_id>
-
- */
-static int
-cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- unsigned char *outdata;
- size_t outdatalen;
- char *keyidstr;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- keyidstr = strdup (line);
- if (!keyidstr)
- return ASSUAN_Out_Of_Core;
- if (ctrl->app_ctx)
- rc = app_decipher (ctrl->app_ctx,
- keyidstr,
- pin_cb, ctx,
- ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
- else
- rc = card_decipher (ctrl->card_ctx,
- keyidstr,
- pin_cb, ctx,
- ctrl->in_data.value, ctrl->in_data.valuelen,
- &outdata, &outdatalen);
- free (keyidstr);
- if (rc)
- {
- log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
- }
- else
- {
- rc = assuan_send_data (ctx, outdata, outdatalen);
- xfree (outdata);
- if (rc)
- return rc; /* that is already an assuan error code */
- }
-
- return map_to_assuan_status (rc);
-}
-
-
-/* SETATTR <name> <value>
-
- This command is used to store data on a a smartcard. The allowed
- names and values are depend on the currently selected smartcard
- application. NAME and VALUE must be percent and '+' escaped.
-
- However, the curent implementation assumes that Name is not escaped;
- this works as long as noone uses arbitrary escaping.
-
- A PIN will be requested for most NAMEs. See the corresponding
- setattr function of the actually used application (app-*.c) for
- details. */
-static int
-cmd_setattr (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- char *keyword;
- int keywordlen;
- size_t nbytes;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- keyword = line;
- for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
- ;
- if (*line)
- *line++ = 0;
- while (spacep (line))
- line++;
- nbytes = percent_plus_unescape (line);
-
- rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
-
- return map_to_assuan_status (rc);
-}
-
-/* GENKEY [--force] <no>
-
- Generate a key on-card identified by NO, which is application
- specific. Return values are application specific. For OpenPGP
- cards 2 status lines are returned:
-
- S KEY-FPR <hexstring>
- S KEY-CREATED-AT <seconds_since_epoch>
- S KEY-DATA [p|n] <hexdata>
-
-
- --force is required to overwriet an already existing key. The
- KEY-CREATED-AT is required for further processing because it is
- part of the hashed key material for the fingerprint.
-
- The public part of the key can also later be retrieved using the
- READKEY command.
-
- */
-static int
-cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- char *keyno;
- int force = has_option (line, "--force");
-
- /* Skip over options. */
- while ( *line == '-' && line[1] == '-' )
- {
- while (!spacep (line))
- line++;
- while (spacep (line))
- line++;
- }
- if (!*line)
- return set_error (Parameter_Error, "no key number given");
- keyno = line;
- while (!spacep (line))
- line++;
- *line = 0;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (!ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* RANDOM <nbytes>
-
- Get NBYTES of random from the card and send them back as data.
-*/
-static int
-cmd_random (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- size_t nbytes;
- unsigned char *buffer;
-
- if (!*line)
- return set_error (Parameter_Error, "number of requested bytes missing");
- nbytes = strtoul (line, NULL, 0);
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (!ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- buffer = xtrymalloc (nbytes);
- if (!buffer)
- return ASSUAN_Out_Of_Core;
-
- rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer);
- if (!rc)
- {
- rc = assuan_send_data (ctx, buffer, nbytes);
- xfree (buffer);
- return rc; /* that is already an assuan error code */
- }
- xfree (buffer);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* PASSWD [--reset] <chvno>
-
- Change the PIN or reset thye retry counter of the card holder
- verfication vector CHVNO. */
-static int
-cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- char *chvnostr;
- int reset_mode = has_option (line, "--reset");
-
- /* Skip over options. */
- while (*line == '-' && line[1] == '-')
- {
- while (!spacep (line))
- line++;
- while (spacep (line))
- line++;
- }
- if (!*line)
- return set_error (Parameter_Error, "no CHV number given");
- chvnostr = line;
- while (!spacep (line))
- line++;
- *line = 0;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (!ctrl->app_ctx)
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
-
- rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx
-);
- if (rc)
- log_error ("command passwd failed: %s\n", gpg_strerror (rc));
- return map_to_assuan_status (rc);
-}
-
-
-
-
-/* Tell the assuan library about our commands */
-static int
-register_commands (ASSUAN_CONTEXT ctx)
-{
- static struct {
- const char *name;
- int (*handler)(ASSUAN_CONTEXT, char *line);
- } table[] = {
- { "SERIALNO", cmd_serialno },
- { "LEARN", cmd_learn },
- { "READCERT", cmd_readcert },
- { "READKEY", cmd_readkey },
- { "SETDATA", cmd_setdata },
- { "PKSIGN", cmd_pksign },
- { "PKAUTH", cmd_pkauth },
- { "PKDECRYPT", cmd_pkdecrypt },
- { "INPUT", NULL },
- { "OUTPUT", NULL },
- { "SETATTR", cmd_setattr },
- { "GENKEY", cmd_genkey },
- { "RANDOM", cmd_random },
- { "PASSWD", cmd_passwd },
- { NULL }
- };
- int i, rc;
-
- for (i=0; table[i].name; i++)
- {
- rc = assuan_register_command (ctx, table[i].name, table[i].handler);
- if (rc)
- return rc;
- }
- assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
-
- assuan_register_reset_notify (ctx, reset_notify);
- assuan_register_option_handler (ctx, option_handler);
- return 0;
-}
-
-
-/* Startup the server. If LISTEN_FD is given as -1, this is simple
- piper server, otherwise it is a regular server */
-void
-scd_command_handler (int listen_fd)
-{
- int rc;
- ASSUAN_CONTEXT ctx;
- struct server_control_s ctrl;
-
- memset (&ctrl, 0, sizeof ctrl);
- scd_init_default_ctrl (&ctrl);
-
- if (listen_fd == -1)
- {
- int filedes[2];
-
- filedes[0] = 0;
- filedes[1] = 1;
- rc = assuan_init_pipe_server (&ctx, filedes);
- }
- else
- {
- rc = assuan_init_socket_server (&ctx, listen_fd);
- }
- if (rc)
- {
- log_error ("failed to initialize the server: %s\n",
- assuan_strerror(rc));
- scd_exit (2);
- }
- rc = register_commands (ctx);
- if (rc)
- {
- log_error ("failed to register commands with Assuan: %s\n",
- assuan_strerror(rc));
- scd_exit (2);
- }
- assuan_set_pointer (ctx, &ctrl);
- ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
- ctrl.server_local->assuan_ctx = ctx;
-
- if (DBG_ASSUAN)
- assuan_set_log_stream (ctx, log_get_stream ());
-
- for (;;)
- {
- rc = assuan_accept (ctx);
- if (rc == -1)
- {
- break;
- }
- else if (rc)
- {
- log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
- break;
- }
-
- rc = assuan_process (ctx);
- if (rc)
- {
- log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
- continue;
- }
- }
- reset_notify (ctx); /* used for cleanup */
-
- assuan_deinit_server (ctx);
-}
-
-
-/* Send a line with status information via assuan and escape all given
- buffers. The variable elements are pairs of (char *, size_t),
- terminated with a (NULL, 0). */
-void
-send_status_info (CTRL ctrl, const char *keyword, ...)
-{
- va_list arg_ptr;
- const unsigned char *value;
- size_t valuelen;
- char buf[950], *p;
- size_t n;
- ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
-
- va_start (arg_ptr, keyword);
-
- p = buf;
- n = 0;
- while ( (value = va_arg (arg_ptr, const unsigned char *)) )
- {
- valuelen = va_arg (arg_ptr, size_t);
- if (!valuelen)
- continue; /* empty buffer */
- if (n)
- {
- *p++ = ' ';
- n++;
- }
- for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
- {
- if (*value < ' ' || *value == '+')
- {
- sprintf (p, "%%%02X", *value);
- p += 3;
- }
- else if (*value == ' ')
- *p++ = '+';
- else
- *p++ = *value;
- }
- }
- *p = 0;
- assuan_write_status (ctx, keyword, buf);
-
- va_end (arg_ptr);
-}
-
diff --git a/scd/iso7816.c b/scd/iso7816.c
deleted file mode 100644
index 8903d8a5c..000000000
--- a/scd/iso7816.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/* iso7816.c - ISO 7816 commands
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-
-#include "scdaemon.h"
-#include "iso7816.h"
-#include "apdu.h"
-
-#define CMD_SELECT_FILE 0xA4
-#define CMD_VERIFY 0x20
-#define CMD_CHANGE_REFERENCE_DATA 0x24
-#define CMD_RESET_RETRY_COUNTER 0x2C
-#define CMD_GET_DATA 0xCA
-#define CMD_PUT_DATA 0xDA
-#define CMD_PSO 0x2A
-#define CMD_INTERNAL_AUTHENTICATE 0x88
-#define CMD_GENERATE_KEYPAIR 0x47
-#define CMD_GET_CHALLENGE 0x84
-
-static gpg_error_t
-map_sw (int sw)
-{
- gpg_err_code_t ec;
-
- switch (sw)
- {
- case SW_EEPROM_FAILURE: ec = GPG_ERR_HARDWARE; break;
- case SW_WRONG_LENGTH: ec = GPG_ERR_INV_VALUE; break;
- case SW_CHV_WRONG: ec = GPG_ERR_BAD_PIN; break;
- case SW_CHV_BLOCKED: ec = GPG_ERR_PIN_BLOCKED; break;
- case SW_USE_CONDITIONS: ec = GPG_ERR_USE_CONDITIONS; break;
- case SW_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break;
- case SW_BAD_PARAMETER: ec = GPG_ERR_INV_VALUE; break;
- case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break;
- case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break;
- case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break;
- case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break;
- case SW_SUCCESS: ec = 0; break;
-
- case SW_HOST_OUT_OF_CORE: ec = GPG_ERR_ENOMEM; break;
- case SW_HOST_INV_VALUE: ec = GPG_ERR_INV_VALUE; break;
- case SW_HOST_INCOMPLETE_CARD_RESPONSE: ec = GPG_ERR_CARD; break;
- default:
- if ((sw & 0x010000))
- ec = GPG_ERR_GENERAL; /* Should not happen. */
- else if ((sw & 0xff00) == SW_MORE_DATA)
- ec = 0; /* This should actually never been seen here. */
- else
- ec = GPG_ERR_CARD;
- }
- return gpg_error (ec);
-}
-
-/* This function is specialized version of the SELECT FILE command.
- SLOT is the card and reader as created for example by
- apdu_open_reader (), AID is a buffer of size AIDLEN holding the
- requested application ID. The function can't be used to enumerate
- AIDs and won't return the AID on success. The return value is 0
- for okay or GNUPG error code. Note that ISO error codes are
- internally mapped. */
-gpg_error_t
-iso7816_select_application (int slot, const char *aid, size_t aidlen)
-{
- int sw;
-
- sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
- return map_sw (sw);
-}
-
-
-/* Perform a VERIFY command on SLOT using the card holder verification
- vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */
-gpg_error_t
-iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
-{
- int sw;
-
- sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
- return map_sw (sw);
-}
-
-/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
- verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
- 0), a "change reference data" is done, otherwise an "exchange
- reference data". The new reference data is expected in NEWCHV of
- length NEWCHVLEN. */
-gpg_error_t
-iso7816_change_reference_data (int slot, int chvno,
- const char *oldchv, size_t oldchvlen,
- const char *newchv, size_t newchvlen)
-{
- int sw;
- char *buf;
-
- if ((!oldchv && oldchvlen)
- || (oldchv && !oldchvlen)
- || !newchv || !newchvlen )
- return gpg_error (GPG_ERR_INV_VALUE);
-
- buf = xtrymalloc (oldchvlen + newchvlen);
- if (!buf)
- return out_of_core ();
- if (oldchvlen)
- memcpy (buf, oldchv, oldchvlen);
- memcpy (buf+oldchvlen, newchv, newchvlen);
-
- sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
- oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
- xfree (buf);
- return map_sw (sw);
-
-}
-
-gpg_error_t
-iso7816_reset_retry_counter (int slot, int chvno,
- const char *newchv, size_t newchvlen)
-{
- int sw;
-
- if (!newchv || !newchvlen )
- return gpg_error (GPG_ERR_INV_VALUE);
-
- sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER,
- 2, chvno, newchvlen, newchv);
- return map_sw (sw);
-}
-
-
-/* Perform a GET DATA command requesting TAG and storing the result in
- a newly allocated buffer at the address passed by RESULT. Return
- the length of this data at the address of RESULTLEN. */
-gpg_error_t
-iso7816_get_data (int slot, int tag,
- unsigned char **result, size_t *resultlen)
-{
- int sw;
-
- if (!result || !resultlen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *result = NULL;
- *resultlen = 0;
-
- sw = apdu_send (slot, 0x00, CMD_GET_DATA,
- ((tag >> 8) & 0xff), (tag & 0xff), -1, NULL,
- result, resultlen);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (*result);
- *result = NULL;
- *resultlen = 0;
- return map_sw (sw);
- }
-
- return 0;
-}
-
-
-/* Perform a PUT DATA command on card in SLOT. Write DATA of length
- DATALEN to TAG. */
-gpg_error_t
-iso7816_put_data (int slot, int tag,
- const unsigned char *data, size_t datalen)
-{
- int sw;
-
- sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA,
- ((tag >> 8) & 0xff), (tag & 0xff),
- datalen, data);
- return map_sw (sw);
-}
-
-
-/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On
- success 0 is returned and the data is availavle in a newly
- allocated buffer stored at RESULT with its length stored at
- RESULTLEN. */
-gpg_error_t
-iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- int sw;
-
- if (!data || !datalen || !result || !resultlen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *result = NULL;
- *resultlen = 0;
-
- sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, data,
- result, resultlen);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (*result);
- *result = NULL;
- *resultlen = 0;
- return map_sw (sw);
- }
-
- return 0;
-}
-
-
-/* Perform the security operation DECIPHER. On
- success 0 is returned and the plaintext is available in a newly
- allocated buffer stored at RESULT with its length stored at
- RESULTLEN. */
-gpg_error_t
-iso7816_decipher (int slot, const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- int sw;
- unsigned char *buf;
-
- if (!data || !datalen || !result || !resultlen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *result = NULL;
- *resultlen = 0;
-
- /* We need to prepend the padding indicator. */
- buf = xtrymalloc (datalen + 1);
- if (!buf)
- return out_of_core ();
- *buf = 0; /* Padding indicator. */
- memcpy (buf+1, data, datalen);
- sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf,
- result, resultlen);
- xfree (buf);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (*result);
- *result = NULL;
- *resultlen = 0;
- return map_sw (sw);
- }
-
- return 0;
-}
-
-
-gpg_error_t
-iso7816_internal_authenticate (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- int sw;
-
- if (!data || !datalen || !result || !resultlen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *result = NULL;
- *resultlen = 0;
-
- sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0,
- datalen, data, result, resultlen);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (*result);
- *result = NULL;
- *resultlen = 0;
- return map_sw (sw);
- }
-
- return 0;
-}
-
-
-static gpg_error_t
-generate_keypair (int slot, int readonly,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- int sw;
-
- if (!data || !datalen || !result || !resultlen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *result = NULL;
- *resultlen = 0;
-
- sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0,
- datalen, data, result, resultlen);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (*result);
- *result = NULL;
- *resultlen = 0;
- return map_sw (sw);
- }
-
- return 0;
-}
-
-
-gpg_error_t
-iso7816_generate_keypair (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- return generate_keypair (slot, 0, data, datalen, result, resultlen);
-}
-
-
-gpg_error_t
-iso7816_read_public_key (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen)
-{
- return generate_keypair (slot, 1, data, datalen, result, resultlen);
-}
-
-
-
-gpg_error_t
-iso7816_get_challenge (int slot, int length, unsigned char *buffer)
-{
- int sw;
- unsigned char *result;
- size_t resultlen, n;
-
- if (!buffer || length < 1)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- do
- {
- result = NULL;
- n = length > 254? 254 : length;
- sw = apdu_send_le (slot, 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL,
- n,
- &result, &resultlen);
- if (sw != SW_SUCCESS)
- {
- /* Make sure that pending buffers are released. */
- xfree (result);
- return map_sw (sw);
- }
- if (resultlen > n)
- resultlen = n;
- memcpy (buffer, result, resultlen);
- buffer += resultlen;
- length -= resultlen;
- xfree (result);
- }
- while (length > 0);
-
- return 0;
-}
diff --git a/scd/iso7816.h b/scd/iso7816.h
deleted file mode 100644
index d7e77a101..000000000
--- a/scd/iso7816.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* iso7816.h - ISO 7816 commands
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef ISO7816_H
-#define ISO7816_H
-
-gpg_error_t iso7816_select_application (int slot,
- const char *aid, size_t aidlen);
-gpg_error_t iso7816_verify (int slot,
- int chvno, const char *chv, size_t chvlen);
-gpg_error_t iso7816_change_reference_data (int slot, int chvno,
- const char *oldchv, size_t oldchvlen,
- const char *newchv, size_t newchvlen);
-gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
- const char *newchv, size_t newchvlen);
-gpg_error_t iso7816_get_data (int slot, int tag,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_put_data (int slot, int tag,
- const unsigned char *data, size_t datalen);
-gpg_error_t iso7816_compute_ds (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_decipher (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_internal_authenticate (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_generate_keypair (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_read_public_key (int slot,
- const unsigned char *data, size_t datalen,
- unsigned char **result, size_t *resultlen);
-gpg_error_t iso7816_get_challenge (int slot,
- int length, unsigned char *buffer);
-
-
-#endif /*ISO7816_H*/
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c
deleted file mode 100644
index 9caf39a8a..000000000
--- a/scd/sc-copykeys.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* sc-copykeys.c - A tool to store keys on a smartcard.
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#define JNLIB_NEED_LOG_LOGV
-#include "scdaemon.h"
-#include <gcrypt.h>
-
-#include "../common/ttyio.h"
-#include "../common/simple-pwquery.h"
-#include "apdu.h" /* for open_reader */
-#include "atr.h"
-#include "app-common.h"
-
-#define _(a) (a)
-
-
-enum cmd_and_opt_values
-{ oVerbose = 'v',
- oReaderPort = 500,
- oDebug,
- oDebugAll,
-
-aTest };
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 301, NULL, 0, "@Options:\n " },
-
- { oVerbose, "verbose", 0, "verbose" },
- { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"},
- { oDebug, "debug" ,4|16, "set debugging flags"},
- { oDebugAll, "debug-all" ,0, "enable full debugging"},
- {0}
-};
-
-
-static void copykeys (APP app, const char *fname);
-
-
-static const char *
-my_strusage (int level)
-{
- const char *p;
- switch (level)
- {
- case 11: p = "sc-copykeys (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: sc-copykeys [options] (-h for help)\n");
- break;
- case 41: p = _("Syntax: sc-copykeys [options] "
- "file-with-key\n"
- "Copy keys to a smartcards\n");
- break;
-
- default: p = NULL;
- }
- return p;
-}
-
-/* Used by gcry for logging */
-static void
-my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
-{
- /* translate the log levels */
- switch (level)
- {
- case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
- case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
- case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
- default: level = JNLIB_LOG_ERROR; break;
- }
- log_logv (level, fmt, arg_ptr);
-}
-
-
-int
-main (int argc, char **argv )
-{
- ARGPARSE_ARGS pargs;
- int slot, rc;
- int reader_port = 32768; /* First USB reader. */
- struct app_ctx_s appbuf;
-
- memset (&appbuf, 0, sizeof appbuf);
-
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- log_set_prefix ("sc-copykeys", 1);
-
- /* check that the libraries are suitable. Do it here because
- the option parsing may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
-
- gcry_set_log_handler (my_gcry_logger, NULL);
- gcry_control (GCRYCTL_DISABLE_SECMEM, 0); /* FIXME - we want to use it */
- /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
-
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags= 1; /* do not remove the args */
- while (arg_parse (&pargs, opts) )
- {
- switch (pargs.r_opt)
- {
- case oVerbose: opt.verbose++; break;
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
- default : pargs.err = 2; break;
- }
- }
- if (log_get_errorcount(0))
- exit(2);
-
- if (argc != 1)
- usage (1);
-
- slot = apdu_open_reader (reader_port);
- if (slot == -1)
- exit (1);
-
- /* FIXME: Use select_application. */
- appbuf.slot = slot;
- rc = app_select_openpgp (&appbuf, &appbuf.serialno, &appbuf.serialnolen);
- if (rc)
- {
- log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
- exit (1);
- }
- appbuf.initialized = 1;
- log_info ("openpgp application selected\n");
-
- copykeys (&appbuf, *argv);
-
-
- return 0;
-}
-
-
-
-void
-send_status_info (CTRL ctrl, const char *keyword, ...)
-{
- /* DUMMY */
-}
-
-
-
-static char *
-read_file (const char *fname, size_t *r_length)
-{
- FILE *fp;
- struct stat st;
- char *buf;
- size_t buflen;
-
- fp = fname? fopen (fname, "rb") : stdin;
- if (!fp)
- {
- log_error ("can't open `%s': %s\n",
- fname? fname: "[stdin]", strerror (errno));
- return NULL;
- }
-
- if (fstat (fileno(fp), &st))
- {
- log_error ("can't stat `%s': %s\n",
- fname? fname: "[stdin]", strerror (errno));
- if (fname)
- fclose (fp);
- return NULL;
- }
-
- buflen = st.st_size;
- buf = xmalloc (buflen+1);
- if (fread (buf, buflen, 1, fp) != 1)
- {
- log_error ("error reading `%s': %s\n",
- fname? fname: "[stdin]", strerror (errno));
- if (fname)
- fclose (fp);
- xfree (buf);
- return NULL;
- }
- if (fname)
- fclose (fp);
-
- *r_length = buflen;
- return buf;
-}
-
-
-static gcry_sexp_t
-read_key (const char *fname)
-{
- char *buf;
- size_t buflen;
- gcry_sexp_t private;
- int rc;
-
- buf = read_file (fname, &buflen);
- if (!buf)
- return NULL;
-
- rc = gcry_sexp_new (&private, buf, buflen, 1);
- if (rc)
- {
- log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc));
- return NULL;
- }
- xfree (buf);
-
- return private;
-}
-
-
-
-static gcry_mpi_t *
-sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created)
-{
- gcry_sexp_t list, l2;
- const char *name;
- const char *s;
- size_t n;
- int i, idx;
- const char *elems;
- gcry_mpi_t *array;
-
- *created = 0;
- list = gcry_sexp_find_token (sexp, "private-key", 0 );
- if(!list)
- return NULL;
-
- /* quick hack to get the creation time. */
- l2 = gcry_sexp_find_token (list, "created", 0);
- if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n)))
- {
- char *tmp = xmalloc (n+1);
- memcpy (tmp, name, n);
- tmp[n] = 0;
- *created = strtoul (tmp, NULL, 10);
- xfree (tmp);
- }
- gcry_sexp_release (l2);
- l2 = gcry_sexp_cadr (list);
- gcry_sexp_release (list);
- list = l2;
- name = gcry_sexp_nth_data (list, 0, &n);
- if(!name || n != 3 || memcmp (name, "rsa", 3))
- {
- gcry_sexp_release (list);
- return NULL;
- }
-
- /* Parameter names used with RSA. */
- elems = "nedpqu";
- array = xcalloc (strlen(elems) + 1, sizeof *array);
- for (idx=0, s=elems; *s; s++, idx++ )
- {
- l2 = gcry_sexp_find_token (list, s, 1);
- if (!l2)
- {
- for (i=0; i<idx; i++)
- gcry_mpi_release (array[i]);
- xfree (array);
- gcry_sexp_release (list);
- return NULL; /* required parameter not found */
- }
- array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (l2);
- if (!array[idx])
- {
- for (i=0; i<idx; i++)
- gcry_mpi_release (array[i]);
- xfree (array);
- gcry_sexp_release (list);
- return NULL; /* required parameter is invalid */
- }
- }
-
- gcry_sexp_release (list);
- return array;
-}
-
-
-/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
-static int
-fpr_is_zero (const char *fpr)
-{
- int i;
-
- for (i=0; i < 20 && !fpr[i]; i++)
- ;
- return (i == 20);
-}
-
-
-static void
-show_sha1_fpr (const unsigned char *fpr)
-{
- int i;
-
- if (fpr)
- {
- for (i=0; i < 20 ; i+=2, fpr += 2 )
- {
- if (i == 10 )
- tty_printf (" ");
- tty_printf (" %02X%02X", *fpr, fpr[1]);
- }
- }
- else
- tty_printf (" [none]");
- tty_printf ("\n");
-}
-
-/* Query the card, show a list of already stored keys and ask the user
- where to store the key. Returns the key number or 0 for cancel
- operation. */
-static int
-query_card (APP app)
-{
- int keyno = 0;
- char *serialno, *disp_name, *pubkey_url;
- unsigned char *fpr1, *fpr2, *fpr3;
-
-
- if (app_openpgp_cardinfo (app,
- &serialno,
- &disp_name,
- &pubkey_url,
- &fpr1, &fpr2, &fpr3))
- return 0;
-
-
- for (;;)
- {
- char *answer;
-
- tty_printf ("\n");
-
- tty_printf ("Serial number ....: %s\n",
- serialno? serialno : "[none]");
- tty_printf ("Name of cardholder: %s\n",
- disp_name && *disp_name? disp_name : "[not set]");
- tty_printf ("URL of public key : %s\n",
- pubkey_url && *pubkey_url? pubkey_url : "[not set]");
- tty_printf ("Signature key ....:");
- show_sha1_fpr (fpr1);
- tty_printf ("Encryption key....:");
- show_sha1_fpr (fpr2);
- tty_printf ("Authentication key:");
- show_sha1_fpr (fpr3);
-
- tty_printf ("\n"
- "1 - store as signature key and reset usage counter\n"
- "2 - store as encryption key\n"
- "3 - store as authentication key\n"
- "Q - quit\n"
- "\n");
-
- answer = tty_get("Your selection? ");
- tty_kill_prompt();
- if (strlen (answer) != 1)
- ;
- else if ( *answer == '1' )
- {
- if ( (fpr1 && !fpr_is_zero (fpr1)) )
- {
- tty_printf ("\n");
- log_error ("WARNING: signature key does already exists!\n");
- tty_printf ("\n");
- if ( tty_get_answer_is_yes ("Replace existing key? ") )
- {
- keyno = 1;
- break;
- }
- }
- else
- {
- keyno = 1;
- break;
- }
- }
- else if ( *answer == '2' )
- {
- if ( (fpr2 && !fpr_is_zero (fpr2)) )
- {
- tty_printf ("\n");
- log_error ("WARNING: encryption key does already exists!\n");
- tty_printf ("\n");
- if ( tty_get_answer_is_yes ("Replace existing key? ") )
- {
- keyno = 2;
- break;
- }
- }
- else
- {
- keyno = 2;
- break;
- }
- }
- else if ( *answer == '3' )
- {
- if ( (fpr3 && !fpr_is_zero (fpr3)) )
- {
- tty_printf ("\n");
- log_error ("WARNING: authentication key does already exists!\n");
- tty_printf ("\n");
- if ( tty_get_answer_is_yes ("Replace existing key? ") )
- {
- keyno = 3;
- break;
- }
- }
- else
- {
- keyno = 3;
- break;
- }
- }
- else if ( *answer == 'q' || *answer == 'Q')
- {
- keyno = 0;
- break;
- }
- }
-
- xfree (serialno);
- xfree (disp_name);
- xfree (pubkey_url);
- xfree (fpr1);
- xfree (fpr2);
- xfree (fpr3);
-
- return keyno;
-}
-
-
-/* Callback function to ask for a PIN. */
-static int
-pincb (void *arg, const char *prompt, char **pinvalue)
-{
- char *pin = xstrdup ("12345678");
-
-/* pin = simple_pwquery (NULL, NULL, prompt, */
-/* "We need the admin's PIN to store the key on the card", */
-/* NULL); */
-/* if (!pin) */
-/* return gpg_error (GPG_ERR_CANCELED); */
-
-
-
- *pinvalue = pin;
- return 0;
-}
-
-
-/* This function expects a file (or NULL for stdin) with the secret
- and public key parameters. This file should consist of an
- S-expression as used by gpg-agent. Only the unprotected format is
- supported. Example:
-
- (private-key
- (rsa
- (n #00e0ce9..[some bytes not shown]..51#)
- (e #010001#)
- (d #046129F..[some bytes not shown]..81#)
- (p #00e861b..[some bytes not shown]..f1#)
- (q #00f7a7c..[some bytes not shown]..61#)
- (u #304559a..[some bytes not shown]..9b#))
- (uri http://foo.bar x-foo:whatever_you_want))
-
-*/
-static void
-copykeys (APP app, const char *fname)
-{
- int rc;
- gcry_sexp_t private;
- gcry_mpi_t *mpis, rsa_n, rsa_e, rsa_p, rsa_q;
- unsigned int nbits;
- size_t n;
- unsigned char *template, *tp;
- unsigned char m[128], e[4];
- size_t mlen, elen;
- unsigned long creation_date;
- time_t created_at;
- int keyno;
-
- if (!strcmp (fname, "-"))
- fname = NULL;
-
- private = read_key (fname);
- if (!private)
- exit (1);
-
- mpis = sexp_to_kparms (private, &creation_date);
- if (!creation_date)
- {
- log_info ("no creation date found - assuming current date\n");
- created_at = time (NULL);
- }
- else
- created_at = creation_date;
- gcry_sexp_release (private);
- if (!mpis)
- {
- log_error ("invalid structure of key file or not RSA\n");
- exit (1);
- }
- /* MPIS is now an array with the key parameters as defined by OpenPGP. */
- rsa_n = mpis[0];
- rsa_e = mpis[1];
- gcry_mpi_release (mpis[2]);
- rsa_p = mpis[3];
- rsa_q = mpis[4];
- gcry_mpi_release (mpis[5]);
- xfree (mpis);
-
- nbits = gcry_mpi_get_nbits (rsa_e);
- if (nbits < 2 || nbits > 32)
- {
- log_error ("public exponent too large (more than 32 bits)\n");
- goto failure;
- }
- nbits = gcry_mpi_get_nbits (rsa_p);
- if (nbits != 512)
- {
- log_error ("length of first RSA prime is not 512\n");
- goto failure;
- }
- nbits = gcry_mpi_get_nbits (rsa_q);
- if (nbits != 512)
- {
- log_error ("length of second RSA prime is not 512\n");
- goto failure;
- }
-
- nbits = gcry_mpi_get_nbits (rsa_n);
- if (nbits != 1024)
- {
- log_error ("length of RSA modulus is not 1024\n");
- goto failure;
- }
-
- keyno = query_card (app);
- if (!keyno)
- goto failure;
-
- /* Build the private key template as described in section 4.3.3.6 of
- the specs.
- 0xC0 <length> public exponent
- 0xC1 <length> prime p
- 0xC2 <length> prime q */
- template = tp = xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64);
- *tp++ = 0xC0;
- *tp++ = 4;
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 4, &n, rsa_e);
- if (rc)
- {
- log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
- goto failure;
- }
- assert (n <= 4);
- memcpy (e, tp, n);
- elen = n;
- if (n != 4)
- {
- memmove (tp+4-n, tp, 4-n);
- memset (tp, 0, 4-n);
- }
- tp += 4;
-
- *tp++ = 0xC1;
- *tp++ = 64;
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_p);
- if (rc)
- {
- log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
- goto failure;
- }
- assert (n == 64);
- tp += 64;
-
- *tp++ = 0xC2;
- *tp++ = 64;
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_q);
- if (rc)
- {
- log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
- goto failure;
- }
- assert (n == 64);
- tp += 64;
- assert (tp - template == 138);
-
- /* (we need the modulus to calculate the fingerprint) */
- rc = gcry_mpi_print (GCRYMPI_FMT_USG, m, 128, &n, rsa_n);
- if (rc)
- {
- log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
- goto failure;
- }
- assert (n == 128);
- mlen = 128;
-
-
- rc = app_openpgp_storekey (app, keyno,
- template, tp - template,
- created_at,
- m, mlen,
- e, elen,
- pincb, NULL);
-
- if (rc)
- {
- log_error ("error storing key: %s\n", gpg_strerror (rc));
- goto failure;
- }
- log_info ("key successfully stored\n");
- {
- unsigned char *mm, *ee;
- size_t mmlen, eelen;
- int i;
-
- rc = app_openpgp_readkey (app, keyno, &mm, &mmlen, &ee, &eelen);
- if (rc)
- {
- log_error ("error reading key back: %s\n", gpg_strerror (rc));
- goto failure;
- }
-
- /* Strip leading zeroes. */
- for (i=0; i < mmlen && !mm[i]; i++)
- ;
- mmlen -= i;
- memmove (mm, mm+i, mmlen);
- for (i=0; i < eelen && !ee[i]; i++)
- ;
- eelen -= i;
- memmove (ee, ee+i, eelen);
-
- if (eelen != elen || mmlen != mlen)
- {
- log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n",
- (unsigned int)mlen, (unsigned int)mmlen,
- (unsigned int)elen, (unsigned int)eelen);
- xfree (mm);
- xfree (ee);
- goto failure;
- }
-
- if (memcmp (m, mm, mlen))
- {
- log_error ("key parameter n mismatch\n");
- log_printhex ("original n: ", m, mlen);
- log_printhex (" copied n: ", mm, mlen);
- xfree (mm);
- xfree (ee);
- goto failure;
- }
- if (memcmp (e, ee, elen))
- {
- log_error ("key parameter e mismatch\n");
- log_printhex ("original e: ", e, elen);
- log_printhex (" copied e: ", ee, elen);
- xfree (mm);
- xfree (ee);
- goto failure;
- }
- xfree (mm);
- xfree (ee);
- }
-
-
- gcry_mpi_release (rsa_e);
- gcry_mpi_release (rsa_p);
- gcry_mpi_release (rsa_q);
- gcry_mpi_release (rsa_n);
- return;
-
- failure:
- gcry_mpi_release (rsa_e);
- gcry_mpi_release (rsa_p);
- gcry_mpi_release (rsa_q);
- gcry_mpi_release (rsa_n);
- exit (1);
-}
-
-
diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c
deleted file mode 100644
index e8f0eb83c..000000000
--- a/scd/sc-investigate.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* sc-investigate.c - A tool to look around on smartcards.
- * Copyright (C) 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#define JNLIB_NEED_LOG_LOGV
-#include "scdaemon.h"
-#include <gcrypt.h>
-
-#include "apdu.h" /* for open_reader */
-#include "atr.h"
-#include "app-common.h"
-
-#define _(a) (a)
-
-
-enum cmd_and_opt_values
-{ oVerbose = 'v',
- oReaderPort = 500,
- oDebug,
- oDebugAll,
-
- oGenRandom,
-
-aTest };
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 301, NULL, 0, "@Options:\n " },
-
- { oVerbose, "verbose", 0, "verbose" },
- { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"},
- { oDebug, "debug" ,4|16, "set debugging flags"},
- { oDebugAll, "debug-all" ,0, "enable full debugging"},
- { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"},
- {0}
-};
-
-static const char *
-my_strusage (int level)
-{
- const char *p;
- switch (level)
- {
- case 11: p = "sc-investigate (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: sc-investigate [options] (-h for help)\n");
- break;
- case 41: p = _("Syntax: sc-investigate [options] [args]]\n"
- "Have a look at smartcards\n");
- break;
-
- default: p = NULL;
- }
- return p;
-}
-
-/* Used by gcry for logging */
-static void
-my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
-{
- /* translate the log levels */
- switch (level)
- {
- case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
- case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
- case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
- default: level = JNLIB_LOG_ERROR; break;
- }
- log_logv (level, fmt, arg_ptr);
-}
-
-
-int
-main (int argc, char **argv )
-{
- ARGPARSE_ARGS pargs;
- int slot, rc;
- int reader_port = 32768; /* First USB reader. */
- struct app_ctx_s appbuf;
- unsigned long gen_random = 0;
-
- memset (&appbuf, 0, sizeof appbuf);
-
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- log_set_prefix ("sc-investigate", 1);
-
- /* check that the libraries are suitable. Do it here because
- the option parsing may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
-
- gcry_set_log_handler (my_gcry_logger, NULL);
- /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
-
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags= 1; /* do not remove the args */
- while (arg_parse (&pargs, opts) )
- {
- switch (pargs.r_opt)
- {
- case oVerbose: opt.verbose++; break;
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
- case oGenRandom: gen_random = pargs.r.ret_ulong; break;
- default : pargs.err = 2; break;
- }
- }
- if (log_get_errorcount(0))
- exit(2);
-
- if (opt.verbose < 2)
- opt.verbose = 2; /* hack to let select_openpgp print some info. */
-
- if (argc)
- usage (1);
-
- slot = apdu_open_reader (reader_port);
- if (slot == -1)
- exit (1);
-
- if (!gen_random)
- {
- rc = atr_dump (slot, stdout);
- if (rc)
- log_error ("can't dump ATR: %s\n", gpg_strerror (rc));
- }
-
- appbuf.slot = slot;
- rc = app_select_openpgp (&appbuf, NULL, NULL);
- if (rc)
- log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
- else
- {
- appbuf.initialized = 1;
- log_info ("openpgp application selected\n");
-
- if (gen_random)
- {
- size_t nbytes;
- unsigned char *buffer;
-
- buffer = xmalloc (4096);
- do
- {
- nbytes = gen_random > 4096? 4096 : gen_random;
- rc = app_get_challenge (&appbuf, nbytes, buffer);
- if (rc)
- log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc));
- else
- {
- if (fwrite (buffer, nbytes, 1, stdout) != 1)
- log_error ("writing to stdout failed: %s\n",
- strerror (errno));
- gen_random -= nbytes;
- }
- }
- while (gen_random && !log_get_errorcount (0));
- xfree (buffer);
- }
- }
-
- return log_get_errorcount (0)? 2:0;
-}
-
-
-
-void
-send_status_info (CTRL ctrl, const char *keyword, ...)
-{
- /* DUMMY */
-}
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
deleted file mode 100644
index 8e0ef37c9..000000000
--- a/scd/scdaemon.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/* scdaemon.c - The GnuPG Smartcard Daemon
- * Copyright (C) 2001, 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <signal.h>
-
-#define JNLIB_NEED_LOG_LOGV
-#include "scdaemon.h"
-#include <ksba.h>
-#include <gcrypt.h>
-
-#include <assuan.h> /* malloc hooks */
-
-#include "i18n.h"
-#include "sysutils.h"
-
-
-
-enum cmd_and_opt_values
-{ aNull = 0,
- oCsh = 'c',
- oQuiet = 'q',
- oSh = 's',
- oVerbose = 'v',
-
- oNoVerbose = 500,
- oOptions,
- oDebug,
- oDebugAll,
- oDebugWait,
- oDebugSC,
- oNoGreeting,
- oNoOptions,
- oHomedir,
- oNoDetach,
- oNoGrab,
- oLogFile,
- oServer,
- oDaemon,
- oBatch,
- oReaderPort,
-
-aTest };
-
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 301, NULL, 0, N_("@Options:\n ") },
-
- { oServer, "server", 0, N_("run in server mode (foreground)") },
- { oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
- { oVerbose, "verbose", 0, N_("verbose") },
- { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
- { oSh, "sh", 0, N_("sh-style command output") },
- { oCsh, "csh", 0, N_("csh-style command output") },
- { oOptions, "options" , 2, N_("read options from file")},
- { oDebug, "debug" ,4|16, N_("set debugging flags")},
- { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
- { oDebugWait,"debug-wait",1, "@"},
- { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")},
- { oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
- { oLogFile, "log-file" ,2, N_("use a log file for the server")},
- { oReaderPort, "reader-port", 1, N_("|N|connect to reader at port N")},
-
- {0}
-};
-
-
-static volatile int caught_fatal_sig = 0;
-
-/* It is possible that we are currently running under setuid permissions */
-static int maybe_setuid = 1;
-
-/* Name of the communication socket */
-static char socket_name[128];
-
-static const char *
-my_strusage (int level)
-{
- const char *p;
- switch (level)
- {
- case 11: p = "scdaemon (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: scdaemon [options] (-h for help)");
- break;
- case 41: p = _("Syntax: scdaemon [options] [command [args]]\n"
- "Smartcard daemon for GnuPG\n");
- break;
-
- default: p = NULL;
- }
- return p;
-}
-
-
-
-static void
-i18n_init (void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file( PACKAGE );
-#else
-#ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-#endif
-#endif
-}
-
-
-
-/* Used by gcry for logging */
-static void
-my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
-{
- /* translate the log levels */
- switch (level)
- {
- case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
- case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
- case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
- default: level = JNLIB_LOG_ERROR; break;
- }
- log_logv (level, fmt, arg_ptr);
-}
-
-
-static void
-cleanup (void)
-{
- if (*socket_name)
- {
- char *p;
-
- remove (socket_name);
- p = strrchr (socket_name, '/');
- if (p)
- {
- *p = 0;
- rmdir (socket_name);
- *p = '/';
- }
- *socket_name = 0;
- }
-}
-
-
-static RETSIGTYPE
-cleanup_sh (int sig)
-{
- if (caught_fatal_sig)
- raise (sig);
- caught_fatal_sig = 1;
-
- /* gcry_control( GCRYCTL_TERM_SECMEM );*/
- cleanup ();
-
-#ifndef HAVE_DOSISH_SYSTEM
- { /* reset action to default action and raise signal again */
- struct sigaction nact;
- nact.sa_handler = SIG_DFL;
- sigemptyset( &nact.sa_mask );
- nact.sa_flags = 0;
- sigaction( sig, &nact, NULL);
- }
-#endif
- raise( sig );
-}
-
-int
-main (int argc, char **argv )
-{
- ARGPARSE_ARGS pargs;
- int orig_argc;
- int may_coredump;
- 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 pipe_server = 0;
- int is_daemon = 0;
- int nodetach = 0;
- int csh_style = 0;
- char *logfile = NULL;
- int debug_wait = 0;
- int reader_port = 32768; /* First USB reader. */
-
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- /* Please note that we may running SUID(ROOT), so be very CAREFUL
- when adding any stuff between here and the call to INIT_SECMEM()
- somewhere after the option parsing */
- log_set_prefix ("scdaemon", 1|4);
- i18n_init ();
-
- /* check that the libraries are suitable. Do it here because
- the option parsing may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
-
- ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
- assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
- gcry_set_log_handler (my_gcry_logger, NULL);
- gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
-
- may_coredump = disable_core_dumps ();
-
- shell = getenv ("SHELL");
- if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
- csh_style = 1;
-
- /* FIXME: Using this homedir option does only make sense when not
- running as a system service. We might want to check for this by
- looking at the uid or ebtter use an explict option for this */
- opt.homedir = getenv("GNUPGHOME");
- if (!opt.homedir || !*opt.homedir)
- opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-
- /* check whether we have a config file 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;
- }
-
- /* initialize the secure memory. */
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- maybe_setuid = 0;
-
- /*
- Now we are working under our real uid
- */
-
-
- if (default_config)
- configname = make_filename (opt.homedir, "scdaemon.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);
- 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) )
- {
- switch (pargs.r_opt)
- {
- 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 oDebugWait: debug_wait = pargs.r.ret_int; break;
- case oDebugSC: opt.debug_sc = 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: opt.homedir = pargs.r.ret_str; 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 oServer: pipe_server = 1; break;
- case oDaemon: is_daemon = 1; break;
-
- case oReaderPort: reader_port = pargs.r.ret_int; break;
-
- default : pargs.err = configfp? 1:2; break;
- }
- }
- if (configfp)
- {
- fclose( configfp );
- configfp = NULL;
- xfree(configname);
- configname = NULL;
- goto next_pass;
- }
- xfree (configname);
- configname = NULL;
- if (log_get_errorcount(0))
- exit(2);
- if (nogreeting )
- greeting = 0;
-
- if (greeting)
- {
- fprintf (stderr, "%s %s; %s\n",
- strusage(11), strusage(13), strusage(14) );
- fprintf (stderr, "%s\n", strusage(15) );
- }
-#ifdef IS_DEVELOPMENT_VERSION
- log_info ("NOTE: this is a development version!\n");
-#endif
-
-
- if (atexit (cleanup))
- {
- log_error ("atexit failed\n");
- cleanup ();
- exit (1);
- }
-
-
- if (debug_wait && pipe_server)
- {
- log_debug ("waiting for debugger - my pid is %u .....\n",
- (unsigned int)getpid());
- sleep (debug_wait);
- log_debug ("... okay\n");
- }
-
- /* now start with logging to a file if this is desired */
- if (logfile)
- {
- log_set_file (logfile);
- log_set_prefix (NULL, 1|2|4);
- }
-
-
- if (pipe_server)
- { /* this is the simple pipe based server */
- scd_command_handler (-1);
- }
- else if (!is_daemon)
- {
- log_info (_("please use the option `--daemon'"
- " to run the program in the background\n"));
- }
- else
- { /* regular server mode */
- int fd;
- pid_t pid;
- int i;
- int len;
- struct sockaddr_un serv_addr;
- char *p;
-
- /* fixme: if there is already a running gpg-agent we should
- share the same directory - and vice versa */
- *socket_name = 0;
- snprintf (socket_name, DIM(socket_name)-1,
- "/tmp/gpg-XXXXXX/S.scdaemon");
- socket_name[DIM(socket_name)-1] = 0;
- p = strrchr (socket_name, '/');
- if (!p)
- BUG ();
- *p = 0;;
- if (!mkdtemp(socket_name))
- {
- log_error ("can't create directory `%s': %s\n",
- socket_name, strerror(errno) );
- exit (1);
- }
- *p = '/';
-
- if (strchr (socket_name, ':') )
- {
- log_error ("colons are not allowed in the socket name\n");
- exit (1);
- }
- if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
- {
- log_error ("name of socket to long\n");
- exit (1);
- }
-
-
- fd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (fd == -1)
- {
- log_error ("can't create socket: %s\n", strerror(errno) );
- exit (1);
- }
-
- memset (&serv_addr, 0, sizeof serv_addr);
- serv_addr.sun_family = AF_UNIX;
- strcpy (serv_addr.sun_path, socket_name);
- len = (offsetof (struct sockaddr_un, sun_path)
- + strlen(serv_addr.sun_path) + 1);
-
- if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1)
- {
- log_error ("error binding socket to `%s': %s\n",
- serv_addr.sun_path, strerror (errno) );
- close (fd);
- exit (1);
- }
-
- if (listen (fd, 5 ) == -1)
- {
- log_error ("listen() failed: %s\n", strerror (errno));
- close (fd);
- exit (1);
- }
-
- if (opt.verbose)
- log_info ("listening on socket `%s'\n", socket_name );
-
-
- fflush (NULL);
- pid = fork ();
- if (pid == (pid_t)-1)
- {
- log_fatal ("fork failed: %s\n", strerror (errno) );
- exit (1);
- }
- else if (pid)
- { /* we are the parent */
- char *infostr;
-
- close (fd);
-
- /* create the info string: <name>:<pid>:<protocol_version> */
- if (asprintf (&infostr, "SCDAEMON_INFO=%s:%lu:1",
- socket_name, (ulong)pid ) < 0)
- {
- log_error ("out of core\n");
- kill (pid, SIGTERM);
- exit (1);
- }
- *socket_name = 0; /* don't let cleanup() remove the socket -
- the child should do this from now on */
- if (argc)
- { /* run the program given on the commandline */
- if (putenv (infostr))
- {
- log_error ("failed to set environment: %s\n",
- strerror (errno) );
- kill (pid, SIGTERM );
- exit (1);
- }
- execvp (argv[0], argv);
- log_error ("failed to run the command: %s\n", strerror (errno));
- kill (pid, SIGTERM);
- exit (1);
- }
- else
- {
- /* print the environment string, so that the caller can use
- shell's eval to set it */
- if (csh_style)
- {
- *strchr (infostr, '=') = ' ';
- printf ( "setenv %s\n", infostr);
- }
- else
- {
- printf ( "%s; export SCDAEMON_INFO;\n", infostr);
- }
- free (infostr);
- exit (0);
- }
- /* NOTREACHED */
- } /* end parent */
-
- /* this is the child */
-
- /* detach from tty and put process into a new session */
- if (!nodetach )
- { /* close stdin, stdout and stderr unless it is the log stream */
- for (i=0; i <= 2; i++)
- {
- if ( log_get_fd () != i)
- close (i);
- }
- if (setsid() == -1)
- {
- log_error ("setsid() failed: %s\n", strerror(errno) );
- cleanup ();
- exit (1);
- }
- }
-
- /* setup signals */
- {
- struct sigaction oact, nact;
-
- nact.sa_handler = cleanup_sh;
- sigemptyset (&nact.sa_mask);
- nact.sa_flags = 0;
-
- sigaction (SIGHUP, NULL, &oact);
- if (oact.sa_handler != SIG_IGN)
- sigaction (SIGHUP, &nact, NULL);
- sigaction( SIGTERM, NULL, &oact );
- if (oact.sa_handler != SIG_IGN)
- sigaction (SIGTERM, &nact, NULL);
- nact.sa_handler = SIG_IGN;
- sigaction (SIGPIPE, &nact, NULL);
- sigaction (SIGINT, &nact, NULL);
- }
-
- if (chdir("/"))
- {
- log_error ("chdir to / failed: %s\n", strerror (errno));
- exit (1);
- }
-
- scd_command_handler (fd);
-
- close (fd);
- }
-
- return 0;
-}
-
-void
-scd_exit (int rc)
-{
- #if 0
-#warning no update_random_seed_file
- update_random_seed_file();
- #endif
-#if 0
- /* at this time a bit annoying */
- if (opt.debug & DBG_MEMSTAT_VALUE)
- {
- gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
- gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
- }
- if (opt.debug)
- gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
-#endif
- gcry_control (GCRYCTL_TERM_SECMEM );
- rc = rc? rc : log_get_errorcount(0)? 2 : 0;
- exit (rc);
-}
-
-
-void
-scd_init_default_ctrl (CTRL ctrl)
-{
-
-}
-
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
deleted file mode 100644
index b21e19f8c..000000000
--- a/scd/scdaemon.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* scdaemon.h - Global definitions for the SCdaemon
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef SCDAEMON_H
-#define SCDAEMON_H
-
-#ifdef GPG_ERR_SOURCE_DEFAULT
-#error GPG_ERR_SOURCE_DEFAULT already defined
-#endif
-#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_SCD
-#include <gpg-error.h>
-#include <errno.h>
-
-#include <time.h>
-#include <gcrypt.h>
-#include "../common/util.h"
-#include "../common/errors.h"
-
-/* Convenience funcion to be used instead of returning the old
- GNUPG_Out_Of_Core. */
-static __inline__ gpg_error_t
-out_of_core (void)
-{
- return gpg_error (gpg_err_code_from_errno (errno));
-}
-
-
-#define MAX_DIGEST_LEN 24
-
-/* A large struct name "opt" to keep global flags */
-struct {
- unsigned int debug; /* debug flags (DBG_foo_VALUE) */
- int debug_sc; /* OpenSC debug level */
- int verbose; /* verbosity level */
- int quiet; /* be as quiet as possible */
- int dry_run; /* don't change any persistent data */
- int batch; /* batch mode */
- const char *homedir; /* configuration directory name */
-} opt;
-
-
-#define DBG_COMMAND_VALUE 1 /* debug commands i/o */
-#define DBG_MPI_VALUE 2 /* debug mpi details */
-#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
-#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
-#define DBG_CACHE_VALUE 64 /* debug the caching */
-#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
-#define DBG_HASHING_VALUE 512 /* debug hashing operations */
-#define DBG_ASSUAN_VALUE 1024
-#define DBG_CARD_IO_VALUE 2048
-
-#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
-#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
-#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
-#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
-#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
-#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
-#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE)
-
-struct server_local_s;
-struct card_ctx_s;
-struct app_ctx_s;
-
-struct server_control_s {
- struct server_local_s *server_local;
- struct card_ctx_s *card_ctx;
- struct app_ctx_s *app_ctx;
- struct {
- unsigned char *value;
- int valuelen;
- } in_data; /* helper to store the value we are going to sign */
-
-};
-
-typedef struct server_control_s *CTRL;
-typedef struct card_ctx_s *CARD;
-typedef struct app_ctx_s *APP;
-
-/*-- scdaemon.c --*/
-void scd_exit (int rc);
-void scd_init_default_ctrl (CTRL ctrl);
-
-/*-- command.c --*/
-void scd_command_handler (int);
-void send_status_info (CTRL ctrl, const char *keyword, ...);
-
-/*-- card.c --*/
-int card_open (CARD *rcard);
-void card_close (CARD card);
-int card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp);
-int card_enum_keypairs (CARD card, int idx,
- unsigned char *keygrip,
- char **keyid);
-int card_enum_certs (CARD card, int idx, char **certid, int *certtype);
-int card_read_cert (CARD card, const char *certidstr,
- unsigned char **cert, size_t *ncert);
-int card_sign (CARD card,
- const char *keyidstr, int hashalgo,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen );
-int card_decipher (CARD card, const char *keyidstr,
- int (pincb)(void*, const char *, char **),
- void *pincb_arg,
- const void *indata, size_t indatalen,
- unsigned char **outdata, size_t *outdatalen);
-
-
-#endif /*SCDAEMON_H*/
diff --git a/sm/ChangeLog b/sm/ChangeLog
deleted file mode 100644
index 59a6b3271..000000000
--- a/sm/ChangeLog
+++ /dev/null
@@ -1,816 +0,0 @@
-2003-07-31 Werner Koch <wk@gnupg.org>
-
- * Makefile.am (gpgsm_LDADD): Added INTLLIBS.
-
-2003-07-29 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Add secmem features and set the random seed file.
- (gpgsm_exit): Update the random seed file and enable debug output.
-
-2003-07-27 Werner Koch <wk@gnupg.org>
-
- Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
-
-2003-06-24 Werner Koch <wk@gnupg.org>
-
- * server.c (gpgsm_status_with_err_code): New.
- * verify.c (gpgsm_verify): Use it here instead of the old
- tokenizing version.
-
- * verify.c (strtimestamp): Renamed to strtimestamp_r
-
- Adjusted for changes in the libgcrypt API. Some more fixes for the
- libgpg-error stuff.
-
-2003-06-04 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (init_membuf,put_membuf,get_membuf): Removed.
- Include new membuf header and changed used type.
-
- Renamed error codes from INVALID to INV and removed _ERROR suffixes.
-
-2003-06-03 Werner Koch <wk@gnupg.org>
-
- Changed all error codes in all files to the new libgpg-error scheme.
-
- * gpgsm.h: Include gpg-error.h .
- * Makefile.am: Link with libgpg-error.
-
-2003-04-29 Werner Koch <wk@gnupg.org>
-
- * Makefile.am: Use libassuan. Don't override LDFLAGS anymore.
- * server.c (register_commands): Adjust for new Assuan semantics.
-
-2002-12-03 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (gpgsm_agent_passwd): New.
- * gpgsm.c (main): New command --passwd and --call-protect-tool
- (run_protect_tool): New.
-
-2002-11-25 Werner Koch <wk@gnupg.org>
-
- * verify.c (gpgsm_verify): Handle content-type attribute.
-
-2002-11-13 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (start_agent): Try to use $GPG_TTY instead of
- ttyname. Changed ttyname to test stdin becuase it can be assumed
- that output redirection is more common that input redirection.
-
-2002-11-12 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: New command --call-dirmngr.
- * call-dirmngr.c (gpgsm_dirmngr_run_command)
- (run_command_inq_cb,run_command_cb)
- (run_command_status_cb): New.
-
-2002-11-11 Werner Koch <wk@gnupg.org>
-
- * certcheck.c (gpgsm_check_cms_signature): Don't double free
- s_sig but free s_pkey at leave.
-
-2002-11-10 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: Removed duplicate --list-secret-key entry.
-
-2002-09-19 Werner Koch <wk@gnupg.org>
-
- * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.
-
- * certchain.c (find_up): Print info when the cert was not found
- by the autorithyKeyIdentifier.
-
-2002-09-03 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Disable the internal libgcrypt locking.
-
-2002-08-21 Werner Koch <wk@gnupg.org>
-
- * import.c (print_imported_summary): Cleaned up. Print new
- not_imported value.
- (check_and_store): Update non_imported counter.
- (print_import_problem): New.
- (check_and_store): Print error status message.
- * server.c (get_status_string): Added STATUS_IMPORT_PROBLEM.
-
-2002-08-20 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Use the log file only in server mode.
-
- * import.c (print_imported_summary): New.
- (check_and_store): Update the counters, take new argument.
- (import_one): Factored out core of gpgsm_import.
- (gpgsm_import): Print counters.
- (gpgsm_import_files): New.
- * gpgsm.c (main): Use the new function for import.
-
-2002-08-19 Werner Koch <wk@gnupg.org>
-
- * decrypt.c (gpgsm_decrypt): Return a better error status token.
- * verify.c (gpgsm_verify): Don't error on messages with no signing
- time or no message digest. This is only the case for messages
- without any signed attributes.
-
-2002-08-16 Werner Koch <wk@gnupg.org>
-
- * certpath.c: Renamed to ..
- * certchain.c: this. Renamed all all other usages of "path" in the
- context of certificates to "chain".
-
- * call-agent.c (learn_cb): Special treatment when the issuer
- certificate is missing.
-
-2002-08-10 Werner Koch <wk@gnupg.org>
-
- * Makefile.am (INCLUDES): Add definition for localedir.
-
- * keylist.c (list_cert_colon): Print the short fingerprint in the
- key ID field.
- * fingerprint.c (gpgsm_get_short_fingerprint): New.
- * verify.c (gpgsm_verify): Print more verbose info for a good
- signature.
-
-2002-08-09 Werner Koch <wk@gnupg.org>
-
- * decrypt.c (prepare_decryption): Hack to detected already
- unpkcsedone keys.
-
- * gpgsm.c (emergency_cleanup): New.
- (main): Initialize the signal handler.
-
- * sign.c (gpgsm_sign): Reset the hash context for subsequent
- signers and release it at the end.
-
-2002-08-05 Werner Koch <wk@gnupg.org>
-
- * server.c (cmd_signer): New command "SIGNER"
- (register_commands): Register it.
- (cmd_sign): Pass the signer list to gpgsm_sign.
- * certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check
- for secret key if set and changed all callers.
- * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt
- multiple signers.
- * gpgsm.c (main): Support more than one -u.
-
- * server.c (cmd_recipient): Return reason code 1 for No_Public_Key
- which is actually what gets returned from add_to_certlist.
-
-2002-07-26 Werner Koch <wk@gnupg.org>
-
- * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup.
- (gpgsm_check_cms_signature): Ditto.
-
-2002-07-22 Werner Koch <wk@gnupg.org>
-
- * keydb.c (keydb_add_resource): Register a lock file.
- (lock_all, unlock_all): Implemented.
-
- * delete.c: New.
- * gpgsm.c: Made --delete-key work.
- * server.c (cmd_delkeys): New.
- (register_commands): New command DELKEYS.
-
- * decrypt.c (gpgsm_decrypt): Print a convenience note when RC2 is
- used and a STATUS_ERROR with the algorithm oid.
-
-2002-07-03 Werner Koch <wk@gnupg.org>
-
- * server.c (gpgsm_status2): Insert a blank between all optional
- arguments when using assuan.
- * server.c (cmd_recipient): No more need for extra blank in constants.
- * import.c (print_imported_status): Ditto.
- * gpgsm.c (main): Ditto.
-
-2002-07-02 Werner Koch <wk@gnupg.org>
-
- * verify.c (gpgsm_verify): Extend the STATUS_BADSIG line with
- the fingerprint.
-
- * certpath.c (check_cert_policy): Don't use log_error to print a
- warning.
-
- * keydb.c (keydb_store_cert): Add optional ar EXISTED and changed
- all callers.
- * call-agent.c (learn_cb): Print info message only for real imports.
-
- * import.c (gpgsm_import): Moved duplicated code to ...
- (check_and_store): new function. Added magic to import the entire
- chain. Print status only for real imports and moved printing code
- to ..
- (print_imported_status): New.
-
- * call-dirmngr.c (gpgsm_dirmngr_isvalid): print status of dirmngr
- call in very verbose mode.
-
- * gpgsm.c (main): Use the same error codes for STATUS_INV_RECP as
- with the server mode.
-
-2002-06-29 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: New option --auto-issuer-key-retrieve.
- * certpath.c (find_up): Try to retrieve an issuer key from an
- external source and from the ephemeral key DB.
- (find_up_store_certs_cb): New.
-
- * keydb.c (keydb_set_ephemeral): Does now return the old
- state. Call the backend only when required.
-
- * call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR.
- (lookup_status_cb): Issue status only when CTRL is not NULL.
- (gpgsm_dirmngr_lookup): Document that CTRL is optional.
-
- * call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT.
-
-2002-06-28 Werner Koch <wk@gnupg.org>
-
- * server.c (cmd_recipient): Add more reason codes.
-
-2002-06-27 Werner Koch <wk@gnupg.org>
-
- * certpath.c (gpgsm_basic_cert_check): Use
- --debug-no-path-validation to also bypass this basic check.
-
- * gpgsm.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
-
- * call-agent.c (start_agent): Create and pass the list of FD to
- keep in the child to assuan.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-06-26 Werner Koch <wk@gnupg.org>
-
- * import.c (gpgsm_import): Print an STATUS_IMPORTED.
-
- * gpgsm.c: --debug-no-path-validation does not take an argument.
-
-2002-06-25 Werner Koch <wk@gnupg.org>
-
- * certdump.c (print_dn_part): Always print a leading slash,
- removed NEED_DELIM arg and changed caller.
-
- * export.c (gpgsm_export): Print LFs to FP and not stdout.
- (print_short_info): Ditto. Make use of gpgsm_print_name.
-
- * server.c (cmd_export): Use output-fd instead of data lines; this
- was actually the specified way.
-
-2002-06-24 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: Removed duped help entry for --list-keys.
-
- * gpgsm.c, gpgsm.h: New option --debug-no-path-validation.
-
- * certpath.c (gpgsm_validate_path): Use it here instead of the
- debug flag hack.
-
- * certpath.c (check_cert_policy): Return No_Policy_Match if the
- policy file could not be opened.
-
-2002-06-20 Werner Koch <wk@gnupg.org>
-
- * certlist.c (gpgsm_add_to_certlist): Fixed locating of a
- certificate with the required key usage.
-
- * gpgsm.c (main): Fixed a segv when using --outfile without an
- argument.
-
- * keylist.c (print_capabilities): Also check for non-repudiation
- and data encipherment.
- * certlist.c (cert_usage_p): Test for signing and encryption was
- swapped. Add a case for certification usage, handle
- non-repudiation and data encipherment.
- (gpgsm_cert_use_cert_p): New.
- (gpgsm_add_to_certlist): Added a CTRL argument and changed all
- callers to pass it.
- * certpath.c (gpgsm_validate_path): Use it here to print a status
- message. Added a CTRL argument and changed all callers to pass it.
- * decrypt.c (gpgsm_decrypt): Print a status message for wrong key
- usage.
- * verify.c (gpgsm_verify): Ditto.
- * keydb.c (classify_user_id): Allow a colon delimited fingerprint.
-
-2002-06-19 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (learn_cb): Use log_info instead of log_error on
- successful import.
-
- * keydb.c (keydb_set_ephemeral): New.
- (keydb_store_cert): New are ephemeral, changed all callers.
- * keylist.c (list_external_cb): Store cert as ephemeral.
- * export.c (gpgsm_export): Kludge to export epehmeral certificates.
-
- * gpgsm.c (main): New command --list-external-keys.
-
-2002-06-17 Werner Koch <wk@gnupg.org>
-
- * certreqgen.c (read_parameters): Improved error handling.
- (gpgsm_genkey): Print error message.
-
-2002-06-13 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): New option --log-file.
-
-2002-06-12 Werner Koch <wk@gnupg.org>
-
- * call-dirmngr.c (lookup_status_cb): New.
- (gpgsm_dirmngr_lookup): Use the status CB. Add new arg CTRL and
- changed caller to pass it.
-
- * gpgsm.c (open_fwrite): New.
- (main): Allow --output for --verify.
-
- * sign.c (hash_and_copy_data): New.
- (gpgsm_sign): Implemented normal (non-detached) signatures.
- * gpgsm.c (main): Ditto.
-
- * certpath.c (gpgsm_validate_path): Special error handling for
- no policy match.
-
-2002-06-10 Werner Koch <wk@gnupg.org>
-
- * server.c (get_status_string): Add STATUS_ERROR.
-
- * certpath.c (gpgsm_validate_path): Tweaked the error checking to
- return error codes in a more sensitive way.
- * verify.c (gpgsm_verify): Send status TRUST_NEVER also for a bad
- CA certificate and when the certificate has been revoked. Issue
- TRUST_FULLY even when the cert has expired. Append an error token
- to these status lines. Issue the new generic error status when a
- cert was not found and when leaving the function.
-
-2002-06-04 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): New command --list-sigs
- * keylist.c (list_cert_std): New. Use it whenever colon mode is
- not used.
- (list_cert_chain): New.
-
-2002-05-31 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Don't print the "go ahead" message for an
- invalid command.
-
-2002-05-23 Werner Koch <wk@gnupg.org>
-
- * import.c (gpgsm_import): Add error messages.
-
-2002-05-21 Werner Koch <wk@gnupg.org>
-
- * keylist.c (list_internal_keys): Renamed from gpgsm_list_keys.
- (list_external_keys): New.
- (gpgsm_list_keys): Dispatcher for above.
- * call-dirmngr.c (lookup_cb,pattern_from_strlist)
- (gpgsm_dirmngr_lookup): New.
- * server.c (option_handler): Handle new option --list-mode.
- (do_listkeys): Handle options and actually use the mode argument.
- (get_status_string): New code TRUNCATED.
-
- * import.c (gpgsm_import): Try to identify the type of input and
- handle certs-only messages.
-
-2002-05-14 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: New option --faked-system-time
- * sign.c (gpgsm_sign): And use it here.
- * certpath.c (gpgsm_validate_path): Ditto.
-
-2002-05-03 Werner Koch <wk@gnupg.org>
-
- * certpath.c (gpgsm_validate_path): Added EXPTIME arg and changed
- all callers.
- * verify.c (gpgsm_verify): Tweaked usage of log_debug and
- log_error. Return EXPSIG status and add expiretime to VALIDSIG.
-
-2002-04-26 Werner Koch <wk@gnupg.org>
-
- * gpgsm.h (DBG_AGENT,DBG_AGENT_VALUE): Replaced by DBG_ASSUAN_*.
- Changed all users.
-
- * call-agent.c (start_agent): Be more silent without -v.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-04-25 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (start_agent): Make copies of old locales and check
- for setlocale.
-
-2002-04-25 Marcus Brinkmann <marcus@g10code.de>
-
- * call-agent.c (start_agent): Fix error handling logic so the
- locale is always correctly reset.
-
-2002-04-25 Marcus Brinkmann <marcus@g10code.de>
-
- * server.c (option_handler): Accept display, ttyname, ttytype,
- lc_ctype and lc_messages options.
- * gpgsm.c (main): Allocate memory for these options.
- * gpgsm.h (struct opt): Make corresponding members non-const.
-
-2002-04-24 Marcus Brinkmann <marcus@g10code.de>
-
- * gpgsm.h (struct opt): New members display, ttyname, ttytype,
- lc_ctype, lc_messages.
- * gpgsm.c (enum cmd_and_opt_values): New members oDisplay,
- oTTYname, oTTYtype, oLCctype, oLCmessages.
- (opts): New entries for these options.
- (main): Handle these new options.
- * call-agent.c (start_agent): Set the various display and tty
- parameter after resetting.
-
-2002-04-18 Werner Koch <wk@gnupg.org>
-
- * certreqgen.c (gpgsm_genkey): Write status output on success.
-
-2002-04-15 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Check ksba version.
-
- * certpath.c (find_up): New to use the authorithKeyIdentifier.
- Use it in all other functions to locate the signing cert..
-
-2002-04-11 Werner Koch <wk@gnupg.org>
-
- * certlist.c (cert_usable_p): New.
- (gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New.
- (gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New.
- (gpgsm_add_to_certlist): Check the key usage.
- * sign.c (gpgsm_sign): Ditto.
- * verify.c (gpgsm_verify): Print a message wehn an unsuitable
- certificate was used.
- * decrypt.c (gpgsm_decrypt): Ditto
- * keylist.c (print_capabilities): Determine values from the cert.
-
-2002-03-28 Werner Koch <wk@gnupg.org>
-
- * keylist.c (list_cert_colon): Fixed listing of crt record; the
- issuer is not at the right place. Print a chainingID.
- * certpath.c (gpgsm_walk_cert_chain): Be a bit more silent on
- common errors.
-
-2002-03-21 Werner Koch <wk@gnupg.org>
-
- * export.c: New.
- * gpgsm.c: Add command --export.
- * server.c (cmd_export): New.
-
-2002-03-13 Werner Koch <wk@gnupg.org>
-
- * decrypt.c (gpgsm_decrypt): Allow multiple recipients.
-
-2002-03-12 Werner Koch <wk@gnupg.org>
-
- * certpath.c (check_cert_policy): Print the policy list.
-
- * verify.c (gpgsm_verify): Detect certs-only message.
-
-2002-03-11 Werner Koch <wk@gnupg.org>
-
- * import.c (gpgsm_import): Print a notice about imported certificates
- when in verbose mode.
-
- * gpgsm.c (main): Print INV_RECP status.
- * server.c (cmd_recipient): Ditto.
-
- * server.c (gpgsm_status2): New. Allows for a list of strings.
- (gpgsm_status): Divert to gpgsm_status2.
-
- * encrypt.c (gpgsm_encrypt): Don't use a default key when no
- recipients are given. Print a NO_RECP status.
-
-2002-03-06 Werner Koch <wk@gnupg.org>
-
- * server.c (cmd_listkeys, cmd_listsecretkeys): Divert to
- (do_listkeys): new. Add pattern parsing.
-
- * keylist.c (gpgsm_list_keys): Handle selection pattern.
-
- * gpgsm.c: New command --learn-card
- * call-agent.c (learn_cb,gpgsm_agent_learn): New.
-
- * gpgsm.c (main): Print error messages for non-implemented commands.
-
- * base64.c (base64_reader_cb): Use case insensitive compare of the
- Content-Type string to detect plain base-64.
-
-2002-03-05 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c, gpgsm.h: Add local_user.
- * sign.c (gpgsm_get_default_cert): New.
- (get_default_signer): Use the new function if local_user is not
- set otherwise used that value.
- * encrypt.c (get_default_recipient): Removed.
- (gpgsm_encrypt): Use gpgsm_get_default_cert.
-
- * verify.c (gpgsm_verify): Better error text for a bad signature
- found by comparing the hashs.
-
-2002-02-27 Werner Koch <wk@gnupg.org>
-
- * call-dirmngr.c, call-agent.c: Add 2 more arguments to all uses
- of assuan_transact.
-
-2002-02-25 Werner Koch <wk@gnupg.org>
-
- * server.c (option_handler): Allow to use -2 for "send all certs
- except the root cert".
- * sign.c (add_certificate_list): Implement it here.
- * certpath.c (gpgsm_is_root_cert): New.
-
-2002-02-19 Werner Koch <wk@gnupg.org>
-
- * certpath.c (check_cert_policy): New.
- (gpgsm_validate_path): And call it from here.
- * gpgsm.c (main): New options --policy-file,
- --disable-policy-checks and --enable-policy-checks.
- * gpgsm.h (opt): Added policy_file, no_policy_checks.
-
-2002-02-18 Werner Koch <wk@gnupg.org>
-
- * certpath.c (gpgsm_validate_path): Ask the agent to add the
- certificate into the trusted list.
- * call-agent.c (gpgsm_agent_marktrusted): New.
-
-2002-02-07 Werner Koch <wk@gnupg.org>
-
- * certlist.c (gpgsm_add_to_certlist): Check that the specified
- name identifies a certificate unambiguously.
- (gpgsm_find_cert): Ditto.
-
- * server.c (cmd_listkeys): Check that the data stream is available.
- (cmd_listsecretkeys): Ditto.
- (has_option): New.
- (cmd_sign): Fix ambiguousity in option recognition.
-
- * gpgsm.c (main): Enable --logger-fd.
-
- * encrypt.c (gpgsm_encrypt): Increased buffer size for better
- performance.
-
- * call-agent.c (gpgsm_agent_pksign): Check the S-Exp received from
- the agent.
-
- * keylist.c (list_cert_colon): Filter out control characters.
-
-2002-02-06 Werner Koch <wk@gnupg.org>
-
- * decrypt.c (gpgsm_decrypt): Bail out after an decryption error.
-
- * server.c (reset_notify): Close input and output FDs.
- (cmd_encrypt,cmd_decrypt,cmd_verify,cmd_sign.cmd_import)
- (cmd_genkey): Close the FDs and release the recipient list even in
- the error case.
-
-2002-02-01 Marcus Brinkmann <marcus@g10code.de>
-
- * sign.c (gpgsm_sign): Do not release certificate twice.
-
-2002-01-29 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (gpgsm_agent_havekey): New.
- * keylist.c (list_cert_colon): New arg HAVE_SECRET, print "crs"
- when we know that the secret key is available.
- (gpgsm_list_keys): New arg MODE, check whether a secret key is
- available. Changed all callers.
- * gpgsm.c (main): New command --list-secret-keys.
- * server.c (cmd_listsecretkeys): New.
- (cmd_listkeys): Return secret keys with "crs" record.
-
-2002-01-28 Werner Koch <wk@gnupg.org>
-
- * certreqgen.c (create_request): Store the email address in the req.
-
-2002-01-25 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): Disable core dumps.
-
- * sign.c (add_certificate_list): New.
- (gpgsm_sign): Add the certificates to the CMS object.
- * certpath.c (gpgsm_walk_cert_chain): New.
- * gpgsm.h (server_control_s): Add included_certs.
- * gpgsm.c: Add option --include-certs.
- (gpgsm_init_default_ctrl): New.
- (main): Call it.
- * server.c (gpgsm_server): Ditto.
- (option_handler): Support --include-certs.
-
-2002-01-23 Werner Koch <wk@gnupg.org>
-
- * certpath.c (gpgsm_validate_path): Print the DN of a missing issuer.
- * certdump.c (gpgsm_dump_string): New.
- (print_dn): Replaced by above.
-
-2002-01-22 Werner Koch <wk@gnupg.org>
-
- * certpath.c (unknown_criticals): New.
- (allowed_ca): New.
- (gpgsm_validate_path): Check validity, CA attribute, path length
- and unknown critical extensions.
-
-2002-01-21 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: Add option --enable-crl-checks.
-
- * call-agent.c (start_agent): Implemented socket based access.
- * call-dirmngr.c (start_dirmngr): Ditto.
-
-2002-01-20 Werner Koch <wk@gnupg.org>
-
- * server.c (option_handler): New.
- (gpgsm_server): Register it with assuan.
-
-2002-01-19 Werner Koch <wk@gnupg.org>
-
- * server.c (gpgsm_server): Use assuan_deinit_server and setup
- assuan logging if enabled.
- * call-agent.c (inq_ciphertext_cb): Don't show the session key in
- an Assuan log file.
-
- * gpgsm.c (my_strusage): Take bugreport address from configure.ac
-
-2002-01-15 Werner Koch <wk@gnupg.org>
-
- * import.c (gpgsm_import): Just do a basic cert check before
- storing it.
- * certpath.c (gpgsm_basic_cert_check): New.
-
- * keydb.c (keydb_store_cert): New.
- * import.c (store_cert): Removed and change all caller to use
- the new function.
- * verify.c (store_cert): Ditto.
-
- * certlist.c (gpgsm_add_to_certlist): Validate the path
-
- * certpath.c (gpgsm_validate_path): Check the trust list.
- * call-agent.c (gpgsm_agent_istrusted): New.
-
-2002-01-14 Werner Koch <wk@gnupg.org>
-
- * call-dirmngr.c (inq_certificate): Changed for new interface semantic.
- * certlist.c (gpgsm_find_cert): New.
-
-2002-01-13 Werner Koch <wk@gnupg.org>
-
- * fingerprint.c (gpgsm_get_certid): Print the serial and not the
- hash after the dot.
-
-2002-01-11 Werner Koch <wk@gnupg.org>
-
- * call-dirmngr.c: New.
- * certpath.c (gpgsm_validate_path): Check the CRL here.
- * fingerprint.c (gpgsm_get_certid): New.
- * gpgsm.c: New options --dirmngr-program and --disable-crl-checks.
-
-2002-01-10 Werner Koch <wk@gnupg.org>
-
- * base64.c (gpgsm_create_writer): Allow to set the object name
-
-2002-01-08 Werner Koch <wk@gnupg.org>
-
- * keydb.c (spacep): Removed because it is now in util.c
-
- * server.c (cmd_genkey): New.
- * certreqgen.c: New. The parameter handling code has been taken
- from gnupg/g10/keygen.c version 1.0.6.
- * call-agent.c (gpgsm_agent_genkey): New.
-
-2002-01-02 Werner Koch <wk@gnupg.org>
-
- * server.c (rc_to_assuan_status): Removed and changed all callers
- to use map_to_assuan_status.
-
-2001-12-20 Werner Koch <wk@gnupg.org>
-
- * verify.c (gpgsm_verify): Implemented non-detached signature
- verification. Add OUT_FP arg, initialize a writer and changed all
- callers.
- * server.c (cmd_verify): Pass an out_fp if one has been set.
-
- * base64.c (base64_reader_cb): Try to detect an S/MIME body part.
-
- * certdump.c (print_sexp): Renamed to gpgsm_dump_serial, made
- global.
- (print_time): Renamed to gpgsm_dump_time, made global.
- (gpgsm_dump_serial): Take a real S-Expression as argument and
- print the first item.
- * keylist.c (list_cert_colon): Ditto.
- * keydb.c (keydb_search_issuer_sn): Ditto.
- * decrypt.c (print_integer_sexp): Removed and made callers
- use gpgsm_dump_serial.
- * verify.c (print_time): Removed, made callers use gpgsm_dump_time.
-
-2001-12-19 Marcus Brinkmann <marcus@g10code.de>
-
- * call-agent.c (start_agent): Add new argument to assuan_pipe_connect.
-
-2001-12-18 Werner Koch <wk@gnupg.org>
-
- * verify.c (print_integer_sexp): Renamed from print_integer and
- print the serial number according to the S-Exp rules.
- * decrypt.c (print_integer_sexp): Ditto.
-
-2001-12-17 Werner Koch <wk@gnupg.org>
-
- * keylist.c (list_cert_colon): Changed for new return value of
- get_serial.
- * keydb.c (keydb_search_issuer_sn): Ditto.
- * certcheck.c (gpgsm_check_cert_sig): Likewise for other S-Exp
- returingin functions.
- * fingerprint.c (gpgsm_get_keygrip): Ditto.
- * encrypt.c (encrypt_dek): Ditto
- * certcheck.c (gpgsm_check_cms_signature): Ditto
- * decrypt.c (prepare_decryption): Ditto.
- * call-agent.c (gpgsm_agent_pkdecrypt): Removed arg ciphertextlen,
- use KsbaSexp type and calculate the length.
-
- * certdump.c (print_sexp): Remaned from print_integer, changed caller.
-
- * Makefile.am: Use the LIBGCRYPT and LIBKSBA variables.
-
- * fingerprint.c (gpgsm_get_keygrip): Use the new
- gcry_pk_get_keygrip to calculate the grip - note the algorithm and
- therefore the grip values changed.
-
-2001-12-15 Werner Koch <wk@gnupg.org>
-
- * certcheck.c (gpgsm_check_cms_signature): Removed the faked-key
- kludge.
- (gpgsm_create_cms_signature): Removed the commented fake key
- code. This makes the function pretty simple.
-
- * gpgsm.c (main): Renamed the default key database to "keyring.kbx".
-
- * decrypt.c (gpgsm_decrypt): Write STATUS_DECRYPTION_*.
- * sign.c (gpgsm_sign): Write a STATUS_SIG_CREATED.
-
-2001-12-14 Werner Koch <wk@gnupg.org>
-
- * keylist.c (list_cert_colon): Kludge to show an email address
- encoded in the subject's DN.
-
- * verify.c (gpgsm_verify): Add hash debug helpers
- * sign.c (gpgsm_sign): Ditto.
-
- * base64.c (base64_reader_cb): Reset the linelen when we need to
- skip the line and adjusted test; I somehow forgot about DeMorgan.
-
- * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify)
- (cmd_import): Close the FDs on success.
- (close_message_fd): New.
- (input_notify): Setting autodetect_encoding to 0 after initializing
- it to 0 is pretty pointless. Easy to fix.
-
- * gpgsm.c (main): New option --debug-wait n, so that it is
- possible to attach gdb when used in server mode.
-
- * sign.c (get_default_signer): Use keydb_classify_name here.
-
-2001-12-14 Marcus Brinkmann <marcus@g10code.de>
-
- * call-agent.c (LINELENGTH): Removed.
- (gpgsm_agent_pksign): Use ASSUAN_LINELENGTH, not LINELENGTH.
- (gpgsm_agent_pkdecrypt): Likewise.
-
-2001-12-13 Werner Koch <wk@gnupg.org>
-
- * keylist.c (list_cert_colon): Print alternative names of subject
- and a few other values.
-
-2001-12-12 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c (main): New options --assume-{armor,base64,binary}.
- * base64.c (base64_reader_cb): Fixed non-autodetection mode.
-
-2001-12-04 Werner Koch <wk@gnupg.org>
-
- * call-agent.c (read_from_agent): Check for inquire responses.
- (request_reply): Handle them using a new callback arg, changed all
- callers.
- (gpgsm_agent_pkdecrypt): New.
-
-2001-11-27 Werner Koch <wk@gnupg.org>
-
- * base64.c: New. Changed all other functions to use this instead
- of direct creation of ksba_reader/writer.
- * gpgsm.c (main): Set ctrl.auto_encoding unless --no-armor is used.
-
-2001-11-26 Werner Koch <wk@gnupg.org>
-
- * gpgsm.c: New option --agent-program
- * call-agent.c (start_agent): Allow to override the default path
- to the agent.
-
- * keydb.c (keydb_add_resource): Create keybox
-
- * keylist.c (gpgsm_list_keys): Fixed non-server keylisting.
-
- * server.c (rc_to_assuan_status): New. Use it for all commands.
-
-
- Copyright 2001, 2002, 2003 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/sm/Makefile.am b/sm/Makefile.am
deleted file mode 100644
index 6345573e5..000000000
--- a/sm/Makefile.am
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-## Process this file with automake to produce Makefile.in
-
-localedir = $(datadir)/locale
-INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
-
-bin_PROGRAMS = gpgsm
-
-AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \
- $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS)
-
-gpgsm_SOURCES = \
- gpgsm.c gpgsm.h \
- misc.c \
- keydb.c keydb.h \
- server.c \
- call-agent.c \
- call-dirmngr.c \
- fingerprint.c \
- base64.c \
- certlist.c \
- certdump.c \
- certcheck.c \
- certchain.c \
- keylist.c \
- verify.c \
- sign.c \
- encrypt.c \
- decrypt.c \
- import.c \
- export.c \
- delete.c \
- certreqgen.c
-
-
-gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \
- $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \
- @INTLLIBS@
diff --git a/sm/base64.c b/sm/base64.c
deleted file mode 100644
index 07f546e85..000000000
--- a/sm/base64.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/* base64.c
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include <ksba.h>
-
-#include "gpgsm.h"
-#include "i18n.h"
-
-#ifdef HAVE_DOSISH_SYSTEM
- #define LF "\r\n"
-#else
- #define LF "\n"
-#endif
-
-/* data used by the reader callbacks */
-struct reader_cb_parm_s {
- FILE *fp;
- unsigned char line[1024];
- int linelen;
- int readpos;
- int have_lf;
- unsigned long line_counter;
-
- int autodetect; /* try to detect the input encoding */
- int assume_pem; /* assume input encoding is PEM */
- int assume_base64; /* assume input is base64 encoded */
-
- int identified;
- int is_pem;
- int is_base64;
- int stop_seen;
- int might_be_smime;
-
- struct {
- int idx;
- unsigned char val;
- int stop_seen;
- } base64;
-};
-
-/* data used by the writer callbacks */
-struct writer_cb_parm_s {
- FILE *fp;
- const char *pem_name;
-
- int wrote_begin;
- int did_finish;
-
- struct {
- int idx;
- int quad_count;
- unsigned char radbuf[4];
- } base64;
-
-};
-
-
-/* context for this module's functions */
-struct base64_context_s {
- union {
- struct reader_cb_parm_s rparm;
- struct writer_cb_parm_s wparm;
- } u;
-};
-
-
-/* The base-64 character list */
-static unsigned char bintoasc[64] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-/* The reverse base-64 list */
-static unsigned char asctobin[256] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff
-};
-
-
-static int
-has_only_base64 (const unsigned char *line, int linelen)
-{
- if (linelen < 20)
- return 0;
- for (; linelen; line++, linelen--)
- {
- if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n'))
- break;
- if ( !strchr (bintoasc, *line) )
- return 0;
- }
- return 1; /* yes */
-}
-
-static int
-is_empty_line (const unsigned char *line, int linelen)
-{
- if (linelen >= 2 && *line == '\r' && line[1] == '\n')
- return 1;
- if (linelen >= 1 && *line == '\n')
- return 1;
- return 0;
-}
-
-
-static int
-base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c, c2;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- next:
- if (!parm->linelen)
- {
- /* read an entire line or up to the size of the buffer */
- parm->line_counter++;
- parm->have_lf = 0;
- for (n=0; n < DIM(parm->line);)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- if (ferror (parm->fp))
- return -1;
- break;
- }
- parm->line[n++] = c;
- if (c == '\n')
- {
- parm->have_lf = 1;
- /* Fixme: we need to skip overlong lines while detecting
- the dashed lines */
- break;
- }
- }
- parm->linelen = n;
- if (!n)
- return -1; /* eof */
- parm->readpos = 0;
- }
-
- if (!parm->identified)
- {
- if (!parm->autodetect)
- {
- if (parm->assume_pem)
- {
- /* wait for the header line */
- parm->linelen = parm->readpos = 0;
- if (!parm->have_lf || strncmp (parm->line, "-----BEGIN ", 11)
- || !strncmp (parm->line+11, "PGP ", 4))
- goto next;
- parm->is_pem = 1;
- }
- else if (parm->assume_base64)
- parm->is_base64 = 1;
- }
- else if (parm->line_counter == 1 && !parm->have_lf)
- {
- /* first line too long - assume DER encoding */
- parm->is_pem = 0;
- }
- else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
- {
- /* the very first byte does pretty much look like a SEQUENCE tag*/
- parm->is_pem = 0;
- }
- else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11)
- && strncmp (parm->line+11, "PGP ", 4) )
- {
- /* Fixme: we must only compare if the line really starts at
- the beginning */
- parm->is_pem = 1;
- parm->linelen = parm->readpos = 0;
- }
- else if ( parm->have_lf && parm->line_counter == 1
- && parm->linelen >= 13
- && !ascii_memcasecmp (parm->line, "Content-Type:", 13))
- { /* might be a S/MIME body */
- parm->might_be_smime = 1;
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- else if (parm->might_be_smime == 1
- && is_empty_line (parm->line, parm->linelen))
- {
- parm->might_be_smime = 2;
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- else if (parm->might_be_smime == 2)
- {
- parm->might_be_smime = 0;
- if ( !has_only_base64 (parm->line, parm->linelen))
- {
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- parm->is_pem = 1;
- }
- else
- {
- parm->linelen = parm->readpos = 0;
- goto next;
- }
- parm->identified = 1;
- parm->base64.stop_seen = 0;
- parm->base64.idx = 0;
- }
-
-
- n = 0;
- if (parm->is_pem || parm->is_base64)
- {
- if (parm->is_pem && parm->have_lf
- && !strncmp (parm->line, "-----END ", 9))
- {
- parm->identified = 0;
- parm->linelen = parm->readpos = 0;
- /* let us return 0 */
- }
- else if (parm->stop_seen)
- { /* skip the rest of the line */
- parm->linelen = parm->readpos = 0;
- }
- else
- {
- int idx = parm->base64.idx;
- unsigned char val = parm->base64.val;
-
- while (n < count && parm->readpos < parm->linelen )
- {
- c = parm->line[parm->readpos++];
- if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
- continue;
- if (c == '=')
- { /* pad character: stop */
- if (idx == 1)
- buffer[n++] = val;
- parm->stop_seen = 1;
- break;
- }
- if( (c = asctobin[(c2=c)]) == 255 )
- {
- log_error (_("invalid radix64 character %02x skipped\n"),
- c2);
- continue;
- }
- switch (idx)
- {
- case 0:
- val = c << 2;
- break;
- case 1:
- val |= (c>>4)&3;
- buffer[n++] = val;
- val = (c<<4)&0xf0;
- break;
- case 2:
- val |= (c>>2)&15;
- buffer[n++] = val;
- val = (c<<6)&0xc0;
- break;
- case 3:
- val |= c&0x3f;
- buffer[n++] = val;
- break;
- }
- idx = (idx+1) % 4;
- }
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
-
- parm->base64.idx = idx;
- parm->base64.val = val;
- }
- }
- else
- { /* DER encoded */
- while (n < count && parm->readpos < parm->linelen)
- buffer[n++] = parm->line[parm->readpos++];
- if (parm->readpos == parm->linelen)
- parm->linelen = parm->readpos = 0;
- }
-
- *nread = n;
- return 0;
-}
-
-
-
-static int
-simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct reader_cb_parm_s *parm = cb_value;
- size_t n;
- int c = 0;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- for (n=0; n < count; n++)
- {
- c = getc (parm->fp);
- if (c == EOF)
- {
- if ( ferror (parm->fp) )
- return -1;
- if (n)
- break; /* return what we have before an EOF */
- return -1;
- }
- *(byte *)buffer++ = c;
- }
-
- *nread = n;
- return 0;
-}
-
-
-
-
-static int
-base64_writer_cb (void *cb_value, const void *buffer, size_t count)
-{
- struct writer_cb_parm_s *parm = cb_value;
- unsigned char radbuf[4];
- int i, c, idx, quad_count;
- const unsigned char *p;
- FILE *fp = parm->fp;
-
- if (!count)
- return 0;
-
- if (!parm->wrote_begin)
- {
- if (parm->pem_name)
- {
- fputs ("-----BEGIN ", fp);
- fputs (parm->pem_name, fp);
- fputs ("-----\n", fp);
- }
- parm->wrote_begin = 1;
- parm->base64.idx = 0;
- parm->base64.quad_count = 0;
- }
-
- idx = parm->base64.idx;
- quad_count = parm->base64.quad_count;
- for (i=0; i < idx; i++)
- radbuf[i] = parm->base64.radbuf[i];
-
- for (p=buffer; count; p++, count--)
- {
- radbuf[idx++] = *p;
- if (idx > 2)
- {
- idx = 0;
- c = bintoasc[(*radbuf >> 2) & 077];
- putc (c, fp);
- c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
- putc (c, fp);
- c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
- putc (c, fp);
- c = bintoasc[radbuf[2]&077];
- putc (c, fp);
- if (++quad_count >= (64/4))
- {
- fputs (LF, fp);
- quad_count = 0;
- }
- }
- }
- for (i=0; i < idx; i++)
- parm->base64.radbuf[i] = radbuf[i];
- parm->base64.idx = idx;
- parm->base64.quad_count = quad_count;
-
- return ferror (fp) ? KSBA_Write_Error:0;
-}
-
-static int
-base64_finish_write (struct writer_cb_parm_s *parm)
-{
- unsigned char radbuf[4];
- int i, c, idx, quad_count;
- FILE *fp = parm->fp;
-
- if (!parm->wrote_begin)
- return 0; /* nothing written */
-
- /* flush the base64 encoding */
- idx = parm->base64.idx;
- quad_count = parm->base64.quad_count;
- for (i=0; i < idx; i++)
- radbuf[i] = parm->base64.radbuf[i];
-
- if (idx)
- {
- c = bintoasc[(*radbuf>>2)&077];
- putc (c, fp);
- if (idx == 1)
- {
- c = bintoasc[((*radbuf << 4) & 060) & 077];
- putc (c, fp);
- putc ('=', fp);
- putc ('=', fp);
- }
- else
- {
- c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
- putc (c, fp);
- c = bintoasc[((radbuf[1] << 2) & 074) & 077];
- putc (c, fp);
- putc ('=', fp);
-
- }
- if (++quad_count >= (64/4))
- {
- fputs (LF, fp);
- quad_count = 0;
- }
- }
-
- if (quad_count)
- fputs (LF, fp);
-
- if (parm->pem_name)
- {
- fputs ("-----END ", fp);
- fputs (parm->pem_name, fp);
- fputs ("-----\n", fp);
- }
- return ferror (fp)? gpg_error (gpg_err_code_from_errno (errno)) : 0;
-}
-
-
-
-
-/* Create a reader for the given file descriptor. Depending on the
- control information an input decoding is automagically choosen.
- The function returns a Base64Context object which must be passed to
- the gpgme_destroy_reader function. The created KsbaReader object
- is also returned, but the caller must not call the
- ksba_reader_release function on. */
-int
-gpgsm_create_reader (Base64Context *ctx,
- CTRL ctrl, FILE *fp, KsbaReader *r_reader)
-{
- int rc;
- KsbaReader r;
-
- *r_reader = NULL;
- *ctx = xtrycalloc (1, sizeof **ctx);
- if (!*ctx)
- return OUT_OF_CORE (errno);
-
- r = ksba_reader_new ();
- if (!r)
- {
- xfree (*ctx); *ctx = NULL;
- return gpg_error (GPG_ERR_ENOMEM);
- }
-
- (*ctx)->u.rparm.fp = fp;
- if (ctrl->is_pem)
- {
- (*ctx)->u.rparm.assume_pem = 1;
- (*ctx)->u.rparm.assume_base64 = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else if (ctrl->is_base64)
- {
- (*ctx)->u.rparm.assume_base64 = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else if (ctrl->autodetect_encoding)
- {
- (*ctx)->u.rparm.autodetect = 1;
- rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
- }
- else
- rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm);
-
- if (rc)
- {
- ksba_reader_release (r);
- xfree (*ctx); *ctx = NULL;
- return map_ksba_err (rc);
- }
-
- *r_reader = r;
- return 0;
-}
-
-
-void
-gpgsm_destroy_reader (Base64Context ctx)
-{
- xfree (ctx);
-}
-
-
-
-/* Create a writer for the given stream. Depending on the control
- information an output encoding is automagically choosen. The
- function returns a Base64Context object which must be passed to the
- gpgme_destroy_writer function. The created KsbaWriter object is
- also returned, but the caller must not call the ksba_reader_release
- function on. */
-int
-gpgsm_create_writer (Base64Context *ctx,
- CTRL ctrl, FILE *fp, KsbaWriter *r_writer)
-{
- int rc;
- KsbaWriter w;
-
- *r_writer = NULL;
- *ctx = xtrycalloc (1, sizeof **ctx);
- if (!*ctx)
- return OUT_OF_CORE (errno);
-
- w = ksba_writer_new ();
- if (!w)
- {
- xfree (*ctx); *ctx = NULL;
- return gpg_error (GPG_ERR_ENOMEM);
- }
-
- if (ctrl->create_pem || ctrl->create_base64)
- {
- (*ctx)->u.wparm.fp = fp;
- if (ctrl->create_pem)
- (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
- : "CMS OBJECT";
- rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
- }
- else
- rc = ksba_writer_set_file (w, fp);
-
- if (rc)
- {
- ksba_writer_release (w);
- xfree (*ctx); *ctx = NULL;
- return map_ksba_err (rc);
- }
-
- *r_writer = w;
- return 0;
-}
-
-
-int
-gpgsm_finish_writer (Base64Context ctx)
-{
- struct writer_cb_parm_s *parm;
-
- if (!ctx)
- return gpg_error (GPG_ERR_INV_VALUE);
- parm = &ctx->u.wparm;
- if (parm->did_finish)
- return 0; /* already done */
- parm->did_finish = 1;
- if (!parm->fp)
- return 0; /* callback was not used */
- return base64_finish_write (parm);
-}
-
-void
-gpgsm_destroy_writer (Base64Context ctx)
-{
- xfree (ctx);
-}
diff --git a/sm/call-agent.c b/sm/call-agent.c
deleted file mode 100644
index 4d26e3450..000000000
--- a/sm/call-agent.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/* call-agent.c - divert operations to the agent
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h>
-#include "i18n.h"
-#include "keydb.h" /* fixme: Move this to import.c */
-#include "../common/membuf.h"
-
-
-static ASSUAN_CONTEXT agent_ctx = NULL;
-static int force_pipe_server = 0;
-
-struct cipher_parm_s {
- ASSUAN_CONTEXT ctx;
- const char *ciphertext;
- size_t ciphertextlen;
-};
-
-struct genkey_parm_s {
- ASSUAN_CONTEXT ctx;
- const char *sexp;
- size_t sexplen;
-};
-
-struct learn_parm_s {
- int error;
- ASSUAN_CONTEXT ctx;
- membuf_t *data;
-};
-
-
-
-/* Try to connect to the agent via socket or fork it off and work by
- pipes. Handle the server's initial greeting */
-static int
-start_agent (void)
-{
- int rc = 0;
- char *infostr, *p;
- ASSUAN_CONTEXT ctx;
- char *dft_display = NULL;
- char *dft_ttyname = NULL;
- char *dft_ttytype = NULL;
- char *old_lc = NULL;
- char *dft_lc = NULL;
-
- if (agent_ctx)
- return 0; /* fixme: We need a context for each thread or serialize
- the access to the agent (which is suitable given that
- the agent is not MT */
-
- infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
- if (!infostr)
- {
- const char *pgmname;
- const char *argv[3];
- int no_close_list[3];
- int i;
-
- if (opt.verbose)
- log_info (_("no running gpg-agent - starting one\n"));
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return tmperr;
- }
-
- if (!opt.agent_program || !*opt.agent_program)
- opt.agent_program = GNUPG_DEFAULT_AGENT;
- if ( !(pgmname = strrchr (opt.agent_program, '/')))
- pgmname = opt.agent_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- no_close_list[i] = -1;
-
- /* connect to the agent and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
- no_close_list);
- }
- else
- {
- int prot;
- int pid;
-
- infostr = xstrdup (infostr);
- if ( !(p = strchr (infostr, ':')) || p == infostr)
- {
- log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
- xfree (infostr);
- force_pipe_server = 1;
- return start_agent ();
- }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
- {
- log_error (_("gpg-agent protocol version %d is not supported\n"),
- prot);
- xfree (infostr);
- force_pipe_server = 1;
- return start_agent ();
- }
-
- rc = assuan_socket_connect (&ctx, infostr, pid);
- xfree (infostr);
- if (rc == ASSUAN_Connect_Failed)
- {
- log_error (_("can't connect to the agent - trying fall back\n"));
- force_pipe_server = 1;
- return start_agent ();
- }
- }
-
- if (rc)
- {
- log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
- return gpg_error (GPG_ERR_NO_AGENT);
- }
- agent_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to agent established\n");
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- dft_display = getenv ("DISPLAY");
- if (opt.display || dft_display)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION display=%s",
- opt.display ? opt.display : dft_display) < 0)
- return OUT_OF_CORE (errno);
- rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- return map_assuan_err (rc);
- }
- if (!opt.ttyname)
- {
- dft_ttyname = getenv ("GPG_TTY");
- if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
- dft_ttyname = ttyname (0);
- }
- if (opt.ttyname || dft_ttyname)
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION ttyname=%s",
- opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
- return OUT_OF_CORE (errno);
- rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- return map_assuan_err (rc);
- }
- dft_ttytype = getenv ("TERM");
- if (opt.ttytype || (dft_ttyname && dft_ttytype))
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION ttytype=%s",
- opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
- return OUT_OF_CORE (errno);
- rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- return map_assuan_err (rc);
- }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
- old_lc = setlocale (LC_CTYPE, NULL);
- if (old_lc)
- {
- old_lc = strdup (old_lc);
- if (!old_lc)
- return OUT_OF_CORE (errno);
- }
- dft_lc = setlocale (LC_CTYPE, "");
-#endif
- if (opt.lc_ctype || (dft_ttyname && dft_lc))
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION lc-ctype=%s",
- opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
- rc = OUT_OF_CORE (errno);
- else
- {
- rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- rc = map_assuan_err (rc);
- }
- }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
- if (old_lc)
- {
- setlocale (LC_CTYPE, old_lc);
- free (old_lc);
- }
-#endif
- if (rc)
- return rc;
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
- old_lc = setlocale (LC_MESSAGES, NULL);
- if (old_lc)
- {
- old_lc = strdup (old_lc);
- if (!old_lc)
- return OUT_OF_CORE (errno);
- }
- dft_lc = setlocale (LC_MESSAGES, "");
-#endif
- if (opt.lc_messages || (dft_ttyname && dft_lc))
- {
- char *optstr;
- if (asprintf (&optstr, "OPTION lc-messages=%s",
- opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
- rc = OUT_OF_CORE (errno);
- else
- {
- rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
- NULL);
- free (optstr);
- if (rc)
- rc = map_assuan_err (rc);
- }
- }
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
- if (old_lc)
- {
- setlocale (LC_MESSAGES, old_lc);
- free (old_lc);
- }
-#endif
-
- return rc;
-}
-
-
-static AssuanError
-membuf_data_cb (void *opaque, const void *buffer, size_t length)
-{
- membuf_t *data = opaque;
-
- if (buffer)
- put_membuf (data, buffer, length);
- return 0;
-}
-
-
-
-
-/* Call the agent to do a sign operation using the key identified by
- the hex string KEYGRIP. */
-int
-gpgsm_agent_pksign (const char *keygrip,
- unsigned char *digest, size_t digestlen, int digestalgo,
- char **r_buf, size_t *r_buflen )
-{
- int rc, i;
- char *p, line[ASSUAN_LINELENGTH];
- membuf_t data;
- size_t len;
-
- *r_buf = NULL;
- rc = start_agent ();
- if (rc)
- return rc;
-
- if (digestlen*2 + 50 > DIM(line))
- return gpg_error (GPG_ERR_GENERAL);
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- sprintf (line, "SETHASH %d ", digestalgo);
- p = line + strlen (line);
- for (i=0; i < digestlen ; i++, p += 2 )
- sprintf (p, "%02X", digest[i]);
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- init_membuf (&data, 1024);
- rc = assuan_transact (agent_ctx, "PKSIGN",
- membuf_data_cb, &data, NULL, NULL, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
- *r_buf = get_membuf (&data, r_buflen);
-
- if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
- {
- xfree (*r_buf); *r_buf = NULL;
- return gpg_error (GPG_ERR_INV_VALUE);
- }
-
- return *r_buf? 0 : OUT_OF_CORE (errno);
-}
-
-
-
-
-/* Handle a CIPHERTEXT inquiry. Note, we only send the data,
- assuan_transact talkes care of flushing and writing the end */
-static AssuanError
-inq_ciphertext_cb (void *opaque, const char *keyword)
-{
- struct cipher_parm_s *parm = opaque;
- AssuanError rc;
-
- assuan_begin_confidential (parm->ctx);
- rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
- assuan_end_confidential (parm->ctx);
- return rc;
-}
-
-
-/* Call the agent to do a decrypt operation using the key identified by
- the hex string KEYGRIP. */
-int
-gpgsm_agent_pkdecrypt (const char *keygrip,
- KsbaConstSexp ciphertext,
- char **r_buf, size_t *r_buflen )
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
- membuf_t data;
- struct cipher_parm_s cipher_parm;
- size_t n, len;
- char *buf, *endp;
- size_t ciphertextlen;
-
- if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
- return gpg_error (GPG_ERR_INV_VALUE);
- *r_buf = NULL;
-
- ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
- if (!ciphertextlen)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- assert ( DIM(line) >= 50 );
- snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
- line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- init_membuf (&data, 1024);
- cipher_parm.ctx = agent_ctx;
- cipher_parm.ciphertext = ciphertext;
- cipher_parm.ciphertextlen = ciphertextlen;
- rc = assuan_transact (agent_ctx, "PKDECRYPT",
- membuf_data_cb, &data,
- inq_ciphertext_cb, &cipher_parm, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
-
- put_membuf (&data, "", 1); /* make sure it is 0 terminated */
- buf = get_membuf (&data, &len);
- if (!buf)
- return gpg_error (GPG_ERR_ENOMEM);
- /* FIXME: We would better a return a full S-exp and not just a part */
- assert (len);
- len--; /* remove the terminating 0 */
- n = strtoul (buf, &endp, 10);
- if (!n || *endp != ':')
- return gpg_error (GPG_ERR_INV_SEXP);
- endp++;
- if (endp-buf+n > len)
- return gpg_error (GPG_ERR_INV_SEXP); /* oops len does not
- match internal len*/
- memmove (buf, endp, n);
- *r_buflen = n;
- *r_buf = buf;
- return 0;
-}
-
-
-
-
-
-/* Handle a KEYPARMS inquiry. Note, we only send the data,
- assuan_transact takes care of flushing and writing the end */
-static AssuanError
-inq_genkey_parms (void *opaque, const char *keyword)
-{
- struct genkey_parm_s *parm = opaque;
- AssuanError rc;
-
- rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
- return rc;
-}
-
-
-
-/* Call the agent to generate a newkey */
-int
-gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
-{
- int rc;
- struct genkey_parm_s gk_parm;
- membuf_t data;
- size_t len;
- char *buf;
-
- *r_pubkey = NULL;
- rc = start_agent ();
- if (rc)
- return rc;
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return map_assuan_err (rc);
-
- init_membuf (&data, 1024);
- gk_parm.ctx = agent_ctx;
- gk_parm.sexp = keyparms;
- gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
- if (!gk_parm.sexplen)
- return gpg_error (GPG_ERR_INV_VALUE);
- rc = assuan_transact (agent_ctx, "GENKEY",
- membuf_data_cb, &data,
- inq_genkey_parms, &gk_parm, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return map_assuan_err (rc);
- }
- buf = get_membuf (&data, &len);
- if (!buf)
- return gpg_error (GPG_ERR_ENOMEM);
- if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
- {
- xfree (buf);
- return gpg_error (GPG_ERR_INV_SEXP);
- }
- *r_pubkey = buf;
- return 0;
-}
-
-
-/* Ask the agent whether the certificate is in the list of trusted
- keys */
-int
-gpgsm_agent_istrusted (KsbaCert cert)
-{
- int rc;
- char *fpr;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- log_error ("error getting the fingerprint\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
- line[DIM(line)-1] = 0;
- xfree (fpr);
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-/* Ask the agent to mark CERT as a trusted Root-CA one */
-int
-gpgsm_agent_marktrusted (KsbaCert cert)
-{
- int rc;
- char *fpr, *dn;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- log_error ("error getting the fingerprint\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- dn = ksba_cert_get_issuer (cert, 0);
- if (!dn)
- {
- xfree (fpr);
- return gpg_error (GPG_ERR_GENERAL);
- }
- snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
- line[DIM(line)-1] = 0;
- ksba_free (dn);
- xfree (fpr);
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-
-
-/* Ask the agent whether the a corresponding secret key is available
- for the given keygrip */
-int
-gpgsm_agent_havekey (const char *hexkeygrip)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- if (!hexkeygrip || strlen (hexkeygrip) != 40)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
- line[DIM(line)-1] = 0;
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
-
-static AssuanError
-learn_cb (void *opaque, const void *buffer, size_t length)
-{
- struct learn_parm_s *parm = opaque;
- size_t len;
- char *buf;
- KsbaCert cert;
- int rc;
-
- if (parm->error)
- return 0;
-
- if (buffer)
- {
- put_membuf (parm->data, buffer, length);
- return 0;
- }
- /* END encountered - process what we have */
- buf = get_membuf (parm->data, &len);
- if (!buf)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
-
-
- /* FIXME: this should go into import.c */
- cert = ksba_cert_new ();
- if (!cert)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
- rc = ksba_cert_init_from_mem (cert, buf, len);
- if (rc)
- {
- log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc));
- ksba_cert_release (cert);
- parm->error = map_ksba_err (rc);
- return 0;
- }
-
- rc = gpgsm_basic_cert_check (cert);
- if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
- { /* For later use we store it in the ephemeral database. */
- log_info ("issuer certificate missing - storing as ephemeral\n");
- keydb_store_cert (cert, 1, NULL);
- }
- else if (rc)
- log_error ("invalid certificate: %s\n", gpg_strerror (rc));
- else
- {
- int existed;
-
- if (!keydb_store_cert (cert, 0, &existed))
- {
- if (opt.verbose > 1 && existed)
- log_info ("certificate already in DB\n");
- else if (opt.verbose && !existed)
- log_info ("certificate imported\n");
- }
- }
-
- ksba_cert_release (cert);
- init_membuf (parm->data, 4096);
- return 0;
-}
-
-/* Call the agent to learn about a smartcard */
-int
-gpgsm_agent_learn ()
-{
- int rc;
- struct learn_parm_s learn_parm;
- membuf_t data;
- size_t len;
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- init_membuf (&data, 4096);
- learn_parm.error = 0;
- learn_parm.ctx = agent_ctx;
- learn_parm.data = &data;
- rc = assuan_transact (agent_ctx, "LEARN --send",
- learn_cb, &learn_parm,
- NULL, NULL, NULL, NULL);
- xfree (get_membuf (&data, &len));
- if (rc)
- return map_assuan_err (rc);
- return learn_parm.error;
-}
-
-
-/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
-int
-gpgsm_agent_passwd (const char *hexkeygrip)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- if (!hexkeygrip || strlen (hexkeygrip) != 40)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
- line[DIM(line)-1] = 0;
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return map_assuan_err (rc);
-}
-
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
deleted file mode 100644
index b182b246c..000000000
--- a/sm/call-dirmngr.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/* call-dirmngr.c - communication with the dromngr
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h>
-
-#include "i18n.h"
-
-struct membuf {
- size_t len;
- size_t size;
- char *buf;
- int out_of_core;
-};
-
-
-
-static ASSUAN_CONTEXT dirmngr_ctx = NULL;
-static int force_pipe_server = 0;
-
-struct inq_certificate_parm_s {
- ASSUAN_CONTEXT ctx;
- KsbaCert cert;
-};
-
-struct lookup_parm_s {
- CTRL ctrl;
- ASSUAN_CONTEXT ctx;
- void (*cb)(void *, KsbaCert);
- void *cb_value;
- struct membuf data;
- int error;
-};
-
-struct run_command_parm_s {
- ASSUAN_CONTEXT ctx;
-};
-
-
-/* A simple implementation of a dynamic buffer. Use init_membuf() to
- create a buffer, put_membuf to append bytes and get_membuf to
- release and return the buffer. Allocation errors are detected but
- only returned at the final get_membuf(), this helps not to clutter
- the code with out of core checks. */
-
-static void
-init_membuf (struct membuf *mb, int initiallen)
-{
- mb->len = 0;
- mb->size = initiallen;
- mb->out_of_core = 0;
- mb->buf = xtrymalloc (initiallen);
- if (!mb->buf)
- mb->out_of_core = 1;
-}
-
-static void
-put_membuf (struct membuf *mb, const void *buf, size_t len)
-{
- if (mb->out_of_core)
- return;
-
- if (mb->len + len >= mb->size)
- {
- char *p;
-
- mb->size += len + 1024;
- p = xtryrealloc (mb->buf, mb->size);
- if (!p)
- {
- mb->out_of_core = 1;
- return;
- }
- mb->buf = p;
- }
- memcpy (mb->buf + mb->len, buf, len);
- mb->len += len;
-}
-
-static void *
-get_membuf (struct membuf *mb, size_t *len)
-{
- char *p;
-
- if (mb->out_of_core)
- {
- xfree (mb->buf);
- mb->buf = NULL;
- return NULL;
- }
-
- p = mb->buf;
- *len = mb->len;
- mb->buf = NULL;
- mb->out_of_core = 1; /* don't allow a reuse */
- return p;
-}
-
-
-
-
-
-/* Try to connect to the agent via socket or fork it off and work by
- pipes. Handle the server's initial greeting */
-static int
-start_dirmngr (void)
-{
- int rc;
- char *infostr, *p;
- ASSUAN_CONTEXT ctx;
-
- if (dirmngr_ctx)
- return 0; /* fixme: We need a context for each thread or serialize
- the access to the dirmngr */
-
- infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
- if (!infostr)
- {
- const char *pgmname;
- const char *argv[3];
- int no_close_list[3];
- int i;
-
- if (opt.verbose)
- log_info (_("no running dirmngr - starting one\n"));
-
- if (fflush (NULL))
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("error flushing pending output: %s\n", strerror (errno));
- return tmperr;
- }
-
- if (!opt.dirmngr_program || !*opt.dirmngr_program)
- opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR;
- if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
- pgmname = opt.dirmngr_program;
- else
- pgmname++;
-
- argv[0] = pgmname;
- argv[1] = "--server";
- argv[2] = NULL;
-
- i=0;
- if (log_get_fd () != -1)
- no_close_list[i++] = log_get_fd ();
- no_close_list[i++] = fileno (stderr);
- no_close_list[i] = -1;
-
- /* connect to the agent and perform initial handshaking */
- rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, (char**)argv,
- no_close_list);
- }
- else
- {
- int prot;
- int pid;
-
- infostr = xstrdup (infostr);
- if ( !(p = strchr (infostr, ':')) || p == infostr)
- {
- log_error (_("malformed DIRMNGR_INFO environment variable\n"));
- xfree (infostr);
- force_pipe_server = 1;
- return start_dirmngr ();
- }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != ':')
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
- {
- log_error (_("dirmngr protocol version %d is not supported\n"),
- prot);
- xfree (infostr);
- force_pipe_server = 1;
- return start_dirmngr ();
- }
-
- rc = assuan_socket_connect (&ctx, infostr, pid);
- xfree (infostr);
- if (rc == ASSUAN_Connect_Failed)
- {
- log_error (_("can't connect to the dirmngr - trying fall back\n"));
- force_pipe_server = 1;
- return start_dirmngr ();
- }
- }
-
- if (rc)
- {
- log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc));
- return gpg_error (GPG_ERR_NO_DIRMNGR);
- }
- dirmngr_ctx = ctx;
-
- if (DBG_ASSUAN)
- log_debug ("connection to dirmngr established\n");
- return 0;
-}
-
-
-
-/* Handle a SENDCERT inquiry. */
-static AssuanError
-inq_certificate (void *opaque, const char *line)
-{
- struct inq_certificate_parm_s *parm = opaque;
- AssuanError rc;
- const unsigned char *der;
- size_t derlen;
-
- if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])))
- {
- log_error ("unsupported inquiry `%s'\n", line);
- return ASSUAN_Inquire_Unknown;
- }
- line += 8;
-
- if (!*line)
- { /* send the current certificate */
- der = ksba_cert_get_image (parm->cert, &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- }
- else
- { /* send the given certificate */
- int err;
- KsbaCert cert;
-
- err = gpgsm_find_cert (line, &cert);
- if (err)
- {
- log_error ("certificate not found: %s\n", gpg_strerror (err));
- rc = ASSUAN_Inquire_Error;
- }
- else
- {
- der = ksba_cert_get_image (cert, &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- ksba_cert_release (cert);
- }
- }
-
- return rc;
-}
-
-
-
-/* Call the directory manager to check whether the certificate is valid
- Returns 0 for valid or usually one of the errors:
-
- GPG_ERR_CERTIFICATE_REVOKED
- GPG_ERR_NO_CRL_KNOWN
- GPG_ERR_CRL_TOO_OLD
- */
-int
-gpgsm_dirmngr_isvalid (KsbaCert cert)
-{
- int rc;
- char *certid;
- char line[ASSUAN_LINELENGTH];
- struct inq_certificate_parm_s parm;
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- certid = gpgsm_get_certid (cert);
- if (!certid)
- {
- log_error ("error getting the certificate ID\n");
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- if (opt.verbose > 1)
- {
- char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
- log_info ("asking dirmngr about %s\n", fpr);
- xfree (fpr);
- }
-
- parm.ctx = dirmngr_ctx;
- parm.cert = cert;
-
- snprintf (line, DIM(line)-1, "ISVALID %s", certid);
- line[DIM(line)-1] = 0;
- xfree (certid);
-
- rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
- inq_certificate, &parm, NULL, NULL);
- if (opt.verbose > 1)
- log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
- return map_assuan_err (rc);
-}
-
-
-
-/* Lookup helpers*/
-static AssuanError
-lookup_cb (void *opaque, const void *buffer, size_t length)
-{
- struct lookup_parm_s *parm = opaque;
- size_t len;
- char *buf;
- KsbaCert cert;
- int rc;
-
- if (parm->error)
- return 0;
-
- if (buffer)
- {
- put_membuf (&parm->data, buffer, length);
- return 0;
- }
- /* END encountered - process what we have */
- buf = get_membuf (&parm->data, &len);
- if (!buf)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
-
- cert = ksba_cert_new ();
- if (!cert)
- {
- parm->error = gpg_error (GPG_ERR_ENOMEM);
- return 0;
- }
- rc = ksba_cert_init_from_mem (cert, buf, len);
- if (rc)
- {
- log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc));
- }
- else
- {
- parm->cb (parm->cb_value, cert);
- }
-
- ksba_cert_release (cert);
- init_membuf (&parm->data, 4096);
- return 0;
-}
-
-/* Return a properly escaped pattern from NAMES. The only error
- return is NULL to indicate a malloc failure. */
-static char *
-pattern_from_strlist (STRLIST names)
-{
- STRLIST sl;
- int n;
- const char *s;
- char *pattern, *p;
-
- for (n=0, sl=names; sl; sl = sl->next)
- {
- for (s=sl->d; *s; s++, n++)
- {
- if (*s == '%' || *s == ' ' || *s == '+')
- n += 2;
- }
- n++;
- }
-
- p = pattern = xtrymalloc (n+1);
- if (!pattern)
- return NULL;
-
- for (n=0, sl=names; sl; sl = sl->next)
- {
- for (s=sl->d; *s; s++)
- {
- switch (*s)
- {
- case '%':
- *p++ = '%';
- *p++ = '2';
- *p++ = '5';
- break;
- case ' ':
- *p++ = '%';
- *p++ = '2';
- *p++ = '0';
- break;
- case '+':
- *p++ = '%';
- *p++ = '2';
- *p++ = 'B';
- break;
- default:
- *p++ = *s;
- break;
- }
- }
- *p++ = ' ';
- }
- if (p == pattern)
- *pattern = 0; /* is empty */
- else
- p[-1] = '\0'; /* remove trailing blank */
-
- return pattern;
-}
-
-static AssuanError
-lookup_status_cb (void *opaque, const char *line)
-{
- struct lookup_parm_s *parm = opaque;
-
- if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
- {
- if (parm->ctrl)
- {
- for (line +=9; *line == ' '; line++)
- ;
- gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
- }
- }
- return 0;
-}
-
-
-/* Run the Directroy Managers lookup command using the pattern
- compiled from the strings given in NAMES. The caller must provide
- the callback CB which will be passed cert by cert. Note that CTRL
- is optional. */
-int
-gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
- void (*cb)(void*, KsbaCert), void *cb_value)
-{
- int rc;
- char *pattern;
- char line[ASSUAN_LINELENGTH];
- struct lookup_parm_s parm;
- size_t len;
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- pattern = pattern_from_strlist (names);
- if (!pattern)
- return OUT_OF_CORE (errno);
- snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
- line[DIM(line)-1] = 0;
- xfree (pattern);
-
- parm.ctrl = ctrl;
- parm.ctx = dirmngr_ctx;
- parm.cb = cb;
- parm.cb_value = cb_value;
- parm.error = 0;
- init_membuf (&parm.data, 4096);
-
- rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
- NULL, NULL, lookup_status_cb, &parm);
- xfree (get_membuf (&parm.data, &len));
- if (rc)
- return map_assuan_err (rc);
- return parm.error;
-}
-
-
-
-/* Run Command helpers*/
-
-/* Fairly simple callback to write all output of dirmngr to stdout. */
-static AssuanError
-run_command_cb (void *opaque, const void *buffer, size_t length)
-{
- if (buffer)
- {
- if ( fwrite (buffer, length, 1, stdout) != 1 )
- log_error ("error writing to stdout: %s\n", strerror (errno));
- }
- return 0;
-}
-
-/* Handle inquiries from the dirmngr COMMAND. */
-static AssuanError
-run_command_inq_cb (void *opaque, const char *line)
-{
- struct run_command_parm_s *parm = opaque;
- AssuanError rc = 0;
-
- if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
- { /* send the given certificate */
- int err;
- KsbaCert cert;
- const unsigned char *der;
- size_t derlen;
-
- line += 8;
- if (!*line)
- return ASSUAN_Inquire_Error;
-
- err = gpgsm_find_cert (line, &cert);
- if (err)
- {
- log_error ("certificate not found: %s\n", gpg_strerror (err));
- rc = ASSUAN_Inquire_Error;
- }
- else
- {
- der = ksba_cert_get_image (cert, &derlen);
- if (!der)
- rc = ASSUAN_Inquire_Error;
- else
- rc = assuan_send_data (parm->ctx, der, derlen);
- ksba_cert_release (cert);
- }
- }
- else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
- { /* Simply show the message given in the argument. */
- line += 9;
- log_info ("dirmngr: %s\n", line);
- }
- else
- {
- log_error ("unsupported inquiry `%s'\n", line);
- rc = ASSUAN_Inquire_Unknown;
- }
-
- return rc;
-}
-
-static AssuanError
-run_command_status_cb (void *opaque, const char *line)
-{
- if (opt.verbose)
- {
- log_info ("dirmngr status: %s\n", line);
- }
- return 0;
-}
-
-
-
-/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
- to stdout. A couple of inquiries are defined (see above). ARGC
- arguments in ARGV are given to the Dirmngr. Spaces, plus and
- percent characters within the argument strings are percent escaped
- so that blanks can act as delimiters. */
-int
-gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
- int argc, char **argv)
-{
- int rc;
- int i;
- const char *s;
- char *line, *p;
- size_t len;
- struct run_command_parm_s parm;
-
- rc = start_dirmngr ();
- if (rc)
- return rc;
-
- parm.ctx = dirmngr_ctx;
-
- len = strlen (command) + 1;
- for (i=0; i < argc; i++)
- len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
- line = xtrymalloc (len);
- if (!line)
- return OUT_OF_CORE (errno);
-
- p = stpcpy (line, command);
- for (i=0; i < argc; i++)
- {
- *p++ = ' ';
- for (s=argv[i]; *s; s++)
- {
- if (!isascii (*s))
- *p++ = *s;
- else if (*s == ' ')
- *p++ = '+';
- else if (!isprint (*s) || *s == '+')
- {
- sprintf (p, "%%%02X", *s);
- p += 3;
- }
- else
- *p++ = *s;
- }
- }
- *p = 0;
-
- rc = assuan_transact (dirmngr_ctx, line,
- run_command_cb, NULL,
- run_command_inq_cb, &parm,
- run_command_status_cb, NULL);
- xfree (line);
- log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
- return map_assuan_err (rc);
-}
diff --git a/sm/certchain.c b/sm/certchain.c
deleted file mode 100644
index 6323c725e..000000000
--- a/sm/certchain.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/* certchain.c - certificate chain validation
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-static int
-unknown_criticals (KsbaCert cert)
-{
- static const char *known[] = {
- "2.5.29.15", /* keyUsage */
- "2.5.29.19", /* basic Constraints */
- "2.5.29.32", /* certificatePolicies */
- NULL
- };
- int rc = 0, i, idx, crit;
- const char *oid;
- KsbaError err;
-
- for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
- &oid, &crit, NULL, NULL));idx++)
- {
- if (!crit)
- continue;
- for (i=0; known[i] && strcmp (known[i],oid); i++)
- ;
- if (!known[i])
- {
- log_error (_("critical certificate extension %s is not supported\n"),
- oid);
- rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT);
- }
- }
- if (err && err != -1)
- rc = map_ksba_err (err);
-
- return rc;
-}
-
-static int
-allowed_ca (KsbaCert cert, int *chainlen)
-{
- KsbaError err;
- int flag;
-
- err = ksba_cert_is_ca (cert, &flag, chainlen);
- if (err)
- return map_ksba_err (err);
- if (!flag)
- {
- log_error (_("issuer certificate is not marked as a CA\n"));
- return gpg_error (GPG_ERR_BAD_CA_CERT);
- }
- return 0;
-}
-
-
-static int
-check_cert_policy (KsbaCert cert)
-{
- KsbaError err;
- char *policies;
- FILE *fp;
- int any_critical;
-
- err = ksba_cert_get_cert_policies (cert, &policies);
- if (err == KSBA_No_Data)
- return 0; /* no policy given */
- if (err)
- return map_ksba_err (err);
-
- /* STRING is a line delimited list of certifiate policies as stored
- in the certificate. The line itself is colon delimited where the
- first field is the OID of the policy and the second field either
- N or C for normal or critical extension */
-
- if (opt.verbose > 1)
- log_info ("certificate's policy list: %s\n", policies);
-
- /* The check is very minimal but won't give false positives */
- any_critical = !!strstr (policies, ":C");
-
- if (!opt.policy_file)
- {
- xfree (policies);
- if (any_critical)
- {
- log_error ("critical marked policy without configured policies\n");
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
- return 0;
- }
-
- fp = fopen (opt.policy_file, "r");
- if (!fp)
- {
- log_error ("failed to open `%s': %s\n",
- opt.policy_file, strerror (errno));
- xfree (policies);
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
-
- for (;;)
- {
- int c;
- char *p, line[256];
- char *haystack, *allowed;
-
- /* read line */
- do
- {
- if (!fgets (line, DIM(line)-1, fp) )
- {
- gpg_error_t tmperr;
-
- xfree (policies);
- if (feof (fp))
- {
- fclose (fp);
- /* with no critical policies this is only a warning */
- if (!any_critical)
- {
- log_info (_("note: certificate policy not allowed\n"));
- return 0;
- }
- log_error (_("certificate policy not allowed\n"));
- return gpg_error (GPG_ERR_NO_POLICY_MATCH);
- }
- tmperr = gpg_error (gpg_err_code_from_errno (errno));
- fclose (fp);
- return tmperr;
- }
-
- if (!*line || line[strlen(line)-1] != '\n')
- {
- /* eat until end of line */
- while ( (c=getc (fp)) != EOF && c != '\n')
- ;
- fclose (fp);
- xfree (policies);
- return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
- : GPG_ERR_INCOMPLETE_LINE);
- }
-
- /* Allow for empty lines and spaces */
- for (p=line; spacep (p); p++)
- ;
- }
- while (!*p || *p == '\n' || *p == '#');
-
- /* parse line */
- for (allowed=line; spacep (allowed); allowed++)
- ;
- p = strpbrk (allowed, " :\n");
- if (!*p || p == allowed)
- {
- fclose (fp);
- xfree (policies);
- return gpg_error (GPG_ERR_CONFIGURATION);
- }
- *p = 0; /* strip the rest of the line */
- /* See whether we find ALLOWED (which is an OID) in POLICIES */
- for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1)
- {
- if ( !(p == policies || p[-1] == '\n') )
- continue; /* does not match the begin of a line */
- if (p[strlen (allowed)] != ':')
- continue; /* the length does not match */
- /* Yep - it does match so return okay */
- fclose (fp);
- xfree (policies);
- return 0;
- }
- }
-}
-
-
-static void
-find_up_store_certs_cb (void *cb_value, KsbaCert cert)
-{
- if (keydb_store_cert (cert, 1, NULL))
- log_error ("error storing issuer certificate as ephemeral\n");
- ++*(int*)cb_value;
-}
-
-
-static int
-find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
-{
- KsbaName authid;
- KsbaSexp authidno;
- int rc = -1;
-
- if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno))
- {
- const char *s = ksba_name_enum (authid, 0);
- if (s && *authidno)
- {
- rc = keydb_search_issuer_sn (kh, s, authidno);
- if (rc)
- keydb_search_reset (kh);
- if (rc == -1)
- { /* And try the ephemeral DB. */
- int old = keydb_set_ephemeral (kh, 1);
- if (!old)
- {
- rc = keydb_search_issuer_sn (kh, s, authidno);
- if (rc)
- keydb_search_reset (kh);
- }
- keydb_set_ephemeral (kh, old);
- }
- }
- /* print a note so that the user does not feel too helpless when
- an issuer certificate was found and gpgsm prints BAD
- signature becuase it is not the correct one. */
- if (rc == -1)
- {
- log_info ("issuer certificate (#");
- gpgsm_dump_serial (authidno);
- log_printf ("/");
- gpgsm_dump_string (s);
- log_printf (") not found\n");
- }
- else if (rc)
- log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
- ksba_name_release (authid);
- xfree (authidno);
- /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
- }
-
- if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
- rc = keydb_search_subject (kh, issuer);
- if (rc == -1)
- {
- /* Not found, lets see whether we have one in the ephemeral key DB. */
- int old = keydb_set_ephemeral (kh, 1);
- if (!old)
- {
- keydb_search_reset (kh);
- rc = keydb_search_subject (kh, issuer);
- }
- keydb_set_ephemeral (kh, old);
- }
-
- if (rc == -1 && opt.auto_issuer_key_retrieve)
- {
- STRLIST names = NULL;
- int count = 0;
- char *pattern;
- const char *s;
-
- if (opt.verbose)
- log_info (_("looking up issuer at external location\n"));
- /* dirmngr is confused about unknown attributes so has a quick
- and ugly hack we locate the CN and use this and the
- following. Fixme: we should have far better parsing in the
- dirmngr. */
- s = strstr (issuer, "CN=");
- if (!s || s == issuer || s[-1] != ',')
- s = issuer;
-
- pattern = xtrymalloc (strlen (s)+2);
- if (!pattern)
- return OUT_OF_CORE (errno);
- strcpy (stpcpy (pattern, "/"), s);
- add_to_strlist (&names, pattern);
- xfree (pattern);
- rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
- free_strlist (names);
- if (opt.verbose)
- log_info (_("number of issuers matching: %d\n"), count);
- if (rc)
- {
- log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
- rc = -1;
- }
- else if (!count)
- rc = -1;
- else
- {
- int old;
- /* The issuers are currently stored in the ephemeral key
- DB, so we temporary switch to ephemeral mode. */
- old = keydb_set_ephemeral (kh, 1);
- keydb_search_reset (kh);
- rc = keydb_search_subject (kh, issuer);
- keydb_set_ephemeral (kh, old);
- }
- }
- return rc;
-}
-
-
-/* Return the next certificate up in the chain starting at START.
- Returns -1 when there are no more certificates. */
-int
-gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next)
-{
- int rc = 0;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
-
- *r_next = NULL;
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- issuer = ksba_cert_get_issuer (start, 0);
- subject = ksba_cert_get_subject (start, 0);
- if (!issuer)
- {
- log_error ("no issuer found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- if (!subject)
- {
- log_error ("no subject found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (!strcmp (issuer, subject))
- {
- rc = -1; /* we are at the root */
- goto leave;
- }
-
- rc = find_up (kh, start, issuer);
- if (rc)
- {
- /* it is quite common not to have a certificate, so better don't
- print an error here */
- if (rc != -1 && opt.verbose > 1)
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- rc = keydb_get_cert (kh, r_next);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- }
-
- leave:
- xfree (issuer);
- xfree (subject);
- keydb_release (kh);
- return rc;
-}
-
-
-/* Check whether the CERT is a root certificate. Returns True if this
- is the case. */
-int
-gpgsm_is_root_cert (KsbaCert cert)
-{
- char *issuer;
- char *subject;
- int yes;
-
- issuer = ksba_cert_get_issuer (cert, 0);
- subject = ksba_cert_get_subject (cert, 0);
- yes = (issuer && subject && !strcmp (issuer, subject));
- xfree (issuer);
- xfree (subject);
- return yes;
-}
-
-
-/* Validate a chain and optionally return the nearest expiration time
- in R_EXPTIME */
-int
-gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime)
-{
- int rc = 0, depth = 0, maxdepth;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
- KsbaCert subject_cert = NULL, issuer_cert = NULL;
- time_t current_time = gnupg_get_time ();
- time_t exptime = 0;
- int any_expired = 0;
- int any_revoked = 0;
- int any_no_crl = 0;
- int any_crl_too_old = 0;
- int any_no_policy_match = 0;
-
- if (r_exptime)
- *r_exptime = 0;
-
- if (opt.no_chain_validation)
- {
- log_info ("WARNING: bypassing certificate chain validation\n");
- return 0;
- }
-
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (DBG_X509)
- gpgsm_dump_cert ("subject", cert);
-
- subject_cert = cert;
- maxdepth = 50;
-
- for (;;)
- {
- xfree (issuer);
- xfree (subject);
- issuer = ksba_cert_get_issuer (subject_cert, 0);
- subject = ksba_cert_get_subject (subject_cert, 0);
-
- if (!issuer)
- {
- log_error ("no issuer found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- {
- time_t not_before, not_after;
-
- not_before = ksba_cert_get_validity (subject_cert, 0);
- not_after = ksba_cert_get_validity (subject_cert, 1);
- if (not_before == (time_t)(-1) || not_after == (time_t)(-1))
- {
- log_error ("certificate with invalid validity\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (not_after)
- {
- if (!exptime)
- exptime = not_after;
- else if (not_after < exptime)
- exptime = not_after;
- }
-
- if (not_before && current_time < not_before)
- {
- log_error ("certificate too young; valid from ");
- gpgsm_dump_time (not_before);
- log_printf ("\n");
- rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
- goto leave;
- }
- if (not_after && current_time > not_after)
- {
- log_error ("certificate has expired at ");
- gpgsm_dump_time (not_after);
- log_printf ("\n");
- any_expired = 1;
- }
- }
-
- rc = unknown_criticals (subject_cert);
- if (rc)
- goto leave;
-
- if (!opt.no_policy_check)
- {
- rc = check_cert_policy (subject_cert);
- if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
- {
- any_no_policy_match = 1;
- rc = 1;
- }
- else if (rc)
- goto leave;
- }
-
- if (!opt.no_crl_check)
- {
- rc = gpgsm_dirmngr_isvalid (subject_cert);
- if (rc)
- {
- switch (rc)
- {
- case GPG_ERR_CERT_REVOKED:
- log_error (_("the certificate has been revoked\n"));
- any_revoked = 1;
- break;
- case GPG_ERR_NO_CRL_KNOWN:
- log_error (_("no CRL found for certificate\n"));
- any_no_crl = 1;
- break;
- case GPG_ERR_CRL_TOO_OLD:
- log_error (_("the available CRL is too old\n"));
- log_info (_("please make sure that the "
- "\"dirmngr\" is properly installed\n"));
- any_crl_too_old = 1;
- break;
- default:
- log_error (_("checking the CRL failed: %s\n"),
- gpg_strerror (rc));
- goto leave;
- }
- rc = 0;
- }
- }
-
- if (subject && !strcmp (issuer, subject))
- {
- if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
- {
- log_error ("selfsigned certificate has a BAD signatures\n");
- rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN
- : GPG_ERR_BAD_CERT);
- goto leave;
- }
- rc = allowed_ca (subject_cert, NULL);
- if (rc)
- goto leave;
-
- rc = gpgsm_agent_istrusted (subject_cert);
- if (!rc)
- ;
- else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
- {
- int rc2;
-
- char *fpr = gpgsm_get_fingerprint_string (subject_cert,
- GCRY_MD_SHA1);
- log_info (_("root certificate is not marked trusted\n"));
- log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
- xfree (fpr);
- rc2 = gpgsm_agent_marktrusted (subject_cert);
- if (!rc2)
- {
- log_info (_("root certificate has now"
- " been marked as trusted\n"));
- rc = 0;
- }
- else
- {
- gpgsm_dump_cert ("issuer", subject_cert);
- log_info ("after checking the fingerprint, you may want "
- "to enter it manually into "
- "\"~/.gnupg-test/trustlist.txt\"\n");
- }
- }
- else
- {
- log_error (_("checking the trust list failed: %s\n"),
- gpg_strerror (rc));
- }
-
- break; /* okay, a self-signed certicate is an end-point */
- }
-
- depth++;
- if (depth > maxdepth)
- {
- log_error (_("certificate chain too long\n"));
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
-
- /* find the next cert up the tree */
- keydb_search_reset (kh);
- rc = find_up (kh, subject_cert, issuer);
- if (rc)
- {
- if (rc == -1)
- {
- log_info ("issuer certificate (#/");
- gpgsm_dump_string (issuer);
- log_printf (") not found\n");
- }
- else
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- ksba_cert_release (issuer_cert); issuer_cert = NULL;
- rc = keydb_get_cert (kh, &issuer_cert);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (DBG_X509)
- {
- log_debug ("got issuer's certificate:\n");
- gpgsm_dump_cert ("issuer", issuer_cert);
- }
-
- if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
- {
- log_error ("certificate has a BAD signatures\n");
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
-
- {
- int chainlen;
- rc = allowed_ca (issuer_cert, &chainlen);
- if (rc)
- goto leave;
- if (chainlen >= 0 && (depth - 1) > chainlen)
- {
- log_error (_("certificate chain longer than allowed by CA (%d)\n"),
- chainlen);
- rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
- goto leave;
- }
- }
-
- rc = gpgsm_cert_use_cert_p (issuer_cert);
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
- numbuf, NULL);
- rc = 0;
- }
-
- if (opt.verbose)
- log_info ("certificate is good\n");
-
- keydb_search_reset (kh);
- subject_cert = issuer_cert;
- issuer_cert = NULL;
- }
-
- if (opt.no_policy_check)
- log_info ("policies not checked due to --disable-policy-checks option\n");
- if (opt.no_crl_check)
- log_info ("CRLs not checked due to --disable-crl-checks option\n");
-
- if (!rc)
- { /* If we encountered an error somewhere during the checks, set
- the error code to the most critical one */
- if (any_revoked)
- rc = gpg_error (GPG_ERR_CERT_REVOKED);
- else if (any_no_crl)
- rc = gpg_error (GPG_ERR_NO_CRL_KNOWN);
- else if (any_crl_too_old)
- rc = gpg_error (GPG_ERR_CRL_TOO_OLD);
- else if (any_no_policy_match)
- rc = gpg_error (GPG_ERR_NO_POLICY_MATCH);
- else if (any_expired)
- rc = gpg_error (GPG_ERR_CERT_EXPIRED);
- }
-
- leave:
- if (r_exptime)
- *r_exptime = exptime;
- xfree (issuer);
- keydb_release (kh);
- ksba_cert_release (issuer_cert);
- if (subject_cert != cert)
- ksba_cert_release (subject_cert);
- return rc;
-}
-
-
-/* Check that the given certificate is valid but DO NOT check any
- constraints. We assume that the issuers certificate is already in
- the DB and that this one is valid; which it should be because it
- has been checked using this function. */
-int
-gpgsm_basic_cert_check (KsbaCert cert)
-{
- int rc = 0;
- char *issuer = NULL;
- char *subject = NULL;
- KEYDB_HANDLE kh = keydb_new (0);
- KsbaCert issuer_cert = NULL;
-
- if (opt.no_chain_validation)
- {
- log_info ("WARNING: bypassing basic certificate checks\n");
- return 0;
- }
-
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- issuer = ksba_cert_get_issuer (cert, 0);
- subject = ksba_cert_get_subject (cert, 0);
- if (!issuer)
- {
- log_error ("no issuer found in certificate\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
-
- if (subject && !strcmp (issuer, subject))
- {
- if (gpgsm_check_cert_sig (cert, cert) )
- {
- log_error ("selfsigned certificate has a BAD signatures\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- }
- else
- {
- /* find the next cert up the tree */
- keydb_search_reset (kh);
- rc = find_up (kh, cert, issuer);
- if (rc)
- {
- if (rc == -1)
- {
- log_info ("issuer certificate (#/");
- gpgsm_dump_string (issuer);
- log_printf (") not found\n");
- }
- else
- log_error ("failed to find issuer's certificate: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_MISSING_CERT);
- goto leave;
- }
-
- ksba_cert_release (issuer_cert); issuer_cert = NULL;
- rc = keydb_get_cert (kh, &issuer_cert);
- if (rc)
- {
- log_error ("failed to get cert: rc=%d\n", rc);
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- if (gpgsm_check_cert_sig (issuer_cert, cert) )
- {
- log_error ("certificate has a BAD signatures\n");
- rc = gpg_error (GPG_ERR_BAD_CERT);
- goto leave;
- }
- if (opt.verbose)
- log_info ("certificate is good\n");
- }
-
- leave:
- xfree (issuer);
- keydb_release (kh);
- ksba_cert_release (issuer_cert);
- return rc;
-}
-
diff --git a/sm/certcheck.c b/sm/certcheck.c
deleted file mode 100644
index 35509c67e..000000000
--- a/sm/certcheck.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/* certcheck.c - check one certificate
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-static int
-do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits,
- gcry_mpi_t *r_val)
-{
- int nframe = (nbits+7) / 8;
- byte *frame;
- int i, n;
- byte asn[100];
- size_t asnlen;
- size_t len;
-
- asnlen = DIM(asn);
- if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
- {
- log_error ("No object identifier for algo %d\n", algo);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- len = gcry_md_get_algo_dlen (algo);
-
- if ( len + asnlen + 4 > nframe )
- {
- log_error ("can't encode a %d bit MD into a %d bits frame\n",
- (int)(len*8), (int)nbits);
- return gpg_error (GPG_ERR_INTERNAL);
- }
-
- /* We encode the MD in this way:
- *
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = xtrymalloc (nframe);
- if (!frame)
- return OUT_OF_CORE (errno);
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - len - asnlen -3 ;
- assert ( i > 1 );
- memset ( frame+n, 0xff, i ); n += i;
- frame[n++] = 0;
- memcpy ( frame+n, asn, asnlen ); n += asnlen;
- memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
- assert ( n == nframe );
- if (DBG_X509)
- {
- int j;
- log_debug ("encoded hash:");
- for (j=0; j < nframe; j++)
- log_printf (" %02X", frame[j]);
- log_printf ("\n");
- }
-
- gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
- xfree (frame);
- return 0;
-}
-
-
-/*
- Check the signature on CERT using the ISSUER-CERT. This function
- does only test the cryptographic signature and nothing else. It is
- assumed that the ISSUER_CERT is valid. */
-int
-gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
-{
- const char *algoid;
- gcry_md_hd_t md;
- int rc, algo;
- gcry_mpi_t frame;
- KsbaSexp p;
- size_t n;
- gcry_sexp_t s_sig, s_hash, s_pkey;
-
- algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
- if (!algo)
- {
- log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
- return gpg_error (GPG_ERR_GENERAL);
- }
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- return rc;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "hash.cert");
-
- rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
- if (rc)
- {
- log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
- gcry_md_close (md);
- return map_ksba_err (rc);
- }
- gcry_md_final (md);
-
- p = ksba_cert_get_sig_val (cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
- ksba_free (p);
- return gpg_error (GPG_ERR_BUG);
- }
- if (DBG_X509)
- {
- int j;
- log_debug ("signature value:");
- for (j=0; j < n; j++)
- log_printf (" %02X", p[j]);
- log_printf ("\n");
- }
-
- rc = gcry_sexp_sscan ( &s_sig, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- return rc;
- }
-
- p = ksba_cert_get_public_key (issuer_cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- gcry_md_close (md);
- ksba_free (p);
- gcry_sexp_release (s_sig);
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- return rc;
- }
-
- rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
- if (rc)
- {
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
- }
-
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
-
-
- rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
- if (DBG_CRYPTO)
- log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
- gcry_md_close (md);
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_pkey);
- return rc;
-}
-
-
-
-int
-gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
- gcry_md_hd_t md, int algo)
-{
- int rc;
- KsbaSexp p;
- gcry_mpi_t frame;
- gcry_sexp_t s_sig, s_hash, s_pkey;
- size_t n;
-
- n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- p = ksba_cert_get_public_key (cert);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- ksba_free (p);
- gcry_sexp_release (s_sig);
- return gpg_error (GPG_ERR_BUG);
- }
- if (DBG_X509)
- log_printhex ("public key: ", p, n);
-
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- ksba_free (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
- return rc;
- }
-
-
- rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
- if (rc)
- {
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_pkey);
- return rc;
- }
- /* put hash into the S-Exp s_hash */
- if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
- BUG ();
- gcry_mpi_release (frame);
-
- rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
- if (DBG_CRYPTO)
- log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
- gcry_sexp_release (s_sig);
- gcry_sexp_release (s_hash);
- gcry_sexp_release (s_pkey);
- return rc;
-}
-
-
-
-int
-gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo,
- char **r_sigval)
-{
- int rc;
- char *grip;
- size_t siglen;
-
- grip = gpgsm_get_keygrip_hexstring (cert);
- if (!grip)
- return gpg_error (GPG_ERR_BAD_CERT);
-
- rc = gpgsm_agent_pksign (grip, gcry_md_read(md, mdalgo),
- gcry_md_get_algo_dlen (mdalgo), mdalgo,
- r_sigval, &siglen);
- xfree (grip);
- return rc;
-}
-
-
-
diff --git a/sm/certdump.c b/sm/certdump.c
deleted file mode 100644
index 703e07186..000000000
--- a/sm/certdump.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/* certdump.c - Dump a certificate for debugging
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct dn_array_s {
- char *key;
- char *value;
-};
-
-
-/* print the first element of an S-Expression */
-void
-gpgsm_print_serial (FILE *fp, KsbaConstSexp p)
-{
- unsigned long n;
- KsbaConstSexp endp;
-
- if (!p)
- fputs (_("none"), fp);
- else if (*p != '(')
- fputs ("[Internal error - not an S-expression]", fp);
- else
- {
- p++;
- n = strtoul (p, (char**)&endp, 10);
- p = endp;
- if (*p!=':')
- fputs ("[Internal Error - invalid S-expression]", fp);
- else
- {
- for (p++; n; n--, p++)
- fprintf (fp, "%02X", *p);
- }
- }
-}
-
-
-void
-gpgsm_dump_serial (KsbaConstSexp p)
-{
- unsigned long n;
- KsbaConstSexp endp;
-
- if (!p)
- log_printf ("none");
- else if (*p != '(')
- log_printf ("ERROR - not an S-expression");
- else
- {
- p++;
- n = strtoul (p, (char**)&endp, 10);
- p = endp;
- if (*p!=':')
- log_printf ("ERROR - invalid S-expression");
- else
- {
- for (p++; n; n--, p++)
- log_printf ("%02X", *p);
- }
- }
-}
-
-void
-gpgsm_print_time (FILE *fp, time_t t)
-{
- if (!t)
- fputs (_("none"), fp);
- else if ( t == (time_t)(-1) )
- fputs ("[Error - Invalid time]", fp);
- else
- {
- struct tm *tp;
-
- tp = gmtime (&t);
- fprintf (fp, "%04d-%02d-%02d %02d:%02d:%02d Z",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec);
- assert (!tp->tm_isdst);
- }
-}
-
-void
-gpgsm_dump_time (time_t t)
-{
-
- if (!t)
- log_printf (_("[none]"));
- else if ( t == (time_t)(-1) )
- log_printf (_("[error]"));
- else
- {
- struct tm *tp;
-
- tp = gmtime (&t);
- log_printf ("%04d-%02d-%02d %02d:%02d:%02d",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec);
- assert (!tp->tm_isdst);
- }
-}
-
-
-
-
-void
-gpgsm_dump_string (const char *string)
-{
-
- if (!string)
- log_printf ("[error]");
- else
- {
- const unsigned char *s;
-
- for (s=string; *s; s++)
- {
- if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
- break;
- }
- if (!*s && *string != '[')
- log_printf ("%s", string);
- else
- {
- log_printf ( "[ ");
- log_printhex (NULL, string, strlen (string));
- log_printf ( " ]");
- }
- }
-}
-
-
-void
-gpgsm_dump_cert (const char *text, KsbaCert cert)
-{
- KsbaSexp sexp;
- unsigned char *p;
- char *dn;
- time_t t;
-
- log_debug ("BEGIN Certificate `%s':\n", text? text:"");
- if (cert)
- {
- sexp = ksba_cert_get_serial (cert);
- log_debug (" serial: ");
- gpgsm_dump_serial (sexp);
- ksba_free (sexp);
- log_printf ("\n");
-
- t = ksba_cert_get_validity (cert, 0);
- log_debug (" notBefore: ");
- gpgsm_dump_time (t);
- log_printf ("\n");
- t = ksba_cert_get_validity (cert, 1);
- log_debug (" notAfter: ");
- gpgsm_dump_time (t);
- log_printf ("\n");
-
- dn = ksba_cert_get_issuer (cert, 0);
- log_debug (" issuer: ");
- gpgsm_dump_string (dn);
- ksba_free (dn);
- log_printf ("\n");
-
- dn = ksba_cert_get_subject (cert, 0);
- log_debug (" subject: ");
- gpgsm_dump_string (dn);
- ksba_free (dn);
- log_printf ("\n");
-
- log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert));
-
- p = gpgsm_get_fingerprint_string (cert, 0);
- log_debug (" SHA1 Fingerprint: %s\n", p);
- xfree (p);
- }
- log_debug ("END Certificate\n");
-}
-
-
-
-/* helper for the rfc2253 string parser */
-static const unsigned char *
-parse_dn_part (struct dn_array_s *array, const unsigned char *string)
-{
- const unsigned char *s, *s1;
- size_t n;
- unsigned char *p;
-
- /* parse attributeType */
- for (s = string+1; *s && *s != '='; s++)
- ;
- if (!*s)
- return NULL; /* error */
- n = s - string;
- if (!n)
- return NULL; /* empty key */
- array->key = p = xtrymalloc (n+1);
- if (!array->key)
- return NULL;
- memcpy (p, string, n);
- p[n] = 0;
- trim_trailing_spaces (p);
- if ( !strcmp (p, "1.2.840.113549.1.9.1") )
- strcpy (p, "EMail");
- string = s + 1;
-
- if (*string == '#')
- { /* hexstring */
- string++;
- for (s=string; hexdigitp (s); s++)
- s++;
- n = s - string;
- if (!n || (n & 1))
- return NULL; /* empty or odd number of digits */
- n /= 2;
- array->value = p = xtrymalloc (n+1);
- if (!p)
- return NULL;
- for (s1=string; n; s1 += 2, n--)
- *p++ = xtoi_2 (s1);
- *p = 0;
- }
- else
- { /* regular v3 quoted string */
- for (n=0, s=string; *s; s++)
- {
- if (*s == '\\')
- { /* pair */
- s++;
- if (*s == ',' || *s == '=' || *s == '+'
- || *s == '<' || *s == '>' || *s == '#' || *s == ';'
- || *s == '\\' || *s == '\"' || *s == ' ')
- n++;
- else if (hexdigitp (s) && hexdigitp (s+1))
- {
- s++;
- n++;
- }
- else
- return NULL; /* invalid escape sequence */
- }
- else if (*s == '\"')
- return NULL; /* invalid encoding */
- else if (*s == ',' || *s == '=' || *s == '+'
- || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
- break;
- else
- n++;
- }
-
- array->value = p = xtrymalloc (n+1);
- if (!p)
- return NULL;
- for (s=string; n; s++, n--)
- {
- if (*s == '\\')
- {
- s++;
- if (hexdigitp (s))
- {
- *p++ = xtoi_2 (s);
- s++;
- }
- else
- *p++ = *s;
- }
- else
- *p++ = *s;
- }
- *p = 0;
- }
- return s;
-}
-
-
-/* Parse a DN and return an array-ized one. This is not a validating
- parser and it does not support any old-stylish syntax; KSBA is
- expected to return only rfc2253 compatible strings. */
-static struct dn_array_s *
-parse_dn (const unsigned char *string)
-{
- struct dn_array_s *array;
- size_t arrayidx, arraysize;
- int i;
-
- arraysize = 7; /* C,ST,L,O,OU,CN,email */
- arrayidx = 0;
- array = xtrymalloc ((arraysize+1) * sizeof *array);
- if (!array)
- return NULL;
- while (*string)
- {
- while (*string == ' ')
- string++;
- if (!*string)
- break; /* ready */
- if (arrayidx >= arraysize)
- {
- struct dn_array_s *a2;
-
- arraysize += 5;
- a2 = xtryrealloc (array, (arraysize+1) * sizeof *array);
- if (!a2)
- goto failure;
- array = a2;
- }
- array[arrayidx].key = NULL;
- array[arrayidx].value = NULL;
- string = parse_dn_part (array+arrayidx, string);
- arrayidx++;
- if (!string)
- goto failure;
- while (*string == ' ')
- string++;
- if (*string && *string != ',' && *string != ';' && *string != '+')
- goto failure; /* invalid delimiter */
- if (*string)
- string++;
- }
- array[arrayidx].key = NULL;
- array[arrayidx].value = NULL;
- return array;
-
- failure:
- for (i=0; i < arrayidx; i++)
- {
- xfree (array[i].key);
- xfree (array[i].value);
- }
- xfree (array);
- return NULL;
-}
-
-
-static void
-print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key)
-{
- int any = 0;
-
- for (; dn->key; dn++)
- {
- if (!strcmp (dn->key, key) && dn->value && *dn->value)
- {
- putc ('/', fp);
- if (any)
- fputs (" + ", fp);
- else
- fprintf (fp, "%s=", key);
- print_sanitized_utf8_string (fp, dn->value, '/');
- any = 1;
- }
- }
-}
-
-/* Print all parts of a DN in a "standard" sequence. We first print
- all the known parts, followed by the uncommon ones */
-static void
-print_dn_parts (FILE *fp, struct dn_array_s *dn)
-{
- const char *stdpart[] = {
- "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL
- };
- int i;
-
- for (i=0; stdpart[i]; i++)
- print_dn_part (fp, dn, stdpart[i]);
-
- /* now print the rest without any specific ordering */
- for (; dn->key; dn++)
- {
- for (i=0; stdpart[i]; i++)
- {
- if (!strcmp (dn->key, stdpart[i]))
- break;
- }
- if (!stdpart[i])
- print_dn_part (fp, dn, dn->key);
- }
-}
-
-
-
-void
-gpgsm_print_name (FILE *fp, const char *name)
-{
- const unsigned char *s;
- int i;
-
- s = name;
- if (!s)
- {
- fputs (_("[Error - No name]"), fp);
- }
- else if (*s == '<')
- {
- const unsigned char *s2 = strchr (s+1, '>');
- if (s2)
- print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0);
- }
- else if (*s == '(')
- fputs (_("[Error - unknown encoding]"), fp);
- else if (!((*s >= '0' && *s < '9')
- || (*s >= 'A' && *s <= 'Z')
- || (*s >= 'a' && *s <= 'z')))
- fputs (_("[Error - invalid encoding]"), fp);
- else
- {
- struct dn_array_s *dn = parse_dn (s);
- if (!dn)
- fputs (_("[Error - invalid DN]"), fp);
- else
- {
- print_dn_parts (fp, dn);
- for (i=0; dn[i].key; i++)
- {
- xfree (dn[i].key);
- xfree (dn[i].value);
- }
- xfree (dn);
- }
- }
-}
-
-
-
diff --git a/sm/certlist.c b/sm/certlist.c
deleted file mode 100644
index eedc99025..000000000
--- a/sm/certlist.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/* certlist.c - build list of certificates
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-/* Return 0 if the cert is usable for encryption. A MODE of 0 checks
- for signing a MODE of 1 checks for encryption, a MODE of 2 checks
- for verification and a MODE of 3 for decryption (just for
- debugging) */
-static int
-cert_usage_p (KsbaCert cert, int mode)
-{
- KsbaError err;
- unsigned int use;
-
- err = ksba_cert_get_key_usage (cert, &use);
- if (err == KSBA_No_Data)
- {
- if (opt.verbose && mode < 2)
- log_info (mode?
- _("no key usage specified - accepted for encryption\n"):
- _("no key usage specified - accepted for signing\n"));
- return 0;
- }
- if (err)
- {
- log_error (_("error getting key usage information: %s\n"),
- ksba_strerror (err));
- return map_ksba_err (err);
- }
-
- if (mode == 4)
- {
- if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
- return 0;
- log_info ( _("certificate should have not been used certification\n"));
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
- }
-
- if ((use & ((mode&1)?
- (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT):
- (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- )
- return 0;
- log_info (mode==3? _("certificate should have not been used for encryption\n"):
- mode==2? _("certificate should have not been used for signing\n"):
- mode==1? _("certificate is not usable for encryption\n"):
- _("certificate is not usable for signing\n"));
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
-}
-
-
-/* Return 0 if the cert is usable for signing */
-int
-gpgsm_cert_use_sign_p (KsbaCert cert)
-{
- return cert_usage_p (cert, 0);
-}
-
-
-/* Return 0 if the cert is usable for encryption */
-int
-gpgsm_cert_use_encrypt_p (KsbaCert cert)
-{
- return cert_usage_p (cert, 1);
-}
-
-int
-gpgsm_cert_use_verify_p (KsbaCert cert)
-{
- return cert_usage_p (cert, 2);
-}
-
-int
-gpgsm_cert_use_decrypt_p (KsbaCert cert)
-{
- return cert_usage_p (cert, 3);
-}
-
-int
-gpgsm_cert_use_cert_p (KsbaCert cert)
-{
- return cert_usage_p (cert, 4);
-}
-
-
-static int
-same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert)
-{
- char *subject2 = ksba_cert_get_subject (cert, 0);
- char *issuer2 = ksba_cert_get_subject (cert, 0);
- int tmp;
-
- tmp = (subject && subject2
- && !strcmp (subject, subject2)
- && issuer && issuer2
- && !strcmp (issuer, issuer2));
- xfree (subject2);
- xfree (issuer2);
- return tmp;
-}
-
-
-
-/* Add a certificate to a list of certificate and make sure that it is
- a valid certificate. With SECRET set to true a secret key must be
- avaibale for the certificate. */
-int
-gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
- CERTLIST *listaddr)
-{
- int rc;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
- KsbaCert cert = NULL;
-
- rc = keydb_classify_name (name, &desc);
- if (!rc)
- {
- kh = keydb_new (0);
- if (!kh)
- rc = gpg_error (GPG_ERR_ENOMEM);
- else
- {
- int wrong_usage = 0;
- char *subject = NULL;
- char *issuer = NULL;
-
- get_next:
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, &cert);
- if (!rc)
- {
- rc = secret? gpgsm_cert_use_sign_p (cert)
- : gpgsm_cert_use_encrypt_p (cert);
- if (gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE)
- {
- /* There might be another certificate with the
- correct usage, so we try again */
- if (!wrong_usage)
- { /* save the first match */
- wrong_usage = rc;
- subject = ksba_cert_get_subject (cert, 0);
- issuer = ksba_cert_get_subject (cert, 0);
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
- }
- else if (same_subject_issuer (subject, issuer, cert))
- {
- wrong_usage = rc;
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
- }
- else
- wrong_usage = rc;
-
- }
- }
- /* we want the error code from the first match in this case */
- if (rc && wrong_usage)
- rc = wrong_usage;
-
- if (!rc)
- {
- next_ambigious:
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else if (!rc)
- {
- KsbaCert cert2 = NULL;
-
- /* We have to ignore ambigious names as long as
- there only fault is a bad key usage */
- if (!keydb_get_cert (kh, &cert2))
- {
- int tmp = (same_subject_issuer (subject, issuer, cert2)
- && ((gpg_err_code (
- secret? gpgsm_cert_use_sign_p (cert2)
- : gpgsm_cert_use_encrypt_p (cert2)
- )
- ) == GPG_ERR_WRONG_KEY_USAGE));
- ksba_cert_release (cert2);
- if (tmp)
- goto next_ambigious;
- }
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- }
- }
- xfree (subject);
- xfree (issuer);
-
- if (!rc && secret)
- {
- char *p;
-
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- if (!gpgsm_agent_havekey (p))
- rc = 0;
- xfree (p);
- }
- }
- if (!rc)
- rc = gpgsm_validate_chain (ctrl, cert, NULL);
- if (!rc)
- {
- CERTLIST cl = xtrycalloc (1, sizeof *cl);
- if (!cl)
- rc = OUT_OF_CORE (errno);
- else
- {
- cl->cert = cert; cert = NULL;
- cl->next = *listaddr;
- *listaddr = cl;
- }
- }
- }
- }
-
- keydb_release (kh);
- ksba_cert_release (cert);
- return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
-}
-
-void
-gpgsm_release_certlist (CERTLIST list)
-{
- while (list)
- {
- CERTLIST cl = list->next;
- ksba_cert_release (list->cert);
- xfree (list);
- list = cl;
- }
-}
-
-
-/* Like gpgsm_add_to_certlist, but look only for one certificate. No
- chain validation is done */
-int
-gpgsm_find_cert (const char *name, KsbaCert *r_cert)
-{
- int rc;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
-
- *r_cert = NULL;
- rc = keydb_classify_name (name, &desc);
- if (!rc)
- {
- kh = keydb_new (0);
- if (!kh)
- rc = gpg_error (GPG_ERR_ENOMEM);
- else
- {
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, r_cert);
- if (!rc)
- {
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else
- {
- if (!rc)
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- ksba_cert_release (*r_cert);
- *r_cert = NULL;
- }
- }
- }
- }
-
- keydb_release (kh);
- return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc;
-}
-
diff --git a/sm/certreqgen.c b/sm/certreqgen.c
deleted file mode 100644
index 0dd4fdde9..000000000
--- a/sm/certreqgen.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/* certreqgen.c - Generate a key and a certification request
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
-The format of the native parameter file is follows:
- o Text only, line length is limited to about 1000 chars.
- o You must use UTF-8 encoding to specify non-ascii characters.
- o Empty lines are ignored.
- o Leading and trailing spaces are ignored.
- o A hash sign as the first non white space character is a comment line.
- o Control statements are indicated by a leading percent sign, the
- arguments are separated by white space from the keyword.
- o Parameters are specified by a keyword, followed by a colon. Arguments
- are separated by white space.
- o The first parameter must be "Key-Type", control statements
- may be placed anywhere.
- o Key generation takes place when either the end of the parameter file
- is reached, the next "Key-Type" parameter is encountered or at the
- controlstatement "%commit"
- o Control statements:
- %echo <text>
- Print <text>.
- %dry-run
- Suppress actual key generation (useful for syntax checking).
- %commit
- Perform the key generation. Note that an implicit commit is done
- at the next "Key-Type" parameter.
- %certfile <filename>
- Do not write the certificate to the keyDB but to <filename>.
- This must be given before the first
- commit to take place, duplicate specification of the same filename
- is ignored, the last filename before a commit is used.
- The filename is used until a new filename is used (at commit points)
- and all keys are written to that file. If a new filename is given,
- this file is created (and overwrites an existing one).
- Both control statements must be given.
- o The order of the parameters does not matter except for "Key-Type"
- which must be the first parameter. The parameters are only for the
- generated keyblock and parameters from previous key generations are not
- used. Some syntactically checks may be performed.
- The currently defined parameters are:
- Key-Type: <algo>
- Starts a new parameter block by giving the type of the
- primary key. The algorithm must be capable of signing.
- This is a required parameter. For now the only supported
- algorithm is "rsa".
- Key-Length: <length-in-bits>
- Length of the key in bits. Default is 1024.
- Key-Usage: <usage-list>
- Space or comma delimited list of key usage, allowed values are
- "encrypt" and "sign". This is used to generate the KeyUsage extension.
- Please make sure that the algorithm is capable of this usage. Default
- is to allow encrypt and sign.
- Name-DN: subject name
- This is the DN name of the subject in rfc2253 format.
- Name-Email: <string>
- The ist the email address
-
-Here is an example:
-$ cat >foo <<EOF
-%echo Generating a standard key
-Key-Type: RSA
-Key-Length: 1024
-Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
-Name-Email: joe@foo.bar
-# Do a commit here, so that we can later print "done" :-)
-%commit
-%echo done
-EOF
-*/
-
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-enum para_name {
- pKEYTYPE,
- pKEYLENGTH,
- pKEYUSAGE,
- pNAMEDN,
- pNAMEEMAIL
-};
-
-struct para_data_s {
- struct para_data_s *next;
- int lnr;
- enum para_name key;
- union {
- unsigned int usage;
- char value[1];
- } u;
-};
-
-struct reqgen_ctrl_s {
- int lnr;
- int dryrun;
- KsbaWriter writer;
-};
-
-
-static int proc_parameters (struct para_data_s *para,
- struct reqgen_ctrl_s *outctrl);
-static int create_request (struct para_data_s *para,
- KsbaConstSexp public,
- struct reqgen_ctrl_s *outctrl);
-
-
-
-static void
-release_parameter_list (struct para_data_s *r)
-{
- struct para_data_s *r2;
-
- for (; r ; r = r2)
- {
- r2 = r->next;
- xfree(r);
- }
-}
-
-static struct para_data_s *
-get_parameter (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r;
-
- for (r = para; r && r->key != key; r = r->next)
- ;
- return r;
-}
-
-static const char *
-get_parameter_value (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r = get_parameter (para, key);
- return (r && *r->u.value)? r->u.value : NULL;
-}
-
-static int
-get_parameter_algo (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r = get_parameter (para, key);
- if (!r)
- return -1;
- if (digitp (r->u.value))
- return atoi( r->u.value );
- return gcry_pk_map_name (r->u.value);
-}
-
-/* parse the usage parameter. Returns 0 on success. Note that we
- only care about sign and encrypt and don't (yet) allow all the
- other X.509 usage to be specified; instead we will use a fixed
- mapping to the X.509 usage flags */
-static int
-parse_parameter_usage (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r = get_parameter (para, key);
- char *p, *pn;
- unsigned int use;
-
- if (!r)
- return 0; /* none (this is an optional parameter)*/
-
- use = 0;
- pn = r->u.value;
- while ( (p = strsep (&pn, " \t,")) )
- {
- if (!*p)
- ;
- else if ( !ascii_strcasecmp (p, "sign") )
- use |= GCRY_PK_USAGE_SIGN;
- else if ( !ascii_strcasecmp (p, "encrypt") )
- use |= GCRY_PK_USAGE_ENCR;
- else
- {
- log_error ("line %d: invalid usage list\n", r->lnr);
- return -1; /* error */
- }
- }
- r->u.usage = use;
- return 0;
-}
-
-
-static unsigned int
-get_parameter_uint (struct para_data_s *para, enum para_name key)
-{
- struct para_data_s *r = get_parameter (para, key);
-
- if (!r)
- return 0;
-
- return (unsigned int)strtoul (r->u.value, NULL, 10);
-}
-
-
-
-/* Read the certificate generation parameters from FP and generate
- (all) certificate requests. */
-static int
-read_parameters (FILE *fp, KsbaWriter writer)
-{
- static struct {
- const char *name;
- enum para_name key;
- } keywords[] = {
- { "Key-Type", pKEYTYPE},
- { "Key-Length", pKEYLENGTH },
- { "Key-Usage", pKEYUSAGE },
- { "Name-DN", pNAMEDN },
- { "Name-Email", pNAMEEMAIL },
- { NULL, 0 }
- };
- char line[1024], *p;
- const char *err = NULL;
- struct para_data_s *para, *r;
- int i, rc = 0, any = 0;
- struct reqgen_ctrl_s outctrl;
-
- memset (&outctrl, 0, sizeof (outctrl));
- outctrl.writer = writer;
-
- err = NULL;
- para = NULL;
- while (fgets (line, DIM(line)-1, fp) )
- {
- char *keyword, *value;
-
- outctrl.lnr++;
- if (*line && line[strlen(line)-1] != '\n')
- {
- err = "line too long";
- break;
- }
- for (p=line; spacep (p); p++)
- ;
- if (!*p || *p == '#')
- continue;
-
- keyword = p;
- if (*keyword == '%')
- {
- for (; !spacep (p); p++)
- ;
- if (*p)
- *p++ = 0;
- for (; spacep (p); p++)
- ;
- value = p;
- trim_trailing_spaces (value);
-
- if (!ascii_strcasecmp (keyword, "%echo"))
- log_info ("%s\n", value);
- else if (!ascii_strcasecmp (keyword, "%dry-run"))
- outctrl.dryrun = 1;
- else if (!ascii_strcasecmp( keyword, "%commit"))
- {
- rc = proc_parameters (para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- release_parameter_list (para);
- para = NULL;
- }
- else
- log_info ("skipping control `%s' (%s)\n", keyword, value);
-
- continue;
- }
-
-
- if (!(p = strchr (p, ':')) || p == keyword)
- {
- err = "missing colon";
- break;
- }
- if (*p)
- *p++ = 0;
- for (; spacep (p); p++)
- ;
- if (!*p)
- {
- err = "missing argument";
- break;
- }
- value = p;
- trim_trailing_spaces (value);
-
- for (i=0; (keywords[i].name
- && ascii_strcasecmp (keywords[i].name, keyword)); i++)
- ;
- if (!keywords[i].name)
- {
- err = "unknown keyword";
- break;
- }
- if (keywords[i].key != pKEYTYPE && !para)
- {
- err = "parameter block does not start with \"Key-Type\"";
- break;
- }
-
- if (keywords[i].key == pKEYTYPE && para)
- {
- rc = proc_parameters (para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- release_parameter_list (para);
- para = NULL;
- }
- else
- {
- for (r = para; r && r->key != keywords[i].key; r = r->next)
- ;
- if (r)
- {
- err = "duplicate keyword";
- break;
- }
- }
-
- r = xtrycalloc (1, sizeof *r + strlen( value ));
- if (!r)
- {
- err = "out of core";
- break;
- }
- r->lnr = outctrl.lnr;
- r->key = keywords[i].key;
- strcpy (r->u.value, value);
- r->next = para;
- para = r;
- }
-
- if (err)
- {
- log_error ("line %d: %s\n", outctrl.lnr, err);
- rc = gpg_error (GPG_ERR_GENERAL);
- }
- else if (ferror(fp))
- {
- log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) );
- rc = gpg_error (GPG_ERR_GENERAL);
- }
- else if (para)
- {
- rc = proc_parameters (para, &outctrl);
- if (rc)
- goto leave;
- any = 1;
- }
-
- if (!rc && !any)
- rc = gpg_error (GPG_ERR_NO_DATA);
-
- leave:
- release_parameter_list (para);
- return rc;
-}
-
-/* check whether there are invalid characters in the email address S */
-static int
-has_invalid_email_chars (const char *s)
-{
- int at_seen=0;
- static char valid_chars[] = "01234567890_-."
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- for (; *s; s++)
- {
- if (*s & 0x80)
- return 1;
- if (*s == '@')
- at_seen++;
- else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+'))
- return 1;
- else if (at_seen && !strchr (valid_chars, *s))
- return 1;
- }
- return at_seen != 1;
-}
-
-
-/* Check that all required parameters are given and perform the action */
-static int
-proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl)
-{
- struct para_data_s *r;
- const char *s;
- int i;
- unsigned int nbits;
- char numbuf[20];
- unsigned char keyparms[100];
- int rc;
- KsbaSexp public;
-
- /* check that we have all required parameters */
- assert (get_parameter (para, pKEYTYPE));
-
- /* We can only use RSA for now. There is a with pkcs-10 on how to
- use ElGamal becuase it is expected that a PK algorithm can always
- be used for signing. */
- i = get_parameter_algo (para, pKEYTYPE);
- if (i < 1 || i != GCRY_PK_RSA )
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: invalid algorithm\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
-
- /* check the keylength */
- if (!get_parameter (para, pKEYLENGTH))
- nbits = 1024;
- else
- nbits = get_parameter_uint (para, pKEYLENGTH);
- if (nbits < 512 || nbits > 4096)
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n",
- r->lnr, nbits);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
-
- /* check the usage */
- if (parse_parameter_usage (para, pKEYUSAGE))
- return gpg_error (GPG_ERR_INV_PARAMETER);
-
- /* check that there is a subject name and that this DN fits our
- requirements */
- if (!(s=get_parameter_value (para, pNAMEDN)))
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: no subject name given\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
- /* fixme check s */
-
- /* check that the optional email address is okay */
- if ((s=get_parameter_value (para, pNAMEEMAIL)))
- {
- if (has_invalid_email_chars (s)
- || *s == '@'
- || s[strlen(s)-1] == '@'
- || s[strlen(s)-1] == '.'
- || strstr(s, ".."))
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: not a valid email address\n", r->lnr);
- return gpg_error (GPG_ERR_INV_PARAMETER);
- }
- }
-
- sprintf (numbuf, "%u", nbits);
- snprintf (keyparms, DIM (keyparms)-1,
- "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf);
- rc = gpgsm_agent_genkey (keyparms, &public);
- if (rc)
- {
- r = get_parameter (para, pKEYTYPE);
- log_error ("line %d: key generation failed: %s\n",
- r->lnr, gpg_strerror (rc));
- return rc;
- }
-
- rc = create_request (para, public, outctrl);
- xfree (public);
-
- return rc;
-}
-
-
-/* Parameters are checked, the key pair has been created. Now
- generate the request and write it out */
-static int
-create_request (struct para_data_s *para, KsbaConstSexp public,
- struct reqgen_ctrl_s *outctrl)
-{
- KsbaCertreq cr;
- KsbaError err;
- gcry_md_hd_t md;
- KsbaStopReason stopreason;
- int rc = 0;
- const char *s;
-
- cr = ksba_certreq_new ();
- if (!cr)
- return gpg_error (GPG_ERR_ENOMEM);
-
- rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "cr.cri");
-
- ksba_certreq_set_hash_function (cr, HASH_FNC, md);
- ksba_certreq_set_writer (cr, outctrl->writer);
-
- err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN));
- if (err)
- {
- log_error ("error setting the subject's name: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- s = get_parameter_value (para, pNAMEEMAIL);
- if (s)
- {
- char *buf;
-
- buf = xtrymalloc (strlen (s) + 3);
- if (!buf)
- {
- rc = OUT_OF_CORE (errno);
- goto leave;
- }
- *buf = '<';
- strcpy (buf+1, s);
- strcat (buf+1, ">");
- err = ksba_certreq_add_subject (cr, buf);
- xfree (buf);
- if (err)
- {
- log_error ("error setting the subject's alternate name: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
-
-
- err = ksba_certreq_set_public_key (cr, public);
- if (err)
- {
- log_error ("error setting the public key: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- do
- {
- err = ksba_certreq_build (cr, &stopreason);
- if (err)
- {
- log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- if (stopreason == KSBA_SR_NEED_SIG)
- {
- gcry_sexp_t s_pkey;
- size_t n;
- unsigned char grip[20], hexgrip[41];
- char *sigval;
- size_t siglen;
-
- n = gcry_sexp_canon_len (public, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- err = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, public, n);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if ( !gcry_pk_get_keygrip (s_pkey, grip) )
- {
- rc = gpg_error (GPG_ERR_GENERAL);
- log_error ("can't figure out the keygrip\n");
- gcry_sexp_release (s_pkey);
- goto leave;
- }
- gcry_sexp_release (s_pkey);
- for (n=0; n < 20; n++)
- sprintf (hexgrip+n*2, "%02X", grip[n]);
-
- rc = gpgsm_agent_pksign (hexgrip,
- gcry_md_read(md, GCRY_MD_SHA1),
- gcry_md_get_algo_dlen (GCRY_MD_SHA1),
- GCRY_MD_SHA1,
- &sigval, &siglen);
- if (rc)
- {
- log_error ("signing failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_certreq_set_sig_val (cr, sigval);
- xfree (sigval);
- if (err)
- {
- log_error ("failed to store the sig_val: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
- }
- while (stopreason != KSBA_SR_READY);
-
-
- leave:
- gcry_md_close (md);
- ksba_certreq_release (cr);
- return rc;
-}
-
-
-
-/* Create a new key by reading the parameters from in_fd. Multiple
- keys may be created */
-int
-gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp)
-{
- int rc;
- FILE *in_fp;
- Base64Context b64writer = NULL;
- KsbaWriter writer;
-
- in_fp = fdopen (dup (in_fd), "rb");
- if (!in_fp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- return tmperr;
- }
-
- ctrl->pem_name = "NEW CERTIFICATE REQUEST";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = read_parameters (in_fp, writer);
- if (rc)
- {
- log_error ("error creating certificate request: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- gpgsm_status (ctrl, STATUS_KEY_CREATED, "P");
- log_info ("certificate request created\n");
-
- leave:
- gpgsm_destroy_writer (b64writer);
- fclose (in_fp);
- return rc;
-}
-
diff --git a/sm/decrypt.c b/sm/decrypt.c
deleted file mode 100644
index 17483aa49..000000000
--- a/sm/decrypt.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/* decrypt.c - Decrypt a message
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct decrypt_filter_parm_s {
- int algo;
- int mode;
- int blklen;
- gcry_cipher_hd_t hd;
- char iv[16];
- size_t ivlen;
- int any_data; /* dod we push anything through the filter at all? */
- unsigned char lastblock[16]; /* to strip the padding we have to
- keep this one */
- char helpblock[16]; /* needed because there is no block buffering in
- libgcrypt (yet) */
- int helpblocklen;
-};
-
-
-
-/* decrypt the session key and fill in the parm structure. The
- algo and the IV is expected to be already in PARM. */
-static int
-prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
- struct decrypt_filter_parm_s *parm)
-{
- char *seskey = NULL;
- size_t n, seskeylen;
- int rc;
-
- rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val,
- &seskey, &seskeylen);
- if (rc)
- {
- log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (DBG_CRYPTO)
- log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
-
- n=0;
- if (seskeylen == 24)
- {
- /* Smells like a 3-des key. This might happen because a SC has
- already done the unpacking. fixme! */
- }
- else
- {
- if (n + 7 > seskeylen )
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
-
- /* FIXME: Actually the leading zero is required but due to the way
- we encode the output in libgcrypt as an MPI we are not able to
- encode that leading zero. However, when using a Smartcard we are
- doing it the rightway and therefore we have to skip the zero. This
- should be fixed in gpg-agent of course. */
- if (!seskey[n])
- n++;
-
- if (seskey[n] != 2 ) /* wrong block type version */
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
-
- for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
- ;
- n++; /* and the zero byte */
- if (n >= seskeylen )
- {
- rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
- goto leave;
- }
- }
-
- if (DBG_CRYPTO)
- log_printhex ("session key:", seskey+n, seskeylen-n);
-
- rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
- if (rc)
- {
- log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
- if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
- {
- log_info (_("WARNING: message was encrypted with "
- "a weak key in the symmetric cipher.\n"));
- rc = 0;
- }
- if (rc)
- {
- log_error("key setup failed: %s\n", gpg_strerror(rc) );
- goto leave;
- }
-
- gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
-
- leave:
- xfree (seskey);
- return rc;
-}
-
-
-/* This function is called by the KSBA writer just before the actual
- write is done. The function must take INLEN bytes from INBUF,
- decrypt it and store it inoutbuf which has a maximum size of
- maxoutlen. The valid bytes in outbuf should be return in outlen.
- Due to different buffer sizes or different length of input and
- output, it may happen that fewer bytes are process or fewer bytes
- are written. */
-static KsbaError
-decrypt_filter (void *arg,
- const void *inbuf, size_t inlen, size_t *inused,
- void *outbuf, size_t maxoutlen, size_t *outlen)
-{
- struct decrypt_filter_parm_s *parm = arg;
- int blklen = parm->blklen;
- size_t orig_inlen = inlen;
-
- /* fixme: Should we issue an error when we have not seen one full block? */
- if (!inlen)
- return KSBA_Bug;
-
- if (maxoutlen < 2*parm->blklen)
- return KSBA_Bug;
- /* make some space becuase we will later need an extra block at the end */
- maxoutlen -= blklen;
-
- if (parm->helpblocklen)
- {
- int i, j;
-
- for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++)
- parm->helpblock[i] = ((const char*)inbuf)[j];
- inlen -= j;
- if (blklen > maxoutlen)
- return KSBA_Bug;
- if (i < blklen)
- {
- parm->helpblocklen = i;
- *outlen = 0;
- }
- else
- {
- parm->helpblocklen = 0;
- if (parm->any_data)
- {
- memcpy (outbuf, parm->lastblock, blklen);
- *outlen =blklen;
- }
- else
- *outlen = 0;
- gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen,
- parm->helpblock, blklen);
- parm->any_data = 1;
- }
- *inused = orig_inlen - inlen;
- return 0;
- }
-
-
- if (inlen > maxoutlen)
- inlen = maxoutlen;
- if (inlen % blklen)
- { /* store the remainder away */
- parm->helpblocklen = inlen%blklen;
- inlen = inlen/blklen*blklen;
- memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen);
- }
-
- *inused = inlen + parm->helpblocklen;
- if (inlen)
- {
- assert (inlen >= blklen);
- if (parm->any_data)
- {
- gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen,
- inbuf, inlen);
- memcpy (outbuf, parm->lastblock, blklen);
- memcpy (parm->lastblock,(char*)outbuf+inlen, blklen);
- *outlen = inlen;
- }
- else
- {
- gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
- memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen);
- *outlen = inlen - blklen;
- parm->any_data = 1;
- }
- }
- else
- *outlen = 0;
- return 0;
-}
-
-
-
-/* Perform a decrypt operation. */
-int
-gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
-{
- int rc;
- KsbaError err;
- Base64Context b64reader = NULL;
- Base64Context b64writer = NULL;
- KsbaReader reader;
- KsbaWriter writer;
- KsbaCMS cms = NULL;
- KsbaStopReason stopreason;
- KEYDB_HANDLE kh;
- int recp;
- FILE *in_fp = NULL;
- struct decrypt_filter_parm_s dfparm;
-
- memset (&dfparm, 0, sizeof dfparm);
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
-
- in_fp = fdopen ( dup (in_fd), "rb");
- if (!in_fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, reader, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* parser loop */
- do
- {
- err = ksba_cms_parse (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA
- || stopreason == KSBA_SR_DETACHED_DATA)
- {
- int algo, mode;
- const char *algoid;
- int any_key = 0;
-
- algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
- algo = gcry_cipher_map_name (algoid);
- mode = gcry_cipher_mode_from_oid (algoid);
- if (!algo || !mode)
- {
- rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
- if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
- log_info (_("(this is the RC2 algorithm)\n"));
- else if (!algoid)
- log_info (_("(this does not seem to be an encrypted"
- " message)\n"));
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
- numbuf, algoid?algoid:"?", NULL);
- }
-
- goto leave;
- }
- dfparm.algo = algo;
- dfparm.mode = mode;
- dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
- if (dfparm.blklen > sizeof (dfparm.helpblock))
- return gpg_error (GPG_ERR_BUG);
-
- rc = ksba_cms_get_content_enc_iv (cms,
- dfparm.iv,
- sizeof (dfparm.iv),
- &dfparm.ivlen);
- if (rc)
- {
- log_error ("error getting IV: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- for (recp=0; !any_key; recp++)
- {
- char *issuer;
- KsbaSexp serial;
- KsbaSexp enc_val;
- char *hexkeygrip = NULL;
-
- err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
- if (err == -1 && recp)
- break; /* no more recipients */
- if (err)
- log_error ("recp %d - error getting info: %s\n",
- recp, ksba_strerror (err));
- else
- {
- KsbaCert cert = NULL;
-
- log_debug ("recp %d - issuer: `%s'\n",
- recp, issuer? issuer:"[NONE]");
- log_debug ("recp %d - serial: ", recp);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
-
- keydb_search_reset (kh);
- rc = keydb_search_issuer_sn (kh, issuer, serial);
- if (rc)
- {
- log_error ("failed to find the certificate: %s\n",
- gpg_strerror(rc));
- goto oops;
- }
-
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_error ("failed to get cert: %s\n", gpg_strerror (rc));
- goto oops;
- }
- /* Just in case there is a problem with the own
- certificate we print this message - should never
- happen of course */
- rc = gpgsm_cert_use_decrypt_p (cert);
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
- gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
- numbuf, NULL);
- rc = 0;
- }
-
- hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
-
- oops:
- xfree (issuer);
- xfree (serial);
- ksba_cert_release (cert);
- }
-
- if (!hexkeygrip)
- ;
- else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
- log_error ("recp %d - error getting encrypted session key\n",
- recp);
- else
- {
- rc = prepare_decryption (hexkeygrip, enc_val, &dfparm);
- xfree (enc_val);
- if (rc)
- {
- log_debug ("decrypting session key failed: %s\n",
- gpg_strerror (rc));
- }
- else
- { /* setup the bulk decrypter */
- any_key = 1;
- ksba_writer_set_filter (writer,
- decrypt_filter,
- &dfparm);
- }
- }
- }
- if (!any_key)
- {
- rc = gpg_error (GPG_ERR_NO_SECKEY);
- goto leave;
- }
- }
- else if (stopreason == KSBA_SR_END_DATA)
- {
- ksba_writer_set_filter (writer, NULL, NULL);
- if (dfparm.any_data)
- { /* write the last block with padding removed */
- int i, npadding = dfparm.lastblock[dfparm.blklen-1];
- if (!npadding || npadding > dfparm.blklen)
- {
- log_error ("invalid padding with value %d\n", npadding);
- rc = gpg_error (GPG_ERR_INV_DATA);
- goto leave;
- }
- rc = ksba_writer_write (writer,
- dfparm.lastblock,
- dfparm.blklen - npadding);
- if (rc)
- {
- rc = map_ksba_err (rc);
- goto leave;
- }
- for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
- {
- if (dfparm.lastblock[i] != npadding)
- {
- log_error ("inconsistent padding\n");
- rc = gpg_error (GPG_ERR_INV_DATA);
- goto leave;
- }
- }
- }
- }
-
- }
- while (stopreason != KSBA_SR_READY);
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);
-
-
- leave:
- if (rc)
- gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
- ksba_cms_release (cms);
- gpgsm_destroy_reader (b64reader);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- if (in_fp)
- fclose (in_fp);
- if (dfparm.hd)
- gcry_cipher_close (dfparm.hd);
- return rc;
-}
-
-
diff --git a/sm/delete.c b/sm/delete.c
deleted file mode 100644
index 53eff864c..000000000
--- a/sm/delete.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* delete.c
- * Copyright (C) 2002 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-/* Delete a certificate or an secret key from a key database. */
-static int
-delete_one (CTRL ctrl, const char *username)
-{
- int rc = 0;
- KEYDB_SEARCH_DESC desc;
- KEYDB_HANDLE kh = NULL;
- KsbaCert cert = NULL;
- int duplicates = 0;
-
- rc = keydb_classify_name (username, &desc);
- if (rc)
- {
- log_error (_("certificate `%s' not found: %s\n"),
- username, gpg_strerror (rc));
- gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "1", NULL);
- goto leave;
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
-
- rc = keydb_search (kh, &desc, 1);
- if (!rc)
- rc = keydb_get_cert (kh, &cert);
- if (!rc)
- {
- char fpr[20];
-
- gpgsm_get_fingerprint (cert, 0, fpr, NULL);
-
- next_ambigious:
- rc = keydb_search (kh, &desc, 1);
- if (rc == -1)
- rc = 0;
- else if (!rc)
- {
- KsbaCert cert2 = NULL;
- char fpr2[20];
-
- /* We ignore all duplicated certificates which might have
- been inserted due to program bugs. */
- if (!keydb_get_cert (kh, &cert2))
- {
- gpgsm_get_fingerprint (cert2, 0, fpr2, NULL);
- ksba_cert_release (cert2);
- if (!memcmp (fpr, fpr2, 20))
- {
- duplicates++;
- goto next_ambigious;
- }
- }
- rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- }
- }
- if (rc)
- {
- if (rc == -1)
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- log_error (_("certificate `%s' not found: %s\n"),
- username, gpg_strerror (rc));
- gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL);
- goto leave;
- }
-
- /* we need to search again to get back to the right position. */
- do
- {
- keydb_search_reset (kh);
- rc = keydb_search (kh, &desc, 1);
- if (rc)
- {
- log_error ("problem re-searching certificate: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- rc = keydb_delete (kh);
- if (rc)
- goto leave;
- if (opt.verbose)
- {
- if (duplicates)
- log_info (_("duplicated certificate `%s' deleted\n"), username);
- else
- log_info (_("certificate `%s' deleted\n"), username);
- }
- }
- while (duplicates--);
-
- leave:
- keydb_release (kh);
- ksba_cert_release (cert);
- return rc;
-}
-
-
-
-/* Delete the certificates specified by NAMES. */
-int
-gpgsm_delete (CTRL ctrl, STRLIST names)
-{
- int rc;
-
- if (!names)
- {
- log_error ("nothing to delete\n");
- return gpg_error (GPG_ERR_NO_DATA);
- }
-
- for (; names; names=names->next )
- {
- rc = delete_one (ctrl, names->d);
- if (rc)
- {
- log_error (_("deleting certificate \"%s\" failed: %s\n"),
- names->d, gpg_strerror (rc) );
- return rc;
- }
- }
-
- return 0;
-}
diff --git a/sm/encrypt.c b/sm/encrypt.c
deleted file mode 100644
index 725a81b70..000000000
--- a/sm/encrypt.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* encrypt.c - Encrypt a message
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-struct dek_s {
- const char *algoid;
- int algo;
- gcry_cipher_hd_t chd;
- char key[32];
- int keylen;
- char iv[32];
- int ivlen;
-};
-typedef struct dek_s *DEK;
-
-struct encrypt_cb_parm_s {
- FILE *fp;
- DEK dek;
- int eof_seen;
- int ready;
- int readerror;
- int bufsize;
- unsigned char *buffer;
- int buflen;
-};
-
-
-
-
-
-/* initialize the data encryptionkey (session key) */
-static int
-init_dek (DEK dek)
-{
- int rc=0, mode, i;
-
- dek->algo = gcry_cipher_map_name (dek->algoid);
- mode = gcry_cipher_mode_from_oid (dek->algoid);
- if (!dek->algo || !mode)
- {
- log_error ("unsupported algorithm `%s'\n", dek->algoid);
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- }
-
- dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
- if (!dek->keylen || dek->keylen > sizeof (dek->key))
- return gpg_error (GPG_ERR_BUG);
-
- dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo);
- if (!dek->ivlen || dek->ivlen > sizeof (dek->iv))
- return gpg_error (GPG_ERR_BUG);
-
- if (dek->keylen < 100/8)
- { /* make sure we don't use weak keys */
- log_error ("key length of `%s' too small\n", dek->algoid);
- return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- }
-
- rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE);
- if (rc)
- {
- log_error ("failed to create cipher context: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- for (i=0; i < 8; i++)
- {
- gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
- rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen);
- if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
- break;
- log_info(_("weak key created - retrying\n") );
- }
- if (rc)
- {
- log_error ("failed to set the key: %s\n", gpg_strerror (rc));
- gcry_cipher_close (dek->chd);
- dek->chd = NULL;
- return rc;
- }
-
- gcry_randomize (dek->iv, dek->ivlen, GCRY_STRONG_RANDOM);
- rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen);
- if (rc)
- {
- log_error ("failed to set the IV: %s\n", gpg_strerror (rc));
- gcry_cipher_close (dek->chd);
- dek->chd = NULL;
- return rc;
- }
-
- return 0;
-}
-
-
-/* Encode the session key. NBITS is the number of bits which should be
- used for packing the session key. returns: An mpi with the session
- key (caller must free) */
-static gcry_mpi_t
-encode_session_key (DEK dek, unsigned int nbits)
-{
- int nframe = (nbits+7) / 8;
- byte *p;
- byte *frame;
- int i,n;
- gcry_mpi_t a;
-
- if (dek->keylen + 7 > nframe || !nframe)
- log_bug ("can't encode a %d bit key in a %d bits frame\n",
- dek->keylen*8, nbits );
-
- /* We encode the session key in this way:
- *
- * 0 2 RND(n bytes) 0 KEY(k bytes)
- *
- * (But how can we store the leading 0 - the external representaion
- * of MPIs doesn't allow leading zeroes =:-)
- *
- * RND are non-zero random bytes.
- * KEY is the encryption key (session key)
- */
-
- frame = gcry_xmalloc_secure (nframe);
- n = 0;
- frame[n++] = 0;
- frame[n++] = 2;
- i = nframe - 3 - dek->keylen;
- assert (i > 0);
- p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
- /* replace zero bytes by new values */
- for (;;)
- {
- int j, k;
- byte *pp;
-
- /* count the zero bytes */
- for(j=k=0; j < i; j++ )
- {
- if( !p[j] )
- k++;
- }
- if( !k )
- break; /* okay: no zero bytes */
-
- k += k/128; /* better get some more */
- pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
- for (j=0; j < i && k; j++)
- {
- if( !p[j] )
- p[j] = pp[--k];
- }
- xfree (pp);
- }
- memcpy (frame+n, p, i);
- xfree (p);
-
- n += i;
- frame[n++] = 0;
- memcpy (frame+n, dek->key, dek->keylen);
- n += dek->keylen;
- assert (n == nframe);
- if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, n, &nframe) )
- BUG ();
- gcry_free(frame);
-
- return a;
-}
-
-
-
-/* encrypt the DEK under the key contained in CERT and return it as a
- canonical S-Exp in encval */
-static int
-encrypt_dek (const DEK dek, KsbaCert cert, char **encval)
-{
- gcry_sexp_t s_ciph, s_data, s_pkey;
- int rc;
- KsbaSexp buf;
- size_t len;
-
- *encval = NULL;
-
- /* get the key from the cert */
- buf = ksba_cert_get_public_key (cert);
- if (!buf)
- {
- log_error ("no public key for recipient\n");
- return gpg_error (GPG_ERR_NO_PUBKEY);
- }
- len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
- if (!len)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return gpg_error (GPG_ERR_BUG);
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len);
- xfree (buf); buf = NULL;
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return rc;
- }
-
- /* put the encoded cleartext into a simple list */
- {
- /* fixme: actually the pkcs-1 encoding should go into libgcrypt */
- gcry_mpi_t data = encode_session_key (dek, gcry_pk_get_nbits (s_pkey));
- if (!data)
- {
- gcry_mpi_release (data);
- return gpg_error (GPG_ERR_GENERAL);
- }
- if (gcry_sexp_build (&s_data, NULL, "%m", data))
- BUG ();
- gcry_mpi_release (data);
- }
-
- /* pass it to libgcrypt */
- rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
- gcry_sexp_release (s_data);
- gcry_sexp_release (s_pkey);
-
- /* reformat it */
- len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, NULL, 0);
- assert (len);
- buf = xtrymalloc (len);
- if (!buf)
- {
- gpg_error_t tmperr = OUT_OF_CORE (errno);
- gcry_sexp_release (s_ciph);
- return tmperr;
- }
- len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, buf, len);
- assert (len);
-
- *encval = buf;
- return 0;
-}
-
-
-
-/* do the actual encryption */
-static int
-encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
-{
- struct encrypt_cb_parm_s *parm = cb_value;
- int blklen = parm->dek->ivlen;
- unsigned char *p;
- size_t n;
-
- *nread = 0;
- if (!buffer)
- return -1; /* not supported */
-
- if (parm->ready)
- return -1;
-
- if (count < blklen)
- BUG ();
-
- if (!parm->eof_seen)
- { /* fillup the buffer */
- p = parm->buffer;
- for (n=parm->buflen; n < parm->bufsize; n++)
- {
- int c = getc (parm->fp);
- if (c == EOF)
- {
- if (ferror (parm->fp))
- {
- parm->readerror = errno;
- return -1;
- }
- parm->eof_seen = 1;
- break;
- }
- p[n] = c;
- }
- parm->buflen = n;
- }
-
- n = parm->buflen < count? parm->buflen : count;
- n = n/blklen * blklen;
- if (n)
- { /* encrypt the stuff */
- gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
- *nread = n;
- /* Who cares about cycles, take the easy way and shift the buffer */
- parm->buflen -= n;
- memmove (parm->buffer, parm->buffer+n, parm->buflen);
- }
- else if (parm->eof_seen)
- { /* no complete block but eof: add padding */
- /* fixme: we should try to do this also in the above code path */
- int i, npad = blklen - (parm->buflen % blklen);
- p = parm->buffer;
- for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++)
- p[n] = npad;
- gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n);
- *nread = n;
- parm->ready = 1;
- }
-
- return 0;
-}
-
-
-
-
-/* Perform an encrypt operation.
-
- Encrypt the data received on DATA-FD and write it to OUT_FP. The
- recipients are take from the certificate given in recplist; if this
- is NULL it will be encrypted for a default recipient */
-int
-gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp)
-{
- int rc = 0;
- Base64Context b64writer = NULL;
- KsbaError err;
- KsbaWriter writer;
- KsbaReader reader = NULL;
- KsbaCMS cms = NULL;
- KsbaStopReason stopreason;
- KEYDB_HANDLE kh = NULL;
- struct encrypt_cb_parm_s encparm;
- DEK dek = NULL;
- int recpno;
- FILE *data_fp = NULL;
- CERTLIST cl;
-
- memset (&encparm, 0, sizeof encparm);
-
- if (!recplist)
- {
- log_error(_("no valid recipients given\n"));
- gpgsm_status (ctrl, STATUS_NO_RECP, "0");
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- goto leave;
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- data_fp = fdopen ( dup (data_fd), "rb");
- if (!data_fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- reader = ksba_reader_new ();
- if (!reader)
- rc = KSBA_Out_Of_Core;
- if (!rc)
- rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
- if (rc)
- {
- rc = map_ksba_err (rc);
- goto leave;
- }
- encparm.fp = data_fp;
-
- ctrl->pem_name = "ENCRYPTED MESSAGE";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, reader, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* We are going to create enveloped data with uninterpreted data as
- inner content */
- err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
- if (!err)
- err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
- if (err)
- {
- log_debug ("ksba_cms_set_content_type failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* create a session key */
- dek = xtrycalloc (1, sizeof *dek); /* hmmm: should we put it into secmem?*/
- if (!dek)
- rc = OUT_OF_CORE (errno);
- else
- {
- dek->algoid = opt.def_cipher_algoid;
- rc = init_dek (dek);
- }
- if (rc)
- {
- log_error ("failed to create the session key: %s\n",
- gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
- if (err)
- {
- log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- encparm.dek = dek;
- /* Use a ~8k (AES) or ~4k (3DES) buffer */
- encparm.bufsize = 500 * dek->ivlen;
- encparm.buffer = xtrymalloc (encparm.bufsize);
- if (!encparm.buffer)
- {
- rc = OUT_OF_CORE (errno);
- goto leave;
- }
-
- /* gather certificates of recipients, encrypt the session key for
- each and store them in the CMS object */
- for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
- {
- char *encval;
-
- rc = encrypt_dek (dek, cl->cert, &encval);
- if (rc)
- {
- log_error ("encryption failed for recipient no. %d: %s\n",
- recpno, gpg_strerror (rc));
- goto leave;
- }
-
- err = ksba_cms_add_recipient (cms, cl->cert);
- if (err)
- {
- log_error ("ksba_cms_add_recipient failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- xfree (encval);
- goto leave;
- }
-
- err = ksba_cms_set_enc_val (cms, recpno, encval);
- xfree (encval);
- if (err)
- {
- log_error ("ksba_cms_set_enc_val failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
-
- /* main control loop for encryption */
- recpno = 0;
- do
- {
- err = ksba_cms_build (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- if (encparm.readerror)
- {
- log_error ("error reading input: %s\n", strerror (encparm.readerror));
- rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
- goto leave;
- }
-
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- log_info ("encrypted data created\n");
-
- leave:
- ksba_cms_release (cms);
- gpgsm_destroy_writer (b64writer);
- ksba_reader_release (reader);
- keydb_release (kh);
- xfree (dek);
- if (data_fp)
- fclose (data_fp);
- xfree (encparm.buffer);
- return rc;
-}
diff --git a/sm/export.c b/sm/export.c
deleted file mode 100644
index 93a55debc..000000000
--- a/sm/export.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* export.c
- * Copyright (C) 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-
-static void print_short_info (KsbaCert cert, FILE *fp);
-
-
-
-/* Export all certificates or just those given in NAMES. */
-void
-gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp)
-{
- KEYDB_HANDLE hd;
- KEYDB_SEARCH_DESC *desc = NULL;
- int ndesc;
- Base64Context b64writer = NULL;
- KsbaWriter writer;
- STRLIST sl;
- KsbaCert cert = NULL;
- int rc=0;
- int count = 0;
- int i;
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
- if (!names)
- ndesc = 1;
- else
- {
- for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
- ;
- }
-
- desc = xtrycalloc (ndesc, sizeof *desc);
- if (!ndesc)
- {
- log_error ("allocating memory for export failed: %s\n",
- gpg_strerror (OUT_OF_CORE (errno)));
- goto leave;
- }
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
- else
- {
- for (ndesc=0, sl=names; sl; sl = sl->next)
- {
- rc = keydb_classify_name (sl->d, desc+ndesc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- sl->d, gpg_strerror (rc));
- rc = 0;
- }
- else
- ndesc++;
- }
- }
-
- /* If all specifications are done by fingerprint, we switch to
- ephemeral mode so that _all_ currently available and matching
- certificates are exported.
-
- fixme: we should in this case keep a list of certificates to
- avoid accidential export of duplicate certificates. */
- if (names && ndesc)
- {
- for (i=0; (i < ndesc
- && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
- || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
- || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++)
- ;
- if (i == ndesc)
- keydb_set_ephemeral (hd, 1);
- }
-
- while (!(rc = keydb_search (hd, desc, ndesc)))
- {
- const unsigned char *image;
- size_t imagelen;
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
-
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- image = ksba_cert_get_image (cert, &imagelen);
- if (!image)
- {
- log_error ("ksba_cert_get_image failed\n");
- goto leave;
- }
-
- if (ctrl->create_pem)
- {
- if (count)
- putc ('\n', fp);
- print_short_info (cert, fp);
- putc ('\n', fp);
- }
- count++;
-
- if (!b64writer)
- {
- ctrl->pem_name = "CERTIFICATE";
- rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- rc = ksba_writer_write (writer, image, imagelen);
- if (rc)
- {
- log_error ("write error: %s\n", ksba_strerror (rc));
- goto leave;
- }
-
- if (ctrl->create_pem)
- {
- /* We want one certificate per PEM block */
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- gpgsm_destroy_writer (b64writer);
- b64writer = NULL;
- }
-
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (rc && rc != -1)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
- else if (b64writer)
- {
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- leave:
- gpgsm_destroy_writer (b64writer);
- ksba_cert_release (cert);
- xfree (desc);
- keydb_release (hd);
-}
-
-
-/* Print some info about the certifciate CERT to FP */
-static void
-print_short_info (KsbaCert cert, FILE *fp)
-{
- char *p;
- KsbaSexp sexp;
- int idx;
-
- for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
- {
- fputs (!idx? "Issuer ...: "
- : "\n aka ...: ", fp);
- gpgsm_print_name (fp, p);
- xfree (p);
- }
- putc ('\n', fp);
-
- fputs ("Serial ...: ", fp);
- sexp = ksba_cert_get_serial (cert);
- if (sexp)
- {
- int len;
- const unsigned char *s = sexp;
-
- if (*s == '(')
- {
- s++;
- for (len=0; *s && *s != ':' && digitp (s); s++)
- len = len*10 + atoi_1 (s);
- if (*s == ':')
- for (s++; len; len--, s++)
- fprintf (fp, "%02X", *s);
- }
- xfree (sexp);
- }
- putc ('\n', fp);
-
- for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
- {
- fputs (!idx? "Subject ..: "
- : "\n aka ..: ", fp);
- gpgsm_print_name (fp, p);
- xfree (p);
- }
- putc ('\n', fp);
-}
-
-
-
-
-
-
diff --git a/sm/fingerprint.c b/sm/fingerprint.c
deleted file mode 100644
index 028c08aab..000000000
--- a/sm/fingerprint.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* fingerprint.c - Get the fingerprint
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-/* Return the fingerprint of the certificate (we can't put this into
- libksba because we need libgcrypt support). The caller must
- provide an array of sufficient length or NULL so that the function
- allocates the array. If r_len is not NULL, the length of the
- digest is returned; well, this can also be done by using
- gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used.
-
- If there is a problem , the function does never return NULL but a
- digest of all 0xff.
- */
-char *
-gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len)
-{
- gcry_md_hd_t md;
- int rc, len;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len);
- if (!array)
- array = xmalloc (len);
-
- if (r_len)
- *r_len = len;
-
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- memset (array, 0xff, len); /* better return an invalid fpr than NULL */
- return array;
- }
-
- rc = ksba_cert_hash (cert, 0, HASH_FNC, md);
- if (rc)
- {
- log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc));
- gcry_md_close (md);
- memset (array, 0xff, len); /* better return an invalid fpr than NULL */
- return array;
- }
- gcry_md_final (md);
- memcpy (array, gcry_md_read(md, algo), len );
- return array;
-}
-
-
-/* Return an allocated buffer with the formatted fingerprint */
-char *
-gpgsm_get_fingerprint_string (KsbaCert cert, int algo)
-{
- unsigned char digest[MAX_DIGEST_LEN];
- char *buf;
- int len, i;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len <= MAX_DIGEST_LEN );
- gpgsm_get_fingerprint (cert, algo, digest, NULL);
- buf = xmalloc (len*3+1);
- *buf = 0;
- for (i=0; i < len; i++ )
- sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]);
- return buf;
-}
-
-/* Return an allocated buffer with the formatted fingerprint as one
- large hexnumber */
-char *
-gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo)
-{
- unsigned char digest[MAX_DIGEST_LEN];
- char *buf;
- int len, i;
-
- if (!algo)
- algo = GCRY_MD_SHA1;
-
- len = gcry_md_get_algo_dlen (algo);
- assert (len <= MAX_DIGEST_LEN );
- gpgsm_get_fingerprint (cert, algo, digest, NULL);
- buf = xmalloc (len*3+1);
- *buf = 0;
- for (i=0; i < len; i++ )
- sprintf (buf+strlen(buf), "%02X", digest[i]);
- return buf;
-}
-
-/* Return a certificate ID. These are the last 4 bytes of the SHA-1
- fingerprint. */
-unsigned long
-gpgsm_get_short_fingerprint (KsbaCert cert)
-{
- unsigned char digest[20];
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL);
- return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]);
-}
-
-
-/* Return the so called KEYGRIP which is the SHA-1 hash of the public
- key parameters expressed as an canoncial encoded S-Exp. array must
- be 20 bytes long. returns the array or a newly allocated one if the
- passed one was NULL */
-char *
-gpgsm_get_keygrip (KsbaCert cert, char *array)
-{
- gcry_sexp_t s_pkey;
- int rc;
- KsbaSexp p;
- size_t n;
-
- p = ksba_cert_get_public_key (cert);
- if (!p)
- return NULL; /* oops */
-
- if (DBG_X509)
- log_debug ("get_keygrip for public key: %s\n", p);
- n = gcry_sexp_canon_len (p, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- return NULL;
- }
- rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
- xfree (p);
- if (rc)
- {
- log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
- return NULL;
- }
- array = gcry_pk_get_keygrip (s_pkey, array);
- gcry_sexp_release (s_pkey);
- if (!array)
- {
- rc = gpg_error (GPG_ERR_GENERAL);
- log_error ("can't calculate keygrip\n");
- return NULL;
- }
- if (DBG_X509)
- log_printhex ("keygrip=", array, 20);
-
- return array;
-}
-
-/* Return an allocated buffer with the keygrip of CERT in from of an
- hexstring. NULL is returned in case of error */
-char *
-gpgsm_get_keygrip_hexstring (KsbaCert cert)
-{
- unsigned char grip[20];
- char *buf, *p;
- int i;
-
- gpgsm_get_keygrip (cert, grip);
- buf = p = xmalloc (20*2+1);
- for (i=0; i < 20; i++, p += 2 )
- sprintf (p, "%02X", grip[i]);
- return buf;
-}
-
-
-
-/* For certain purposes we need a certificate id which has an upper
- limit of the size. We use the hash of the issuer name and the
- serial number for this. In most cases the serial number is not
- that large and the resulting string can be passed on an assuan
- command line. Everything is hexencoded with the serialnumber
- delimted from the has by a dot.
-
- The caller must free the string.
-*/
-char *
-gpgsm_get_certid (KsbaCert cert)
-{
- KsbaSexp serial;
- unsigned char *p;
- char *endp;
- unsigned char hash[20];
- unsigned long n;
- char *certid;
- int i;
-
- p = ksba_cert_get_issuer (cert, 0);
- if (!p)
- return NULL; /* Ooops: No issuer */
- gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p));
- xfree (p);
-
- serial = ksba_cert_get_serial (cert);
- if (!serial)
- return NULL; /* oops: no serial number */
- p = serial;
- if (*p != '(')
- {
- log_error ("Ooops: invalid serial number\n");
- xfree (serial);
- return NULL;
- }
- p++;
- n = strtoul (p, &endp, 10);
- p = endp;
- if (*p != ':')
- {
- log_error ("Ooops: invalid serial number (no colon)\n");
- xfree (serial);
- return NULL;
- }
- p++;
-
- certid = xtrymalloc ( 40 + 1 + n*2 + 1);
- if (!certid)
- {
- xfree (serial);
- return NULL; /* out of core */
- }
-
- for (i=0, endp = certid; i < 20; i++, endp += 2 )
- sprintf (endp, "%02X", hash[i]);
- *endp++ = '.';
- for (i=0; i < n; i++, endp += 2)
- sprintf (endp, "%02X", p[i]);
- *endp = 0;
-
- xfree (serial);
- return certid;
-}
-
-
-
-
-
-
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
deleted file mode 100644
index c392886ba..000000000
--- a/sm/gpgsm.c
+++ /dev/null
@@ -1,1458 +0,0 @@
-/* gpgsm.c - GnuPG for S/MIME
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <assuan.h> /* malloc hooks */
-
-#include "../kbx/keybox.h" /* malloc hooks */
-#include "i18n.h"
-#include "keydb.h"
-#include "sysutils.h"
-
-enum cmd_and_opt_values {
- aNull = 0,
- oArmor = 'a',
- aDetachedSign = 'b',
- aSym = 'c',
- aDecrypt = 'd',
- aEncr = 'e',
- oInteractive = 'i',
- oKOption = 'k',
- oDryRun = 'n',
- oOutput = 'o',
- oQuiet = 'q',
- oRecipient = 'r',
- aSign = 's',
- oTextmodeShort= 't',
- oUser = 'u',
- oVerbose = 'v',
- oCompress = 'z',
- oNotation = 'N',
- oBatch = 500,
- aClearsign,
- aStore,
- aKeygen,
- aSignEncr,
- aSignKey,
- aLSignKey,
- aListPackets,
- aEditKey,
- aDeleteKey,
- aImport,
- aVerify,
- aVerifyFiles,
- aListKeys,
- aListExternalKeys,
- aListSigs,
- aListSecretKeys,
- aSendKeys,
- aRecvKeys,
- aExport,
- aCheckKeys, /* nyi */
- aServer,
- aLearnCard,
- aCallDirmngr,
- aCallProtectTool,
- aPasswd,
-
- oOptions,
- oDebug,
- oDebugAll,
- oDebugWait,
- oDebugNoChainValidation,
- oLogFile,
-
- oEnableSpecialFilenames,
-
- oAgentProgram,
- oDisplay,
- oTTYname,
- oTTYtype,
- oLCctype,
- oLCmessages,
-
- oDirmngrProgram,
- oFakedSystemTime,
-
-
- oAssumeArmor,
- oAssumeBase64,
- oAssumeBinary,
-
- oBase64,
- oNoArmor,
-
- oDisableCRLChecks,
- oEnableCRLChecks,
-
- oIncludeCerts,
- oPolicyFile,
- oDisablePolicyChecks,
- oEnablePolicyChecks,
- oAutoIssuerKeyRetrieve,
-
-
- oTextmode,
- oFingerprint,
- oWithFingerprint,
- oAnswerYes,
- oAnswerNo,
- oKeyring,
- oSecretKeyring,
- oDefaultKey,
- oDefRecipient,
- oDefRecipientSelf,
- oNoDefRecipient,
- oStatusFD,
- oNoComment,
- oNoVersion,
- oEmitVersion,
- oCompletesNeeded,
- oMarginalsNeeded,
- oMaxCertDepth,
- oLoadExtension,
- oRFC1991,
- oOpenPGP,
- oCipherAlgo,
- oDigestAlgo,
- oCompressAlgo,
- oCommandFD,
- oNoVerbose,
- oTrustDBName,
- oNoSecmemWarn,
- oNoDefKeyring,
- oNoGreeting,
- oNoTTY,
- oNoOptions,
- oNoBatch,
- oHomedir,
- oWithColons,
- oWithKeyData,
- oSkipVerify,
- oCompressKeys,
- oCompressSigs,
- oAlwaysTrust,
- oRunAsShmCP,
- oSetFilename,
- oSetPolicyURL,
- oUseEmbeddedFilename,
- oComment,
- oDefaultComment,
- oThrowKeyid,
- oForceV3Sigs,
- oForceMDC,
- oS2KMode,
- oS2KDigest,
- oS2KCipher,
- oCharset,
- oNotDashEscaped,
- oEscapeFrom,
- oLockOnce,
- oLockMultiple,
- oLockNever,
- oKeyServer,
- oEncryptTo,
- oNoEncryptTo,
- oLoggerFD,
- oUtf8Strings,
- oNoUtf8Strings,
- oDisableCipherAlgo,
- oDisablePubkeyAlgo,
- oAllowNonSelfsignedUID,
- oAllowFreeformUID,
- oNoLiteral,
- oSetFilesize,
- oHonorHttpProxy,
- oFastListMode,
- oListOnly,
- oIgnoreTimeConflict,
- oNoRandomSeedFile,
- oNoAutoKeyRetrieve,
- oUseAgent,
- oMergeOnly,
- oTryAllSecrets,
- oTrustedKey,
- oEmuMDEncodeBug,
- aDummy
- };
-
-
-static ARGPARSE_OPTS opts[] = {
-
- { 300, NULL, 0, N_("@Commands:\n ") },
-
- { aSign, "sign", 256, N_("|[file]|make a signature")},
- { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
- { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
- { aEncr, "encrypt", 256, N_("encrypt data")},
- { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
- { aDecrypt, "decrypt", 256, N_("decrypt data (default)")},
- { aVerify, "verify" , 256, N_("verify a signature")},
- { aVerifyFiles, "verify-files" , 256, "@" },
- { aListKeys, "list-keys", 256, N_("list keys")},
- { aListExternalKeys, "list-external-keys", 256, N_("list external keys")},
- { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
- { aListSigs, "list-sigs", 256, N_("list certificate chain")},
- { aListSigs, "check-sigs",256, "@"},
- { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
- { aKeygen, "gen-key", 256, N_("generate a new key pair")},
- { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
- { aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
- { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
- { aImport, "import", 256 , N_("import certificates")},
- { aExport, "export", 256 , N_("export certificates")},
- { aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
- { aServer, "server", 256, N_("run in server mode")},
- { aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")},
- { aCallProtectTool, "call-protect-tool", 256,
- N_("invoke gpg-protect-tool")},
- { aPasswd, "passwd", 256, N_("change a passphrase")},
-
- { 301, NULL, 0, N_("@\nOptions:\n ") },
-
- { oArmor, "armor", 0, N_("create ascii armored output")},
- { oArmor, "armour", 0, "@" },
- { oBase64, "base64", 0, N_("create base-64 encoded output")},
-
- { oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")},
- { oAssumeBase64, "assume-base64", 0,
- N_("assume input is in base-64 format")},
- { oAssumeBinary, "assume-binary", 0,
- N_("assume input is in binary format")},
-
- { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
-
-
- { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")},
- { oEnableCRLChecks, "enable-crl-checks", 0, "@"},
-
- { oIncludeCerts, "include-certs", 1,
- N_("|N|number of certificates to include") },
-
- { oPolicyFile, "policy-file", 2,
- N_("|FILE|take policy information from FILE") },
-
- { oDisablePolicyChecks, "disable-policy-checks", 0,
- N_("do not check certificate policies")},
- { oEnablePolicyChecks, "enable-policy-checks", 0, "@"},
-
- { oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0,
- N_("fetch missing issuer certificates")},
-
-#if 0
- { oDefRecipient, "default-recipient" ,2,
- N_("|NAME|use NAME as default recipient")},
- { oDefRecipientSelf, "default-recipient-self" ,0,
- N_("use the default key as default recipient")},
- { oNoDefRecipient, "no-default-recipient", 0, "@" },
- { oEncryptTo, "encrypt-to", 2, "@" },
- { oNoEncryptTo, "no-encrypt-to", 0, "@" },
-
-#endif
- { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
-
-#if 0
- { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
- { oTextmodeShort, NULL, 0, "@"},
- { oTextmode, "textmode", 0, N_("use canonical text mode")},
-#endif
-
- { oOutput, "output", 2, N_("use as output file")},
- { oVerbose, "verbose", 0, N_("verbose") },
- { oQuiet, "quiet", 0, N_("be somewhat more quiet") },
- { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
- { oLogFile, "log-file" ,2, N_("use a log file for the server")},
-#if 0
- { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
- { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
-#endif
- { oDryRun, "dry-run", 0, N_("do not make any changes") },
- /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
- /*{ oUseAgent, "use-agent",0, N_("use the gpg-agent")},*/
- { oBatch, "batch", 0, N_("batch mode: never ask")},
- { oAnswerYes, "yes", 0, N_("assume yes on most questions")},
- { oAnswerNo, "no", 0, N_("assume no on most questions")},
-
- { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")},
- { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
- { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
- { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
- { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
- { oOptions, "options" , 2, N_("read options from file")},
-
- { oDebug, "debug" ,4|16, "@"},
- { oDebugAll, "debug-all" ,0, "@"},
- { oDebugWait, "debug-wait" ,1, "@"},
- { oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"},
- { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
- { aDummy, "no-comment", 0, "@"},
- { aDummy, "completes-needed", 1, "@"},
- { aDummy, "marginals-needed", 1, "@"},
- { oMaxCertDepth, "max-cert-depth", 1, "@" },
- { aDummy, "trusted-key", 2, "@"},
- { oLoadExtension, "load-extension" ,2,
- N_("|FILE|load extension module FILE")},
- { aDummy, "rfc1991", 0, "@"},
- { aDummy, "openpgp", 0, "@"},
- { aDummy, "s2k-mode", 1, "@"},
- { aDummy, "s2k-digest-algo",2, "@"},
- { aDummy, "s2k-cipher-algo",2, "@"},
- { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
- { oDigestAlgo, "digest-algo", 2 ,
- N_("|NAME|use message digest algorithm NAME")},
-#if 0
- { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
-#endif
- { aDummy, "throw-keyid", 0, "@"},
- { aDummy, "notation-data", 2, "@"},
-
- { 302, NULL, 0, N_(
- "@\n(See the man page for a complete listing of all commands and options)\n"
- )},
-
- { 303, NULL, 0, N_("@\nExamples:\n\n"
- " -se -r Bob [file] sign and encrypt for user Bob\n"
- " --clearsign [file] make a clear text signature\n"
- " --detach-sign [file] make a detached signature\n"
- " --list-keys [names] show keys\n"
- " --fingerprint [names] show fingerprints\n" ) },
-
- /* hidden options */
- { oNoVerbose, "no-verbose", 0, "@"},
-
- { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
-
-
- { oTrustDBName, "trustdb-name", 2, "@" },
- { oNoSecmemWarn, "no-secmem-warning", 0, "@" },
- { oNoArmor, "no-armor", 0, "@"},
- { oNoArmor, "no-armour", 0, "@"},
- { oNoDefKeyring, "no-default-keyring", 0, "@" },
- { oNoGreeting, "no-greeting", 0, "@" },
- { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
- { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
- { oAgentProgram, "agent-program", 2 , "@" },
- { oDisplay, "display", 2, "@" },
- { oTTYname, "ttyname", 2, "@" },
- { oTTYtype, "ttytype", 2, "@" },
- { oLCctype, "lc-ctype", 2, "@" },
- { oLCmessages, "lc-messages", 2, "@" },
- { oDirmngrProgram, "dirmngr-program", 2 , "@" },
- { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */
-
-
- { oNoBatch, "no-batch", 0, "@" },
- { oWithColons, "with-colons", 0, "@"},
- { oWithKeyData,"with-key-data", 0, "@"},
- { aListKeys, "list-key", 0, "@" }, /* alias */
- { aListSigs, "list-sig", 0, "@" }, /* alias */
- { aListSigs, "check-sig",0, "@" }, /* alias */
- { oSkipVerify, "skip-verify",0, "@" },
- { oCompressKeys, "compress-keys",0, "@"},
- { oCompressSigs, "compress-sigs",0, "@"},
- { oAlwaysTrust, "always-trust", 0, "@"},
- { oNoVersion, "no-version", 0, "@"},
- { oLockOnce, "lock-once", 0, "@" },
- { oLockMultiple, "lock-multiple", 0, "@" },
- { oLockNever, "lock-never", 0, "@" },
- { oLoggerFD, "logger-fd",1, "@" },
- { oWithFingerprint, "with-fingerprint", 0, "@" },
- { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" },
- { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" },
- { oHonorHttpProxy,"honor-http-proxy", 0, "@" },
- { oListOnly, "list-only", 0, "@"},
- { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
- { oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
-{0} };
-
-
-
-int gpgsm_errors_seen = 0;
-
-/* It is possible that we are currentlu running under setuid permissions */
-static int maybe_setuid = 1;
-
-/* Option --enable-special-filenames */
-static int allow_special_filenames;
-
-
-static char *build_list (const char *text,
- const char *(*mapf)(int), int (*chkf)(int));
-static void set_cmd (enum cmd_and_opt_values *ret_cmd,
- enum cmd_and_opt_values new_cmd );
-
-static void emergency_cleanup (void);
-static int check_special_filename (const char *fname);
-static int open_read (const char *filename);
-static FILE *open_fwrite (const char *filename);
-static void run_protect_tool (int argc, char **argv);
-
-
-static int
-our_pk_test_algo (int algo)
-{
- return 1;
-}
-
-static int
-our_cipher_test_algo (int algo)
-{
- return 1;
-}
-
-static int
-our_md_test_algo (int algo)
-{
- return 1;
-}
-
-static const char *
-my_strusage( int level )
-{
- static char *digests, *pubkeys, *ciphers;
- const char *p;
-
- switch (level)
- {
- case 11: p = "gpgsm (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: gpgsm [options] [files] (-h for help)");
- break;
- case 41:
- p = _("Syntax: gpgsm [options] [files]\n"
- "sign, check, encrypt or decrypt using the S/MIME protocol\n"
- "default operation depends on the input data\n");
- break;
-
- case 31: p = "\nHome: "; break;
- case 32: p = opt.homedir; break;
- case 33: p = _("\nSupported algorithms:\n"); break;
- case 34:
- if (!ciphers)
- ciphers = build_list ("Cipher: ", gcry_cipher_algo_name,
- our_cipher_test_algo );
- p = ciphers;
- break;
- case 35:
- if (!pubkeys)
- pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name,
- our_pk_test_algo );
- p = pubkeys;
- break;
- case 36:
- if (!digests)
- digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
- p = digests;
- break;
-
- default: p = NULL; break;
- }
- return p;
-}
-
-
-static char *
-build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
-{
- int i;
- size_t n=strlen(text)+2;
- char *list, *p;
-
- if (maybe_setuid) {
- gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
- }
-
- for (i=1; i < 110; i++ )
- if (!chkf(i))
- n += strlen(mapf(i)) + 2;
- list = xmalloc (21 + n);
- *list = 0;
- for (p=NULL, i=1; i < 110; i++)
- {
- if (!chkf(i))
- {
- if( !p )
- p = stpcpy (list, text );
- else
- p = stpcpy (p, ", ");
- p = stpcpy (p, mapf(i) );
- }
- }
- if (p)
- p = stpcpy(p, "\n" );
- return list;
-}
-
-
-static void
-i18n_init(void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file (PACKAGE);
-#else
-# ifdef ENABLE_NLS
-# ifdef HAVE_LC_MESSAGES
- setlocale (LC_TIME, "");
- setlocale (LC_MESSAGES, "");
-# else
- setlocale (LC_ALL, "" );
-# endif
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-# endif
-#endif
-}
-
-
-static void
-wrong_args (const char *text)
-{
- fputs (_("usage: gpgsm [options] "), stderr);
- fputs (text, stderr);
- putc ('\n', stderr);
- gpgsm_exit (2);
-}
-
-
-static void
-set_debug(void)
-{
- if (opt.debug & DBG_MPI_VALUE)
- gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
- if (opt.debug & DBG_CRYPTO_VALUE )
- gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
-}
-
-
-static void
-set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
-{
- enum cmd_and_opt_values cmd = *ret_cmd;
-
- if (!cmd || cmd == new_cmd)
- cmd = new_cmd;
- else if ( cmd == aSign && new_cmd == aEncr )
- cmd = aSignEncr;
- else if ( cmd == aEncr && new_cmd == aSign )
- cmd = aSignEncr;
- else if ( (cmd == aSign && new_cmd == aClearsign)
- || (cmd == aClearsign && new_cmd == aSign) )
- cmd = aClearsign;
- else
- {
- log_error(_("conflicting commands\n"));
- gpgsm_exit(2);
- }
-
- *ret_cmd = cmd;
-}
-
-
-int
-main ( int argc, char **argv)
-{
- ARGPARSE_ARGS pargs;
- int orig_argc;
- char **orig_argv;
- const char *fname;
- /* char *username;*/
- int may_coredump;
- STRLIST sl, remusr= NULL, locusr=NULL;
- STRLIST nrings=NULL;
- int detached_sig = 0;
- FILE *configfp = NULL;
- char *configname = NULL;
- unsigned configlineno;
- int parse_debug = 0;
- int no_more_options = 0;
- int default_config =1;
- int default_keyring = 1;
- char *logfile = NULL;
- int greeting = 0;
- int nogreeting = 0;
- int debug_wait = 0;
- int use_random_seed = 1;
- int with_fpr = 0;
- char *def_digest_string = NULL;
- enum cmd_and_opt_values cmd = 0;
- struct server_control_s ctrl;
- CERTLIST recplist = NULL;
- CERTLIST signerlist = NULL;
-
- /* trap_unaligned ();*/
- set_strusage (my_strusage);
- gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
- /* We don't need any locking in libgcrypt unless we use any kind of
- threading. */
- gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
-
- /* Please note that we may running SUID(ROOT), so be very CAREFUL
- when adding any stuff between here and the call to secmem_init()
- somewhere after the option parsing */
- log_set_prefix ("gpgsm", 1);
- /* check that the libraries are suitable. Do it here because the
- option parse may need services of the library */
- if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
- {
- log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
- NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
- }
- if (!ksba_check_version (NEED_KSBA_VERSION) )
- {
- log_fatal( _("libksba is too old (need %s, have %s)\n"),
- NEED_KSBA_VERSION, ksba_check_version (NULL) );
- }
-
- gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
-
- may_coredump = disable_core_dumps ();
-
- gnupg_init_signals (0, emergency_cleanup);
-
- create_dotlock (NULL); /* register locking cleanup */
- i18n_init();
-
- opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/
-#ifdef __MINGW32__
- opt.homedir = read_w32_registry_string ( NULL,
- "Software\\GNU\\GnuPG", "HomeDir" );
-#else
- opt.homedir = getenv ("GNUPGHOME");
-#endif
- if (!opt.homedir || !*opt.homedir )
- opt.homedir = GNUPG_DEFAULT_HOMEDIR;
-
- /* first check whether we have a config file 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 config 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;
- else if (pargs.r_opt == aCallProtectTool)
- break; /* This break makes sure that --version and --help are
- passed to the protect-tool. */
- }
-
-
- /* initialize the secure memory. */
- gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
- maybe_setuid = 0;
-
- /*
- Now we are now working under our real uid
- */
-
- ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
- assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
- keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-
- /* Setup a default control structure for command line mode */
- memset (&ctrl, 0, sizeof ctrl);
- gpgsm_init_default_ctrl (&ctrl);
- ctrl.no_server = 1;
- ctrl.status_fd = -1; /* not status output */
- ctrl.autodetect_encoding = 1;
-
- /* set the default option file */
- if (default_config )
- configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
- /* cet the default policy file */
- opt.policy_file = make_filename (opt.homedir, "policies.txt", 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));
- gpgsm_exit(2);
- }
- xfree(configname);
- configname = NULL;
- }
- if (parse_debug && configname)
- log_info (_("reading options from `%s'\n"), configname);
- default_config = 0;
- }
-
- while (!no_more_options
- && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
- {
- switch (pargs.r_opt)
- {
- case aServer:
- opt.batch = 1;
- set_cmd (&cmd, aServer);
- break;
- case aCallDirmngr:
- opt.batch = 1;
- set_cmd (&cmd, aCallDirmngr);
- break;
-
- case aCallProtectTool:
- opt.batch = 1;
- set_cmd (&cmd, aCallProtectTool);
- no_more_options = 1; /* Stop parsing. */
- break;
-
- case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
- case aImport: set_cmd (&cmd, aImport); break;
- case aSendKeys: set_cmd (&cmd, aSendKeys); break;
- case aRecvKeys: set_cmd (&cmd, aRecvKeys); break;
- case aExport: set_cmd (&cmd, aExport); break;
- case aListKeys: set_cmd (&cmd, aListKeys); break;
- case aListExternalKeys: set_cmd (&cmd, aListExternalKeys); break;
- case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break;
- case aListSigs: set_cmd (&cmd, aListSigs); break;
-
- case aLearnCard: set_cmd (&cmd, aLearnCard); break;
-
- case aPasswd: set_cmd (&cmd, aPasswd); break;
-
- case aDeleteKey:
- set_cmd (&cmd, aDeleteKey);
- /*greeting=1;*/
- break;
-
- case aDetachedSign:
- detached_sig = 1;
- set_cmd (&cmd, aSign );
- break;
-
- case aSym: set_cmd (&cmd, aSym); break;
- case aDecrypt: set_cmd (&cmd, aDecrypt); break;
- case aEncr: set_cmd (&cmd, aEncr); break;
- case aSign: set_cmd (&cmd, aSign ); break;
- case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break;
- case aClearsign: set_cmd (&cmd, aClearsign); break;
- case aVerify: set_cmd (&cmd, aVerify); break;
-
-
- /* output encoding selection */
- case oArmor:
- ctrl.create_pem = 1;
- break;
- case oBase64:
- ctrl.create_pem = 0;
- ctrl.create_base64 = 1;
- break;
- case oNoArmor:
- ctrl.create_pem = 0;
- ctrl.create_base64 = 0;
- break;
-
- /* Input encoding selection */
- case oAssumeArmor:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 1;
- ctrl.is_base64 = 0;
- break;
- case oAssumeBase64:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 0;
- ctrl.is_base64 = 1;
- break;
- case oAssumeBinary:
- ctrl.autodetect_encoding = 0;
- ctrl.is_pem = 0;
- ctrl.is_base64 = 0;
- break;
-
- case oDisableCRLChecks:
- opt.no_crl_check = 1;
- break;
- case oEnableCRLChecks:
- opt.no_crl_check = 0;
- break;
-
- case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break;
-
- case oPolicyFile:
- xfree (opt.policy_file);
- if (*pargs.r.ret_str)
- opt.policy_file = xstrdup (pargs.r.ret_str);
- else
- opt.policy_file = NULL;
- break;
-
- case oDisablePolicyChecks:
- opt.no_policy_check = 1;
- break;
- case oEnablePolicyChecks:
- opt.no_policy_check = 0;
- break;
-
- case oAutoIssuerKeyRetrieve:
- opt.auto_issuer_key_retrieve = 1;
- break;
-
- case oOutput: opt.outfile = pargs.r.ret_str; break;
-
-
- case oQuiet: opt.quiet = 1; break;
- case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
- case oDryRun: opt.dry_run = 1; break;
-
- case oVerbose:
- opt.verbose++;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- break;
- case oNoVerbose:
- opt.verbose = 0;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- break;
-
- case oLogFile: logfile = pargs.r.ret_str; break;
-
- case oBatch:
- opt.batch = 1;
- greeting = 0;
- break;
- case oNoBatch: opt.batch = 0; break;
-
- case oAnswerYes: opt.answer_yes = 1; break;
- case oAnswerNo: opt.answer_no = 1; break;
-
- case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
-
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
- case oDebugWait: debug_wait = pargs.r.ret_int; break;
- case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
-
- case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
- case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
- case oWithFingerprint:
- with_fpr=1; /*fall thru*/
- case oFingerprint:
- opt.fingerprint++;
- 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 oNoOptions: break; /* no-options */
- case oHomedir: opt.homedir = pargs.r.ret_str; break;
- case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
- case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
- case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
- case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
- case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
- case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
- case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
-
- case oFakedSystemTime:
- gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0);
- break;
-
- case oNoDefKeyring: default_keyring = 0; break;
- case oNoGreeting: nogreeting = 1; break;
-
- case oDefaultKey:
- /* fixme:opt.def_secret_key = pargs.r.ret_str;*/
- break;
- case oDefRecipient:
- if (*pargs.r.ret_str)
- opt.def_recipient = xstrdup (pargs.r.ret_str);
- break;
- case oDefRecipientSelf:
- xfree (opt.def_recipient);
- opt.def_recipient = NULL;
- opt.def_recipient_self = 1;
- break;
- case oNoDefRecipient:
- xfree (opt.def_recipient);
- opt.def_recipient = NULL;
- opt.def_recipient_self = 0;
- break;
-
- case oWithKeyData: opt.with_key_data=1; /* fall thru */
- case oWithColons: ctrl.with_colons = 1; break;
-
- case oSkipVerify: opt.skip_verify=1; break;
-
- case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break;
- case oEncryptTo: /* store the recipient in the second list */
- sl = add_to_strlist (&remusr, pargs.r.ret_str);
- sl->flags = 1;
- break;
-
- case oRecipient: /* store the recipient */
- add_to_strlist ( &remusr, pargs.r.ret_str);
- break;
-
- case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
- case oTextmode: /*fixme:opt.textmode=1;*/ break;
-
- case oUser: /* store the local users, the first one is the default */
- if (!opt.local_user)
- opt.local_user = pargs.r.ret_str;
- add_to_strlist (&locusr, pargs.r.ret_str);
- break;
-
- case oNoSecmemWarn:
- gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
- break;
-
- case oCipherAlgo:
- opt.def_cipher_algoid = pargs.r.ret_str;
- break;
-
- case oDisableCipherAlgo:
- {
- int algo = gcry_cipher_map_name (pargs.r.ret_str);
- gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
- }
- break;
- case oDisablePubkeyAlgo:
- {
- int algo = gcry_pk_map_name (pargs.r.ret_str);
- gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
- }
- break;
-
- case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
- case oNoRandomSeedFile: use_random_seed = 0; break;
-
- case oEnableSpecialFilenames: allow_special_filenames =1; break;
-
-
- case aDummy:
- break;
- default:
- pargs.err = configfp? 1:2;
- break;
- }
- }
-
- if (configfp)
- {
- fclose (configfp);
- configfp = NULL;
- xfree (configname);
- configname = NULL;
- goto next_pass;
- }
-
- xfree (configname);
- configname = NULL;
-
- if (log_get_errorcount(0))
- gpgsm_exit(2);
-
- if (nogreeting)
- greeting = 0;
-
- if (greeting)
- {
- fprintf(stderr, "%s %s; %s\n",
- strusage(11), strusage(13), strusage(14) );
- fprintf(stderr, "%s\n", strusage(15) );
- }
-# ifdef IS_DEVELOPMENT_VERSION
- if (!opt.batch)
- {
- log_info ("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
- log_info ("It is only intended for test purposes and should NOT be\n");
- log_info ("used in a production environment or with production keys!\n");
- }
-# endif
-
- if (may_coredump && !opt.quiet)
- log_info (_("WARNING: program may create a core file!\n"));
-
- if (logfile && cmd == aServer)
- {
- log_set_file (logfile);
- log_set_prefix (NULL, 1|2|4);
- }
-
- if (gnupg_faked_time_p ())
- {
- log_info (_("WARNING: running with faked system time: "));
- gpgsm_dump_time (gnupg_get_time ());
- log_printf ("\n");
- }
-
-/*FIXME if (opt.batch) */
-/* tty_batchmode (1); */
-
- gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
-
- set_debug ();
-
- /* FIXME: should set filenames of libgcrypt explicitly
- * gpg_opt_homedir = opt.homedir; */
-
- /* must do this after dropping setuid, because the mapping functions
- may try to load an module and we may have disabled an algorithm */
- if ( !gcry_cipher_map_name (opt.def_cipher_algoid)
- || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
- log_error (_("selected cipher algorithm is invalid\n"));
-
- if (def_digest_string)
- {
- opt.def_digest_algo = gcry_md_map_name (def_digest_string);
- xfree (def_digest_string);
- def_digest_string = NULL;
- if (our_md_test_algo(opt.def_digest_algo) )
- log_error (_("selected digest algorithm is invalid\n"));
- }
-
- if (log_get_errorcount(0))
- gpgsm_exit(2);
-
- /* set the random seed file */
- if (use_random_seed) {
- char *p = make_filename (opt.homedir, "random_seed", NULL);
- gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
- xfree(p);
- }
-
-
- if (!cmd && opt.fingerprint && !with_fpr)
- set_cmd (&cmd, aListKeys);
-
- if (!nrings && default_keyring) /* add default keybox */
- keydb_add_resource ("pubring.kbx", 0, 0);
- for (sl = nrings; sl; sl = sl->next)
- keydb_add_resource (sl->d, 0, 0);
- FREE_STRLIST(nrings);
-
-
- for (sl = locusr; sl; sl = sl->next)
- {
- int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist);
- if (rc)
- {
- log_error (_("can't sign using `%s': %s\n"),
- sl->d, gpg_strerror (rc));
- gpgsm_status2 (&ctrl, STATUS_INV_RECP,
- gpg_err_code (rc) == -1? "1":
- gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
- gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
- gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
- gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
- gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
- gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
- gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
- gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
- gpg_err_code (rc) == GPG_ERR_NO_SECKEY? "9":
- "0",
- sl->d, NULL);
- }
- }
- for (sl = remusr; sl; sl = sl->next)
- {
- int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist);
- if (rc)
- {
- log_error (_("can't encrypt to `%s': %s\n"),
- sl->d, gpg_strerror (rc));
- gpgsm_status2 (&ctrl, STATUS_INV_RECP,
- gpg_err_code (rc) == -1? "1":
- gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1":
- gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2":
- gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
- gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4":
- gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5":
- gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6":
- gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7":
- gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
- "0",
- sl->d, NULL);
- }
- }
- if (log_get_errorcount(0))
- gpgsm_exit(1); /* must stop for invalid recipients */
-
-
-
- fname = argc? *argv : NULL;
-
- switch (cmd)
- {
- case aServer:
- if (debug_wait)
- {
- log_debug ("waiting for debugger - my pid is %u .....\n",
- (unsigned int)getpid());
- sleep (debug_wait);
- log_debug ("... okay\n");
- }
- gpgsm_server ();
- break;
-
- case aCallDirmngr:
- if (!argc)
- wrong_args (_("--call-dirmngr <command> {args}"));
- else
- if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1))
- gpgsm_exit (1);
- break;
-
- case aCallProtectTool:
- run_protect_tool (argc, argv);
- break;
-
- case aEncr: /* encrypt the given file */
- if (!argc)
- gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
- else if (argc == 1)
- gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */
- else
- wrong_args (_("--encrypt [datafile]"));
- break;
-
- case aSign: /* sign the given file */
- /* FIXME: We don't handle --output yet. We should also allow
- to concatenate multiple files for signing because that is
- what gpg does.*/
- if (!argc)
- gpgsm_sign (&ctrl, signerlist,
- 0, detached_sig, stdout); /* create from stdin */
- else if (argc == 1)
- gpgsm_sign (&ctrl, signerlist,
- open_read (*argv), detached_sig, stdout); /* from file */
- else
- wrong_args (_("--sign [datafile]"));
- break;
-
- case aSignEncr: /* sign and encrypt the given file */
- log_error ("this command has not yet been implemented\n");
- break;
-
- case aClearsign: /* make a clearsig */
- log_error ("this command has not yet been implemented\n");
- break;
-
- case aVerify:
- {
- FILE *fp = NULL;
-
- if (argc == 2 && opt.outfile)
- log_info ("option --output ignored for a detached signature\n");
- else if (opt.outfile)
- fp = open_fwrite (opt.outfile);
-
- if (!argc)
- gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
- else if (argc == 1)
- gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */
- else if (argc == 2) /* detached signature (sig, detached) */
- gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL);
- else
- wrong_args (_("--verify [signature [detached_data]]"));
-
- if (fp && fp != stdout)
- fclose (fp);
- }
- break;
-
- case aVerifyFiles:
- log_error ("this command has not yet been implemented\n");
- break;
-
- case aDecrypt:
- if (!argc)
- gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */
- else if (argc == 1)
- gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */
- else
- wrong_args (_("--decrypt [filename]"));
- break;
-
- case aDeleteKey:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_delete (&ctrl, sl);
- free_strlist(sl);
- break;
-
- case aListSigs:
- ctrl.with_chain = 1;
- case aListKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aListExternalKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<7)));
- free_strlist(sl);
- break;
-
- case aListSecretKeys:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6)));
- free_strlist(sl);
- break;
-
- case aKeygen: /* generate a key */
- log_error ("this function is not yet available from the commandline\n");
- break;
-
- case aImport:
- gpgsm_import_files (&ctrl, argc, argv, open_read);
- break;
-
- case aExport:
- for (sl=NULL; argc; argc--, argv++)
- add_to_strlist (&sl, *argv);
- gpgsm_export (&ctrl, sl, stdout);
- free_strlist(sl);
- break;
-
-
- case aSendKeys:
- case aRecvKeys:
- log_error ("this command has not yet been implemented\n");
- break;
-
-
- case aLearnCard:
- if (argc)
- wrong_args ("--learn-card");
- else
- {
- int rc = gpgsm_agent_learn ();
- if (rc)
- log_error ("error learning card: %s\n", gpg_strerror (rc));
- }
- break;
-
- case aPasswd:
- if (argc != 1)
- wrong_args ("--passwd <key-Id>");
- else
- {
- int rc;
- KsbaCert cert = NULL;
- char *grip = NULL;
-
- rc = gpgsm_find_cert (*argv, &cert);
- if (rc)
- ;
- else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
- rc = gpg_error (GPG_ERR_BUG);
- else
- rc = gpgsm_agent_passwd (grip);
- if (rc)
- log_error ("error changing passphrase: %s\n", gpg_strerror (rc));
- xfree (grip);
- ksba_cert_release (cert);
- }
- break;
-
- default:
- log_error ("invalid command (there is no implicit command)\n");
- break;
- }
-
- /* cleanup */
- gpgsm_release_certlist (recplist);
- gpgsm_release_certlist (signerlist);
- FREE_STRLIST(remusr);
- FREE_STRLIST(locusr);
- gpgsm_exit(0);
- return 8; /*NEVER REACHED*/
-}
-
-/* Note: This function is used by signal handlers!. */
-static void
-emergency_cleanup (void)
-{
- gcry_control (GCRYCTL_TERM_SECMEM );
-}
-
-
-void
-gpgsm_exit (int rc)
-{
- gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
- if (opt.debug & DBG_MEMSTAT_VALUE)
- {
- gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
- gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
- }
- if (opt.debug)
- gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
- emergency_cleanup ();
- rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
- exit (rc);
-}
-
-
-void
-gpgsm_init_default_ctrl (struct server_control_s *ctrl)
-{
- ctrl->include_certs = 1; /* only include the signer's cert */
-}
-
-
-
-/* Check whether the filename has the form "-&nnnn", where n is a
- non-zero number. Returns this number or -1 if it is not the case. */
-static int
-check_special_filename (const char *fname)
-{
- if (allow_special_filenames
- && fname && *fname == '-' && fname[1] == '&' ) {
- int i;
-
- fname += 2;
- for (i=0; isdigit (fname[i]); i++ )
- ;
- if ( !fname[i] )
- return atoi (fname);
- }
- return -1;
-}
-
-
-
-/* Open the FILENAME for read and return the filedescriptor. Stop
- with an error message in case of problems. "-" denotes stdin and
- if special filenames are allowed the given fd is opened instead. */
-static int
-open_read (const char *filename)
-{
- int fd;
-
- if (filename[0] == '-' && !filename[1])
- return 0; /* stdin */
- fd = check_special_filename (filename);
- if (fd != -1)
- return fd;
- fd = open (filename, O_RDONLY);
- if (fd == -1)
- {
- log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
- gpgsm_exit (2);
- }
- return fd;
-}
-
-/* Open FILENAME for fwrite and return the stream. Stop with an error
- message in case of problems. "-" denotes stdout and if special
- filenames are allowed the given fd is opened instead. Caller must
- close the returned stream unless it is stdout. */
-static FILE *
-open_fwrite (const char *filename)
-{
- int fd;
- FILE *fp;
-
- if (filename[0] == '-' && !filename[1])
- return stdout;
-
- fd = check_special_filename (filename);
- if (fd != -1)
- {
- fp = fdopen (dup (fd), "wb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- gpgsm_exit (2);
- }
- return fp;
- }
- fp = fopen (filename, "wb");
- if (!fp)
- {
- log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
- gpgsm_exit (2);
- }
- return fp;
-}
-
-
-static void
-run_protect_tool (int argc, char **argv)
-{
- char *pgm = GNUPG_PROTECT_TOOL;
- char **av;
- int i;
-
- av = xcalloc (argc+2, sizeof *av);
- av[0] = strrchr (pgm, '/');
- if (!av[0])
- av[0] = pgm;
- for (i=1; argc; i++, argc--, argv++)
- av[i] = *argv;
- av[i] = NULL;
- execv (pgm, av);
- log_error ("error executing `%s': %s\n", pgm, strerror (errno));
- gpgsm_exit (2);
-}
-
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
deleted file mode 100644
index f996d578c..000000000
--- a/sm/gpgsm.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/* gpgsm.h - Global definitions for GpgSM
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GPGSM_H
-#define GPGSM_H
-
-#ifdef GPG_ERR_SOURCE_DEFAULT
-#error GPG_ERR_SOURCE_DEFAULT already defined
-#endif
-#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGSM
-#include <gpg-error.h>
-
-#include <ksba.h>
-#include "../common/util.h"
-#include "../common/errors.h"
-
-#define OUT_OF_CORE(a) (gpg_error (gpg_err_code_from_errno ((a))))
-
-#define MAX_DIGEST_LEN 24
-
-/* A large struct name "opt" to keep global flags */
-struct {
- unsigned int debug; /* debug flags (DBG_foo_VALUE) */
- int verbose; /* verbosity level */
- int quiet; /* be as quiet as possible */
- int batch; /* run in batch mode, i.e w/o any user interaction */
- int answer_yes; /* assume yes on most questions */
- int answer_no; /* assume no on most questions */
- int dry_run; /* don't change any persistent data */
-
- const char *homedir; /* configuration directory name */
- const char *agent_program;
- char *display;
- char *ttyname;
- char *ttytype;
- char *lc_ctype;
- char *lc_messages;
-
- const char *dirmngr_program;
- char *outfile; /* name of output file */
-
- int with_key_data;/* include raw key in the column delimted output */
-
- int fingerprint; /* list fingerprints in all key listings */
-
- int armor; /* force base64 armoring (see also ctrl.with_base64) */
- int no_armor; /* don't try to figure out whether data is base64 armored*/
-
- const char *def_cipher_algoid; /* cipher algorithm to use if
- nothing else is specified */
-
- int def_digest_algo; /* Ditto for hash algorithm */
- int def_compress_algo; /* Ditto for compress algorithm */
-
- char *def_recipient; /* userID of the default recipient */
- int def_recipient_self; /* The default recipient is the default key */
-
- char *local_user; /* NULL or argument to -u */
-
- int always_trust; /* Trust the given keys even if there is no
- valid certification chain */
- int skip_verify; /* do not check signatures on data */
-
- int lock_once; /* Keep lock once they are set */
-
- int ignore_time_conflict; /* Ignore certain time conflicts */
-
- int no_crl_check; /* Don't do a CRL check */
-
- char *policy_file; /* full pathname of policy file */
- int no_policy_check; /* ignore certificate policies */
- int no_chain_validation; /* Bypass all cert chain validity tests */
-
- int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */
-} opt;
-
-
-#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */
-#define DBG_MPI_VALUE 2 /* debug mpi details */
-#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
-#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
-#define DBG_CACHE_VALUE 64 /* debug the caching */
-#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
-#define DBG_HASHING_VALUE 512 /* debug hashing operations */
-#define DBG_ASSUAN_VALUE 1024 /* debug assuan communication */
-
-#define DBG_X509 (opt.debug & DBG_X509_VALUE)
-#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
-#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
-#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
-#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
-#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
-
-struct server_local_s;
-
-/* Note that the default values for this are set by
- gpgsm_init_default_ctrl() */
-struct server_control_s {
- int no_server; /* we are not running under server control */
- int status_fd; /* only for non-server mode */
- struct server_local_s *server_local;
- int with_colons; /* use column delimited output format */
- int with_chain; /* include the certifying certs in a listing */
-
- int autodetect_encoding; /* try to detect the input encoding */
- int is_pem; /* Is in PEM format */
- int is_base64; /* is in plain base-64 format */
-
- int create_base64; /* Create base64 encoded output */
- int create_pem; /* create PEM output */
- const char *pem_name; /* PEM name to use */
-
- int include_certs; /* -1 to send all certificates in the chain
- along with a signature or the number of
- certificates up the chain (0 = none, 1 = only
- signer) */
-};
-typedef struct server_control_s *CTRL;
-
-/* data structure used in base64.c */
-typedef struct base64_context_s *Base64Context;
-
-
-struct certlist_s {
- struct certlist_s *next;
- KsbaCert cert;
-};
-typedef struct certlist_s *CERTLIST;
-
-/*-- gpgsm.c --*/
-void gpgsm_exit (int rc);
-void gpgsm_init_default_ctrl (struct server_control_s *ctrl);
-
-/*-- server.c --*/
-void gpgsm_server (void);
-void gpgsm_status (CTRL ctrl, int no, const char *text);
-void gpgsm_status2 (CTRL ctrl, int no, ...);
-void gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text,
- gpg_err_code_t ec);
-
-/*-- fingerprint --*/
-char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len);
-char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo);
-char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo);
-unsigned long gpgsm_get_short_fingerprint (KsbaCert cert);
-char *gpgsm_get_keygrip (KsbaCert cert, char *array);
-char *gpgsm_get_keygrip_hexstring (KsbaCert cert);
-char *gpgsm_get_certid (KsbaCert cert);
-
-
-/*-- base64.c --*/
-int gpgsm_create_reader (Base64Context *ctx,
- CTRL ctrl, FILE *fp, KsbaReader *r_reader);
-void gpgsm_destroy_reader (Base64Context ctx);
-int gpgsm_create_writer (Base64Context *ctx,
- CTRL ctrl, FILE *fp, KsbaWriter *r_writer);
-int gpgsm_finish_writer (Base64Context ctx);
-void gpgsm_destroy_writer (Base64Context ctx);
-
-
-/*-- certdump.c --*/
-void gpgsm_print_serial (FILE *fp, KsbaConstSexp p);
-void gpgsm_print_time (FILE *fp, time_t t);
-void gpgsm_print_name (FILE *fp, const char *string);
-
-void gpgsm_dump_cert (const char *text, KsbaCert cert);
-void gpgsm_dump_serial (KsbaConstSexp p);
-void gpgsm_dump_time (time_t t);
-void gpgsm_dump_string (const char *string);
-
-
-
-/*-- certcheck.c --*/
-int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert);
-int gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
- gcry_md_hd_t md, int hash_algo);
-/* fixme: move create functions to another file */
-int gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo,
- char **r_sigval);
-
-
-/*-- certchain.c --*/
-int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next);
-int gpgsm_is_root_cert (KsbaCert cert);
-int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime);
-int gpgsm_basic_cert_check (KsbaCert cert);
-
-/*-- certlist.c --*/
-int gpgsm_cert_use_sign_p (KsbaCert cert);
-int gpgsm_cert_use_encrypt_p (KsbaCert cert);
-int gpgsm_cert_use_verify_p (KsbaCert cert);
-int gpgsm_cert_use_decrypt_p (KsbaCert cert);
-int gpgsm_cert_use_cert_p (KsbaCert cert);
-int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
- CERTLIST *listaddr);
-void gpgsm_release_certlist (CERTLIST list);
-int gpgsm_find_cert (const char *name, KsbaCert *r_cert);
-
-/*-- keylist.c --*/
-void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode);
-
-/*-- import.c --*/
-int gpgsm_import (CTRL ctrl, int in_fd);
-int gpgsm_import_files (CTRL ctrl, int nfiles, char **files,
- int (*of)(const char *fname));
-
-/*-- export.c --*/
-void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp);
-
-/*-- delete.c --*/
-int gpgsm_delete (CTRL ctrl, STRLIST names);
-
-/*-- verify.c --*/
-int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp);
-
-/*-- sign.c --*/
-int gpgsm_get_default_cert (KsbaCert *r_cert);
-int gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
- int data_fd, int detached, FILE *out_fp);
-
-/*-- encrypt.c --*/
-int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
-
-/*-- decrypt.c --*/
-int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp);
-
-/*-- certreqgen.c --*/
-int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp);
-
-/*-- call-agent.c --*/
-int gpgsm_agent_pksign (const char *keygrip,
- unsigned char *digest,
- size_t digestlen,
- int digestalgo,
- char **r_buf, size_t *r_buflen);
-int gpgsm_agent_pkdecrypt (const char *keygrip,
- KsbaConstSexp ciphertext,
- char **r_buf, size_t *r_buflen);
-int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey);
-int gpgsm_agent_istrusted (KsbaCert cert);
-int gpgsm_agent_havekey (const char *hexkeygrip);
-int gpgsm_agent_marktrusted (KsbaCert cert);
-int gpgsm_agent_learn (void);
-int gpgsm_agent_passwd (const char *hexkeygrip);
-
-/*-- call-dirmngr.c --*/
-int gpgsm_dirmngr_isvalid (KsbaCert cert);
-int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
- void (*cb)(void*, KsbaCert), void *cb_value);
-int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
- int argc, char **argv);
-
-
-
-
-
-#endif /*GPGSM_H*/
diff --git a/sm/import.c b/sm/import.c
deleted file mode 100644
index 17dc3d66c..000000000
--- a/sm/import.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* import.c - Import certificates
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct stats_s {
- unsigned long count;
- unsigned long imported;
- unsigned long unchanged;
- unsigned long not_imported;
-};
-
-
-
-static void
-print_imported_status (CTRL ctrl, KsbaCert cert)
-{
- char *fpr;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL);
- xfree (fpr);
-}
-
-
-/* Print an IMPORT_PROBLEM status. REASON is one of:
- 0 := "No specific reason given".
- 1 := "Invalid Certificate".
- 2 := "Issuer Certificate missing".
- 3 := "Certificate Chain too long".
- 4 := "Error storing certificate".
-*/
-static void
-print_import_problem (CTRL ctrl, KsbaCert cert, int reason)
-{
- char *fpr = NULL;
- char buf[25];
- int i;
-
- sprintf (buf, "%d", reason);
- if (cert)
- {
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- /* detetect an error (all high) value */
- for (i=0; fpr[i] == 'F'; i++)
- ;
- if (!fpr[i])
- {
- xfree (fpr);
- fpr = NULL;
- }
- }
- gpgsm_status2 (ctrl, STATUS_IMPORT_PROBLEM, buf, fpr, NULL);
- xfree (fpr);
-}
-
-
-void
-print_imported_summary (CTRL ctrl, struct stats_s *stats)
-{
- char buf[14*25];
-
- if (!opt.quiet)
- {
- log_info (_("total number processed: %lu\n"), stats->count);
- if (stats->imported)
- {
- log_info (_(" imported: %lu"), stats->imported );
- log_printf ("\n");
- }
- if (stats->unchanged)
- log_info (_(" unchanged: %lu\n"), stats->unchanged);
- if (stats->not_imported)
- log_info (_(" not imported: %lu\n"), stats->not_imported);
- }
-
- sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu",
- stats->count,
- stats->imported,
- stats->unchanged,
- stats->not_imported
- );
- gpgsm_status (ctrl, STATUS_IMPORT_RES, buf);
-}
-
-
-
-static void
-check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth)
-{
- int rc;
-
- stats->count++;
- if ( depth >= 50 )
- {
- log_error (_("certificate chain too long\n"));
- stats->not_imported++;
- print_import_problem (ctrl, cert, 3);
- return;
- }
-
- rc = gpgsm_basic_cert_check (cert);
- if (!rc)
- {
- int existed;
-
- if (!keydb_store_cert (cert, 0, &existed))
- {
- KsbaCert next = NULL;
-
- if (!existed)
- {
- print_imported_status (ctrl, cert);
- stats->imported++;
- }
- else
- stats->unchanged++;
-
- if (opt.verbose > 1 && existed)
- {
- if (depth)
- log_info ("issuer certificate already in DB\n");
- else
- log_info ("certificate already in DB\n");
- }
- else if (opt.verbose && !existed)
- {
- if (depth)
- log_info ("issuer certificate imported\n");
- else
- log_info ("certificate imported\n");
- }
- /* Now lets walk up the chain and import all certificates up
- the chain.*/
- else if (!gpgsm_walk_cert_chain (cert, &next))
- {
- check_and_store (ctrl, stats, next, depth+1);
- ksba_cert_release (next);
- }
- }
- else
- {
- log_error (_("error storing certificate\n"));
- stats->not_imported++;
- print_import_problem (ctrl, cert, 4);
- }
- }
- else
- {
- log_error (_("basic certificate checks failed - not imported\n"));
- stats->not_imported++;
- print_import_problem (ctrl, cert,
- gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 :
- gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0);
- }
-}
-
-
-
-
-static int
-import_one (CTRL ctrl, struct stats_s *stats, int in_fd)
-{
- int rc;
- Base64Context b64reader = NULL;
- KsbaReader reader;
- KsbaCert cert = NULL;
- KsbaCMS cms = NULL;
- FILE *fp = NULL;
- KsbaContentType ct;
-
- fp = fdopen ( dup (in_fd), "rb");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- ct = ksba_cms_identify (reader);
- if (ct == KSBA_CT_SIGNED_DATA)
- { /* This is probably a signed-only message - import the certs */
- KsbaStopReason stopreason;
- int i;
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- rc = ksba_cms_set_reader_writer (cms, reader, NULL);
- if (rc)
- {
- log_error ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (rc));
- rc = map_ksba_err (rc);
- goto leave;
- }
-
-
- do
- {
- rc = ksba_cms_parse (cms, &stopreason);
- if (rc)
- {
- log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc));
- rc = map_ksba_err (rc);
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA)
- log_info ("not a certs-only message\n");
- }
- while (stopreason != KSBA_SR_READY);
-
- for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
- {
- check_and_store (ctrl, stats, cert, 0);
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (!i)
- log_error ("no certificate found\n");
- }
- else if (ct == KSBA_CT_NONE)
- { /* Failed to identify this message - assume a certificate */
-
- cert = ksba_cert_new ();
- if (!cert)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- rc = ksba_cert_read_der (cert, reader);
- if (rc)
- {
- rc = map_ksba_err (rc);
- goto leave;
- }
-
- check_and_store (ctrl, stats, cert, 0);
- }
- else
- {
- log_error ("can't extract certificates from input\n");
- rc = gpg_error (GPG_ERR_NO_DATA);
- }
-
- leave:
- ksba_cms_release (cms);
- ksba_cert_release (cert);
- gpgsm_destroy_reader (b64reader);
- if (fp)
- fclose (fp);
- return rc;
-}
-
-
-int
-gpgsm_import (CTRL ctrl, int in_fd)
-{
- int rc;
- struct stats_s stats;
-
- memset (&stats, 0, sizeof stats);
- rc = import_one (ctrl, &stats, in_fd);
- print_imported_summary (ctrl, &stats);
- /* If we never printed an error message do it now so that a command
- line invocation will return with an error (log_error keeps a
- global errorcount) */
- if (rc && !log_get_errorcount (0))
- log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
- return rc;
-}
-
-
-int
-gpgsm_import_files (CTRL ctrl, int nfiles, char **files,
- int (*of)(const char *fname))
-{
- int rc = 0;
- struct stats_s stats;
-
- memset (&stats, 0, sizeof stats);
-
- if (!nfiles)
- rc = import_one (ctrl, &stats, 0);
- else
- {
- for (; nfiles && !rc ; nfiles--, files++)
- {
- int fd = of (*files);
- rc = import_one (ctrl, &stats, fd);
- close (fd);
- if (rc == -1)
- rc = 0;
- }
- }
- print_imported_summary (ctrl, &stats);
- /* If we never printed an error message do it now so that a command
- line invocation will return with an error (log_error keeps a
- global errorcount) */
- if (rc && !log_get_errorcount (0))
- log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
- return rc;
-}
-
-
diff --git a/sm/keydb.c b/sm/keydb.c
deleted file mode 100644
index fe6556549..000000000
--- a/sm/keydb.c
+++ /dev/null
@@ -1,1282 +0,0 @@
-/* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "gpgsm.h"
-#include "../kbx/keybox.h"
-#include "keydb.h"
-#include "i18n.h"
-
-#define DIRSEP_C '/'
-
-static int active_handles;
-
-typedef enum {
- KEYDB_RESOURCE_TYPE_NONE = 0,
- KEYDB_RESOURCE_TYPE_KEYBOX
-} KeydbResourceType;
-#define MAX_KEYDB_RESOURCES 20
-
-struct resource_item {
- KeydbResourceType type;
- union {
- KEYBOX_HANDLE kr;
- } u;
- void *token;
- int secret;
- DOTLOCK lockhandle;
-};
-
-static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
-static int used_resources;
-
-struct keydb_handle {
- int locked;
- int found;
- int current;
- int is_ephemeral;
- int used; /* items in active */
- struct resource_item active[MAX_KEYDB_RESOURCES];
-};
-
-
-static int lock_all (KEYDB_HANDLE hd);
-static void unlock_all (KEYDB_HANDLE hd);
-
-
-/*
- * Register a resource (which currently may only be a keybox file).
- * The first keybox which is added by this function is
- * created if it does not exist.
- * Note: this function may be called before secure memory is
- * available.
- */
-int
-keydb_add_resource (const char *url, int force, int secret)
-{
- static int any_secret, any_public;
- const char *resname = url;
- char *filename = NULL;
- int rc = 0;
- FILE *fp;
- KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
- const char *created_fname = NULL;
-
- /* Do we have an URL?
- gnupg-kbx:filename := this is a plain keybox
- filename := See what is is, but create as plain keybox.
- */
- if (strlen (resname) > 10)
- {
- if (!strncmp (resname, "gnupg-kbx:", 10) )
- {
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- resname += 10;
- }
-#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
- else if (strchr (resname, ':'))
- {
- log_error ("invalid key resource URL `%s'\n", url );
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
- }
-
- if (*resname != DIRSEP_C )
- { /* do tilde expansion etc */
- if (strchr(resname, DIRSEP_C) )
- filename = make_filename (resname, NULL);
- else
- filename = make_filename (opt.homedir, resname, NULL);
- }
- else
- filename = xstrdup (resname);
-
- if (!force)
- force = secret? !any_secret : !any_public;
-
- /* see whether we can determine the filetype */
- if (rt == KEYDB_RESOURCE_TYPE_NONE)
- {
- FILE *fp2 = fopen( filename, "rb" );
-
- if (fp2) {
- u32 magic;
-
- /* FIXME: check for the keybox magic */
- if (fread( &magic, 4, 1, fp2) == 1 )
- {
- if (magic == 0x13579ace || magic == 0xce9a5713)
- ; /* GDBM magic - no more support */
- else
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- }
- else /* maybe empty: assume ring */
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- fclose (fp2);
- }
- else /* no file yet: create ring */
- rt = KEYDB_RESOURCE_TYPE_KEYBOX;
- }
-
- switch (rt)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- log_error ("unknown type of key resource `%s'\n", url );
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
-
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- fp = fopen (filename, "rb");
- if (!fp && !force)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- goto leave;
- }
-
- if (!fp)
- { /* no file */
-#if 0 /* no autocreate of the homedirectory yet */
- {
- char *last_slash_in_filename;
-
- last_slash_in_filename = strrchr (filename, DIRSEP_C);
- *last_slash_in_filename = 0;
- if (access (filename, F_OK))
- { /* on the first time we try to create the default
- homedir and in this case the process will be
- terminated, so that on the next invocation can
- read the options file in on startup */
- try_make_homedir (filename);
- rc = gpg_error (GPG_ERR_FILE_OPEN_ERROR);
- *last_slash_in_filename = DIRSEP_C;
- goto leave;
- }
- *last_slash_in_filename = DIRSEP_C;
- }
-#endif
- fp = fopen (filename, "w");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error (_("error creating keybox `%s': %s\n"),
- filename, strerror(errno));
- goto leave;
- }
-
- if (!opt.quiet)
- log_info (_("keybox `%s' created\n"), filename);
- created_fname = filename;
- }
- fclose (fp);
- fp = NULL;
- /* now register the file */
- {
-
- void *token = keybox_register_file (filename, secret);
- if (!token)
- ; /* already registered - ignore it */
- else if (used_resources >= MAX_KEYDB_RESOURCES)
- rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
- else
- {
- all_resources[used_resources].type = rt;
- all_resources[used_resources].u.kr = NULL; /* Not used here */
- all_resources[used_resources].token = token;
- all_resources[used_resources].secret = secret;
-
- all_resources[used_resources].lockhandle
- = create_dotlock (filename);
- if (!all_resources[used_resources].lockhandle)
- log_fatal ( _("can't create lock for `%s'\n"), filename);
-
- used_resources++;
- }
- }
- break;
- default:
- log_error ("resource type of `%s' not supported\n", url);
- rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
- goto leave;
- }
-
- /* fixme: check directory permissions and print a warning */
-
- leave:
- if (rc)
- log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror(rc));
- else if (secret)
- any_secret = 1;
- else
- any_public = 1;
- xfree (filename);
- return rc;
-}
-
-
-KEYDB_HANDLE
-keydb_new (int secret)
-{
- KEYDB_HANDLE hd;
- int i, j;
-
- hd = xcalloc (1, sizeof *hd);
- hd->found = -1;
-
- assert (used_resources <= MAX_KEYDB_RESOURCES);
- for (i=j=0; i < used_resources; i++)
- {
- if (!all_resources[i].secret != !secret)
- continue;
- switch (all_resources[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- hd->active[j].type = all_resources[i].type;
- hd->active[j].token = all_resources[i].token;
- hd->active[j].secret = all_resources[i].secret;
- hd->active[j].lockhandle = all_resources[i].lockhandle;
- hd->active[j].u.kr = keybox_new (all_resources[i].token, secret);
- if (!hd->active[j].u.kr)
- {
- xfree (hd);
- return NULL; /* fixme: release all previously allocated handles*/
- }
- j++;
- break;
- }
- }
- hd->used = j;
-
- active_handles++;
- return hd;
-}
-
-void
-keydb_release (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd)
- return;
- assert (active_handles > 0);
- active_handles--;
-
- unlock_all (hd);
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- keybox_release (hd->active[i].u.kr);
- break;
- }
- }
-
- xfree (hd);
-}
-
-
-/* Return the name of the current resource. This is function first
- looks for the last found found, then for the current search
- position, and last returns the first available resource. The
- returned string is only valid as long as the handle exists. This
- function does only return NULL if no handle is specified, in all
- other error cases an empty string is returned. */
-const char *
-keydb_get_resource_name (KEYDB_HANDLE hd)
-{
- int idx;
- const char *s = NULL;
-
- if (!hd)
- return NULL;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- idx = 0;
-
- switch (hd->active[idx].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- s = NULL;
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- s = keybox_get_resource_name (hd->active[idx].u.kr);
- break;
- }
-
- return s? s: "";
-}
-
-/* Switch the handle into ephemeral mode and return the orginal value. */
-int
-keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
-{
- int i;
-
- if (!hd)
- return 0;
-
- yes = !!yes;
- if (hd->is_ephemeral != yes)
- {
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- keybox_set_ephemeral (hd->active[i].u.kr, yes);
- break;
- }
- }
- }
-
- i = hd->is_ephemeral;
- hd->is_ephemeral = yes;
- return i;
-}
-
-
-
-static int
-lock_all (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- /* Fixme: This locking scheme may lead to deadlock if the resources
- are not added in the same sequence by all processes. We are
- cuurently only allowing one resource so it is not a problem. */
- for (i=0; i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- rc = make_dotlock (hd->active[i].lockhandle, -1);
- break;
- }
- if (rc)
- break;
- }
-
- if (rc)
- {
- /* revert the already set locks */
- for (i--; i >= 0; i--)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- release_dotlock (hd->active[i].lockhandle);
- break;
- }
- }
- }
- else
- hd->locked = 1;
-
- return rc;
-}
-
-static void
-unlock_all (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd->locked)
- return;
-
- for (i=hd->used-1; i >= 0; i--)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- release_dotlock (hd->active[i].lockhandle);
- break;
- }
- }
- hd->locked = 0;
-}
-
-
-#if 0
-/*
- * Return the last found keybox. Caller must free it.
- * The returned keyblock has the kbode flag bit 0 set for the node with
- * the public key used to locate the keyblock or flag bit 1 set for
- * the user ID node.
- */
-int
-keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
- break;
- }
-
- return rc;
-}
-
-/*
- * update the current keyblock with KB
- */
-int
-keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_keyblock (hd->active[hd->found].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * Insert a new KB into one of the resources.
- */
-int
-keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = -1;
- int idx;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if( opt.dry_run )
- return 0;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- return G10ERR_GENERAL;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[idx].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-#endif /*disabled code*/
-
-
-
-/*
- Return the last found keybox. Caller must free it. The returned
- keyblock has the kbode flag bit 0 set for the node with the public
- key used to locate the keyblock or flag bit 1 set for the user ID
- node. */
-int
-keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert)
-{
- int rc = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert);
- break;
- }
-
- return rc;
-}
-
-/*
- * Insert a new Certificate into one of the resources.
- */
-int
-keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert)
-{
- int rc = -1;
- int idx;
- char digest[20];
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if (opt.dry_run)
- return 0;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- return gpg_error (GPG_ERR_GENERAL);
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
-
- switch (hd->active[idx].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-
-/* update the current keyblock with KB */
-int
-keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert)
-{
- int rc = 0;
- char digest[20];
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if (opt.dry_run)
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * The current keyblock or cert will be deleted.
- */
-int
-keydb_delete (KEYDB_HANDLE hd)
-{
- int rc = -1;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_delete (hd->active[hd->found].u.kr);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-
-/*
- * Locate the default writable key resource, so that the next
- * operation (which is only relevant for inserts) will be done on this
- * resource.
- */
-int
-keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
-{
- int rc;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- rc = keydb_search_reset (hd); /* this does reset hd->current */
- if (rc)
- return rc;
-
- for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
- {
- switch (hd->active[hd->current].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- BUG();
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (keybox_is_writable (hd->active[hd->current].token))
- return 0; /* found (hd->current is set to it) */
- break;
- }
- }
-
- return -1;
-}
-
-/*
- * Rebuild the caches of all key resources.
- */
-void
-keydb_rebuild_caches (void)
-{
- int i;
-
- for (i=0; i < used_resources; i++)
- {
- if (all_resources[i].secret)
- continue;
- switch (all_resources[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
-/* rc = keybox_rebuild_cache (all_resources[i].token); */
-/* if (rc) */
-/* log_error (_("failed to rebuild keybox cache: %s\n"), */
-/* g10_errstr (rc)); */
- break;
- }
- }
-}
-
-
-
-/*
- * Start the next search on this handle right at the beginning
- */
-int
-keydb_search_reset (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- hd->current = 0;
- hd->found = -1;
- /* and reset all resources */
- for (i=0; !rc && i < hd->used; i++)
- {
- switch (hd->active[i].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_search_reset (hd->active[i].u.kr);
- break;
- }
- }
- return rc; /* fixme: we need to map error codes or share them with
- all modules*/
-}
-
-/*
- * Search through all keydb resources, starting at the current position,
- * for a keyblock which contains one of the keys described in the DESC array.
- */
-int
-keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
-{
- int rc = -1;
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
- {
- switch (hd->active[hd->current].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- BUG(); /* we should never see it here */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc);
- break;
- }
- if (rc == -1) /* EOF -> switch to next resource */
- hd->current++;
- else if (!rc)
- hd->found = hd->current;
- }
-
- return rc;
-}
-
-
-int
-keydb_search_first (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FIRST;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_next (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_NEXT;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
-/* desc.u.kid[0] = kid[0]; */
-/* desc.u.kid[1] = kid[1]; */
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FPR;
- memcpy (desc.u.fpr, fpr, 20);
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_ISSUER;
- desc.u.name = issuer;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-int
-keydb_search_issuer_sn (KEYDB_HANDLE hd,
- const char *issuer, KsbaConstSexp serial)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
- const unsigned char *s;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN;
- s = serial;
- if (*s !='(')
- return gpg_error (GPG_ERR_INV_VALUE);
- s++;
- for (desc.snlen = 0; digitp (s); s++)
- desc.snlen = 10*desc.snlen + atoi_1 (s);
- if (*s !=':')
- return gpg_error (GPG_ERR_INV_VALUE);
- desc.sn = s+1;
- desc.u.name = issuer;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-int
-keydb_search_subject (KEYDB_HANDLE hd, const char *name)
-{
- KEYDB_SEARCH_DESC desc;
- int rc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_SUBJECT;
- desc.u.name = name;
- rc = keydb_search (hd, &desc, 1);
- return rc;
-}
-
-
-static int
-hextobyte (const unsigned char *s)
-{
- int c;
-
- if( *s >= '0' && *s <= '9' )
- c = 16 * (*s - '0');
- else if ( *s >= 'A' && *s <= 'F' )
- c = 16 * (10 + *s - 'A');
- else if ( *s >= 'a' && *s <= 'f' )
- c = 16 * (10 + *s - 'a');
- else
- return -1;
- s++;
- if ( *s >= '0' && *s <= '9' )
- c += *s - '0';
- else if ( *s >= 'A' && *s <= 'F' )
- c += 10 + *s - 'A';
- else if ( *s >= 'a' && *s <= 'f' )
- c += 10 + *s - 'a';
- else
- return -1;
- return c;
-}
-
-
-static int
-classify_user_id (const char *name,
- KEYDB_SEARCH_DESC *desc,
- int *force_exact )
-{
- const char *s;
- int hexprefix = 0;
- int hexlength;
- int mode = 0;
-
- /* clear the structure so that the mode field is set to zero unless
- * we set it to the correct value right at the end of this function */
- memset (desc, 0, sizeof *desc);
- *force_exact = 0;
- /* skip leading spaces. Fixme: what about trailing white space? */
- for(s = name; *s && spacep (s); s++ )
- ;
-
- switch (*s)
- {
- case 0: /* empty string is an error */
- return 0;
-
- case '.': /* an email address, compare from end */
- mode = KEYDB_SEARCH_MODE_MAILEND;
- s++;
- desc->u.name = s;
- break;
-
- case '<': /* an email address */
- mode = KEYDB_SEARCH_MODE_MAIL;
- s++;
- desc->u.name = s;
- break;
-
- case '@': /* part of an email address */
- mode = KEYDB_SEARCH_MODE_MAILSUB;
- s++;
- desc->u.name = s;
- break;
-
- case '=': /* exact compare */
- mode = KEYDB_SEARCH_MODE_EXACT;
- s++;
- desc->u.name = s;
- break;
-
- case '*': /* case insensitive substring search */
- mode = KEYDB_SEARCH_MODE_SUBSTR;
- s++;
- desc->u.name = s;
- break;
-
- case '+': /* compare individual words */
- mode = KEYDB_SEARCH_MODE_WORDS;
- s++;
- desc->u.name = s;
- break;
-
- case '/': /* subject's DN */
- s++;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_SUBJECT;
- break;
-
- case '#':
- {
- const char *si;
-
- s++;
- if ( *s == '/')
- { /* "#/" indicates an issuer's DN */
- s++;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_ISSUER;
- }
- else
- { /* serialnumber + optional issuer ID */
- for (si=s; *si && *si != '/'; si++)
- {
- if (!strchr("01234567890abcdefABCDEF", *si))
- return 0; /* invalid digit in serial number*/
- }
- desc->sn = s;
- desc->snlen = -1;
- if (!*si)
- mode = KEYDB_SEARCH_MODE_SN;
- else
- {
- s = si+1;
- if (!*s || spacep (s))
- return 0; /* no DN or prefixed with a space */
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_ISSUER_SN;
- }
- }
- }
- break;
-
- case ':': /*Unified fingerprint */
- {
- const char *se, *si;
- int i;
-
- se = strchr (++s,':');
- if (!se)
- return 0;
- for (i=0,si=s; si < se; si++, i++ )
- {
- if (!strchr("01234567890abcdefABCDEF", *si))
- return 0; /* invalid digit */
- }
- if (i != 32 && i != 40)
- return 0; /* invalid length of fpr*/
- for (i=0,si=s; si < se; i++, si +=2)
- desc->u.fpr[i] = hextobyte(si);
- for (; i < 20; i++)
- desc->u.fpr[i]= 0;
- s = se + 1;
- mode = KEYDB_SEARCH_MODE_FPR;
- }
- break;
-
- default:
- if (s[0] == '0' && s[1] == 'x')
- {
- hexprefix = 1;
- s += 2;
- }
-
- hexlength = strspn(s, "0123456789abcdefABCDEF");
- if (hexlength >= 8 && s[hexlength] =='!')
- {
- *force_exact = 1;
- hexlength++; /* just for the following check */
- }
-
- /* check if a hexadecimal number is terminated by EOS or blank */
- if (hexlength && s[hexlength] && !spacep (s+hexlength))
- {
- if (hexprefix) /* a "0x" prefix without correct */
- return 0; /* termination is an error */
- /* The first chars looked like a hex number, but really is
- not */
- hexlength = 0;
- }
-
- if (*force_exact)
- hexlength--; /* remove the bang */
-
- if (hexlength == 8
- || (!hexprefix && hexlength == 9 && *s == '0'))
- { /* short keyid */
- unsigned long kid;
- if (hexlength == 9)
- s++;
- kid = strtoul( s, NULL, 16 );
- desc->u.kid[4] = kid >> 24;
- desc->u.kid[5] = kid >> 16;
- desc->u.kid[6] = kid >> 8;
- desc->u.kid[7] = kid;
- mode = KEYDB_SEARCH_MODE_SHORT_KID;
- }
- else if (hexlength == 16
- || (!hexprefix && hexlength == 17 && *s == '0'))
- { /* complete keyid */
- unsigned long kid0, kid1;
- char buf[9];
- if (hexlength == 17)
- s++;
- mem2str(buf, s, 9 );
- kid0 = strtoul (buf, NULL, 16);
- kid1 = strtoul (s+8, NULL, 16);
- desc->u.kid[0] = kid0 >> 24;
- desc->u.kid[1] = kid0 >> 16;
- desc->u.kid[2] = kid0 >> 8;
- desc->u.kid[3] = kid0;
- desc->u.kid[4] = kid1 >> 24;
- desc->u.kid[5] = kid1 >> 16;
- desc->u.kid[6] = kid1 >> 8;
- desc->u.kid[7] = kid1;
- mode = KEYDB_SEARCH_MODE_LONG_KID;
- }
- else if (hexlength == 32
- || (!hexprefix && hexlength == 33 && *s == '0'))
- { /* md5 fingerprint */
- int i;
- if (hexlength == 33)
- s++;
- memset(desc->u.fpr+16, 0, 4);
- for (i=0; i < 16; i++, s+=2)
- {
- int c = hextobyte(s);
- if (c == -1)
- return 0;
- desc->u.fpr[i] = c;
- }
- mode = KEYDB_SEARCH_MODE_FPR16;
- }
- else if (hexlength == 40
- || (!hexprefix && hexlength == 41 && *s == '0'))
- { /* sha1/rmd160 fingerprint */
- int i;
- if (hexlength == 41)
- s++;
- for (i=0; i < 20; i++, s+=2)
- {
- int c = hextobyte(s);
- if (c == -1)
- return 0;
- desc->u.fpr[i] = c;
- }
- mode = KEYDB_SEARCH_MODE_FPR20;
- }
- else if (!hexprefix)
- {
- /* The fingerprint in an X.509 listing is often delimited by
- colons, so we try to single this case out. */
- mode = 0;
- hexlength = strspn (s, ":0123456789abcdefABCDEF");
- if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
- {
- int i;
-
- for (i=0; i < 20; i++, s += 3)
- {
- int c = hextobyte(s);
- if (c == -1 || (i < 19 && s[2] != ':'))
- break;
- desc->u.fpr[i] = c;
- }
- if (i == 20)
- mode = KEYDB_SEARCH_MODE_FPR20;
- }
- if (!mode) /* default is substring search */
- {
- *force_exact = 0;
- desc->u.name = s;
- mode = KEYDB_SEARCH_MODE_SUBSTR;
- }
- }
- else
- { /* hex number with a prefix but a wrong length */
- return 0;
- }
- }
-
- desc->mode = mode;
- return mode;
-}
-
-
-int
-keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc)
-{
- int dummy;
- KEYDB_SEARCH_DESC dummy_desc;
-
- if (!desc)
- desc = &dummy_desc;
-
- if (!classify_user_id (name, desc, &dummy))
- return gpg_error (GPG_ERR_INV_NAME);
- return 0;
-}
-
-
-/* Store the certificate in the key DB but make sure that it does not
- already exists. We do this simply by comparing the fingerprint.
- If EXISTED is not NULL it will be set to true if the certificate
- was already in the DB. */
-int
-keydb_store_cert (KsbaCert cert, int ephemeral, int *existed)
-{
- KEYDB_HANDLE kh;
- int rc;
- unsigned char fpr[20];
-
- if (existed)
- *existed = 0;
-
- if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL))
- {
- log_error (_("failed to get the fingerprint\n"));
- return gpg_error (GPG_ERR_GENERAL);
- }
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocate keyDB handle\n"));
- return gpg_error (GPG_ERR_ENOMEM);;
- }
-
- if (ephemeral)
- keydb_set_ephemeral (kh, 1);
-
- rc = keydb_search_fpr (kh, fpr);
- if (rc != -1)
- {
- keydb_release (kh);
- if (!rc)
- {
- if (existed)
- *existed = 1;
- return 0; /* okay */
- }
- log_error (_("problem looking for existing certificate: %s\n"),
- gpg_strerror (rc));
- return rc;
- }
-
- rc = keydb_locate_writable (kh, 0);
- if (rc)
- {
- log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc));
- keydb_release (kh);
- return rc;
- }
-
- rc = keydb_insert_cert (kh, cert);
- if (rc)
- {
- log_error (_("error storing certificate: %s\n"), gpg_strerror (rc));
- keydb_release (kh);
- return rc;
- }
- keydb_release (kh);
- return 0;
-}
-
-
-
diff --git a/sm/keydb.h b/sm/keydb.h
deleted file mode 100644
index ad7eaf51d..000000000
--- a/sm/keydb.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* keydb.h - Key database
- * Copyright (C) 1998, 1999, 2000, 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GNUPG_KEYDB_H
-#define GNUPG_KEYDB_H
-
-#include <ksba.h>
-
-#include "../kbx/keybox-search-desc.h"
-
-typedef struct keydb_handle *KEYDB_HANDLE;
-
-
-/*-- keydb.c --*/
-int keydb_add_resource (const char *url, int force, int secret);
-KEYDB_HANDLE keydb_new (int secret);
-void keydb_release (KEYDB_HANDLE hd);
-int keydb_set_ephemeral (KEYDB_HANDLE hd, int yes);
-const char *keydb_get_resource_name (KEYDB_HANDLE hd);
-
-#if 0 /* pgp stuff */
-int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
-int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
-int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
-#endif
-
-int keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert);
-int keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert);
-int keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert);
-
-int keydb_delete (KEYDB_HANDLE hd);
-
-int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
-void keydb_rebuild_caches (void);
-
-int keydb_search_reset (KEYDB_HANDLE hd);
-int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc);
-int keydb_search_first (KEYDB_HANDLE hd);
-int keydb_search_next (KEYDB_HANDLE hd);
-int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
-int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
-int keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer);
-int keydb_search_issuer_sn (KEYDB_HANDLE hd,
- const char *issuer, const unsigned char *serial);
-int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer);
-
-int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc);
-
-int keydb_store_cert (KsbaCert cert, int ephemeral, int *existed);
-
-
-#endif /*GNUPG_KEYDB_H*/
-
-
-
-
diff --git a/sm/keylist.c b/sm/keylist.c
deleted file mode 100644
index 634bda292..000000000
--- a/sm/keylist.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/* keylist.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-struct list_external_parm_s {
- FILE *fp;
- int print_header;
- int with_colons;
- int with_chain;
-};
-
-
-
-static void
-print_key_data (KsbaCert cert, FILE *fp)
-{
-#if 0
- int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
- int i;
-
- for(i=0; i < n; i++ )
- {
- fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
- mpi_print(stdout, pk->pkey[i], 1 );
- putchar(':');
- putchar('\n');
- }
-#endif
-}
-
-static void
-print_capabilities (KsbaCert cert, FILE *fp)
-{
- KsbaError err;
- unsigned int use;
-
- err = ksba_cert_get_key_usage (cert, &use);
- if (err == KSBA_No_Data)
- {
- putc ('e', fp);
- putc ('s', fp);
- putc ('c', fp);
- putc ('E', fp);
- putc ('S', fp);
- putc ('C', fp);
- return;
- }
- if (err)
- {
- log_error (_("error getting key usage information: %s\n"),
- ksba_strerror (err));
- return;
- }
-
- if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
- putc ('e', fp);
- if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- putc ('s', fp);
- if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- putc ('c', fp);
- if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
- putc ('E', fp);
- if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
- putc ('S', fp);
- if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- putc ('C', fp);
-}
-
-
-static void
-print_time (time_t t, FILE *fp)
-{
- if (!t)
- ;
- else if ( t == (time_t)(-1) )
- putc ('?', fp);
- else
- fprintf (fp, "%lu", (unsigned long)t);
-}
-
-
-/* return an allocated string with the email address extracted from a
- DN */
-static char *
-email_kludge (const char *name)
-{
- const unsigned char *p;
- unsigned char *buf;
- int n;
-
- if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
- return NULL;
- /* This looks pretty much like an email address in the subject's DN
- we use this to add an additional user ID entry. This way,
- openSSL generated keys get a nicer and usable listing */
- name += 22;
- for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
- ;
- if (*p != '#' || !n)
- return NULL;
- buf = xtrymalloc (n+3);
- if (!buf)
- return NULL; /* oops, out of core */
- *buf = '<';
- for (n=1, p=name; *p != '#'; p +=2, n++)
- buf[n] = xtoi_2 (p);
- buf[n++] = '>';
- buf[n] = 0;
- return buf;
-}
-
-
-
-
-/* List one certificate in colon mode */
-static void
-list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
-{
- int idx, trustletter = 0;
- char *p;
- KsbaSexp sexp;
- char *fpr;
-
- fputs (have_secret? "crs:":"crt:", fp);
- trustletter = 0;
-#if 0
- if (is_not_valid (cert))
- putc ('i', fp);
- else if ( is_revoked (cert) )
- putc ('r', fp);
- else if ( has_expired (cert))
- putcr ('e', fp);
- else
-#endif
- {
- trustletter = '?'; /*get_validity_info ( pk, NULL );*/
- putc (trustletter, fp);
- }
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- fprintf (fp, ":%u:%d:%s:",
- /*keylen_of_cert (cert)*/1024,
- /* pubkey_algo_of_cert (cert)*/1,
- fpr+24);
-
- /* we assume --fixed-list-mode for gpgsm */
- print_time ( ksba_cert_get_validity (cert, 0), fp);
- putc (':', fp);
- print_time ( ksba_cert_get_validity (cert, 1), fp);
- putc (':', fp);
- /* field 8, serial number: */
- if ((sexp = ksba_cert_get_serial (cert)))
- {
- int len;
- const unsigned char *s = sexp;
-
- if (*s == '(')
- {
- s++;
- for (len=0; *s && *s != ':' && digitp (s); s++)
- len = len*10 + atoi_1 (s);
- if (*s == ':')
- for (s++; len; len--, s++)
- fprintf (fp,"%02X", *s);
- }
- xfree (sexp);
- }
- putc (':', fp);
- /* field 9, ownertrust - not used here */
- putc (':', fp);
- /* field 10, old user ID - we use it here for the issuer DN */
- if ((p = ksba_cert_get_issuer (cert,0)))
- {
- print_sanitized_string (fp, p, ':');
- xfree (p);
- }
- putc (':', fp);
- /* field 11, signature class - not used */
- putc (':', fp);
- /* field 12, capabilities: */
- print_capabilities (cert, fp);
- putc (':', fp);
- putc ('\n', fp);
-
- /* FPR record */
- fprintf (fp, "fpr:::::::::%s:::", fpr);
- xfree (fpr); fpr = NULL;
- /* print chaining ID (field 13)*/
- {
- KsbaCert next;
-
- if (!gpgsm_walk_cert_chain (cert, &next))
- {
- p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
- fputs (p, fp);
- xfree (p);
- ksba_cert_release (next);
- }
- }
- putc (':', fp);
- putc ('\n', fp);
-
-
- if (opt.with_key_data)
- {
- if ( (p = gpgsm_get_keygrip_hexstring (cert)))
- {
- fprintf (fp, "grp:::::::::%s:\n", p);
- xfree (p);
- }
- print_key_data (cert, fp);
- }
-
- for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
- {
- fprintf (fp, "uid:%c::::::::", trustletter);
- print_sanitized_string (fp, p, ':');
- putc (':', fp);
- putc (':', fp);
- putc ('\n', fp);
- if (!idx)
- {
- /* It would be better to get the faked email address from
- the keydb. But as long as we don't have a way to pass
- the meta data back, we just check it the same way as the
- code used to create the keybox meta data does */
- char *pp = email_kludge (p);
- if (pp)
- {
- fprintf (fp, "uid:%c::::::::", trustletter);
- print_sanitized_string (fp, pp, ':');
- putc (':', fp);
- putc (':', fp);
- putc ('\n', fp);
- xfree (pp);
- }
- }
- xfree (p);
- }
-}
-
-
-/* List one certificate in standard mode */
-static void
-list_cert_std (KsbaCert cert, FILE *fp, int have_secret)
-{
- KsbaError kerr;
- KsbaSexp sexp;
- char *dn;
- time_t t;
- int idx;
- int is_ca, chainlen;
- unsigned int kusage;
- char *string, *p;
-
- sexp = ksba_cert_get_serial (cert);
- fputs ("Serial number: ", fp);
- gpgsm_print_serial (fp, sexp);
- ksba_free (sexp);
- putc ('\n', fp);
-
- dn = ksba_cert_get_issuer (cert, 0);
- fputs (" Issuer: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- dn = ksba_cert_get_subject (cert, 0);
- fputs (" Subject: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
- {
- fputs (" aka: ", fp);
- gpgsm_print_name (fp, dn);
- ksba_free (dn);
- putc ('\n', fp);
- }
-
- t = ksba_cert_get_validity (cert, 0);
- fputs (" validity: ", fp);
- gpgsm_print_time (fp, t);
- fputs (" through ", fp);
- t = ksba_cert_get_validity (cert, 1);
- gpgsm_print_time (fp, t);
- putc ('\n', fp);
-
- kerr = ksba_cert_get_key_usage (cert, &kusage);
- if (kerr != KSBA_No_Data)
- {
- fputs (" key usage:", fp);
- if (kerr)
- fprintf (fp, " [error: %s]", ksba_strerror (kerr));
- else
- {
- if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
- fputs (" digitalSignature", fp);
- if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
- fputs (" nonRepudiation", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
- fputs (" keyEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
- fputs (" dataEncipherment", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
- fputs (" keyAgreement", fp);
- if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
- fputs (" certSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
- fputs (" crlSign", fp);
- if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
- fputs (" encipherOnly", fp);
- if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
- fputs (" decipherOnly", fp);
- }
- putc ('\n', fp);
- }
-
- kerr = ksba_cert_get_cert_policies (cert, &string);
- if (kerr != KSBA_No_Data)
- {
- fputs (" policies: ", fp);
- if (kerr)
- fprintf (fp, "[error: %s]", ksba_strerror (kerr));
- else
- {
- for (p=string; *p; p++)
- {
- if (*p == '\n')
- *p = ',';
- }
- print_sanitized_string (fp, string, 0);
- xfree (string);
- }
- putc ('\n', fp);
- }
-
- kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen);
- if (kerr || is_ca)
- {
- fputs (" chain length: ", fp);
- if (kerr)
- fprintf (fp, "[error: %s]", ksba_strerror (kerr));
- else if (chainlen == -1)
- fputs ("unlimited", fp);
- else
- fprintf (fp, "%d", chainlen);
- putc ('\n', fp);
- }
-
-
- dn = gpgsm_get_fingerprint_string (cert, 0);
- fprintf (fp, " fingerprint: %s\n", dn?dn:"error");
- xfree (dn);
-}
-
-/* Same as standard mode mode list all certifying certts too */
-static void
-list_cert_chain (KsbaCert cert, FILE *fp)
-{
- KsbaCert next = NULL;
-
- list_cert_std (cert, fp, 0);
- ksba_cert_ref (cert);
- while (!gpgsm_walk_cert_chain (cert, &next))
- {
- ksba_cert_release (cert);
- fputs ("Certified by\n", fp);
- list_cert_std (next, fp, 0);
- cert = next;
- }
- ksba_cert_release (cert);
- putc ('\n', fp);
-}
-
-
-
-/* List all internal keys or just the key given as NAMES.
- */
-static void
-list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
-{
- KEYDB_HANDLE hd;
- KEYDB_SEARCH_DESC *desc = NULL;
- STRLIST sl;
- int ndesc;
- KsbaCert cert = NULL;
- int rc=0;
- const char *lastresname, *resname;
- int have_secret;
-
- hd = keydb_new (0);
- if (!hd)
- {
- log_error ("keydb_new failed\n");
- goto leave;
- }
-
- if (!names)
- ndesc = 1;
- else
- {
- for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
- ;
- }
-
- desc = xtrycalloc (ndesc, sizeof *desc);
- if (!ndesc)
- {
- log_error ("out of core\n");
- goto leave;
- }
-
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
- else
- {
- for (ndesc=0, sl=names; sl; sl = sl->next)
- {
- rc = keydb_classify_name (sl->d, desc+ndesc);
- if (rc)
- {
- log_error ("key `%s' not found: %s\n",
- sl->d, gpg_strerror (rc));
- rc = 0;
- }
- else
- ndesc++;
- }
-
- }
-
- /* it would be nice to see which of the given users did actually
- match one in the keyring. To implement this we need to have a
- found flag for each entry in desc and to set this we must check
- all those entries after a match to mark all matched one -
- currently we stop at the first match. To do this we need an
- extra flag to enable this feature so */
-
- lastresname = NULL;
- while (!(rc = keydb_search (hd, desc, ndesc)))
- {
- if (!names)
- desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
-
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- resname = keydb_get_resource_name (hd);
-
- if (lastresname != resname )
- {
- int i;
-
- if (ctrl->no_server)
- {
- fprintf (fp, "%s\n", resname );
- for (i=strlen(resname); i; i-- )
- putchar('-');
- putc ('\n', fp);
- lastresname = resname;
- }
- }
-
- have_secret = 0;
- if (mode)
- {
- char *p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- if (!gpgsm_agent_havekey (p))
- have_secret = 1;
- xfree (p);
- }
- }
-
- if (!mode
- || ((mode & 1) && !have_secret)
- || ((mode & 2) && have_secret) )
- {
- if (ctrl->with_colons)
- list_cert_colon (cert, fp, have_secret);
- else if (ctrl->with_chain)
- list_cert_chain (cert, fp);
- else
- {
- list_cert_std (cert, fp, have_secret);
- putc ('\n', fp);
- }
- }
- ksba_cert_release (cert);
- cert = NULL;
- }
- if (rc && rc != -1)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
-
- leave:
- ksba_cert_release (cert);
- xfree (desc);
- keydb_release (hd);
-}
-
-
-
-static void
-list_external_cb (void *cb_value, KsbaCert cert)
-{
- struct list_external_parm_s *parm = cb_value;
-
- if (keydb_store_cert (cert, 1, NULL))
- log_error ("error storing certificate as ephemeral\n");
-
- if (parm->print_header)
- {
- const char *resname = "[external keys]";
- int i;
-
- fprintf (parm->fp, "%s\n", resname );
- for (i=strlen(resname); i; i-- )
- putchar('-');
- putc ('\n', parm->fp);
- parm->print_header = 0;
- }
-
- if (parm->with_colons)
- list_cert_colon (cert, parm->fp, 0);
- else if (parm->with_chain)
- list_cert_chain (cert, parm->fp);
- else
- {
- list_cert_std (cert, parm->fp, 0);
- putc ('\n', parm->fp);
- }
-}
-
-
-/* List external keys similar to internal one. Note: mode does not
- make sense here because it would be unwise to list external secret
- keys */
-static void
-list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
-{
- int rc;
- struct list_external_parm_s parm;
-
- parm.fp = fp;
- parm.print_header = ctrl->no_server;
- parm.with_colons = ctrl->with_colons;
- parm.with_chain = ctrl->with_chain;
-
- rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
- if (rc)
- log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
-}
-
-/* List all keys or just the key given as NAMES.
- MODE controls the operation mode:
- Bit 0-2:
- 0 = list all public keys but don't flag secret ones
- 1 = list only public keys
- 2 = list only secret keys
- 3 = list secret and public keys
- Bit 6: list internal keys
- Bit 7: list external keys
- */
-void
-gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
-{
- if ((mode & (1<<6)))
- list_internal_keys (ctrl, names, fp, (mode & 3));
- if ((mode & (1<<7)))
- list_external_keys (ctrl, names, fp);
-}
diff --git a/sm/misc.c b/sm/misc.c
deleted file mode 100644
index 3260b90b2..000000000
--- a/sm/misc.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* misc.c - Miscellaneous fucntions
- * Copyright (C) 2001 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <ksba.h>
-
-#include "gpgsm.h"
-
diff --git a/sm/server.c b/sm/server.c
deleted file mode 100644
index dda150964..000000000
--- a/sm/server.c
+++ /dev/null
@@ -1,1070 +0,0 @@
-/* server.c - Server mode and main entry point
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include <assuan.h>
-
-#include "gpgsm.h"
-
-#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
-
-
-/* The filepointer for status message used in non-server mode */
-static FILE *statusfp;
-
-/* Data used to assuciate an Assuan context with local server data */
-struct server_local_s {
- ASSUAN_CONTEXT assuan_ctx;
- int message_fd;
- int list_internal;
- int list_external;
- CERTLIST recplist;
- CERTLIST signerlist;
-};
-
-
-
-/* note, that it is sufficient to allocate the target string D as
- long as the source string S, i.e.: strlen(s)+1; */
-static void
-strcpy_escaped_plus (char *d, const unsigned char *s)
-{
- while (*s)
- {
- if (*s == '%' && s[1] && s[2])
- {
- s++;
- *d++ = xtoi_2 ( s);
- s += 2;
- }
- else if (*s == '+')
- *d++ = ' ', s++;
- else
- *d++ = *s++;
- }
- *d = 0;
-}
-
-
-
-
-/* Check whether the option NAME appears in LINE */
-static int
-has_option (const char *line, const char *name)
-{
- const char *s;
- int n = strlen (name);
-
- s = strstr (line, name);
- return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
-
-
-static void
-close_message_fd (CTRL ctrl)
-{
- if (ctrl->server_local->message_fd != -1)
- {
- close (ctrl->server_local->message_fd);
- ctrl->server_local->message_fd = -1;
- }
-}
-
-
-static int
-option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (!strcmp (key, "include-certs"))
- {
- int i = *value? atoi (value) : -1;
- if (ctrl->include_certs < -2)
- return ASSUAN_Parameter_Error;
- ctrl->include_certs = i;
- }
- else if (!strcmp (key, "display"))
- {
- if (opt.display)
- free (opt.display);
- opt.display = strdup (value);
- if (!opt.display)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "ttyname"))
- {
- if (opt.ttyname)
- free (opt.ttyname);
- opt.ttyname = strdup (value);
- if (!opt.ttyname)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "ttytype"))
- {
- if (opt.ttytype)
- free (opt.ttytype);
- opt.ttytype = strdup (value);
- if (!opt.ttytype)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "lc-ctype"))
- {
- if (opt.lc_ctype)
- free (opt.lc_ctype);
- opt.lc_ctype = strdup (value);
- if (!opt.lc_ctype)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "lc-messages"))
- {
- if (opt.lc_messages)
- free (opt.lc_messages);
- opt.lc_messages = strdup (value);
- if (!opt.lc_messages)
- return ASSUAN_Out_Of_Core;
- }
- else if (!strcmp (key, "list-mode"))
- {
- int i = *value? atoi (value) : 0;
- if (!i || i == 1) /* default and mode 1 */
- {
- ctrl->server_local->list_internal = 1;
- ctrl->server_local->list_external = 0;
- }
- else if (i == 2)
- {
- ctrl->server_local->list_internal = 0;
- ctrl->server_local->list_external = 1;
- }
- else if (i == 3)
- {
- ctrl->server_local->list_internal = 1;
- ctrl->server_local->list_external = 1;
- }
- else
- return ASSUAN_Parameter_Error;
- }
- else
- return ASSUAN_Invalid_Option;
-
- return 0;
-}
-
-
-
-
-static void
-reset_notify (ASSUAN_CONTEXT ctx)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- gpgsm_release_certlist (ctrl->server_local->recplist);
- gpgsm_release_certlist (ctrl->server_local->signerlist);
- ctrl->server_local->recplist = NULL;
- ctrl->server_local->signerlist = NULL;
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-}
-
-
-static void
-input_notify (ASSUAN_CONTEXT ctx, const char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- ctrl->autodetect_encoding = 0;
- ctrl->is_pem = 0;
- ctrl->is_base64 = 0;
- if (strstr (line, "--armor"))
- ctrl->is_pem = 1;
- else if (strstr (line, "--base64"))
- ctrl->is_base64 = 1;
- else if (strstr (line, "--binary"))
- ;
- else
- ctrl->autodetect_encoding = 1;
-}
-
-static void
-output_notify (ASSUAN_CONTEXT ctx, const char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
-
- ctrl->create_pem = 0;
- ctrl->create_base64 = 0;
- if (strstr (line, "--armor"))
- ctrl->create_pem = 1;
- else if (strstr (line, "--base64"))
- ctrl->create_base64 = 1; /* just the raw output */
-}
-
-
-
-/* RECIPIENT <userID>
-
- Set the recipient for the encryption. <userID> should be the
- internal representation of the key; the server may accept any other
- way of specification [we will support this]. If this is a valid and
- trusted recipient the server does respond with OK, otherwise the
- return is an ERR with the reason why the recipient can't be used,
- the encryption will then not be done for this recipient. IF the
- policy is not to encrypt at all if not all recipients are valid, the
- client has to take care of this. All RECIPIENT commands are
- cumulative until a RESET or an successful ENCRYPT command. */
-static int
-cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
-
- rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist);
- if (rc)
- {
- gpg_err_code_t r = gpg_err_code (rc);
- gpgsm_status2 (ctrl, STATUS_INV_RECP,
- r == -1? "1":
- r == GPG_ERR_NO_PUBKEY? "1":
- r == GPG_ERR_AMBIGUOUS_NAME? "2":
- r == GPG_ERR_WRONG_KEY_USAGE? "3":
- r == GPG_ERR_CERT_REVOKED? "4":
- r == GPG_ERR_CERT_EXPIRED? "5":
- r == GPG_ERR_NO_CRL_KNOWN? "6":
- r == GPG_ERR_CRL_TOO_OLD? "7":
- r == GPG_ERR_NO_POLICY_MATCH? "8":
- "0",
- line, NULL);
- }
-
- return map_to_assuan_status (rc);
-}
-
-/* SIGNER <userID>
-
- Set the signer's keys for the signature creation. <userID> should
- be the internal representation of the key; the server may accept any
- other way of specification [we will support this]. If this is a
- valid and usable signing key the server does respond with OK,
- otherwise it returns an ERR with the reason why the key can't be
- used, the signing will then not be done for this key. If the policy
- is not to sign at all if not all signer keys are valid, the client
- has to take care of this. All SIGNER commands are cumulative until
- a RESET but they are *not* reset by an SIGN command becuase it can
- be expected that set of signers are used for more than one sign
- operation.
-
- Note that this command returns an INV_RECP status which is a bit
- strange, but they are very similar. */
-static int
-cmd_signer (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
-
- rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist);
- if (rc)
- {
- gpg_err_code_t r = gpg_err_code (rc);
- gpgsm_status2 (ctrl, STATUS_INV_RECP,
- r == -1? "1":
- r == GPG_ERR_NO_PUBKEY? "1":
- r == GPG_ERR_AMBIGUOUS_NAME? "2":
- r == GPG_ERR_WRONG_KEY_USAGE? "3":
- r == GPG_ERR_CERT_REVOKED? "4":
- r == GPG_ERR_CERT_EXPIRED? "5":
- r == GPG_ERR_NO_CRL_KNOWN? "6":
- r == GPG_ERR_CRL_TOO_OLD? "7":
- r == GPG_ERR_NO_POLICY_MATCH? "8":
- r == GPG_ERR_NO_SECKEY? "9":
- "0",
- line, NULL);
- }
- return map_to_assuan_status (rc);
-}
-
-
-/* ENCRYPT
-
- Do the actual encryption process. Takes the plaintext from the INPUT
- command, writes to the ciphertext to the file descriptor set with
- the OUTPUT command, take the recipients form all the recipients set
- so far. If this command fails the clients should try to delete all
- output currently done or otherwise mark it as invalid. GPGSM does
- ensure that there won't be any security problem with leftover data
- on the output in this case.
-
- This command should in general not fail, as all necessary checks
- have been done while setting the recipients. The input and output
- pipes are closed. */
-static int
-cmd_encrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_encrypt (assuan_get_pointer (ctx),
- ctrl->server_local->recplist,
- inp_fd, out_fp);
- fclose (out_fp);
-
- gpgsm_release_certlist (ctrl->server_local->recplist);
- ctrl->server_local->recplist = NULL;
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
- return map_to_assuan_status (rc);
-}
-
-/* DECRYPT
-
- This performs the decrypt operation after doing some check on the
- internal state. (e.g. that only needed data has been set). Because
- it utilizes the GPG-Agent for the session key decryption, there is
- no need to ask the client for a protecting passphrase - GpgAgent
- does take care of this by requesting this from the user. */
-static int
-cmd_decrypt (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* VERIFY
-
- This does a verify operation on the message send to the input-FD.
- The result is written out using status lines. If an output FD was
- given, the signed text will be written to that.
-
- If the signature is a detached one, the server will inquire about
- the signed material and the client must provide it.
- */
-static int
-cmd_verify (ASSUAN_CONTEXT ctx, char *line)
-{
- int rc;
- CTRL ctrl = assuan_get_pointer (ctx);
- int fd = assuan_get_input_fd (ctx);
- int out_fd = assuan_get_output_fd (ctx);
- FILE *out_fp = NULL;
-
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- if (out_fd != -1)
- {
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- }
-
- rc = gpgsm_verify (assuan_get_pointer (ctx), fd,
- ctrl->server_local->message_fd, out_fp);
- if (out_fp)
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* SIGN [--detached]
-
- Sign the data set with the INPUT command and write it to the sink
- set by OUTPUT. With "--detached" specified, a detached signature is
- created (surprise). */
-static int
-cmd_sign (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int detached;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- detached = has_option (line, "--detached");
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
-
- rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
- inp_fd, detached, out_fp);
- fclose (out_fp);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-/* IMPORT
-
- Import the certificates read form the input-fd, return status
- message for each imported one. The import checks the validity of
- the certificate but not of the entire chain. It is possible to
- import expired certificates. */
-static int
-cmd_import (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int rc;
- int fd = assuan_get_input_fd (ctx);
-
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- rc = gpgsm_import (assuan_get_pointer (ctx), fd);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-static int
-cmd_export (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int fd = assuan_get_output_fd (ctx);
- FILE *out_fp;
- char *p;
- STRLIST list, sl;
-
- if (fd == -1)
- return set_error (No_Output, NULL);
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- out_fp = fdopen ( dup(fd), "w");
- if (!out_fp)
- {
- free_strlist (list);
- return set_error (General_Error, "fdopen() failed");
- }
-
- gpgsm_export (ctrl, list, out_fp);
- fclose (out_fp);
- free_strlist (list);
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
- return 0;
-}
-
-
-static int
-cmd_delkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- char *p;
- STRLIST list, sl;
- int rc;
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- rc = gpgsm_delete (ctrl, list);
- free_strlist (list);
-
- /* close and reset the fd */
- close_message_fd (ctrl);
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-
-/* MESSAGE FD=<n>
-
- Set the file descriptor to read a message which is used with
- detached signatures */
-static int
-cmd_message (ASSUAN_CONTEXT ctx, char *line)
-{
- char *endp;
- int fd;
- CTRL ctrl = assuan_get_pointer (ctx);
-
- if (strncmp (line, "FD=", 3))
- return set_error (Syntax_Error, "FD=<n> expected");
- line += 3;
- if (!digitp (line))
- return set_error (Syntax_Error, "number required");
- fd = strtoul (line, &endp, 10);
- if (*endp)
- return set_error (Syntax_Error, "garbage found");
- if (fd == -1)
- return set_error (No_Input, NULL);
-
- ctrl->server_local->message_fd = fd;
- return 0;
-}
-
-
-static int
-do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- FILE *fp = assuan_get_data_fp (ctx);
- char *p;
- STRLIST list, sl;
- unsigned int listmode;
-
- if (!fp)
- return set_error (General_Error, "no data stream");
-
- /* break the line down into an STRLIST */
- list = NULL;
- for (p=line; *p; line = p)
- {
- while (*p && *p != ' ')
- p++;
- if (*p)
- *p++ = 0;
- if (*line)
- {
- sl = xtrymalloc (sizeof *sl + strlen (line));
- if (!sl)
- {
- free_strlist (list);
- return ASSUAN_Out_Of_Core;
- }
- sl->flags = 0;
- strcpy_escaped_plus (sl->d, line);
- sl->next = list;
- list = sl;
- }
- }
-
- ctrl->with_colons = 1;
- listmode = mode;
- if (ctrl->server_local->list_internal)
- listmode |= (1<<6);
- if (ctrl->server_local->list_external)
- listmode |= (1<<7);
- gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
- free_strlist (list);
- return 0;
-}
-
-static int
-cmd_listkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- return do_listkeys (ctx, line, 3);
-}
-
-static int
-cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line)
-{
- return do_listkeys (ctx, line, 2);
-}
-
-
-/* GENKEY
-
- Read the parameters in native format from the input fd and write a
- certificate request to the output.
- */
-static int
-cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
-{
- CTRL ctrl = assuan_get_pointer (ctx);
- int inp_fd, out_fd;
- FILE *out_fp;
- int rc;
-
- inp_fd = assuan_get_input_fd (ctx);
- if (inp_fd == -1)
- return set_error (No_Input, NULL);
- out_fd = assuan_get_output_fd (ctx);
- if (out_fd == -1)
- return set_error (No_Output, NULL);
-
- out_fp = fdopen ( dup(out_fd), "w");
- if (!out_fp)
- return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_genkey (ctrl, inp_fd, out_fp);
- fclose (out_fp);
-
- /* close and reset the fds */
- assuan_close_input_fd (ctx);
- assuan_close_output_fd (ctx);
-
- return map_to_assuan_status (rc);
-}
-
-
-
-
-
-/* Tell the assuan library about our commands */
-static int
-register_commands (ASSUAN_CONTEXT ctx)
-{
- static struct {
- const char *name;
- int (*handler)(ASSUAN_CONTEXT, char *line);
- } table[] = {
- { "RECIPIENT", cmd_recipient },
- { "SIGNER", cmd_signer },
- { "ENCRYPT", cmd_encrypt },
- { "DECRYPT", cmd_decrypt },
- { "VERIFY", cmd_verify },
- { "SIGN", cmd_sign },
- { "IMPORT", cmd_import },
- { "EXPORT", cmd_export },
- { "INPUT", NULL },
- { "OUTPUT", NULL },
- { "MESSAGE", cmd_message },
- { "LISTKEYS", cmd_listkeys },
- { "LISTSECRETKEYS",cmd_listsecretkeys },
- { "GENKEY", cmd_genkey },
- { "DELKEYS", cmd_delkeys },
- { NULL }
- };
- int i, rc;
-
- for (i=0; table[i].name; i++)
- {
- rc = assuan_register_command (ctx, table[i].name, table[i].handler);
- if (rc)
- return rc;
- }
- return 0;
-}
-
-/* Startup the server */
-void
-gpgsm_server (void)
-{
- int rc;
- int filedes[2];
- ASSUAN_CONTEXT ctx;
- struct server_control_s ctrl;
-
- memset (&ctrl, 0, sizeof ctrl);
- gpgsm_init_default_ctrl (&ctrl);
-
- /* For now we use a simple pipe based server so that we can work
- from scripts. We will later add options to run as a daemon and
- wait for requests on a Unix domain socket */
- filedes[0] = 0;
- filedes[1] = 1;
- rc = assuan_init_pipe_server (&ctx, filedes);
- if (rc)
- {
- log_error ("failed to initialize the server: %s\n",
- assuan_strerror(rc));
- gpgsm_exit (2);
- }
- rc = register_commands (ctx);
- if (rc)
- {
- log_error ("failed to the register commands with Assuan: %s\n",
- assuan_strerror(rc));
- gpgsm_exit (2);
- }
- assuan_set_hello_line (ctx, "GNU Privacy Guard's S/M server ready");
-
- assuan_register_reset_notify (ctx, reset_notify);
- assuan_register_input_notify (ctx, input_notify);
- assuan_register_output_notify (ctx, output_notify);
- assuan_register_option_handler (ctx, option_handler);
-
- assuan_set_pointer (ctx, &ctrl);
- ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
- ctrl.server_local->assuan_ctx = ctx;
- ctrl.server_local->message_fd = -1;
- ctrl.server_local->list_internal = 1;
- ctrl.server_local->list_external = 0;
-
- if (DBG_ASSUAN)
- assuan_set_log_stream (ctx, log_get_stream ());
-
- for (;;)
- {
- rc = assuan_accept (ctx);
- if (rc == -1)
- {
- break;
- }
- else if (rc)
- {
- log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
- break;
- }
-
- rc = assuan_process (ctx);
- if (rc)
- {
- log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
- continue;
- }
- }
-
- gpgsm_release_certlist (ctrl.server_local->recplist);
- ctrl.server_local->recplist = NULL;
- gpgsm_release_certlist (ctrl.server_local->signerlist);
- ctrl.server_local->signerlist = NULL;
-
- assuan_deinit_server (ctx);
-}
-
-
-static const char *
-get_status_string ( int no )
-{
- const char *s;
-
- switch (no)
- {
- case STATUS_ENTER : s = "ENTER"; break;
- case STATUS_LEAVE : s = "LEAVE"; break;
- case STATUS_ABORT : s = "ABORT"; break;
- case STATUS_GOODSIG: s = "GOODSIG"; break;
- case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break;
- case STATUS_KEYREVOKED: s = "KEYREVOKED"; break;
- case STATUS_BADSIG : s = "BADSIG"; break;
- case STATUS_ERRSIG : s = "ERRSIG"; break;
- case STATUS_BADARMOR : s = "BADARMOR"; break;
- case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break;
- case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break;
- case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break;
- case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break;
- case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break;
- case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break;
- case STATUS_GET_BOOL : s = "GET_BOOL"; break;
- case STATUS_GET_LINE : s = "GET_LINE"; break;
- case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break;
- case STATUS_GOT_IT : s = "GOT_IT"; break;
- case STATUS_SHM_INFO : s = "SHM_INFO"; break;
- case STATUS_SHM_GET : s = "SHM_GET"; break;
- case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break;
- case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break;
- case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break;
- case STATUS_VALIDSIG : s = "VALIDSIG"; break;
- case STATUS_SIG_ID : s = "SIG_ID"; break;
- case STATUS_ENC_TO : s = "ENC_TO"; break;
- case STATUS_NODATA : s = "NODATA"; break;
- case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break;
- case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break;
- case STATUS_NO_SECKEY : s = "NO_SECKEY"; break;
- case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break;
- case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break;
- case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break;
- case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break;
- case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break;
- case STATUS_GOODMDC : s = "GOODMDC"; break;
- case STATUS_BADMDC : s = "BADMDC"; break;
- case STATUS_ERRMDC : s = "ERRMDC"; break;
- case STATUS_IMPORTED : s = "IMPORTED"; break;
- case STATUS_IMPORT_RES : s = "IMPORT_RES"; break;
- case STATUS_FILE_START : s = "FILE_START"; break;
- case STATUS_FILE_DONE : s = "FILE_DONE"; break;
- case STATUS_FILE_ERROR : s = "FILE_ERROR"; break;
- case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break;
- case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break;
- case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break;
- case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break;
- case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break;
- case STATUS_PROGRESS : s = "PROGRESS"; break;
- case STATUS_SIG_CREATED : s = "SIG_CREATED"; break;
- case STATUS_SESSION_KEY : s = "SESSION_KEY"; break;
- case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break;
- case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break;
- case STATUS_POLICY_URL : s = "POLICY_URL" ; break;
- case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break;
- case STATUS_END_STREAM : s = "END_STREAM"; break;
- case STATUS_KEY_CREATED : s = "KEY_CREATED"; break;
- case STATUS_UNEXPECTED : s = "UNEXPECTED"; break;
- case STATUS_INV_RECP : s = "INV_RECP"; break;
- case STATUS_NO_RECP : s = "NO_RECP"; break;
- case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break;
- case STATUS_EXPSIG : s = "EXPSIG"; break;
- case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break;
- case STATUS_TRUNCATED : s = "TRUNCATED"; break;
- case STATUS_ERROR : s = "ERROR"; break;
- case STATUS_IMPORT_PROBLEM : s = "IMPORT_PROBLEM"; break;
- default: s = "?"; break;
- }
- return s;
-}
-
-
-void
-gpgsm_status2 (CTRL ctrl, int no, ...)
-{
- va_list arg_ptr;
- const char *text;
-
- va_start (arg_ptr, no);
-
- if (ctrl->no_server)
- {
- if (ctrl->status_fd == -1)
- return; /* no status wanted */
- if (!statusfp)
- {
- if (ctrl->status_fd == 1)
- statusfp = stdout;
- else if (ctrl->status_fd == 2)
- statusfp = stderr;
- else
- statusfp = fdopen (ctrl->status_fd, "w");
-
- if (!statusfp)
- {
- log_fatal ("can't open fd %d for status output: %s\n",
- ctrl->status_fd, strerror(errno));
- }
- }
-
- fputs ("[GNUPG:] ", statusfp);
- fputs (get_status_string (no), statusfp);
-
- while ( (text = va_arg (arg_ptr, const char*) ))
- {
- putc ( ' ', statusfp );
- for (; *text; text++)
- {
- if (*text == '\n')
- fputs ( "\\n", statusfp );
- else if (*text == '\r')
- fputs ( "\\r", statusfp );
- else
- putc ( *(const byte *)text, statusfp );
- }
- }
- putc ('\n', statusfp);
- fflush (statusfp);
- }
- else
- {
- ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
- char buf[950], *p;
- size_t n;
-
- p = buf;
- n = 0;
- while ( (text = va_arg (arg_ptr, const char *)) )
- {
- if (n)
- {
- *p++ = ' ';
- n++;
- }
- for ( ; *text && n < DIM (buf)-2; n++)
- *p++ = *text++;
- }
- *p = 0;
- assuan_write_status (ctx, get_status_string (no), buf);
- }
-
- va_end (arg_ptr);
-}
-
-void
-gpgsm_status (CTRL ctrl, int no, const char *text)
-{
- gpgsm_status2 (ctrl, no, text, NULL);
-}
-
-void
-gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text,
- gpg_err_code_t ec)
-{
- char buf[30];
-
- sprintf (buf, "%u", (unsigned int)ec);
- if (text)
- gpgsm_status2 (ctrl, no, text, buf, NULL);
- else
- gpgsm_status2 (ctrl, no, buf, NULL);
-}
-
-#if 0
-/*
- * Write a status line with a buffer using %XX escapes. If WRAP is >
- * 0 wrap the line after this length. If STRING is not NULL it will
- * be prepended to the buffer, no escaping is done for string.
- * A wrap of -1 forces spaces not to be encoded as %20.
- */
-void
-write_status_text_and_buffer ( int no, const char *string,
- const char *buffer, size_t len, int wrap )
-{
- const char *s, *text;
- int esc, first;
- int lower_limit = ' ';
- size_t n, count, dowrap;
-
- if( !statusfp )
- return; /* not enabled */
-
- if (wrap == -1) {
- lower_limit--;
- wrap = 0;
- }
-
- text = get_status_string (no);
- count = dowrap = first = 1;
- do {
- if (dowrap) {
- fprintf (statusfp, "[GNUPG:] %s ", text );
- count = dowrap = 0;
- if (first && string) {
- fputs (string, statusfp);
- count += strlen (string);
- }
- first = 0;
- }
- for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) {
- if ( *s == '%' || *(const byte*)s <= lower_limit
- || *(const byte*)s == 127 )
- esc = 1;
- if ( wrap && ++count > wrap ) {
- dowrap=1;
- break;
- }
- }
- if (esc) {
- s--; n++;
- }
- if (s != buffer)
- fwrite (buffer, s-buffer, 1, statusfp );
- if ( esc ) {
- fprintf (statusfp, "%%%02X", *(const byte*)s );
- s++; n--;
- }
- buffer = s;
- len = n;
- if ( dowrap && len )
- putc ( '\n', statusfp );
- } while ( len );
-
- putc ('\n',statusfp);
- fflush (statusfp);
-}
-#endif
diff --git a/sm/sign.c b/sm/sign.c
deleted file mode 100644
index 0afb52b62..000000000
--- a/sm/sign.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/* sign.c - Sign a message
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-
-static void
-hash_data (int fd, gcry_md_hd_t md)
-{
- FILE *fp;
- char buffer[4096];
- int nread;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- gcry_md_write (md, buffer, nread);
- }
- while (nread);
- if (ferror (fp))
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- fclose (fp);
-}
-
-static int
-hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer)
-{
- KsbaError err;
- FILE *fp;
- char buffer[4096];
- int nread;
- int rc = 0;
- int any = 0;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return tmperr;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- if (nread)
- {
- any = 1;
- gcry_md_write (md, buffer, nread);
- err = ksba_writer_write_octet_string (writer, buffer, nread, 0);
- if (err)
- {
- log_error ("write failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- }
- }
- }
- while (nread && !rc);
- if (ferror (fp))
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- }
- fclose (fp);
- if (!any)
- {
- /* We can't allow to sign an empty message because it does not
- make much sense and more seriously, ksba-cms_build has
- already written the tag for data and now expects an octet
- string but an octet string of zeize 0 is illegal. */
- log_error ("cannot sign an empty message\n");
- rc = gpg_error (GPG_ERR_NO_DATA);
- }
- if (!rc)
- {
- err = ksba_writer_write_octet_string (writer, NULL, 0, 1);
- if (err)
- {
- log_error ("write failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- }
- }
-
- return rc;
-}
-
-
-/* Get the default certificate which is defined as the first one our
- keyDB retruns and has a secret key available */
-int
-gpgsm_get_default_cert (KsbaCert *r_cert)
-{
- KEYDB_HANDLE hd;
- KsbaCert cert = NULL;
- int rc;
- char *p;
-
- hd = keydb_new (0);
- if (!hd)
- return gpg_error (GPG_ERR_GENERAL);
- rc = keydb_search_first (hd);
- if (rc)
- {
- keydb_release (hd);
- return rc;
- }
-
- do
- {
- rc = keydb_get_cert (hd, &cert);
- if (rc)
- {
- log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
- keydb_release (hd);
- return rc;
- }
-
- p = gpgsm_get_keygrip_hexstring (cert);
- if (p)
- {
- if (!gpgsm_agent_havekey (p))
- {
- xfree (p);
- keydb_release (hd);
- *r_cert = cert;
- return 0; /* got it */
- }
- xfree (p);
- }
-
- ksba_cert_release (cert);
- cert = NULL;
- }
- while (!(rc = keydb_search_next (hd)));
- if (rc && rc != -1)
- log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc));
-
- ksba_cert_release (cert);
- keydb_release (hd);
- return rc;
-}
-
-
-static KsbaCert
-get_default_signer (void)
-{
- KEYDB_SEARCH_DESC desc;
- KsbaCert cert = NULL;
- KEYDB_HANDLE kh = NULL;
- int rc;
-
- if (!opt.local_user)
- {
- rc = gpgsm_get_default_cert (&cert);
- if (rc)
- {
- if (rc != -1)
- log_debug ("failed to find default certificate: %s\n",
- gpg_strerror (rc));
- return NULL;
- }
- return cert;
- }
-
- rc = keydb_classify_name (opt.local_user, &desc);
- if (rc)
- {
- log_error ("failed to find default signer: %s\n", gpg_strerror (rc));
- return NULL;
- }
-
- kh = keydb_new (0);
- if (!kh)
- return NULL;
-
- rc = keydb_search (kh, &desc, 1);
- if (rc)
- {
- log_debug ("failed to find default certificate: rc=%d\n", rc);
- }
- else
- {
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_debug ("failed to get cert: rc=%d\n", rc);
- }
- }
-
- keydb_release (kh);
- return cert;
-}
-
-/* Depending on the options in CTRL add the certificate CERT as well as
- other certificate up in the chain to the Root-CA to the CMS
- object. */
-static int
-add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
-{
- KsbaError err;
- int rc = 0;
- KsbaCert next = NULL;
- int n;
- int not_root = 0;
-
- ksba_cert_ref (cert);
-
- n = ctrl->include_certs;
- if (n == -2)
- {
- not_root = 1;
- n = -1;
- }
- if (n < 0 || n > 50)
- n = 50; /* We better apply an upper bound */
-
- if (n)
- {
- if (not_root && gpgsm_is_root_cert (cert))
- err = 0;
- else
- err = ksba_cms_add_cert (cms, cert);
- if (err)
- goto ksba_failure;
- }
- while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) )
- {
- if (not_root && gpgsm_is_root_cert (next))
- err = 0;
- else
- err = ksba_cms_add_cert (cms, next);
- ksba_cert_release (cert);
- cert = next; next = NULL;
- if (err)
- goto ksba_failure;
- }
- ksba_cert_release (cert);
-
- return rc == -1? 0: rc;
-
- ksba_failure:
- ksba_cert_release (cert);
- log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err));
- return map_ksba_err (err);
-}
-
-
-
-
-/* Perform a sign operation.
-
- Sign the data received on DATA-FD in embedded mode or in detached
- mode when DETACHED is true. Write the signature to OUT_FP. The
- keys used to sign are taken from SIGNERLIST or the default one will
- be used if the value of this argument is NULL. */
-int
-gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
- int data_fd, int detached, FILE *out_fp)
-{
- int i, rc;
- KsbaError err;
- Base64Context b64writer = NULL;
- KsbaWriter writer;
- KsbaCMS cms = NULL;
- KsbaStopReason stopreason;
- KEYDB_HANDLE kh = NULL;
- gcry_md_hd_t data_md = NULL;
- int signer;
- const char *algoid;
- int algo;
- time_t signed_at;
- CERTLIST cl;
- int release_signerlist = 0;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
- ctrl->pem_name = "SIGNED MESSAGE";
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, NULL, writer);
- if (err)
- {
- log_debug ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* We are going to create signed data with data as encap. content */
- err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
- if (!err)
- err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
- if (err)
- {
- log_debug ("ksba_cms_set_content_type failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* If no list of signers is given, use a default one. */
- if (!signerlist)
- {
- KsbaCert cert = get_default_signer ();
- if (!cert)
- {
- log_error ("no default signer found\n");
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
- signerlist = xtrycalloc (1, sizeof *signerlist);
- if (!signerlist)
- {
- rc = OUT_OF_CORE (errno);
- ksba_cert_release (cert);
- goto leave;
- }
- signerlist->cert = cert;
- release_signerlist = 1;
- }
-
-
- /* Gather certificates of signers and store them in the CMS object. */
- for (cl=signerlist; cl; cl = cl->next)
- {
- rc = gpgsm_cert_use_sign_p (cl->cert);
- if (rc)
- goto leave;
-
- err = ksba_cms_add_signer (cms, cl->cert);
- if (err)
- {
- log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- rc = add_certificate_list (ctrl, cms, cl->cert);
- if (rc)
- {
- log_error ("failed to store list of certificates: %s\n",
- gpg_strerror(rc));
- goto leave;
- }
- /* Set the hash algorithm we are going to use */
- err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
- if (err)
- {
- log_debug ("ksba_cms_add_digest_algo failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
-
- /* Prepare hashing (actually we are figuring out what we have set above)*/
- rc = gcry_md_open (&data_md, 0, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (data_md, "sign.data");
-
- for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
- {
- algo = gcry_md_map_name (algoid);
- if (!algo)
- {
- log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- gcry_md_enable (data_md, algo);
- }
-
- if (detached)
- { /* we hash the data right now so that we can store the message
- digest. ksba_cms_build() takes this as an flag that detached
- data is expected. */
- unsigned char *digest;
- size_t digest_len;
- /* Fixme do this for all signers and get the algo to use from
- the signer's certificate - does not make mich sense, bu we
- should do this consistent as we have already done it above */
- algo = GCRY_MD_SHA1;
- hash_data (data_fd, data_md);
- digest = gcry_md_read (data_md, algo);
- digest_len = gcry_md_get_algo_dlen (algo);
- if ( !digest || !digest_len)
- {
- log_error ("problem getting the hash of the data\n");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
- if (err)
- {
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
- }
-
- signed_at = gnupg_get_time ();
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_signing_time (cms, signer, signed_at);
- if (err)
- {
- log_error ("ksba_cms_set_signing_time failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
-
- do
- {
- err = ksba_cms_build (cms, &stopreason);
- if (err)
- {
- log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- if (stopreason == KSBA_SR_BEGIN_DATA)
- { /* hash the data and store the message digest */
- unsigned char *digest;
- size_t digest_len;
-
- assert (!detached);
- /* Fixme: get the algo to use from the signer's certificate
- - does not make much sense, but we should do this
- consistent as we have already done it above. Code is
- mostly duplicated above. */
-
- algo = GCRY_MD_SHA1;
- rc = hash_and_copy_data (data_fd, data_md, writer);
- if (rc)
- goto leave;
- digest = gcry_md_read (data_md, algo);
- digest_len = gcry_md_get_algo_dlen (algo);
- if ( !digest || !digest_len)
- {
- log_error ("problem getting the hash of the data\n");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- err = ksba_cms_set_message_digest (cms, signer,
- digest, digest_len);
- if (err)
- {
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- }
- }
- else if (stopreason == KSBA_SR_NEED_SIG)
- { /* calculate the signature for all signers */
- gcry_md_hd_t md;
-
- algo = GCRY_MD_SHA1;
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "sign.attr");
- ksba_cms_set_hash_function (cms, HASH_FNC, md);
- for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
- {
- char *sigval = NULL;
- char *buf, *fpr;
-
- if (signer)
- gcry_md_reset (md);
- rc = ksba_cms_hash_signed_attrs (cms, signer);
- if (rc)
- {
- log_debug ("hashing signed attrs failed: %s\n",
- ksba_strerror (rc));
- gcry_md_close (md);
- goto leave;
- }
-
- rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval);
- if (rc)
- {
- gcry_md_close (md);
- goto leave;
- }
-
- err = ksba_cms_set_sig_val (cms, signer, sigval);
- xfree (sigval);
- if (err)
- {
- log_error ("failed to store the signature: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- gcry_md_close (md);
- goto leave;
- }
-
- /* write a status message */
- fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1);
- if (!fpr)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- gcry_md_close (md);
- goto leave;
- }
- rc = asprintf (&buf, "%c %d %d 00 %lu %s",
- detached? 'D':'S',
- GCRY_PK_RSA, /* FIXME: get pk algo from cert */
- algo,
- (ulong)signed_at,
- fpr);
- xfree (fpr);
- if (rc < 0)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- gcry_md_close (md);
- goto leave;
- }
- rc = 0;
- gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
- free (buf); /* yes, we must use the regular free() here */
- }
- gcry_md_close (md);
-
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- log_info ("signature created\n");
-
-
- leave:
- if (release_signerlist)
- gpgsm_release_certlist (signerlist);
- ksba_cms_release (cms);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- gcry_md_close (data_md);
- return rc;
-}
diff --git a/sm/verify.c b/sm/verify.c
deleted file mode 100644
index 6dd4f4e5b..000000000
--- a/sm/verify.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* verify.c - Verify a messages signature
- * Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <assert.h>
-
-#include "gpgsm.h"
-#include <gcrypt.h>
-#include <ksba.h>
-
-#include "keydb.h"
-#include "i18n.h"
-
-static char *
-strtimestamp_r (time_t atime)
-{
- char *buffer = xmalloc (15);
-
- if (atime < 0)
- strcpy (buffer, "????" "-??" "-??");
- else if (!atime)
- strcpy (buffer, "none");
- else
- {
- struct tm *tp;
-
- tp = gmtime( &atime );
- sprintf (buffer, "%04d-%02d-%02d",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday);
- }
- return buffer;
-}
-
-
-
-/* Hash the data for a detached signature */
-static void
-hash_data (int fd, gcry_md_hd_t md)
-{
- FILE *fp;
- char buffer[4096];
- int nread;
-
- fp = fdopen ( dup (fd), "rb");
- if (!fp)
- {
- log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
- return;
- }
-
- do
- {
- nread = fread (buffer, 1, DIM(buffer), fp);
- gcry_md_write (md, buffer, nread);
- }
- while (nread);
- if (ferror (fp))
- log_error ("read error on fd %d: %s\n", fd, strerror (errno));
- fclose (fp);
-}
-
-
-
-
-/* Perform a verify operation. To verify detached signatures, data_fd
- must be different than -1. With OUT_FP given and a non-detached
- signature, the signed material is written to that stream. */
-int
-gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
-{
- int i, rc;
- Base64Context b64reader = NULL;
- Base64Context b64writer = NULL;
- KsbaError err;
- KsbaReader reader;
- KsbaWriter writer = NULL;
- KsbaCMS cms = NULL;
- KsbaStopReason stopreason;
- KsbaCert cert;
- KEYDB_HANDLE kh;
- gcry_md_hd_t data_md = NULL;
- int signer;
- const char *algoid;
- int algo;
- int is_detached;
- FILE *fp = NULL;
- char *p;
-
- kh = keydb_new (0);
- if (!kh)
- {
- log_error (_("failed to allocated keyDB handle\n"));
- rc = gpg_error (GPG_ERR_GENERAL);
- goto leave;
- }
-
-
- fp = fdopen ( dup (in_fd), "rb");
- if (!fp)
- {
- rc = gpg_error (gpg_err_code_from_errno (errno));
- log_error ("fdopen() failed: %s\n", strerror (errno));
- goto leave;
- }
-
- rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
- if (rc)
- {
- log_error ("can't create reader: %s\n", gpg_strerror (rc));
- goto leave;
- }
-
- if (out_fp)
- {
- rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
- if (rc)
- {
- log_error ("can't create writer: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- cms = ksba_cms_new ();
- if (!cms)
- {
- rc = gpg_error (GPG_ERR_ENOMEM);
- goto leave;
- }
-
- err = ksba_cms_set_reader_writer (cms, reader, writer);
- if (err)
- {
- log_error ("ksba_cms_set_reader_writer failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- rc = gcry_md_open (&data_md, 0, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (data_md, "vrfy.data");
-
- is_detached = 0;
- do
- {
- err = ksba_cms_parse (cms, &stopreason);
- if (err)
- {
- log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- if (stopreason == KSBA_SR_NEED_HASH)
- {
- is_detached = 1;
- if (opt.verbose)
- log_info ("detached signature\n");
- }
-
- if (stopreason == KSBA_SR_NEED_HASH
- || stopreason == KSBA_SR_BEGIN_DATA)
- { /* We are now able to enable the hash algorithms */
- for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
- {
- algo = gcry_md_map_name (algoid);
- if (!algo)
- log_error ("unknown hash algorithm `%s'\n",
- algoid? algoid:"?");
- else
- gcry_md_enable (data_md, algo);
- }
- if (is_detached)
- {
- if (data_fd == -1)
- log_info ("detached signature w/o data "
- "- assuming certs-only\n");
- else
- hash_data (data_fd, data_md);
- }
- else
- {
- ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
- }
- }
- else if (stopreason == KSBA_SR_END_DATA)
- { /* The data bas been hashed */
-
- }
- }
- while (stopreason != KSBA_SR_READY);
-
- if (b64writer)
- {
- rc = gpgsm_finish_writer (b64writer);
- if (rc)
- {
- log_error ("write failed: %s\n", gpg_strerror (rc));
- goto leave;
- }
- }
-
- if (data_fd != -1 && !is_detached)
- {
- log_error ("data given for a non-detached signature\n");
- rc = gpg_error (GPG_ERR_CONFLICT);
- goto leave;
- }
-
- for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
- {
- /* Fixme: it might be better to check the validity of the
- certificate first before entering it into the DB. This way
- we would avoid cluttering the DB with invalid
- certificates. */
- keydb_store_cert (cert, 0, NULL);
- ksba_cert_release (cert);
- }
-
- cert = NULL;
- err = 0;
- for (signer=0; ; signer++)
- {
- char *issuer = NULL;
- KsbaSexp sigval = NULL;
- time_t sigtime, keyexptime;
- KsbaSexp serial;
- char *msgdigest = NULL;
- size_t msgdigestlen;
- char *ctattr;
-
- err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
- if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached)
- {
- log_info ("certs-only message accepted\n");
- err = 0;
- break;
- }
- if (err)
- {
- if (signer && err == -1)
- err = 0;
- break;
- }
- if (DBG_X509)
- {
- log_debug ("signer %d - issuer: `%s'\n",
- signer, issuer? issuer:"[NONE]");
- log_debug ("signer %d - serial: ", signer);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
- }
-
- err = ksba_cms_get_signing_time (cms, signer, &sigtime);
- if (err == KSBA_No_Data)
- sigtime = 0;
- else if (err)
- {
- log_error ("error getting signing time: %s\n", ksba_strerror (err));
- sigtime = (time_t)-1;
- }
-
- err = ksba_cms_get_message_digest (cms, signer,
- &msgdigest, &msgdigestlen);
- if (!err)
- {
- algoid = ksba_cms_get_digest_algo (cms, signer);
- algo = gcry_md_map_name (algoid);
- if (DBG_X509)
- log_debug ("signer %d - digest algo: %d\n", signer, algo);
- if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) )
- {
- log_error ("digest algo %d has not been enabled\n", algo);
- goto next_signer;
- }
- }
- else if (err == KSBA_No_Data)
- {
- assert (!msgdigest);
- err = 0;
- algoid = NULL;
- algo = 0;
- }
- else /* real error */
- break;
-
- err = ksba_cms_get_sigattr_oids (cms, signer,
- "1.2.840.113549.1.9.3",&ctattr);
- if (!err)
- {
- const char *s;
-
- if (DBG_X509)
- log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
- s = ksba_cms_get_content_oid (cms, 1);
- if (!s || strcmp (ctattr, s))
- {
- log_error ("content-type attribute does not match "
- "actual content-type\n");
- ksba_free (ctattr);
- ctattr = NULL;
- goto next_signer;
- }
- ksba_free (ctattr);
- ctattr = NULL;
- }
- else if (err != -1)
- {
- log_error ("error getting content-type attribute: %s\n",
- ksba_strerror (err));
- goto next_signer;
- }
- err = 0;
-
-
- sigval = ksba_cms_get_sig_val (cms, signer);
- if (!sigval)
- {
- log_error ("no signature value available\n");
- goto next_signer;
- }
- if (DBG_X509)
- log_debug ("signer %d - signature available", signer);
-
- /* Find the certificate of the signer */
- keydb_search_reset (kh);
- rc = keydb_search_issuer_sn (kh, issuer, serial);
- if (rc)
- {
- if (rc == -1)
- {
- log_error ("certificate not found\n");
- rc = gpg_error (GPG_ERR_NO_PUBKEY);
- }
- else
- log_error ("failed to find the certificate: %s\n",
- gpg_strerror(rc));
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc);
-
- gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
- numbuf, NULL);
- }
- /* fixme: we might want to append the issuer and serial
- using our standard notation */
- goto next_signer;
- }
-
- rc = keydb_get_cert (kh, &cert);
- if (rc)
- {
- log_error ("failed to get cert: %s\n", gpg_strerror (rc));
- goto next_signer;
- }
-
- log_info (_("Signature made "));
- if (sigtime)
- gpgsm_dump_time (sigtime);
- else
- log_printf (_("[date not given]"));
- log_printf (_(" using certificate ID %08lX\n"),
- gpgsm_get_short_fingerprint (cert));
-
-
- if (msgdigest)
- { /* Signed attributes are available. */
- gcry_md_hd_t md;
- unsigned char *s;
-
- /* check that the message digest in the signed attributes
- matches the one we calculated on the data */
- s = gcry_md_read (data_md, algo);
- if ( !s || !msgdigestlen
- || gcry_md_get_algo_dlen (algo) != msgdigestlen
- || !s || memcmp (s, msgdigest, msgdigestlen) )
- {
- char *fpr;
-
- log_error ("invalid signature: message digest attribute "
- "does not match calculated one\n");
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- gpgsm_status (ctrl, STATUS_BADSIG, fpr);
- xfree (fpr);
- goto next_signer;
- }
-
- rc = gcry_md_open (&md, algo, 0);
- if (rc)
- {
- log_error ("md_open failed: %s\n", gpg_strerror (rc));
- goto next_signer;
- }
- if (DBG_HASHING)
- gcry_md_start_debug (md, "vrfy.attr");
-
- ksba_cms_set_hash_function (cms, HASH_FNC, md);
- rc = ksba_cms_hash_signed_attrs (cms, signer);
- if (rc)
- {
- log_error ("hashing signed attrs failed: %s\n",
- ksba_strerror (rc));
- gcry_md_close (md);
- goto next_signer;
- }
- rc = gpgsm_check_cms_signature (cert, sigval, md, algo);
- gcry_md_close (md);
- }
- else
- {
- rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo);
- }
-
- if (rc)
- {
- char *fpr;
-
- log_error ("invalid signature: %s\n", gpg_strerror (rc));
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- gpgsm_status (ctrl, STATUS_BADSIG, fpr);
- xfree (fpr);
- goto next_signer;
- }
- rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
- if (rc)
- {
- gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
- gpg_err_code (rc));
- rc = 0;
- }
-
- if (DBG_X509)
- log_debug ("signature okay - checking certs\n");
- rc = gpgsm_validate_chain (ctrl, cert, &keyexptime);
- if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
- {
- gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL);
- rc = 0;
- }
- else
- gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
-
- {
- char *buf, *fpr, *tstr;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
- tstr = strtimestamp_r (sigtime);
- buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120);
- sprintf (buf, "%s %s %lu %lu", fpr, tstr,
- (unsigned long)sigtime, (unsigned long)keyexptime );
- xfree (tstr);
- xfree (fpr);
- gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
- xfree (buf);
- }
-
- if (rc) /* of validate_chain */
- {
- log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
- if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
- || gpg_err_code (rc) == GPG_ERR_BAD_CERT
- || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
- || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
- gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
- gpg_err_code (rc));
- else
- gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL,
- gpg_err_code (rc));
- goto next_signer;
- }
-
- for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
- {
- log_info (!i? _("Good signature from")
- : _(" aka"));
- log_printf (" \"");
- gpgsm_print_name (log_get_stream (), p);
- log_printf ("\"\n");
- ksba_free (p);
- }
-
- gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL);
-
-
- next_signer:
- rc = 0;
- xfree (issuer);
- xfree (serial);
- xfree (sigval);
- xfree (msgdigest);
- ksba_cert_release (cert);
- cert = NULL;
- }
- rc = 0;
- if (err)
- {
- log_error ("ksba error: %s\n", ksba_strerror (err));
- rc = map_ksba_err (rc);
- }
-
-
-
- leave:
- ksba_cms_release (cms);
- gpgsm_destroy_reader (b64reader);
- gpgsm_destroy_writer (b64writer);
- keydb_release (kh);
- gcry_md_close (data_md);
- if (fp)
- fclose (fp);
-
- if (rc)
- {
- char numbuf[50];
- sprintf (numbuf, "%d", rc );
- gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
- numbuf, NULL);
- }
-
- return rc;
-}
-