From cvs at cvs.gnupg.org Mon Jul 1 21:17:46 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 01 Jul 2013 21:17:46 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.20-11-ga139884 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via a1398844adb84392f4a1da6db2e50b914a1aada1 (commit) via e0659690186f833e0e91b0a1cfef655c2d10ed87 (commit) via b4cb20cfc3fe2296a163355f386544096e48c147 (commit) via 4b4df62eaf7f46f83540536bfa373e78be2a6d7d (commit) via cf7f9303272db65465ff45348cf18f7298e41e30 (commit) via 901162579119585ebd3df9001b0370e6d32934ab (commit) via 336112e519079f43278a8ca8c2937417bc667d8f (commit) via fc7d033d8e62f6a289fdf7dba26af076accb5fd2 (commit) via 7ce72c97bfe1ab2f58248a6afe629aafa20d058b (commit) from 8ddf604659b93754ffa6dea295678a8adc293f90 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a1398844adb84392f4a1da6db2e50b914a1aada1 Author: Werner Koch Date: Mon Jul 1 20:49:50 2013 +0200 Update NEWS. -- diff --git a/NEWS b/NEWS index bf6e11c..4295ee9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Noteworthy changes in version 2.0.21 (unreleased) ------------------------------------------------- + * The included ssh agent does now support ECDSA keys. + + Noteworthy changes in version 2.0.20 (2013-05-10) ------------------------------------------------- commit e0659690186f833e0e91b0a1cfef655c2d10ed87 Author: Werner Koch Date: Mon Jul 1 20:34:55 2013 +0200 ssh: Mark unused arg. * agent/command-ssh.c (ssh_signature_encoder_ecdsa): Cast spec to void. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 826d175..5da1a71 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1248,6 +1248,8 @@ ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec, gpg_error_t err; int i; + (void)spec; + innerlen = 0; for (i = 0; i < DIM(data); i++) { commit b4cb20cfc3fe2296a163355f386544096e48c147 Author: Werner Koch Date: Wed Dec 12 18:47:21 2012 +0100 ssh: Support ECDSA keys. * agent/command-ssh.c (SPEC_FLAG_IS_ECDSA): New. (struct ssh_key_type_spec): Add fields CURVE_NAME and HASH_ALGO. (ssh_key_types): Add types ecdsa-sha2-nistp{256,384,521}. (ssh_signature_encoder_t): Add arg spec and adjust all callers. (ssh_signature_encoder_ecdsa): New. (sexp_key_construct, sexp_key_extract, ssh_receive_key) (ssh_convert_key_to_blob): Support ecdsa. (ssh_identifier_from_curve_name): New. (ssh_send_key_public): Retrieve and pass the curve_name. (key_secret_to_public): Ditto. (data_sign): Add arg SPEC and change callers to pass it. (ssh_handler_sign_request): Get the hash algo from SPEC. * common/ssh-utils.c (get_fingerprint): Support ecdsa. * agent/protect.c (protect_info): Add flag ECC_HACK. (agent_protect): Allow the use of the "curve" parameter. * agent/t-protect.c (test_agent_protect): Add a test case for ecdsa. * agent/command-ssh.c (ssh_key_grip): Print a better error code. -- The 3 standard curves are now supported in gpg-agent's ssh-agent protocol implementation. I tested this with all 3 curves and keys generated by OpenSSH 5.9p1. Using existing non-ssh generated keys will likely fail for now. To fix this, the code should first undergo some more cleanup; then the fixes are pretty straightforward. And yes, the data structures are way too complicated. (cherry picked from commit 649b31c663b8674bc874b4ef283d714a13dc8cfe) Solved conflicts: agent/protect.c agent/t-protect.c common/ssh-utils.c (different variabale name) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 6b73a5d..826d175 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -17,7 +17,18 @@ * along with this program; if not, see . */ -/* Only v2 of the ssh-agent protocol is implemented. */ +/* Only v2 of the ssh-agent protocol is implemented. Relevant RFCs + are: + + RFC-4250 - Protocol Assigned Numbers + RFC-4251 - Protocol Architecture + RFC-4252 - Authentication Protocol + RFC-4253 - Transport Layer Protocol + RFC-5656 - ECC support + + The protocol for the agent is defined in OpenSSH's PROTOCL.agent + file. + */ #include @@ -62,6 +73,7 @@ #define SSH_DSA_SIGNATURE_PADDING 20 #define SSH_DSA_SIGNATURE_ELEMS 2 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0) +#define SPEC_FLAG_IS_ECDSA (1 << 1) /* The name of the control file. */ #define SSH_CONTROL_FILE_NAME "sshcontrol" @@ -100,6 +112,10 @@ typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl, estream_t request, estream_t response); + +struct ssh_key_type_spec; +typedef struct ssh_key_type_spec ssh_key_type_spec_t; + /* Type, which is used for associating request handlers with the appropriate request IDs. */ typedef struct ssh_request_spec @@ -120,12 +136,13 @@ typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, /* The encoding of a generated signature is dependent on the algorithm; therefore algorithm specific signature encoding functions are necessary. */ -typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob, +typedef gpg_error_t (*ssh_signature_encoder_t) (ssh_key_type_spec_t *spec, + estream_t signature_blob, gcry_mpi_t *mpis); /* Type, which is used for boundling all the algorithm specific information together in a single object. */ -typedef struct ssh_key_type_spec +struct ssh_key_type_spec { /* Algorithm identifier as used by OpenSSH. */ const char *ssh_identifier; @@ -158,9 +175,16 @@ typedef struct ssh_key_type_spec algorithm. */ ssh_signature_encoder_t signature_encoder; + /* The name of the ECC curve or NULL. */ + const char *curve_name; + + /* The hash algorithm to be used with this key. 0 for using the + default. */ + int hash_algo; + /* Misc flags. */ unsigned int flags; -} ssh_key_type_spec_t; +}; /* An object used to access the sshcontrol file. */ @@ -205,10 +229,15 @@ static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, estream_t response); static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis); -static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob, +static gpg_error_t ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec, + estream_t signature_blob, gcry_mpi_t *mpis); -static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, +static gpg_error_t ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec, + estream_t signature_blob, gcry_mpi_t *mpis); +static gpg_error_t ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec, + estream_t signature_blob, + gcry_mpi_t *mpis); @@ -241,13 +270,29 @@ static ssh_key_type_spec_t ssh_key_types[] = { "ssh-rsa", "rsa", "nedupq", "en", "s", "nedpqu", ssh_key_modifier_rsa, ssh_signature_encoder_rsa, - SPEC_FLAG_USE_PKCS1V2 + NULL, 0, SPEC_FLAG_USE_PKCS1V2 }, { "ssh-dss", "dsa", "pqgyx", "pqgy", "rs", "pqgyx", NULL, ssh_signature_encoder_dsa, - 0 + NULL, 0, 0 + }, + { + "ecdsa-sha2-nistp256", "ecdsa", "qd", "q", "rs", "qd", + NULL, ssh_signature_encoder_ecdsa, + "nistp256", GCRY_MD_SHA256, SPEC_FLAG_IS_ECDSA }, + { + "ecdsa-sha2-nistp384", "ecdsa", "qd", "q", "rs", "qd", + NULL, ssh_signature_encoder_ecdsa, + "nistp384", GCRY_MD_SHA384, SPEC_FLAG_IS_ECDSA + }, + { + "ecdsa-sha2-nistp521", "ecdsa", "qd", "q", "rs", "qd", + NULL, ssh_signature_encoder_ecdsa, + "nistp521", GCRY_MD_SHA512, SPEC_FLAG_IS_ECDSA + } + }; @@ -342,6 +387,7 @@ stream_write_byte (estream_t stream, unsigned char b) return err; } + /* Read a uint32 from STREAM, store it in UINT32. */ static gpg_error_t stream_read_uint32 (estream_t stream, u32 *uint32) @@ -432,8 +478,9 @@ stream_write_data (estream_t stream, const unsigned char *buffer, size_t size) } /* Read a binary string from STREAM into STRING, store size of string - in STRING_SIZE; depending on SECURE use secure memory for - string. */ + in STRING_SIZE. Append a hidden nul so that the result may + directly be used as a C string. Depending on SECURE use secure + memory for STRING. */ static gpg_error_t stream_read_string (estream_t stream, unsigned int secure, unsigned char **string, u32 *string_size) @@ -1115,13 +1162,16 @@ ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis) /* Signature encoder function for RSA. */ static gpg_error_t -ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) +ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec, + estream_t signature_blob, gcry_mpi_t *mpis) { unsigned char *data; size_t data_n; gpg_error_t err; gcry_mpi_t s; + (void)spec; + s = mpis[0]; err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s); @@ -1139,7 +1189,8 @@ ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) /* Signature encoder function for DSA. */ static gpg_error_t -ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) +ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec, + estream_t signature_blob, gcry_mpi_t *mpis) { unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS]; unsigned char *data; @@ -1147,8 +1198,12 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) gpg_error_t err; int i; + (void)spec; + data = NULL; + /* FIXME: Why this complicated code? Why collecting boths mpis in a + buffer instead of writing them out one after the other? */ for (i = 0; i < 2; i++) { err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]); @@ -1181,23 +1236,63 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) return err; } + +/* Signature encoder function for ECDSA. */ +static gpg_error_t +ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec, + estream_t stream, gcry_mpi_t *mpis) +{ + unsigned char *data[2] = {NULL, NULL}; + size_t data_n[2]; + size_t innerlen; + gpg_error_t err; + int i; + + innerlen = 0; + for (i = 0; i < DIM(data); i++) + { + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &data[i], &data_n[i], mpis[i]); + if (err) + goto out; + innerlen += 4 + data_n[i]; + } + + err = stream_write_uint32 (stream, innerlen); + if (err) + goto out; + + for (i = 0; i < DIM(data); i++) + { + err = stream_write_string (stream, data[i], data_n[i]); + if (err) + goto out; + } + + out: + for (i = 0; i < DIM(data); i++) + xfree (data[i]); + return err; +} + + /* S-Expressions. */ /* This function constructs a new S-Expression for the key identified - by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in - *SEXP. Returns usual error code. */ + by the KEY_SPEC, SECRET, CURVE_NAME, MPIS, and COMMENT, which is to + be stored at R_SEXP. Returns an error code. */ static gpg_error_t sexp_key_construct (gcry_sexp_t *r_sexp, ssh_key_type_spec_t key_spec, int secret, - gcry_mpi_t *mpis, const char *comment) + const char *curve_name, gcry_mpi_t *mpis, + const char *comment) { const char *key_identifier[] = { "public-key", "private-key" }; gpg_error_t err; gcry_sexp_t sexp_new = NULL; - char *formatbuf = NULL; + void *formatbuf = NULL; void **arg_list = NULL; int arg_idx; estream_t format; @@ -1220,7 +1315,7 @@ sexp_key_construct (gcry_sexp_t *r_sexp, /* Key identifier, algorithm identifier, mpis, comment, and a NULL as a safeguard. */ - arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1 + 1)); + arg_list = xtrymalloc (sizeof (*arg_list) * (2 + 1 + elems_n + 1 + 1)); if (!arg_list) { err = gpg_error_from_syserror (); @@ -1231,6 +1326,11 @@ sexp_key_construct (gcry_sexp_t *r_sexp, es_fputs ("(%s(%s", format); arg_list[arg_idx++] = &key_identifier[secret]; arg_list[arg_idx++] = &key_spec.identifier; + if (curve_name) + { + es_fputs ("(curve%s)", format); + arg_list[arg_idx++] = &curve_name; + } for (i = 0; i < elems_n; i++) { @@ -1262,7 +1362,6 @@ sexp_key_construct (gcry_sexp_t *r_sexp, } format = NULL; - log_debug ("sexp formatbuf='%s' nargs=%d\n", formatbuf, arg_idx); err = gcry_sexp_build_array (&sexp_new, NULL, formatbuf, arg_list); if (err) goto out; @@ -1282,34 +1381,28 @@ sexp_key_construct (gcry_sexp_t *r_sexp, /* This functions breaks up the key contained in the S-Expression SEXP according to KEY_SPEC. The MPIs are bundled in a newly create list, which is to be stored in MPIS; a newly allocated string - holding the comment will be stored in COMMENT; SECRET will be - filled with a boolean flag specifying what kind of key it is. - Returns usual error code. */ + holding the curve name may be stored at RCURVE, and a comment will + be stored at COMMENT; SECRET will be filled with a boolean flag + specifying what kind of key it is. Returns an error code. */ static gpg_error_t sexp_key_extract (gcry_sexp_t sexp, ssh_key_type_spec_t key_spec, int *secret, - gcry_mpi_t **mpis, char **comment) + gcry_mpi_t **mpis, char **r_curve, char **comment) { - gpg_error_t err; - gcry_sexp_t value_list; - gcry_sexp_t value_pair; - gcry_sexp_t comment_list; + gpg_error_t err = 0; + gcry_sexp_t value_list = NULL; + gcry_sexp_t value_pair = NULL; + gcry_sexp_t comment_list = NULL; unsigned int i; - char *comment_new; + char *comment_new = NULL; const char *data; size_t data_n; int is_secret; size_t elems_n; const char *elems; - gcry_mpi_t *mpis_new; + gcry_mpi_t *mpis_new = NULL; gcry_mpi_t mpi; - - err = 0; - value_list = NULL; - value_pair = NULL; - comment_list = NULL; - comment_new = NULL; - mpis_new = NULL; + char *curve_name = NULL; data = gcry_sexp_nth_data (sexp, 0, &data_n); if (! data) @@ -1375,6 +1468,51 @@ sexp_key_extract (gcry_sexp_t sexp, if (err) goto out; + if ((key_spec.flags & SPEC_FLAG_IS_ECDSA)) + { + /* Parse the "curve" parameter. We currently expect the curve + name for ECC and not the parameters of the curve. This can + easily be changed but then we need to find the curve name + from the parameters using gcry_pk_get_curve. */ + const char *mapped; + + value_pair = gcry_sexp_find_token (value_list, "curve", 5); + if (!value_pair) + { + err = gpg_error (GPG_ERR_INV_CURVE); + goto out; + } + curve_name = gcry_sexp_nth_string (value_pair, 1); + if (!curve_name) + { + err = gpg_error (GPG_ERR_INV_CURVE); /* (Or out of core.) */ + goto out; + } + + /* Fixme: The mapping should be done by using gcry_pk_get_curve + et al to iterate over all name aliases. */ + if (!strcmp (curve_name, "NIST P-256")) + mapped = "nistp256"; + else if (!strcmp (curve_name, "NIST P-384")) + mapped = "nistp384"; + else if (!strcmp (curve_name, "NIST P-521")) + mapped = "nistp521"; + else + mapped = NULL; + if (mapped) + { + xfree (curve_name); + curve_name = xtrystrdup (mapped); + if (!curve_name) + { + err = gpg_error_from_syserror (); + goto out; + } + } + gcry_sexp_release (value_pair); + value_pair = NULL; + } + /* We do not require a comment sublist to be present here. */ data = NULL; data_n = 0; @@ -1399,6 +1537,7 @@ sexp_key_extract (gcry_sexp_t sexp, *secret = is_secret; *mpis = mpis_new; *comment = comment_new; + *r_curve = curve_name; out: @@ -1408,6 +1547,7 @@ sexp_key_extract (gcry_sexp_t sexp, if (err) { + xfree (curve_name); xfree (comment_new); mpint_list_free (mpis_new); } @@ -1494,6 +1634,24 @@ ssh_key_type_lookup (const char *ssh_name, const char *name, return err; } + +/* Lookup the ssh-identifier for the ECC curve CURVE_NAME. Returns + NULL if not found. */ +static const char * +ssh_identifier_from_curve_name (const char *curve_name) +{ + int i; + + for (i = 0; i < DIM (ssh_key_types); i++) + if (ssh_key_types[i].curve_name + && !strcmp (ssh_key_types[i].curve_name, curve_name)) + return ssh_key_types[i].ssh_identifier; + + return NULL; +} + + + /* Receive a key from STREAM, according to the key specification given as KEY_SPEC. Depending on SECRET, receive a secret or a public key. If READ_COMMENT is true, receive a comment string as well. @@ -1510,6 +1668,8 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, ssh_key_type_spec_t spec; gcry_mpi_t *mpi_list = NULL; const char *elems; + char *curve_name = NULL; + err = stream_read_cstring (stream, &key_type); @@ -1520,6 +1680,50 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, if (err) goto out; + if ((spec.flags & SPEC_FLAG_IS_ECDSA)) + { + /* The format of an ECDSA key is: + * string key_type ("ecdsa-sha2-nistp256" | + * "ecdsa-sha2-nistp384" | + * "ecdsa-sha2-nistp521" ) + * string ecdsa_curve_name + * string ecdsa_public_key + * mpint ecdsa_private + * + * Note that we use the mpint reader instead of the string + * reader for ecsa_public_key. + */ + unsigned char *buffer; + const char *mapped; + + err = stream_read_string (stream, 0, &buffer, NULL); + if (err) + goto out; + curve_name = buffer; + /* Fixme: Check that curve_name matches the keytype. */ + /* Because Libgcrypt < 1.6 has no support for the "nistpNNN" + curve names, we need to translate them here to Libgcrypt's + native names. */ + if (!strcmp (curve_name, "nistp256")) + mapped = "NIST P-256"; + else if (!strcmp (curve_name, "nistp384")) + mapped = "NIST P-384"; + else if (!strcmp (curve_name, "nistp521")) + mapped = "NIST P-521"; + else + mapped = NULL; + if (mapped) + { + xfree (curve_name); + curve_name = xtrystrdup (mapped); + if (!curve_name) + { + err = gpg_error_from_syserror (); + goto out; + } + } + } + err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list); if (err) goto out; @@ -1543,7 +1747,8 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, goto out; } - err = sexp_key_construct (&key, spec, secret, mpi_list, comment? comment:""); + err = sexp_key_construct (&key, spec, secret, curve_name, mpi_list, + comment? comment:""); if (err) goto out; @@ -1552,8 +1757,8 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, *key_new = key; out: - mpint_list_free (mpi_list); + xfree (curve_name); xfree (key_type); xfree (comment); @@ -1565,7 +1770,8 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, BLOB/BLOB_SIZE. Returns zero on success or an error code. */ static gpg_error_t ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, - const char *type, gcry_mpi_t *mpis) + ssh_key_type_spec_t *spec, + const char *curve_name, gcry_mpi_t *mpis) { unsigned char *blob_new; long int blob_size_new; @@ -1587,14 +1793,31 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, goto out; } - err = stream_write_cstring (stream, type); - if (err) - goto out; + if ((spec->flags & SPEC_FLAG_IS_ECDSA) && curve_name) + { + const char *sshname = ssh_identifier_from_curve_name (curve_name); + if (!curve_name) + { + err = gpg_error (GPG_ERR_UNKNOWN_CURVE); + goto out; + } + err = stream_write_cstring (stream, sshname); + if (err) + goto out; + err = stream_write_cstring (stream, curve_name); + if (err) + goto out; + } + else + { + err = stream_write_cstring (stream, spec->ssh_identifier); + if (err) + goto out; + } - for (i = 0; mpis[i] && (! err); i++) - err = stream_write_mpi (stream, mpis[i]); - if (err) - goto out; + for (i = 0; mpis[i]; i++) + if ((err = stream_write_mpi (stream, mpis[i]))) + goto out; blob_size_new = es_ftell (stream); if (blob_size_new == -1) @@ -1636,22 +1859,19 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, OVERRIDE_COMMENT is not NULL, it will be used instead of the comment stored in the key. */ static gpg_error_t -ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, +ssh_send_key_public (estream_t stream, + gcry_sexp_t key_public, const char *override_comment) { ssh_key_type_spec_t spec; - gcry_mpi_t *mpi_list; - char *key_type; - char *comment; - unsigned char *blob; + gcry_mpi_t *mpi_list = NULL; + char *key_type = NULL; + char *curve; + char *comment = NULL; + unsigned char *blob = NULL; size_t blob_n; gpg_error_t err; - key_type = NULL; - mpi_list = NULL; - comment = NULL; - blob = NULL; - err = sexp_extract_identifier (key_public, &key_type); if (err) goto out; @@ -1660,12 +1880,11 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, if (err) goto out; - err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment); + err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &curve, &comment); if (err) goto out; - err = ssh_convert_key_to_blob (&blob, &blob_n, - spec.ssh_identifier, mpi_list); + err = ssh_convert_key_to_blob (&blob, &blob_n, &spec, curve, mpi_list); if (err) goto out; @@ -1679,8 +1898,9 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, out: mpint_list_free (mpi_list); - xfree (key_type); + xfree (curve); xfree (comment); + xfree (key_type); xfree (blob); return err; @@ -1733,7 +1953,10 @@ static gpg_error_t ssh_key_grip (gcry_sexp_t key, unsigned char *buffer) { if (!gcry_pk_get_keygrip (key, buffer)) - return gpg_error (GPG_ERR_INTERNAL); + { + gpg_error_t err = gcry_pk_testkey (key); + return err? err : gpg_error (GPG_ERR_INTERNAL); + } return 0; } @@ -1746,6 +1969,7 @@ static gpg_error_t key_secret_to_public (gcry_sexp_t *key_public, ssh_key_type_spec_t spec, gcry_sexp_t key_secret) { + char *curve; char *comment; gcry_mpi_t *mpis; gpg_error_t err; @@ -1754,16 +1978,18 @@ key_secret_to_public (gcry_sexp_t *key_public, comment = NULL; mpis = NULL; - err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment); + err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, + &curve, &comment); if (err) goto out; - err = sexp_key_construct (key_public, spec, 0, mpis, comment); + err = sexp_key_construct (key_public, spec, 0, curve, mpis, comment); out: mpint_list_free (mpis); xfree (comment); + xfree (curve); return err; } @@ -2136,7 +2362,7 @@ data_hash (unsigned char *data, size_t data_n, signature in newly allocated memory in SIG and it's size in SIG_N; SIG_ENCODER is the signature encoder to use. */ static gpg_error_t -data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, +data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec, unsigned char **sig, size_t *sig_n) { gpg_error_t err; @@ -2147,10 +2373,6 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, gcry_mpi_t sig_value = NULL; unsigned char *sig_blob = NULL; size_t sig_blob_n = 0; - char *identifier = NULL; - const char *identifier_raw; - size_t identifier_n; - ssh_key_type_spec_t spec; int ret; unsigned int i; const char *elems; @@ -2229,29 +2451,11 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, goto out; } - identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n); - if (! identifier_raw) - { - err = gpg_error (GPG_ERR_INV_SEXP); - goto out; - } - - identifier = make_cstring (identifier_raw, identifier_n); - if (! identifier) - { - err = gpg_error_from_syserror (); - goto out; - } - - err = ssh_key_type_lookup (NULL, identifier, &spec); - if (err) - goto out; - - err = stream_write_cstring (stream, spec.ssh_identifier); + err = stream_write_cstring (stream, spec->ssh_identifier); if (err) goto out; - elems = spec.elems_signature; + elems = spec->elems_signature; elems_n = strlen (elems); mpis = xtrycalloc (elems_n + 1, sizeof *mpis); @@ -2263,7 +2467,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, for (i = 0; i < elems_n; i++) { - sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1); + sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1); if (! sublist) { err = gpg_error (GPG_ERR_INV_SEXP); @@ -2284,7 +2488,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, if (err) goto out; - err = (*sig_encoder) (stream, mpis); + err = spec->signature_encoder (spec, stream, mpis); if (err) goto out; @@ -2327,7 +2531,6 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, gcry_sexp_release (signature_sexp); gcry_sexp_release (sublist); mpint_list_free (mpis); - xfree (identifier); return err; } @@ -2350,6 +2553,7 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) u32 flags; gpg_error_t err; gpg_error_t ret_err; + int hash_algo; key_blob = NULL; data = NULL; @@ -2376,14 +2580,18 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) if (err) goto out; + hash_algo = spec.hash_algo; + if (!hash_algo) + hash_algo = GCRY_MD_SHA1; /* Use the default. */ + /* Hash data. */ - hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1); + hash_n = gcry_md_get_algo_dlen (hash_algo); if (! hash_n) { err = gpg_error (GPG_ERR_INTERNAL); goto out; } - err = data_hash (data, data_size, GCRY_MD_SHA1, hash); + err = data_hash (data, data_size, hash_algo, hash); if (err) goto out; @@ -2394,14 +2602,17 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) /* Sign data. */ - ctrl->digest.algo = GCRY_MD_SHA1; + ctrl->digest.algo = hash_algo; memcpy (ctrl->digest.value, hash, hash_n); ctrl->digest.valuelen = hash_n; - ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2); + if ((spec.flags & SPEC_FLAG_USE_PKCS1V2)) + ctrl->digest.raw_value = 0; + else + ctrl->digest.raw_value = 1; ctrl->have_keygrip = 1; memcpy (ctrl->keygrip, key_grip, 20); - err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n); + err = data_sign (ctrl, &spec, &sig, &sig_n); out: @@ -2522,6 +2733,7 @@ reenter_compare_cb (struct pin_entry_info_s *pi) return -1; } + /* Store the ssh KEY into our local key storage and protect it after asking for a passphrase. Cache that passphrase. TTL is the maximum caching time for that key. If the key already exists in @@ -2572,7 +2784,6 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl, int confirm) goto out; } - pi = gcry_calloc_secure (2, sizeof (*pi) + 100 + 1); if (!pi) { diff --git a/agent/protect.c b/agent/protect.c index d4d7e00..2eefd6d 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -51,10 +51,14 @@ static struct { const char *algo; const char *parmlist; int prot_from, prot_to; + int ecc_hack; } protect_info[] = { { "rsa", "nedpqu", 2, 5 }, { "dsa", "pqgyx", 4, 4 }, { "elg", "pgyx", 3, 3 }, + { "ecdsa","pabgnqd", 6, 6, 1 }, + { "ecdh", "pabgnqd", 6, 6, 1 }, + { "ecc", "pabgnqd", 6, 6, 1 }, { NULL } }; @@ -401,6 +405,8 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, unsigned char **result, size_t *resultlen) { int rc; + const char *parmlist; + int prot_from_idx, prot_to_idx; const unsigned char *s; const unsigned char *hash_begin, *hash_end; const unsigned char *prot_begin, *prot_end, *real_end; @@ -445,10 +451,13 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, if (!protect_info[infidx].algo) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + parmlist = protect_info[infidx].parmlist; + prot_from_idx = protect_info[infidx].prot_from; + prot_to_idx = protect_info[infidx].prot_to; prot_begin = prot_end = NULL; - for (i=0; (c=protect_info[infidx].parmlist[i]); i++) + for (i=0; (c=parmlist[i]); i++) { - if (i == protect_info[infidx].prot_from) + if (i == prot_from_idx) prot_begin = s; if (*s != '(') return gpg_error (GPG_ERR_INV_SEXP); @@ -458,7 +467,20 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, if (!n) return gpg_error (GPG_ERR_INV_SEXP); if (n != 1 || c != *s) - return gpg_error (GPG_ERR_INV_SEXP); + { + if (n == 5 && !memcmp (s, "curve", 5) + && !i && protect_info[infidx].ecc_hack) + { + /* This is a private ECC key but the first parameter is + the name of the curve. We change the parameter list + here to the one we expect in this case. */ + parmlist = "?qd"; + prot_from_idx = 2; + prot_to_idx = 2; + } + else + return gpg_error (GPG_ERR_INV_SEXP); + } s += n; n = snext (&s); if (!n) @@ -467,7 +489,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, if (*s != ')') return gpg_error (GPG_ERR_INV_SEXP); depth--; - if (i == protect_info[infidx].prot_to) + if (i == prot_to_idx) prot_end = s; s++; } @@ -484,7 +506,6 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, assert (!depth); real_end = s-1; - /* Hash the stuff. Because the timestamp_exp won't get protected, we can't simply hash a continuous buffer but need to use several md_writes. */ diff --git a/agent/t-protect.c b/agent/t-protect.c index 0e29caf..16ff7d7 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -137,7 +137,24 @@ test_agent_protect (void) "\x9B\x7B\xE8\xDD\x1F\x87\x4E\x79\x7B\x50\x12\xA7\xB4\x8B\x52\x38\xEC\x7C\xBB\xB9" "\x55\x87\x11\x1C\x74\xE7\x7F\xA0\xBA\xE3\x34\x5D\x61\xBF\x29\x29\x29\x00" }; - + + struct key_spec key_ecdsa_valid = + { + "\x28\x31\x31\x3A\x70\x72\x69\x76\x61\x74\x65\x2D\x6B\x65\x79\x28" + "\x35\x3A\x65\x63\x64\x73\x61\x28\x35\x3A\x63\x75\x72\x76\x65\x31" + "\x30\x3A\x4E\x49\x53\x54\x20\x50\x2D\x32\x35\x36\x29\x28\x31\x3A" + "\x71\x36\x35\x3A\x04\x64\x5A\x12\x6F\x86\x7C\x43\x87\x2B\x7C\xAF" + "\x77\xFE\xD8\x22\x31\xEA\xE6\x89\x9F\xAA\xEA\x63\x26\xBC\x49\xED" + "\x85\xC6\xD2\xC9\x8B\x38\xD2\x78\x75\xE6\x1C\x27\x57\x01\xC5\xA1" + "\xE3\xF9\x1F\xBE\xCF\xC1\x72\x73\xFE\xA4\x58\xB6\x6A\x92\x7D\x33" + "\x1D\x02\xC9\xCB\x12\x29\x28\x31\x3A\x64\x33\x33\x3A\x00\x81\x2D" + "\x69\x9A\x5F\x5B\x6F\x2C\x99\x61\x36\x15\x6B\x44\xD8\x06\xC1\x54" + "\xC1\x4C\xFB\x70\x6A\xB6\x64\x81\x78\xF3\x94\x2F\x30\x5D\x29\x29" + "\x28\x37\x3A\x63\x6F\x6D\x6D\x65\x6E\x74\x32\x32\x3A\x2F\x68\x6F" + "\x6D\x65\x2F\x77\x6B\x2F\x2E\x73\x73\x68\x2F\x69\x64\x5F\x65\x63" + "\x64\x73\x61\x29\x29" + }; + struct { const char *key; @@ -167,6 +184,9 @@ test_agent_protect (void) { key_rsa_bogus_1.string, "passphrase", 0, 0, NULL, 0, GPG_ERR_INV_SEXP, NULL, 0 }, + { key_ecdsa_valid.string, + "passphrase", 0, 0, NULL, 0, 0, NULL, 0 }, + /* FIXME: add more test data. */ }; @@ -177,12 +197,12 @@ test_agent_protect (void) &specs[i].result, &specs[i].resultlen); if (gpg_err_code (ret) != specs[i].ret_expected) { - printf ("agent_protect() returned `%i/%s'; expected `%i/%s'\n", - ret, gpg_strerror (ret), + printf ("agent_protect(%d) returned '%i/%s'; expected '%i/%s'\n", + i, ret, gpg_strerror (ret), specs[i].ret_expected, gpg_strerror (specs[i].ret_expected)); abort (); } - + if (specs[i].no_result_expected) { assert (! specs[i].result); @@ -234,14 +254,14 @@ static void test_make_shadow_info (void) { #if 0 - static struct + static struct { - const char *snstr; + const char *snstr; const char *idstr; const char *expected; } data[] = { { "", "", NULL }, - + }; int i; unsigned char *result; @@ -298,7 +318,7 @@ main (int argc, char **argv) (void)argv; gcry_control (GCRYCTL_DISABLE_SECMEM); - + test_agent_protect (); test_agent_unprotect (); test_agent_private_key_type (); diff --git a/common/ssh-utils.c b/common/ssh-utils.c index e2de802..d8f057d 100644 --- a/common/ssh-utils.c +++ b/common/ssh-utils.c @@ -89,6 +89,34 @@ get_fingerprint (gcry_sexp_t key, void **r_fpr, size_t *r_len, elems = "pqgy"; gcry_md_write (md, "\0\0\0\x07ssh-dss", 11); break; + case GCRY_PK_ECDSA: + /* We only support the 3 standard curves for now. It is just a + quick hack. */ + elems = "q"; + gcry_md_write (md, "\0\0\0\x13" "ecdsa-sha2-nistp", 20); + l2 = gcry_sexp_find_token (list, "curve", 0); + if (!l2) + elems = ""; + else + { + gcry_free (name); + name = gcry_sexp_nth_string (l2, 1); + gcry_sexp_release (l2); + l2 = NULL; + if (!name) + elems = ""; + else if (!strcmp (name, "NIST P-256") || !strcmp (name, "nistp256")) + gcry_md_write (md, "256\0\0\0\x08nistp256", 15); + else if (!strcmp (name, "NIST P-384") || !strcmp (name, "nistp384")) + gcry_md_write (md, "384\0\0\0\x08nistp521", 15); + else if (!strcmp (name, "NIST P-521") || !strcmp (name, "nistp521")) + gcry_md_write (md, "521\0\0\0\x08nistp521", 15); + else + elems = ""; + } + if (!*elems) + err = gpg_err_make (errsource, GPG_ERR_UNKNOWN_CURVE); + break; default: elems = ""; err = gpg_err_make (errsource, GPG_ERR_PUBKEY_ALGO); commit 4b4df62eaf7f46f83540536bfa373e78be2a6d7d Author: Werner Koch Date: Mon Jul 1 20:27:39 2013 +0200 estream: New function es_fclose_snatch. * common/estream.c (cookie_ioctl_function_t): New type. (es_fclose_snatch): New function. (COOKIE_IOCTL_SNATCH_BUFFER): New constant. (struct estream_internal): Add field FUNC_IOCTL. (es_initialize): Clear FUNC_IOCTL. (es_func_mem_ioctl): New function. (es_fopenmem): Init FUNC_IOCTL. -- (back ported from commit id 7737a2c269657189a583cde7f214f20871d264f8) Signed-off-by: Werner Koch diff --git a/common/estream.c b/common/estream.c index 9c781a0..304e0e6 100644 --- a/common/estream.c +++ b/common/estream.c @@ -217,8 +217,16 @@ static int estream_pth_killed; #define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR) -/* An internal stream object. */ +/* A private cookie function to implement an internal IOCTL + service. */ +typedef int (*cookie_ioctl_function_t) (void *cookie, int cmd, + void *ptr, size_t *len); +/* IOCTL commands for the private cookie function. */ +#define COOKIE_IOCTL_SNATCH_BUFFER 1 + + +/* An internal stream object. */ struct estream_internal { unsigned char buffer[BUFFER_BLOCK_SIZE]; @@ -232,6 +240,7 @@ struct estream_internal es_cookie_read_function_t func_read; es_cookie_write_function_t func_write; es_cookie_seek_function_t func_seek; + cookie_ioctl_function_t func_ioctl; es_cookie_close_function_t func_close; int strategy; int fd; @@ -773,6 +782,34 @@ es_func_mem_seek (void *cookie, off_t *offset, int whence) } +/* An IOCTL function for memory objects. */ +static int +es_func_mem_ioctl (void *cookie, int cmd, void *ptr, size_t *len) +{ + estream_cookie_mem_t mem_cookie = cookie; + int ret; + + if (cmd == COOKIE_IOCTL_SNATCH_BUFFER) + { + /* Return the internal buffer of the stream to the caller and + invalidate it for the stream. */ + *(void**)ptr = mem_cookie->memory; + *len = mem_cookie->offset; + mem_cookie->memory = NULL; + mem_cookie->memory_size = 0; + mem_cookie->offset = 0; + ret = 0; + } + else + { + _set_errno (EINVAL); + ret = -1; + } + + return ret; +} + + /* Destroy function for memory objects. */ static int es_func_mem_destroy (void *cookie) @@ -1312,6 +1349,7 @@ es_initialize (estream_t stream, stream->intern->func_read = functions.func_read; stream->intern->func_write = functions.func_write; stream->intern->func_seek = functions.func_seek; + stream->intern->func_ioctl = NULL; stream->intern->func_close = functions.func_close; stream->intern->strategy = _IOFBF; stream->intern->fd = fd; @@ -2317,6 +2355,9 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode) if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0)) (*estream_functions_mem.func_close) (cookie); + if (stream) + stream->intern->func_ioctl = es_func_mem_ioctl; + return stream; } @@ -2604,6 +2645,66 @@ es_fclose (estream_t stream) return err; } + +/* This is a special version of es_fclose which can be used with + es_fopenmem to return the memory buffer. This is feature is useful + to write to a memory buffer using estream. Note that the function + does not close the stream if the stream does not support snatching + the buffer. On error NULL is stored at R_BUFFER. Note that if no + write operation has happened, NULL may also be stored at BUFFER on + success. The caller needs to release the returned memory using + es_free. */ +int +es_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen) +{ + int err; + + /* Note: There is no need to lock the stream in a close call. The + object will be destroyed after the close and thus any other + contender for the lock would work on a closed stream. */ + + if (r_buffer) + { + cookie_ioctl_function_t func_ioctl = stream->intern->func_ioctl; + size_t buflen; + + *r_buffer = NULL; + + if (!func_ioctl) + { + _set_errno (EOPNOTSUPP); + err = -1; + goto leave; + } + + if (stream->flags.writing) + { + err = es_flush (stream); + if (err) + goto leave; + stream->flags.writing = 0; + } + + err = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_SNATCH_BUFFER, + r_buffer, &buflen); + if (err) + goto leave; + if (r_buflen) + *r_buflen = buflen; + } + + err = es_destroy (stream, 0); + + leave: + if (err && r_buffer) + { + mem_free (*r_buffer); + *r_buffer = NULL; + } + return err; +} + + int es_fileno_unlocked (estream_t stream) { diff --git a/common/estream.h b/common/estream.h index 69f19f4..f72e4c6 100644 --- a/common/estream.h +++ b/common/estream.h @@ -85,6 +85,7 @@ #define es_freopen _ESTREAM_PREFIX(es_freopen) #define es_fopencookie _ESTREAM_PREFIX(es_fopencookie) #define es_fclose _ESTREAM_PREFIX(es_fclose) +#define es_fclose_snatch _ESTREAM_PREFIX(es_fclose_snatch) #define es_fileno _ESTREAM_PREFIX(es_fileno) #define es_fileno_unlocked _ESTREAM_PREFIX(es_fileno_unlocked) #define es_flockfile _ESTREAM_PREFIX(es_flockfile) @@ -253,6 +254,7 @@ estream_t es_fopencookie (void *ES__RESTRICT cookie, const char *ES__RESTRICT mode, es_cookie_io_functions_t functions); int es_fclose (estream_t stream); +int es_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen); int es_fileno (estream_t stream); int es_fileno_unlocked (estream_t stream); commit cf7f9303272db65465ff45348cf18f7298e41e30 Author: Werner Koch Date: Tue Dec 11 14:50:34 2012 +0100 ssh: Rewrite a function for better maintainability * agent/command-ssh.c (ssh_signature_encoder_dsa): Rewrite. -- Using es_fopenmem instead of a preallocated buffer is safer and easier to read. (cherry picked from commit f76a0312c3794afd81fe1e172df15eb0612deae0) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 18e155d..6b73a5d 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1190,65 +1190,51 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in *SEXP. Returns usual error code. */ static gpg_error_t -sexp_key_construct (gcry_sexp_t *sexp, +sexp_key_construct (gcry_sexp_t *r_sexp, ssh_key_type_spec_t key_spec, int secret, gcry_mpi_t *mpis, const char *comment) { const char *key_identifier[] = { "public-key", "private-key" }; - gcry_sexp_t sexp_new; - char *sexp_template; - size_t sexp_template_n; gpg_error_t err; + gcry_sexp_t sexp_new = NULL; + char *formatbuf = NULL; + void **arg_list = NULL; + int arg_idx; + estream_t format; const char *elems; size_t elems_n; - unsigned int i; - unsigned int j; - void **arg_list; + unsigned int i, j; - err = 0; - sexp_new = NULL; - arg_list = NULL; if (secret) elems = key_spec.elems_sexp_order; else elems = key_spec.elems_key_public; elems_n = strlen (elems); - /* - Calculate size for sexp_template_n: - - "(%s(%s)(comment%s))" -> 20 + sizeof (). - - mpi: (X%m) -> 5. - - */ - sexp_template_n = 20 + (elems_n * 5); - sexp_template = xtrymalloc (sexp_template_n); - if (! sexp_template) + format = es_fopenmem (0, "a+b"); + if (!format) { err = gpg_error_from_syserror (); goto out; } - /* Key identifier, algorithm identifier, mpis, comment. */ - arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1)); - if (! arg_list) + /* Key identifier, algorithm identifier, mpis, comment, and a NULL + as a safeguard. */ + arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1 + 1)); + if (!arg_list) { err = gpg_error_from_syserror (); goto out; } + arg_idx = 0; - i = 0; - arg_list[i++] = &key_identifier[secret]; - arg_list[i++] = &key_spec.identifier; + es_fputs ("(%s(%s", format); + arg_list[arg_idx++] = &key_identifier[secret]; + arg_list[arg_idx++] = &key_spec.identifier; - *sexp_template = 0; - sexp_template_n = 0; - sexp_template_n = sprintf (sexp_template + sexp_template_n, "(%%s(%%s"); for (i = 0; i < elems_n; i++) { - sexp_template_n += sprintf (sexp_template + sexp_template_n, "(%c%%m)", - elems[i]); + es_fprintf (format, "(%c%%m)", elems[i]); if (secret) { for (j = 0; j < elems_n; j++) @@ -1257,27 +1243,42 @@ sexp_key_construct (gcry_sexp_t *sexp, } else j = i; - arg_list[i + 2] = &mpis[j]; + arg_list[arg_idx++] = &mpis[j]; } - sexp_template_n += sprintf (sexp_template + sexp_template_n, - ")(comment%%s))"); + es_fputs (")(comment%s))", format); + arg_list[arg_idx++] = &comment; + arg_list[arg_idx] = NULL; - arg_list[i + 2] = &comment; + es_putc (0, format); + if (es_ferror (format)) + { + err = gpg_error_from_syserror (); + goto out; + } + if (es_fclose_snatch (format, &formatbuf, NULL)) + { + err = gpg_error_from_syserror (); + goto out; + } + format = NULL; - err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list); + log_debug ("sexp formatbuf='%s' nargs=%d\n", formatbuf, arg_idx); + err = gcry_sexp_build_array (&sexp_new, NULL, formatbuf, arg_list); if (err) goto out; - *sexp = sexp_new; + *r_sexp = sexp_new; + err = 0; out: - + es_fclose (format); xfree (arg_list); - xfree (sexp_template); + xfree (formatbuf); return err; } + /* This functions breaks up the key contained in the S-Expression SEXP according to KEY_SPEC. The MPIs are bundled in a newly create list, which is to be stored in MPIS; a newly allocated string commit 901162579119585ebd3df9001b0370e6d32934ab Author: Werner Koch Date: Mon Dec 10 18:27:23 2012 +0100 ssh: Improve key lookup for many keys. * agent/command-ssh.c: Remove dirent.h. (control_file_s): Add struct item. (rewind_control_file): New. (search_control_file): Factor code out to ... (read_control_file_item): New. (ssh_handler_request_identities): Change to iterate over entries in sshcontrol. -- Formerly we scanned the private key directory for matches of entries in sshcontrol. This patch changes it to scan the sshcontrol file and thus considers only keys configured there. The rationale for this is that it is common to have only a few ssh keys but many private keys. Even if that assumption does not hold true, the scanning of the sshcontrol file is faster than reading the directory and only then scanning the ssh control for each directory entry. (cherry picked from commit d2777f84be0ded5906a9bec3bc23cfed0a9be02f) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 5be86be..18e155d 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "agent.h" @@ -169,6 +168,14 @@ struct control_file_s { char *fname; /* Name of the file. */ FILE *fp; /* This is never NULL. */ + int lnr; /* The current line number. */ + struct { + int valid; /* True if the data of this structure is valid. */ + int disabled; /* The item is disabled. */ + int ttl; /* The TTL of the item. */ + int confirm; /* The confirm flag is set. */ + char hexgrip[40+1]; /* The hexgrip of the item (uppercase). */ + } item; }; typedef struct control_file_s *control_file_t; @@ -742,6 +749,15 @@ open_control_file (control_file_t *r_cf, int append) static void +rewind_control_file (control_file_t cf) +{ + fseek (cf->fp, 0, SEEK_SET); + cf->lnr = 0; + clearerr (cf->fp); +} + + +static void close_control_file (control_file_t cf) { if (!cf) @@ -752,29 +768,19 @@ close_control_file (control_file_t cf) } -/* Search the control file CF from the beginning until a matching - HEXGRIP is found; return success in this case and store true at - DISABLED if the found key has been disabled. If R_TTL is not NULL - a specified TTL for that key is stored there. If R_CONFIRM is not - NULL it is set to 1 if the key has the confirm flag set. */ + +/* Read the next line from the control file and store the data in CF. + Returns 0 on success, GPG_ERR_EOF on EOF, or other error codes. */ static gpg_error_t -search_control_file (control_file_t cf, const char *hexgrip, - int *r_disabled, int *r_ttl, int *r_confirm) +read_control_file_item (control_file_t cf) { int c, i, n; char *p, *pend, line[256]; - long ttl; - int lnr = 0; + long ttl = 0; - assert (strlen (hexgrip) == 40 ); - - if (r_confirm) - *r_confirm = 0; - - fseek (cf->fp, 0, SEEK_SET); + cf->item.valid = 0; clearerr (cf->fp); - *r_disabled = 0; - next_line: + do { if (!fgets (line, DIM(line)-1, cf->fp) ) @@ -783,7 +789,7 @@ search_control_file (control_file_t cf, const char *hexgrip, return gpg_error (GPG_ERR_EOF); return gpg_error_from_syserror (); } - lnr++; + cf->lnr++; if (!*line || line[strlen(line)-1] != '\n') { @@ -800,35 +806,34 @@ search_control_file (control_file_t cf, const char *hexgrip, } while (!*p || *p == '\n' || *p == '#'); - *r_disabled = 0; + cf->item.disabled = 0; if (*p == '!') { - *r_disabled = 1; + cf->item.disabled = 1; for (p++; spacep (p); p++) ; } for (i=0; hexdigitp (p) && i < 40; p++, i++) - if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p)) - goto next_line; + cf->item.hexgrip[i] = (*p >= 'a'? (*p & 0xdf): *p); + cf->item.hexgrip[i] = 0; if (i != 40 || !(spacep (p) || *p == '\n')) { - log_error ("invalid formatted line in `%s', line %d\n", cf->fname, lnr); + log_error ("%s:%d: invalid formatted line\n", cf->fname, cf->lnr); return gpg_error (GPG_ERR_BAD_DATA); } ttl = strtol (p, &pend, 10); p = pend; - if (!(spacep (p) || *p == '\n') || ttl < -1) + if (!(spacep (p) || *p == '\n') || (int)ttl < -1) { - log_error ("invalid TTL value in `%s', line %d; assuming 0\n", - cf->fname, lnr); - ttl = 0; + log_error ("%s:%d: invalid TTL value; assuming 0\n", cf->fname, cf->lnr); + cf->item.ttl = 0; } - if (r_ttl) - *r_ttl = ttl; + cf->item.ttl = ttl; /* Now check for key-value pairs of the form NAME[=VALUE]. */ + cf->item.confirm = 0; while (*p) { for (; spacep (p) && *p != '\n'; p++) @@ -838,22 +843,68 @@ search_control_file (control_file_t cf, const char *hexgrip, n = strcspn (p, "= \t\n"); if (p[n] == '=') { - log_error ("assigning a value to a flag is not yet supported; " - "in `%s', line %d; flag ignored\n", cf->fname, lnr); + log_error ("%s:%d: assigning a value to a flag is not yet supported; " + "flag ignored\n", cf->fname, cf->lnr); p++; } else if (n == 7 && !memcmp (p, "confirm", 7)) { - if (r_confirm) - *r_confirm = 1; + cf->item.confirm = 1; } else - log_error ("invalid flag `%.*s' in `%s', line %d; ignored\n", - n, p, cf->fname, lnr); + log_error ("%s:%d: invalid flag '%.*s'; ignored\n", + cf->fname, cf->lnr, n, p); p += n; } - return 0; /* Okay: found it. */ + /* log_debug ("%s:%d: grip=%s ttl=%d%s%s\n", */ + /* cf->fname, cf->lnr, */ + /* cf->item.hexgrip, cf->item.ttl, */ + /* cf->item.disabled? " disabled":"", */ + /* cf->item.confirm? " confirm":""); */ + + cf->item.valid = 1; + return 0; /* Okay: valid entry found. */ +} + + + +/* Search the control file CF from the beginning until a matching + HEXGRIP is found; return success in this case and store true at + DISABLED if the found key has been disabled. If R_TTL is not NULL + a specified TTL for that key is stored there. If R_CONFIRM is not + NULL it is set to 1 if the key has the confirm flag set. */ +static gpg_error_t +search_control_file (control_file_t cf, const char *hexgrip, + int *r_disabled, int *r_ttl, int *r_confirm) +{ + gpg_error_t err; + + assert (strlen (hexgrip) == 40 ); + + *r_disabled = 0; + if (r_ttl) + *r_ttl = 0; + if (r_confirm) + *r_confirm = 0; + + rewind_control_file (cf); + while (!(err=read_control_file_item (cf))) + { + if (!cf->item.valid) + continue; /* Should not happen. */ + if (!strcmp (hexgrip, cf->item.hexgrip)) + break; + } + if (!err) + { + *r_disabled = cf->item.disabled; + if (r_ttl) + *r_ttl = cf->item.ttl; + if (r_confirm) + *r_confirm = cf->item.confirm; + } + return err; } @@ -1898,19 +1949,13 @@ static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) { - char *key_type; ssh_key_type_spec_t spec; - struct dirent *dir_entry; - char *key_directory; - size_t key_directory_n; - char *key_path; - unsigned char *buffer; - size_t buffer_n; + char *key_fname = NULL; + char *fnameptr; u32 key_counter; estream_t key_blobs; gcry_sexp_t key_secret; gcry_sexp_t key_public; - DIR *dir; gpg_error_t err; int ret; control_file_t cf = NULL; @@ -1921,14 +1966,9 @@ ssh_handler_request_identities (ctrl_t ctrl, /* Prepare buffer stream. */ - key_directory = NULL; key_secret = NULL; key_public = NULL; - key_type = NULL; - key_path = NULL; key_counter = 0; - buffer = NULL; - dir = NULL; err = 0; key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); @@ -1938,34 +1978,6 @@ ssh_handler_request_identities (ctrl_t ctrl, goto out; } - /* Open key directory. */ - key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL); - if (! key_directory) - { - err = gpg_err_code_from_errno (errno); - goto out; - } - key_directory_n = strlen (key_directory); - - key_path = xtrymalloc (key_directory_n + 46); - if (! key_path) - { - err = gpg_err_code_from_errno (errno); - goto out; - } - - sprintf (key_path, "%s/", key_directory); - sprintf (key_path + key_directory_n + 41, ".key"); - - dir = opendir (key_directory); - if (! dir) - { - err = gpg_err_code_from_errno (errno); - goto out; - } - - - /* First check whether a key is currently available in the card reader - this should be allowed even without being listed in sshcontrol. */ @@ -1984,77 +1996,93 @@ ssh_handler_request_identities (ctrl_t ctrl, } - /* Then look at all the registered an allowed keys. */ + /* Prepare buffer for key name construction. */ + { + char *dname; + dname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL); + if (!dname) + { + err = gpg_err_code_from_syserror (); + goto out; + } - /* Fixme: We should better iterate over the control file and check - whether the key file is there. This is better in respect to - performance if there are a lot of keys in our key storage. */ - /* FIXME: make sure that buffer gets deallocated properly. */ + key_fname = xtrymalloc (strlen (dname) + 1 + 40 + 4 + 1); + if (!key_fname) + { + err = gpg_err_code_from_syserror (); + xfree (dname); + goto out; + } + fnameptr = stpcpy (stpcpy (key_fname, dname), "/"); + xfree (dname); + } + + /* Then look at all the registered and non-disabled keys. */ err = open_control_file (&cf, 0); if (err) goto out; - while ( (dir_entry = readdir (dir)) ) + while (!read_control_file_item (cf)) { - if ((strlen (dir_entry->d_name) == 44) - && (! strncmp (dir_entry->d_name + 40, ".key", 4))) - { - char hexgrip[41]; - int disabled; - - /* We do only want to return keys listed in our control - file. */ - strncpy (hexgrip, dir_entry->d_name, 40); - hexgrip[40] = 0; - if ( strlen (hexgrip) != 40 ) - continue; - if (search_control_file (cf, hexgrip, &disabled, NULL, NULL) - || disabled) - continue; - - strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); + if (!cf->item.valid) + continue; /* Should not happen. */ + if (cf->item.disabled) + continue; + assert (strlen (cf->item.hexgrip) == 40); - /* Read file content. */ - err = file_to_buffer (key_path, &buffer, &buffer_n); - if (err) - goto out; + stpcpy (stpcpy (fnameptr, cf->item.hexgrip), ".key"); - err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n); - if (err) - goto out; + /* Read file content. */ + { + unsigned char *buffer; + size_t buffer_n; + + err = file_to_buffer (key_fname, &buffer, &buffer_n); + if (err) + { + log_error ("%s:%d: key '%s' skipped: %s\n", + cf->fname, cf->lnr, cf->item.hexgrip, + gpg_strerror (err)); + continue; + } - xfree (buffer); - buffer = NULL; + err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n); + xfree (buffer); + if (err) + goto out; + } - err = sexp_extract_identifier (key_secret, &key_type); - if (err) - goto out; + { + char *key_type = NULL; - err = ssh_key_type_lookup (NULL, key_type, &spec); - if (err) - goto out; + err = sexp_extract_identifier (key_secret, &key_type); + if (err) + goto out; - xfree (key_type); - key_type = NULL; + err = ssh_key_type_lookup (NULL, key_type, &spec); + xfree (key_type); + if (err) + goto out; + } - err = key_secret_to_public (&key_public, spec, key_secret); - if (err) - goto out; + err = key_secret_to_public (&key_public, spec, key_secret); + if (err) + goto out; - gcry_sexp_release (key_secret); - key_secret = NULL; + gcry_sexp_release (key_secret); + key_secret = NULL; - err = ssh_send_key_public (key_blobs, key_public, NULL); - if (err) - goto out; + err = ssh_send_key_public (key_blobs, key_public, NULL); + if (err) + goto out; - gcry_sexp_release (key_public); - key_public = NULL; + gcry_sexp_release (key_public); + key_public = NULL; - key_counter++; - } + key_counter++; } + err = 0; ret = es_fseek (key_blobs, 0, SEEK_SET); if (ret) @@ -2064,43 +2092,27 @@ ssh_handler_request_identities (ctrl_t ctrl, } out: - /* Send response. */ gcry_sexp_release (key_secret); gcry_sexp_release (key_public); - if (! err) + if (!err) { ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); - if (ret_err) - goto leave; - ret_err = stream_write_uint32 (response, key_counter); - if (ret_err) - goto leave; - ret_err = stream_copy (response, key_blobs); - if (ret_err) - goto leave; + if (!ret_err) + ret_err = stream_write_uint32 (response, key_counter); + if (!ret_err) + ret_err = stream_copy (response, key_blobs); } else { ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); - goto leave; - }; - - leave: - - if (key_blobs) - es_fclose (key_blobs); - if (dir) - closedir (dir); + } + es_fclose (key_blobs); close_control_file (cf); - - xfree (key_directory); - xfree (key_path); - xfree (buffer); - xfree (key_type); + xfree (key_fname); return ret_err; } commit 336112e519079f43278a8ca8c2937417bc667d8f Author: Werner Koch Date: Mon Dec 10 16:39:12 2012 +0100 ssh: Cleanup sshcontrol file access code. * agent/command-ssh.c (SSH_CONTROL_FILE_NAME): New macro to replace the direct use of the string. (struct control_file_s, control_file_t): New. (open_control_file, close_control_file): New. Use them instead of using fopen/fclose directly. -- (cherry picked from commit 25fb53ab4ae7e1c098500229c776d29b82713a20) Fixed conflicts in some variabale names. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index fe0980e..5be86be 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1,5 +1,5 @@ /* command-ssh.c - gpg-agent's ssh-agent emulation layer - * Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc. + * Copyright (C) 2004, 2005, 2006, 2009, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -64,6 +64,8 @@ #define SSH_DSA_SIGNATURE_ELEMS 2 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0) +/* The name of the control file. */ +#define SSH_CONTROL_FILE_NAME "sshcontrol" /* The blurb we put into the header of a newly created control file. */ static const char sshcontrolblurb[] = @@ -80,7 +82,6 @@ static const char sshcontrolblurb[] = "\n"; - /* Macros. */ /* Return a new uint32 with b0 being the most significant byte and b3 @@ -163,6 +164,16 @@ typedef struct ssh_key_type_spec } ssh_key_type_spec_t; +/* An object used to access the sshcontrol file. */ +struct control_file_s +{ + char *fname; /* Name of the file. */ + FILE *fp; /* This is never NULL. */ +}; +typedef struct control_file_s *control_file_t; + + + /* Prototypes. */ static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, estream_t request, @@ -660,92 +671,124 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) -/* Open the ssh control file and create it if not available. With +/* Open the ssh control file and create it if not available. With APPEND passed as true the file will be opened in append mode, - otherwise in read only mode. On success a file pointer is stored - at the address of R_FP. */ + otherwise in read only mode. On success 0 is returned and a new + control file object stored at R_CF. On error an error code is + returned and NULL is stored at R_CF. */ static gpg_error_t -open_control_file (FILE **r_fp, int append) +open_control_file (control_file_t *r_cf, int append) { gpg_error_t err; - char *fname; - FILE *fp; + control_file_t cf; + + cf = xtrycalloc (1, sizeof *cf); + if (!cf) + { + err = gpg_error_from_syserror (); + goto leave; + } /* Note: As soon as we start to use non blocking functions here (i.e. where Pth might switch threads) we need to employ a mutex. */ - *r_fp = NULL; - fname = make_filename (opt.homedir, "sshcontrol", NULL); + cf->fname = make_filename_try (opt.homedir, SSH_CONTROL_FILE_NAME, NULL); + if (!cf->fname) + { + err = gpg_error_from_syserror (); + goto leave; + } /* FIXME: With "a+" we are not able to check whether this will will be created and thus the blurb needs to be written first. */ - fp = fopen (fname, append? "a+":"r"); - if (!fp && errno == ENOENT) + cf->fp = fopen (cf->fname, append? "a+":"r"); + if (!cf->fp && errno == ENOENT) { - estream_t stream = es_fopen (fname, "wx,mode=-rw-r"); + estream_t stream = es_fopen (cf->fname, "wx,mode=-rw-r"); if (!stream) { err = gpg_error_from_syserror (); - log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err)); - xfree (fname); - return err; + log_error (_("can't create `%s': %s\n"), + cf->fname, gpg_strerror (err)); + goto leave; } es_fputs (sshcontrolblurb, stream); es_fclose (stream); - fp = fopen (fname, append? "a+":"r"); + cf->fp = fopen (cf->fname, append? "a+":"r"); } - if (!fp) + if (!cf->fp) { - err = gpg_error (gpg_err_code_from_errno (errno)); - log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err)); - xfree (fname); - return err; + err = gpg_error_from_syserror (); + log_error (_("can't open `%s': %s\n"), + cf->fname, gpg_strerror (err)); + goto leave; } - *r_fp = fp; + err = 0; - return 0; + leave: + if (err && cf) + { + if (cf->fp) + fclose (cf->fp); + xfree (cf->fname); + xfree (cf); + } + else + *r_cf = cf; + + return err; +} + + +static void +close_control_file (control_file_t cf) +{ + if (!cf) + return; + fclose (cf->fp); + xfree (cf->fname); + xfree (cf); } -/* Search the file at stream FP from the beginning until a matching +/* Search the control file CF from the beginning until a matching HEXGRIP is found; return success in this case and store true at DISABLED if the found key has been disabled. If R_TTL is not NULL a specified TTL for that key is stored there. If R_CONFIRM is not NULL it is set to 1 if the key has the confirm flag set. */ static gpg_error_t -search_control_file (FILE *fp, const char *hexgrip, +search_control_file (control_file_t cf, const char *hexgrip, int *r_disabled, int *r_ttl, int *r_confirm) { int c, i, n; char *p, *pend, line[256]; long ttl; int lnr = 0; - const char fname[] = "sshcontrol"; assert (strlen (hexgrip) == 40 ); if (r_confirm) *r_confirm = 0; - fseek (fp, 0, SEEK_SET); - clearerr (fp); + fseek (cf->fp, 0, SEEK_SET); + clearerr (cf->fp); *r_disabled = 0; next_line: do { - if (!fgets (line, DIM(line)-1, fp) ) + if (!fgets (line, DIM(line)-1, cf->fp) ) { - if (feof (fp)) + if (feof (cf->fp)) return gpg_error (GPG_ERR_EOF); - return gpg_error (gpg_err_code_from_errno (errno)); + return gpg_error_from_syserror (); } lnr++; if (!*line || line[strlen(line)-1] != '\n') { /* Eat until end of line */ - while ( (c=getc (fp)) != EOF && c != '\n') + while ( (c=getc (cf->fp)) != EOF && c != '\n') ; return gpg_error (*line? GPG_ERR_LINE_TOO_LONG : GPG_ERR_INCOMPLETE_LINE); @@ -770,7 +813,7 @@ search_control_file (FILE *fp, const char *hexgrip, goto next_line; if (i != 40 || !(spacep (p) || *p == '\n')) { - log_error ("invalid formatted line in `%s', line %d\n", fname, lnr); + log_error ("invalid formatted line in `%s', line %d\n", cf->fname, lnr); return gpg_error (GPG_ERR_BAD_DATA); } @@ -779,7 +822,7 @@ search_control_file (FILE *fp, const char *hexgrip, if (!(spacep (p) || *p == '\n') || ttl < -1) { log_error ("invalid TTL value in `%s', line %d; assuming 0\n", - fname, lnr); + cf->fname, lnr); ttl = 0; } if (r_ttl) @@ -796,7 +839,7 @@ search_control_file (FILE *fp, const char *hexgrip, if (p[n] == '=') { log_error ("assigning a value to a flag is not yet supported; " - "in `%s', line %d; flag ignored\n", fname, lnr); + "in `%s', line %d; flag ignored\n", cf->fname, lnr); p++; } else if (n == 7 && !memcmp (p, "confirm", 7)) @@ -806,7 +849,7 @@ search_control_file (FILE *fp, const char *hexgrip, } else log_error ("invalid flag `%.*s' in `%s', line %d; ignored\n", - n, p, fname, lnr); + n, p, cf->fname, lnr); p += n; } @@ -825,16 +868,16 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr, int ttl, int confirm) { gpg_error_t err; - FILE *fp; + control_file_t cf; int disabled; (void)ctrl; - err = open_control_file (&fp, 1); + err = open_control_file (&cf, 1); if (err) return err; - err = search_control_file (fp, hexgrip, &disabled, NULL, NULL); + err = search_control_file (cf, hexgrip, &disabled, NULL, NULL); if (err && gpg_err_code(err) == GPG_ERR_EOF) { struct tm *tp; @@ -843,15 +886,16 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr, /* Not yet in the file - add it. Because the file has been opened in append mode, we simply need to write to it. */ tp = localtime (&atime); - fprintf (fp, ("# Key added on: %04d-%02d-%02d %02d:%02d:%02d\n" - "# Fingerprint: %s\n" - "%s %d%s\n"), + fprintf (cf->fp, + ("# Key added on: %04d-%02d-%02d %02d:%02d:%02d\n" + "# Fingerprint: %s\n" + "%s %d%s\n"), 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec, fmtfpr, hexgrip, ttl, confirm? " confirm":""); } - fclose (fp); + close_control_file (cf); return 0; } @@ -860,20 +904,20 @@ add_control_entry (ctrl_t ctrl, const char *hexgrip, const char *fmtfpr, static int ttl_from_sshcontrol (const char *hexgrip) { - FILE *fp; + control_file_t cf; int disabled, ttl; if (!hexgrip || strlen (hexgrip) != 40) return 0; /* Wrong input: Use global default. */ - if (open_control_file (&fp, 0)) + if (open_control_file (&cf, 0)) return 0; /* Error: Use the global default TTL. */ - if (search_control_file (fp, hexgrip, &disabled, &ttl, NULL) + if (search_control_file (cf, hexgrip, &disabled, &ttl, NULL) || disabled) ttl = 0; /* Use the global default if not found or disabled. */ - fclose (fp); + close_control_file (cf); return ttl; } @@ -883,21 +927,21 @@ ttl_from_sshcontrol (const char *hexgrip) static int confirm_flag_from_sshcontrol (const char *hexgrip) { - FILE *fp; + control_file_t cf; int disabled, confirm; if (!hexgrip || strlen (hexgrip) != 40) return 1; /* Wrong input: Better ask for confirmation. */ - if (open_control_file (&fp, 0)) + if (open_control_file (&cf, 0)) return 1; /* Error: Better ask for confirmation. */ - if (search_control_file (fp, hexgrip, &disabled, NULL, &confirm) + if (search_control_file (cf, hexgrip, &disabled, NULL, &confirm) || disabled) confirm = 0; /* If not found or disabled, there is no reason to ask for confirmation. */ - fclose (fp); + close_control_file (cf); return confirm; } @@ -1869,7 +1913,7 @@ ssh_handler_request_identities (ctrl_t ctrl, DIR *dir; gpg_error_t err; int ret; - FILE *ctrl_fp = NULL; + control_file_t cf = NULL; char *cardsn; gpg_error_t ret_err; @@ -1944,10 +1988,10 @@ ssh_handler_request_identities (ctrl_t ctrl, /* Fixme: We should better iterate over the control file and check - whether the key file is there. This is better in resepct to - performance if tehre are a lot of key sin our key storage. */ + whether the key file is there. This is better in respect to + performance if there are a lot of keys in our key storage. */ /* FIXME: make sure that buffer gets deallocated properly. */ - err = open_control_file (&ctrl_fp, 0); + err = open_control_file (&cf, 0); if (err) goto out; @@ -1965,7 +2009,7 @@ ssh_handler_request_identities (ctrl_t ctrl, hexgrip[40] = 0; if ( strlen (hexgrip) != 40 ) continue; - if (search_control_file (ctrl_fp, hexgrip, &disabled, NULL, NULL) + if (search_control_file (cf, hexgrip, &disabled, NULL, NULL) || disabled) continue; @@ -2051,8 +2095,7 @@ ssh_handler_request_identities (ctrl_t ctrl, if (dir) closedir (dir); - if (ctrl_fp) - fclose (ctrl_fp); + close_control_file (cf); xfree (key_directory); xfree (key_path); commit fc7d033d8e62f6a289fdf7dba26af076accb5fd2 Author: Werner Koch Date: Mon Jul 1 18:29:21 2013 +0200 ssh: Do not look for a card based ssh key if scdaemon is disabled. * agent/command-ssh.c (ssh_handler_request_identities): Do not call card_key_available if the scdaemon is disabled. -- (back ported from commit id 781e9746dff21fc2721373205e63d1d09722d590) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index e96d6f5..fe0980e 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1926,7 +1926,8 @@ ssh_handler_request_identities (ctrl_t ctrl, reader - this should be allowed even without being listed in sshcontrol. */ - if (!card_key_available (ctrl, &key_public, &cardsn)) + if (!opt.disable_scdaemon + && !card_key_available (ctrl, &key_public, &cardsn)) { err = ssh_send_key_public (key_blobs, key_public, cardsn); gcry_sexp_release (key_public); commit 7ce72c97bfe1ab2f58248a6afe629aafa20d058b Author: Werner Koch Date: Mon Jul 1 18:08:56 2013 +0200 ssh: Make the mode extension "x" portable by a call to es_fopen. * agent/command-ssh.c (open_control_file): Use_es_fopen to support the "wx" mode flag. -- This also patch also specifies a file mode parameter. However, this will only be used with an updated version of es_stream which we have not yet done. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 2f96ef5..e96d6f5 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -681,18 +681,16 @@ open_control_file (FILE **r_fp, int append) fp = fopen (fname, append? "a+":"r"); if (!fp && errno == ENOENT) { - /* Fixme: "x" is a GNU extension. We might want to use the es_ - functions here. */ - fp = fopen (fname, "wx"); - if (!fp) + estream_t stream = es_fopen (fname, "wx,mode=-rw-r"); + if (!stream) { - err = gpg_error (gpg_err_code_from_errno (errno)); + err = gpg_error_from_syserror (); log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err)); xfree (fname); return err; } - fputs (sshcontrolblurb, fp); - fclose (fp); + es_fputs (sshcontrolblurb, stream); + es_fclose (stream); fp = fopen (fname, append? "a+":"r"); } ----------------------------------------------------------------------- Summary of changes: NEWS | 3 + agent/command-ssh.c | 950 +++++++++++++++++++++++++++++++++------------------ agent/protect.c | 31 ++- agent/t-protect.c | 36 ++- common/estream.c | 103 ++++++- common/estream.h | 2 + common/ssh-utils.c | 28 ++ 7 files changed, 798 insertions(+), 355 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jul 3 15:00:07 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 03 Jul 2013 15:00:07 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.20-17-g8b0cf1f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via 8b0cf1f59e660b1562ca3421b784172df84b1c5d (commit) via 0c01a0436961af5b427a8ace8e57d12be22dbc96 (commit) via 9f32499f99a0817f63f7a73b09bdcebe60d4775d (commit) via ed056d67c7c93306b68829f83a2565e978dcfd9b (commit) via 27e403bff7a6e46a390ae5f3d63ea63701d1435d (commit) via 9b8518ffc97696634cd6d493fed872a512993c52 (commit) from a1398844adb84392f4a1da6db2e50b914a1aada1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8b0cf1f59e660b1562ca3421b784172df84b1c5d Author: Werner Koch Date: Wed Jul 3 13:40:16 2013 +0200 po: Auto updates. -- diff --git a/po/be.po b/po/be.po index d29db17..da9d281 100644 --- a/po/be.po +++ b/po/be.po @@ -345,7 +345,10 @@ msgstr "" msgid "allow presetting passphrase" msgstr "?????????????????? ????????????\n" -msgid "enable ssh-agent emulation" +msgid "enable ssh support" +msgstr "" + +msgid "enable putty support" msgstr "" msgid "|FILE|write environment settings also to FILE" diff --git a/po/ca.po b/po/ca.po index 9ccfa8a..b4957ad 100644 --- a/po/ca.po +++ b/po/ca.po @@ -375,8 +375,21 @@ msgstr "" msgid "allow presetting passphrase" msgstr "error en la creaci?? de la contrasenya: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +# G??nere? Nombre? ivb +# Werner FIXME: please add translator comment saying *what* is +# uncompressed so we know the gender. jm +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "no ??s suportat" + +# G??nere? Nombre? ivb +# Werner FIXME: please add translator comment saying *what* is +# uncompressed so we know the gender. jm +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "no ??s suportat" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7686,12 +7699,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "s'ha utilitzat una clau secreta incorrecta" -# G??nere? Nombre? ivb -# Werner FIXME: please add translator comment saying *what* is -# uncompressed so we know the gender. jm -#~ msgid "not supported" -#~ msgstr "no ??s suportat" - #~ msgid "bad key" #~ msgstr "la clau ??s incorrecta" diff --git a/po/cs.po b/po/cs.po index a94d3c9..688bcfd 100644 --- a/po/cs.po +++ b/po/cs.po @@ -373,9 +373,16 @@ msgstr "dovolit klient??m ozna??it kl????e za ???d??v??ryhodn?????" msgid "allow presetting passphrase" msgstr "umo??nit p??ednastaven?? hesla" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "zapnout emulaci ssh-agenta" +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "nepodporov??no" + msgid "|FILE|write environment settings also to FILE" msgstr "|SOUBOR|zapsat nastaven?? prost??ed?? t???? do SOUBORU" @@ -7220,9 +7227,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "je pou??it ??patn?? tajn?? kl????" -#~ msgid "not supported" -#~ msgstr "nepodporov??no" - #~ msgid "bad key" #~ msgstr "??patn?? kl????" diff --git a/po/da.po b/po/da.po index 3e9608b..365f6bd 100644 --- a/po/da.po +++ b/po/da.po @@ -358,9 +358,14 @@ msgstr "tillad klienter at markere n??gler som ??trusted?? (trov??rdige)" msgid "allow presetting passphrase" msgstr "tillad forh??ndsindstilling af adgangsfrase" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "aktiver ssh-agent-emulering" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|FIL|skriv ogs?? milj??indstillinger til FIL" diff --git a/po/el.po b/po/el.po index 02fb3f7..afc6a69 100644 --- a/po/el.po +++ b/po/el.po @@ -352,8 +352,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "?????? ??? ?????????? ??? ?????? ??????: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "??? ?????????????" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "??? ?????????????" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7520,9 +7527,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "????? ????? ???????? ????????" -#~ msgid "not supported" -#~ msgstr "??? ?????????????" - #~ msgid "bad key" #~ msgstr "???? ??????" diff --git a/po/eo.po b/po/eo.po index 89d5724..c3f568d 100644 --- a/po/eo.po +++ b/po/eo.po @@ -352,8 +352,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "eraro dum kreado de pasfrazo: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "ne realigita" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "ne realigita" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7415,9 +7422,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "mal?usta sekreta ?losilo uzata" -#~ msgid "not supported" -#~ msgstr "ne realigita" - #~ msgid "bad key" #~ msgstr "malbona ?losilo" diff --git a/po/es.po b/po/es.po index af58643..b3e9654 100644 --- a/po/es.po +++ b/po/es.po @@ -372,9 +372,16 @@ msgstr "permitir que los clientes marquen claves como \"fiables\"" msgid "allow presetting passphrase" msgstr "permitir preestablecer frase contrase?a" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "permitir emulaci?n de ssh-agent" +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "no disponible" + msgid "|FILE|write environment settings also to FILE" msgstr "|FICHERO|escribir variables de entorno tambi?n en FICHERO" @@ -7332,9 +7339,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "clave secreta incorrecta" -#~ msgid "not supported" -#~ msgstr "no disponible" - #~ msgid "bad key" #~ msgstr "clave incorrecta" diff --git a/po/et.po b/po/et.po index b4560ea..6a047e9 100644 --- a/po/et.po +++ b/po/et.po @@ -349,8 +349,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "viga parooli loomisel: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "ei ole toetatud" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "ei ole toetatud" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7417,9 +7424,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "kasutati valet salajast v?tit" -#~ msgid "not supported" -#~ msgstr "ei ole toetatud" - #~ msgid "bad key" #~ msgstr "halb v?ti" diff --git a/po/fi.po b/po/fi.po index a33efa5..15d22f4 100644 --- a/po/fi.po +++ b/po/fi.po @@ -365,8 +365,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "virhe luotaessa salasanaa: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "ei tuettu" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "ei tuettu" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7502,9 +7509,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "k??ytetty salainen avain on v????r??" -#~ msgid "not supported" -#~ msgstr "ei tuettu" - #~ msgid "bad key" #~ msgstr "avain ei kelpaa" diff --git a/po/fr.po b/po/fr.po index 17d33d5..61faa9b 100644 --- a/po/fr.po +++ b/po/fr.po @@ -356,9 +356,16 @@ msgstr "permettre de marquer la confiance des clefs" msgid "allow presetting passphrase" msgstr "permettre de pr??configurer la phrase de passe" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "activer l'??mulation de ssh-agent" +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "non pris en charge" + msgid "|FILE|write environment settings also to FILE" msgstr "|FICHIER|??crire aussi les r??glages d'env. dans FICHIER" @@ -7339,9 +7346,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "mauvaise clef secr??te utilis??e" -#~ msgid "not supported" -#~ msgstr "non pris en charge" - #~ msgid "bad key" #~ msgstr "mauvaise clef" diff --git a/po/gl.po b/po/gl.po index c54c55b..fb7a180 100644 --- a/po/gl.po +++ b/po/gl.po @@ -352,8 +352,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "erro ao crea-lo contrasinal: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "non est? soportado" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "non est? soportado" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7526,9 +7533,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "empregouse unha chave secreta err?nea" -#~ msgid "not supported" -#~ msgstr "non est? soportado" - #~ msgid "bad key" #~ msgstr "chave incorrecta" diff --git a/po/hu.po b/po/hu.po index d63681d..2aa53f6 100644 --- a/po/hu.po +++ b/po/hu.po @@ -349,8 +349,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "Hiba a jelsz? l?trehoz?sakor: %s.\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "nem t?mogatott" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "nem t?mogatott" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7463,9 +7470,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "rossz titkos kulcs haszn?lata" -#~ msgid "not supported" -#~ msgstr "nem t?mogatott" - #~ msgid "bad key" #~ msgstr "rossz kulcs" diff --git a/po/id.po b/po/id.po index 9a5b483..8cf6765 100644 --- a/po/id.po +++ b/po/id.po @@ -354,8 +354,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "kesalahan penciptaan passphrase: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "tidak didukung" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "tidak didukung" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7464,9 +7471,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "digunakan kunci rahasia yang salah" -#~ msgid "not supported" -#~ msgstr "tidak didukung" - #~ msgid "bad key" #~ msgstr "kunci yang buruk" diff --git a/po/it.po b/po/it.po index 3b8b797..eed6c30 100644 --- a/po/it.po +++ b/po/it.po @@ -349,8 +349,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "errore nella creazione della passhprase: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "non gestito" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "non gestito" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7521,9 +7528,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "? stata usata la chiave segreta sbagliata" -#~ msgid "not supported" -#~ msgstr "non gestito" - #~ msgid "bad key" #~ msgstr "chiave sbagliata" diff --git a/po/ja.po b/po/ja.po index d3ab450..6944f33 100644 --- a/po/ja.po +++ b/po/ja.po @@ -342,9 +342,14 @@ msgstr "???????????????????????????\"trusted\"????????????????????????????????? msgid "allow presetting passphrase" msgstr "?????????????????????????????????????????????" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "ssh-agent??????????????????????????????????????????" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|FILE|FILE???????????????????????????????????????" diff --git a/po/nb.po b/po/nb.po index 8fd63eb..809016d 100644 --- a/po/nb.po +++ b/po/nb.po @@ -361,7 +361,10 @@ msgstr "" msgid "allow presetting passphrase" msgstr "feil ved opprettelse av passfrase: %s\n" -msgid "enable ssh-agent emulation" +msgid "enable ssh support" +msgstr "" + +msgid "enable putty support" msgstr "" msgid "|FILE|write environment settings also to FILE" diff --git a/po/pl.po b/po/pl.po index 27a4e95..62abfa5 100644 --- a/po/pl.po +++ b/po/pl.po @@ -352,9 +352,14 @@ msgstr "zezwolenie klientom na oznaczanie kluczy jako \"zaufanych\"" msgid "allow presetting passphrase" msgstr "zezwolenie na predefiniowane has?o" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "w??czenie emulacji ssh-agenta" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|PLIK|zapis ustawie? ?rodowiska tak?e do PLIKU" diff --git a/po/pt.po b/po/pt.po index 915bac2..302399f 100644 --- a/po/pt.po +++ b/po/pt.po @@ -353,8 +353,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "erro na cria??o da frase secreta: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "n?o suportado" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "n?o suportado" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7459,9 +7466,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "chave secreta incorrecta" -#~ msgid "not supported" -#~ msgstr "n?o suportado" - #~ msgid "bad key" #~ msgstr "chave incorrecta" diff --git a/po/pt_BR.po b/po/pt_BR.po index 523b5ec..0a1aff5 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -357,8 +357,17 @@ msgstr "" msgid "allow presetting passphrase" msgstr "erro na cria??o da frase secreta: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +# suportado ??? +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "n?o suportado" + +# suportado ??? +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "n?o suportado" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7289,10 +7298,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "chave secreta incorreta" -# suportado ??? -#~ msgid "not supported" -#~ msgstr "n?o suportado" - #~ msgid "bad key" #~ msgstr "chave incorreta" diff --git a/po/ro.po b/po/ro.po index 173c800..6583ef9 100644 --- a/po/ro.po +++ b/po/ro.po @@ -363,8 +363,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "eroare la crearea frazei-parol?: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "nu este suportat(?)" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "nu este suportat(?)" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7413,9 +7420,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "a fost folosit? o cheie secret? gre?it?" -#~ msgid "not supported" -#~ msgstr "nu este suportat(?)" - #~ msgid "bad key" #~ msgstr "cheie incorect?" diff --git a/po/ru.po b/po/ru.po index 99ef956..0d6e3b2 100644 --- a/po/ru.po +++ b/po/ru.po @@ -355,9 +355,14 @@ msgstr "?????????????????? ???????????????? ???????????????? ?????????? ?????? \ msgid "allow presetting passphrase" msgstr "?????????????????? ?????????????????????????????????? ??????????-????????????" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "?????????????????? ???????????????? ssh-????????????" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|FILE|?????????????????? ?????????????????? ?????????????????? ?? ?? ????????" diff --git a/po/sk.po b/po/sk.po index 004c07e..12be517 100644 --- a/po/sk.po +++ b/po/sk.po @@ -352,8 +352,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "chyba pri vytv?ran? hesla: %s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "nepodporovan?" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "nepodporovan?" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7482,9 +7489,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "bol pou?it? nespr?vny tajn? k???" -#~ msgid "not supported" -#~ msgstr "nepodporovan?" - #~ msgid "bad key" #~ msgstr "nespr?vny k???" diff --git a/po/sv.po b/po/sv.po index b9c1ba4..9a62da2 100644 --- a/po/sv.po +++ b/po/sv.po @@ -372,9 +372,14 @@ msgstr "till??t klienter att markera nycklar som \"trusted\"" msgid "allow presetting passphrase" msgstr "till??t f??rinst??llning av l??senfras" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "aktivera ssh-agent-emulering" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|FIL|skriv ??ven milj??inst??llningar till FIL" diff --git a/po/tr.po b/po/tr.po index 40bcbbb..1c73672 100644 --- a/po/tr.po +++ b/po/tr.po @@ -347,9 +347,14 @@ msgstr "istemcilerin anahtarlar?? \"g??venilir\" olarak imlemesine izin verilir" msgid "allow presetting passphrase" msgstr "anahtar parolas??n??n ??nceden atanmas??na izin verilir" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "ssh-agent ??yk??n??m?? etkinle??ir" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "|DOSYA|ortam ayarlar??n?? ayr??ca DOSYAya da yazar" diff --git a/po/uk.po b/po/uk.po index e14cc6e..571c754 100644 --- a/po/uk.po +++ b/po/uk.po @@ -357,9 +357,14 @@ msgstr "?????????????????? ???????????????? ?????????????????? ?????????? ???? msgid "allow presetting passphrase" msgstr "?????????????????? ?????????????????? ???????????????????????? ????????????" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "?????????????????? ???????????????? ssh-????????????" +msgid "enable putty support" +msgstr "" + msgid "|FILE|write environment settings also to FILE" msgstr "???????????????? ?????????????????? ???????????????????? ?? ???? ??????????" diff --git a/po/zh_CN.po b/po/zh_CN.po index f8ed174..7f1a90f 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -361,8 +361,15 @@ msgstr "" msgid "allow presetting passphrase" msgstr "????????????????????????????????????%s\n" -msgid "enable ssh-agent emulation" -msgstr "" +#, fuzzy +#| msgid "not supported" +msgid "enable ssh support" +msgstr "????????????" + +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "????????????" msgid "|FILE|write environment settings also to FILE" msgstr "" @@ -7183,9 +7190,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "????????????????????????" -#~ msgid "not supported" -#~ msgstr "????????????" - #~ msgid "bad key" #~ msgstr "???????????????" diff --git a/po/zh_TW.po b/po/zh_TW.po index 5ffea7a..7c6df10 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -336,9 +336,16 @@ msgstr "????????????????????????????????? \"?????????\"" msgid "allow presetting passphrase" msgstr "????????????????????????" -msgid "enable ssh-agent emulation" +#, fuzzy +#| msgid "enable ssh-agent emulation" +msgid "enable ssh support" msgstr "?????? ssh-agent ??????" +#, fuzzy +#| msgid "not supported" +msgid "enable putty support" +msgstr "?????????" + msgid "|FILE|write environment settings also to FILE" msgstr "|??????|????????????????????????????????????" @@ -7006,9 +7013,6 @@ msgstr "" #~ msgid "wrong secret key used" #~ msgstr "?????????????????????" -#~ msgid "not supported" -#~ msgstr "?????????" - #~ msgid "bad key" #~ msgstr "???????????????" commit 0c01a0436961af5b427a8ace8e57d12be22dbc96 Author: Werner Koch Date: Wed Jul 3 13:32:52 2013 +0200 Update the German translation. diff --git a/po/de.po b/po/de.po index cb89471..14ff5f1 100644 --- a/po/de.po +++ b/po/de.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg-2.0.18\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"PO-Revision-Date: 2013-04-24 09:33+0200\n" +"PO-Revision-Date: 2013-07-03 13:32+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: German \n" "Language: de\n" @@ -359,8 +359,11 @@ msgstr "erlaube Aufrufern Schl??ssel als \"vertrauensw??rdig\" zu markieren" msgid "allow presetting passphrase" msgstr "erlaube ein \"preset\" von Passphrases" -msgid "enable ssh-agent emulation" -msgstr "Die ssh-agent-Emulation anschalten" +msgid "enable ssh support" +msgstr "Die ssh-agent Komponente anschalten" + +msgid "enable putty support" +msgstr "Die Pageant Komponente anschalten" msgid "|FILE|write environment settings also to FILE" msgstr "|DATEI|Schreibe die Umgebungsvariablen auf DATEI" commit 9f32499f99a0817f63f7a73b09bdcebe60d4775d Author: Werner Koch Date: Wed Jul 3 13:29:47 2013 +0200 ssh: Add support for Putty. * agent/gpg-agent.c [W32]: Include Several Windows header. (opts): Change help text for enable-ssh-support. (opts, main): Add option --enable-putty-support (putty_support, PUTTY_IPC_MAGIC, PUTTY_IPC_MAXLEN): New for W32. (agent_init_default_ctrl): Add and asssert call. (putty_message_proc, putty_message_thread): New. (handle_connections) [W32]: Start putty message thread. * common/sysutils.c (w32_get_user_sid): New for W32 only * tools/gpgconf-comp.c (gc_options_gpg_agent): Add --enable-ssh-support and --enable-putty-support. Make the configuration group visible at basic level. * agent/command-ssh.c (serve_mmapped_ssh_request): New for W32 only. -- This patch enables support for Putty. It has been tested with Putty 0.62 using an Unix created ssh key copied to the private-keys-v1.d directory on Windows and with a manually crafted sshcontrol file. It also works with a smartcard key. May thanks to gniibe who implemented a proxy in Python to test the putty/gpg-agent communication. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 4295ee9..adaa257 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ Noteworthy changes in version 2.0.21 (unreleased) * The included ssh agent does now support ECDSA keys. + * New option --enable-putty-support to allow gpg-agent to act as a + Pageant replacement including full smartcard support. + Noteworthy changes in version 2.0.20 (2013-05-10) ------------------------------------------------- diff --git a/agent/agent.h b/agent/agent.h index 15cf8bf..4afe6e9 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -220,6 +220,10 @@ gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...) void bump_key_eventcounter (void); void bump_card_eventcounter (void); void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t); +#ifdef HAVE_W32_SYSTEM +int serve_mmapped_ssh_request (ctrl_t ctrl, + unsigned char *request, size_t maxreqlen); +#endif /*HAVE_W32_SYSTEM*/ /*-- command-ssh.c --*/ void start_command_handler_ssh (ctrl_t, gnupg_fd_t); diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 4cd3537..6533730 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -3362,3 +3362,149 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client) if (stream_sock) es_fclose (stream_sock); } + + +#ifdef HAVE_W32_SYSTEM +/* Serve one ssh-agent request. This is used for the Putty support. + REQUEST is the the mmapped memory which may be accessed up to a + length of MAXREQLEN. Returns 0 on success which also indicates + that a valid SSH response message is now in REQUEST. */ +int +serve_mmapped_ssh_request (ctrl_t ctrl, + unsigned char *request, size_t maxreqlen) +{ + gpg_error_t err; + int send_err = 0; + int valid_response = 0; + ssh_request_spec_t *spec; + u32 msglen; + estream_t request_stream, response_stream; + + if (setup_ssh_env (ctrl)) + goto leave; /* Error setting up the environment. */ + + if (maxreqlen < 5) + goto leave; /* Caller error. */ + + msglen = uint32_construct (request[0], request[1], request[2], request[3]); + if (msglen < 1 || msglen > maxreqlen - 4) + { + log_error ("ssh message len (%u) out of range", (unsigned int)msglen); + goto leave; + } + + spec = request_spec_lookup (request[4]); + if (!spec) + { + send_err = 1; /* Unknown request type. */ + goto leave; + } + + /* Create a stream object with the data part of the request. */ + if (spec->secret_input) + request_stream = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); + else + request_stream = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+"); + if (!request_stream) + { + err = gpg_error_from_syserror (); + goto leave; + } + /* We have to disable the estream buffering, because the estream + core doesn't know about secure memory. */ + if (es_setvbuf (request_stream, NULL, _IONBF, 0)) + { + err = gpg_error_from_syserror (); + goto leave; + } + /* Copy the request to the stream but omit the request type. */ + err = stream_write_data (request_stream, request + 5, msglen - 1); + if (err) + goto leave; + es_rewind (request_stream); + + response_stream = es_fopenmem (0, "r+b"); + if (!response_stream) + { + err = gpg_error_from_syserror (); + goto leave; + } + + if (opt.verbose) + log_info ("ssh request handler for %s (%u) started\n", + spec->identifier, spec->type); + + err = (*spec->handler) (ctrl, request_stream, response_stream); + + if (opt.verbose) + { + if (err) + log_info ("ssh request handler for %s (%u) failed: %s\n", + spec->identifier, spec->type, gpg_strerror (err)); + else + log_info ("ssh request handler for %s (%u) ready\n", + spec->identifier, spec->type); + } + + es_fclose (request_stream); + request_stream = NULL; + + if (err) + { + send_err = 1; + goto leave; + } + + /* Put the response back into the mmapped buffer. */ + { + void *response_data; + size_t response_size; + + /* NB: In contrast to the request-stream, the response stream + includes the the message type byte. */ + if (es_fclose_snatch (response_stream, &response_data, &response_size)) + { + log_error ("snatching ssh response failed: %s", + gpg_strerror (gpg_error_from_syserror ())); + send_err = 1; /* Ooops. */ + goto leave; + } + + if (opt.verbose > 1) + log_info ("sending ssh response of length %u\n", + (unsigned int)response_size); + if (response_size > maxreqlen - 4) + { + log_error ("invalid length of the ssh response: %s", + gpg_strerror (GPG_ERR_INTERNAL)); + es_free (response_data); + send_err = 1; + goto leave; + } + + request[0] = response_size >> 24; + request[1] = response_size >> 16; + request[2] = response_size >> 8; + request[3] = response_size >> 0; + memcpy (request+4, response_data, response_size); + es_free (response_data); + valid_response = 1; + } + + leave: + if (send_err) + { + request[0] = 0; + request[1] = 0; + request[2] = 0; + request[3] = 1; + request[4] = SSH_RESPONSE_FAILURE; + valid_response = 1; + } + + /* Reset the SCD in case it has been used. */ + agent_reset_scd (ctrl); + + return valid_response? 0 : -1; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ba25875..9d53de9 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1,6 +1,7 @@ /* gpg-agent.c - The GnuPG Agent * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2007, 2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch * * This file is part of GnuPG. * @@ -30,7 +31,16 @@ #include #include #include -#ifndef HAVE_W32_SYSTEM +#ifdef HAVE_W32_SYSTEM +# ifndef WINVER +# define WINVER 0x0500 /* Same as in common/sysutils.c */ +# endif +# ifdef HAVE_WINSOCK2_H +# include +# endif +# include +# include +#else /*!HAVE_W32_SYSTEM*/ # include # include #endif /*!HAVE_W32_SYSTEM*/ @@ -106,6 +116,7 @@ enum cmd_and_opt_values oKeepTTY, oKeepDISPLAY, oSSHSupport, + oPuttySupport, oDisableScdaemon, oWriteEnvFile }; @@ -177,7 +188,14 @@ static ARGPARSE_OPTS opts[] = { N_("allow clients to mark keys as \"trusted\"")}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, - { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") }, + { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh support") }, + { oPuttySupport, "enable-putty-support", 0, +#ifdef HAVE_W32_SYSTEM + N_("enable putty support") +#else + "@" +#endif + }, { oWriteEnvFile, "write-env-file", 2|8, N_("|FILE|write environment settings also to FILE")}, {0} @@ -202,6 +220,17 @@ static ARGPARSE_OPTS opts[] = { #endif +#ifdef HAVE_W32_SYSTEM +/* Flag indicating that support for Putty has been enabled. */ +static int putty_support; +/* A magic value used with WM_COPYDATA. */ +#define PUTTY_IPC_MAGIC 0x804e50ba +/* To avoid surprises we limit the size of the mapped IPC file to this + value. Putty currently (0.62) uses 8k, thus 16k should be enough + for the foreseeable future. */ +#define PUTTY_IPC_MAXLEN 16384 +#endif /*HAVE_W32_SYSTEM*/ + /* The list of open file descriptors at startup. Note that this list has been allocated using the standard malloc. */ static int *startup_fd_list; @@ -805,6 +834,13 @@ main (int argc, char **argv ) case oKeepDISPLAY: opt.keep_display = 1; break; case oSSHSupport: opt.ssh_support = 1; break; + case oPuttySupport: +# ifdef HAVE_W32_SYSTEM + putty_support = 1; + opt.ssh_support = 1; +# endif + break; + case oWriteEnvFile: if (pargs.r_type) env_file_name = pargs.r.ret_str; @@ -928,6 +964,11 @@ main (int argc, char **argv ) GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("disable-scdaemon:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); +#ifdef HAVE_W32_SYSTEM + printf ("enable-putty-support:%lu:\n", GC_OPT_FLAG_NONE); +#else + printf ("enable-ssh-support:%lu:\n", GC_OPT_FLAG_NONE); +#endif agent_exit (0); } @@ -1292,6 +1333,8 @@ agent_exit (int rc) static void agent_init_default_ctrl (ctrl_t ctrl) { + assert (ctrl->session_env); + /* Note we ignore malloc errors because we can't do much about it and the request will fail anyway shortly after this initialization. */ @@ -1309,7 +1352,6 @@ agent_init_default_ctrl (ctrl_t ctrl) xfree (ctrl->lc_messages); ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages) /**/ : NULL; - } @@ -1788,6 +1830,199 @@ check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce) } +#ifdef HAVE_W32_SYSTEM +/* The window message processing function for Putty. Warning: This + code runs as a native Windows thread. Use of our own functions + needs to be bracket with pth_leave/pth_enter. */ +static LRESULT CALLBACK +putty_message_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + int ret = 0; + int w32rc; + COPYDATASTRUCT *cds; + const char *mapfile; + HANDLE maphd; + PSID mysid = NULL; + PSID mapsid = NULL; + void *data = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + ctrl_t ctrl = NULL; + + if (msg != WM_COPYDATA) + { + /* pth_leave (); */ + /* log_debug ("putty loop: received WM_%u\n", msg ); */ + /* pth_enter (); */ + return DefWindowProc (hwnd, msg, wparam, lparam); + } + + cds = (COPYDATASTRUCT*)lparam; + if (cds->dwData != PUTTY_IPC_MAGIC) + return 0; /* Ignore data with the wrong magic. */ + mapfile = cds->lpData; + if (!cds->cbData || mapfile[cds->cbData - 1]) + return 0; /* Ignore empty and non-properly terminated strings. */ + + if (DBG_ASSUAN) + { + pth_leave (); + log_debug ("ssh map file '%s'", mapfile); + pth_enter (); + } + + maphd = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE, mapfile); + if (DBG_ASSUAN) + { + pth_leave (); + log_debug ("ssh map handle %p\n", maphd); + pth_enter (); + } + + if (!maphd || maphd == INVALID_HANDLE_VALUE) + return 0; + + pth_leave (); + + mysid = w32_get_user_sid (); + if (!mysid) + { + log_error ("error getting my sid\n"); + goto leave; + } + + w32rc = GetSecurityInfo (maphd, SE_KERNEL_OBJECT, + OWNER_SECURITY_INFORMATION, + &mapsid, NULL, NULL, NULL, + &psd); + if (w32rc) + { + log_error ("error getting sid of ssh map file: rc=%d", w32rc); + goto leave; + } + + if (DBG_ASSUAN) + { + char *sidstr; + + if (!ConvertSidToStringSid (mysid, &sidstr)) + sidstr = NULL; + log_debug (" my sid: '%s'", sidstr? sidstr: "[error]"); + LocalFree (sidstr); + if (!ConvertSidToStringSid (mapsid, &sidstr)) + sidstr = NULL; + log_debug ("ssh map file sid: '%s'", sidstr? sidstr: "[error]"); + LocalFree (sidstr); + } + + if (!EqualSid (mysid, mapsid)) + { + log_error ("ssh map file has a non-matching sid\n"); + goto leave; + } + + data = MapViewOfFile (maphd, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (DBG_ASSUAN) + log_debug ("ssh IPC buffer at %p\n", data); + if (!data) + goto leave; + + /* log_printhex ("request:", data, 20); */ + + ctrl = xtrycalloc (1, sizeof *ctrl); + if (!ctrl) + { + log_error ("error allocating connection control data: %s\n", + strerror (errno) ); + goto leave; + } + ctrl->session_env = session_env_new (); + if (!ctrl->session_env) + { + log_error ("error allocating session environment block: %s\n", + strerror (errno) ); + goto leave; + } + + agent_init_default_ctrl (ctrl); + if (!serve_mmapped_ssh_request (ctrl, data, PUTTY_IPC_MAXLEN)) + ret = 1; /* Valid ssh message has been constructed. */ + agent_deinit_default_ctrl (ctrl); + /* log_printhex (" reply:", data, 20); */ + + leave: + xfree (ctrl); + if (data) + UnmapViewOfFile (data); + xfree (mapsid); + if (psd) + LocalFree (psd); + xfree (mysid); + CloseHandle (maphd); + + pth_enter (); + + return ret; +} +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +/* The thread handling Putty's IPC requests. */ +static void * +putty_message_thread (void *arg) +{ + WNDCLASS wndwclass = {0, putty_message_proc, 0, 0, + NULL, NULL, NULL, NULL, NULL, "Pageant"}; + HWND hwnd; + MSG msg; + + (void)arg; + + if (opt.verbose) + log_info ("putty message loop thread 0x%lx started\n", pth_thread_id ()); + + /* The message loop runs as thread independet from out Pth system. + This also meand that we need to make sure that we switch back to + our system before calling any no-windows function. */ + pth_enter (); + + /* First create a window to make sure that a message queue exists + for this thread. */ + if (!RegisterClass (&wndwclass)) + { + pth_leave (); + log_error ("error registering Pageant window class"); + return NULL; + } + hwnd = CreateWindowEx (0, "Pageant", "Pageant", 0, + 0, 0, 0, 0, + HWND_MESSAGE, /* hWndParent */ + NULL, /* hWndMenu */ + NULL, /* hInstance */ + NULL); /* lpParm */ + if (!hwnd) + { + pth_leave (); + log_error ("error creating Pageant window"); + return NULL; + } + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* Back to Pth. */ + pth_leave (); + + if (opt.verbose) + log_info ("putty message loop thread 0x%lx stopped\n", pth_thread_id ()); + return NULL; +} +#endif /*HAVE_W32_SYSTEM*/ + + /* This is the standard connection thread's main function. */ static void * start_connection_thread (void *arg) @@ -1897,6 +2132,21 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh) #endif time_ev = NULL; + /* On Windows we need to fire up a separate thread to listen for + requests from Putty (an SSH client), so we can replace Putty's + Pageant (its ssh-agent implementation). */ +#ifdef HAVE_W32_SYSTEM + if (putty_support) + { + pth_attr_set (tattr, PTH_ATTR_NAME, "putty message loop"); + if (!pth_spawn (tattr, putty_message_thread, NULL)) + { + log_error ("error spawning putty message loop: %s\n", + strerror (errno) ); + } + } +#endif /*HAVE_W32_SYSTEM*/ + /* Set a flag to tell call-scd.c that it may enable event notifications. */ opt.sigusr2_enabled = 1; diff --git a/common/sysutils.c b/common/sysutils.c index 82bc81f..8f93ff5 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -1,6 +1,7 @@ /* sysutils.c - system helpers * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, * 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 2013 Werner Koch * * This file is part of GnuPG. * @@ -495,3 +496,59 @@ gnupg_allow_set_foregound_window (pid_t pid) (unsigned long)pid, w32_strerror (-1)); #endif } + + +#ifdef HAVE_W32_SYSTEM +/* Return the user's security identifier from the current process. */ +PSID +w32_get_user_sid (void) +{ + int okay = 0; + HANDLE proc = NULL; + HANDLE token = NULL; + TOKEN_USER *user = NULL; + PSID sid = NULL; + DWORD tokenlen, sidlen; + + proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId()); + if (!proc) + goto leave; + + if (!OpenProcessToken (proc, TOKEN_QUERY, &token)) + goto leave; + + if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen) + && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto leave; + + user = xtrymalloc (tokenlen); + if (!user) + goto leave; + + if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen)) + goto leave; + if (!IsValidSid (user->User.Sid)) + goto leave; + sidlen = GetLengthSid (user->User.Sid); + sid = xtrymalloc (sidlen); + if (!sid) + goto leave; + if (!CopySid (sidlen, sid, user->User.Sid)) + goto leave; + okay = 1; + + leave: + xfree (user); + if (token) + CloseHandle (token); + if (proc) + CloseHandle (proc); + + if (!okay) + { + xfree (sid); + sid = NULL; + } + return sid; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/common/sysutils.h b/common/sysutils.h index fd4340f..0a05e2b 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -51,8 +51,9 @@ void gnupg_allow_set_foregound_window (pid_t pid); #ifdef HAVE_W32_SYSTEM +void *w32_get_user_sid (void); -#include "../jnlib/w32help.h" +# include "../jnlib/w32help.h" #endif /*HAVE_W32_SYSTEM*/ diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 49c082b..72e7134 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -482,7 +482,7 @@ static gc_option_t gc_options_gpg_agent[] = GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Configuration", - GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", @@ -490,6 +490,12 @@ static gc_option_t gc_options_gpg_agent[] = { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "do not use the SCdaemon", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "enable ssh support", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "enable putty support", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, commit ed056d67c7c93306b68829f83a2565e978dcfd9b Author: Werner Koch Date: Wed Jul 3 13:10:29 2013 +0200 agent: Fix binary vs. text mode problem in ssh. * agent/command-ssh.c (file_to_buffer) (ssh_handler_request_identities): Open streams in binary mode. (start_command_handler_ssh): Factor some code out to .. (setup_ssh_env): new function. -- This is for now a theoretical fix because there is no ssh client yet which uses the GnuPG style IPC. OpenSSL for Cygwin uses only a quite similar one. gniibe suggested to implement that IPC style in Libassuan so that a Cygwin version of OpenSSL may be used with GnuPG. Signed-off-by: Werner Koch diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 5da1a71..4cd3537 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -683,7 +683,7 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) buffer_new = NULL; err = 0; - stream = es_fopen (filename, "r"); + stream = es_fopen (filename, "rb"); if (! stream) { err = gpg_error_from_syserror (); @@ -2200,7 +2200,7 @@ ssh_handler_request_identities (ctrl_t ctrl, key_counter = 0; err = 0; - key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+b"); if (! key_blobs) { err = gpg_error_from_syserror (); @@ -3275,44 +3275,51 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) return !!err; } -/* Start serving client on SOCK_CLIENT. */ -void -start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client) + +/* Because the ssh protocol does not send us information about the the + current TTY setting, we use this function to use those from startup + or those explictly set. */ +static gpg_error_t +setup_ssh_env (ctrl_t ctrl) { - estream_t stream_sock = NULL; + static const char *names[] = + {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL}; gpg_error_t err = 0; - int ret; + int idx; + const char *value; - /* Because the ssh protocol does not send us information about the - the current TTY setting, we resort here to use those from startup - or those explictly set. */ - { - static const char *names[] = - {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL}; - int idx; - const char *value; + for (idx=0; !err && names[idx]; idx++) + if (!session_env_getenv (ctrl->session_env, names[idx]) + && (value = session_env_getenv (opt.startup_env, names[idx]))) + err = session_env_setenv (ctrl->session_env, names[idx], value); - for (idx=0; !err && names[idx]; idx++) - if (!session_env_getenv (ctrl->session_env, names[idx]) - && (value = session_env_getenv (opt.startup_env, names[idx]))) - err = session_env_setenv (ctrl->session_env, names[idx], value); + if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype) + if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype))) + err = gpg_error_from_syserror (); - if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype) - if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype))) - err = gpg_error_from_syserror (); + if (!err && !ctrl->lc_messages && opt.startup_lc_messages) + if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages))) + err = gpg_error_from_syserror (); - if (!err && !ctrl->lc_messages && opt.startup_lc_messages) - if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages))) - err = gpg_error_from_syserror (); + if (err) + log_error ("error setting default session environment: %s\n", + gpg_strerror (err)); - if (err) - { - log_error ("error setting default session environment: %s\n", - gpg_strerror (err)); - goto out; - } - } + return err; +} + + +/* Start serving client on SOCK_CLIENT. */ +void +start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client) +{ + estream_t stream_sock = NULL; + gpg_error_t err; + int ret; + err = setup_ssh_env (ctrl); + if (err) + goto out; /* Create stream from socket. */ stream_sock = es_fdopen (FD2INT(sock_client), "r+"); commit 27e403bff7a6e46a390ae5f3d63ea63701d1435d Author: Werner Koch Date: Wed Jul 3 12:59:56 2013 +0200 Silence deprecated warnings from gcc 4.6.3. * configure.ac (AH_BOTTOM): Define GCRYPT_NO_DEPRECATED. -- Frankly, I don't understand why gcc prints them. We don't use them. Signed-off-by: Werner Koch diff --git a/configure.ac b/configure.ac index b85124c..702b8d3 100644 --- a/configure.ac +++ b/configure.ac @@ -442,6 +442,9 @@ AH_BOTTOM([ /* We don't want the old assuan codes anymore. */ #define _ASSUAN_ONLY_GPG_ERRORS 1 +/* We don't need any of the old gcrypt functions. */ +#define GCRYPT_NO_DEPRECATED 1 + /* We explicitly need to disable PTH's soft mapping as Debian currently enables it by default for no reason. */ #define PTH_SYSCALL_SOFT 0 commit 9b8518ffc97696634cd6d493fed872a512993c52 Author: Werner Koch Date: Wed Jul 3 09:30:22 2013 +0200 estream: Backport es_fopemem_init from master. * common/estream.c (es_fopenmem_init): New. Signed-off-by: Werner Koch diff --git a/common/estream.c b/common/estream.c index 304e0e6..35b2af0 100644 --- a/common/estream.c +++ b/common/estream.c @@ -2362,6 +2362,38 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode) } +/* This is the same as es_fopenmem but intializes the memory with a + copy of (DATA,DATALEN). The stream is initally set to the + beginning. If MEMLIMIT is not 0 but shorter than DATALEN it + DATALEN will be used as the value for MEMLIMIT. */ +estream_t +es_fopenmem_init (size_t memlimit, const char *ES__RESTRICT mode, + const void *data, size_t datalen) +{ + estream_t stream; + + if (memlimit && memlimit < datalen) + memlimit = datalen; + + stream = es_fopenmem (memlimit, mode); + if (stream && data && datalen) + { + if (es_writen (stream, data, datalen, NULL)) + { + int saveerrno = errno; + es_fclose (stream); + stream = NULL; + _set_errno (saveerrno); + } + else + { + es_seek (stream, 0L, SEEK_SET, NULL); + es_set_indicators (stream, 0, 0); + } + } + return stream; +} + estream_t es_fopencookie (void *ES__RESTRICT cookie, diff --git a/common/estream.h b/common/estream.h index f72e4c6..35df20b 100644 --- a/common/estream.h +++ b/common/estream.h @@ -76,6 +76,7 @@ #define es_fopen _ESTREAM_PREFIX(es_fopen) #define es_mopen _ESTREAM_PREFIX(es_mopen) #define es_fopenmem _ESTREAM_PREFIX(es_fopenmem) +#define es_fopenmem_init _ESTREAM_PREFIX(es_fopenmem_init) #define es_fdopen _ESTREAM_PREFIX(es_fdopen) #define es_fdopen_nc _ESTREAM_PREFIX(es_fdopen_nc) #define es_fpopen _ESTREAM_PREFIX(es_fpopen) @@ -243,6 +244,8 @@ estream_t es_mopen (unsigned char *ES__RESTRICT data, void (*func_free) (void *mem), const char *ES__RESTRICT mode); estream_t es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode); +estream_t es_fopenmem_init (size_t memlimit, const char *ES__RESTRICT mode, + const void *data, size_t datalen); estream_t es_fdopen (int filedes, const char *mode); estream_t es_fdopen_nc (int filedes, const char *mode); estream_t es_fpopen (FILE *fp, const char *mode); ----------------------------------------------------------------------- Summary of changes: NEWS | 3 + agent/agent.h | 4 + agent/command-ssh.c | 217 ++++++++++++++++++++++++++++++++++++------ agent/gpg-agent.c | 256 +++++++++++++++++++++++++++++++++++++++++++++++++- common/estream.c | 32 ++++++ common/estream.h | 3 + common/sysutils.c | 57 +++++++++++ common/sysutils.h | 3 +- configure.ac | 3 + po/be.po | 5 +- po/ca.po | 23 +++-- po/cs.po | 12 ++- po/da.po | 7 +- po/de.po | 9 +- po/el.po | 14 ++- po/eo.po | 14 ++- po/es.po | 12 ++- po/et.po | 14 ++- po/fi.po | 14 ++- po/fr.po | 12 ++- po/gl.po | 14 ++- po/hu.po | 14 ++- po/id.po | 14 ++- po/it.po | 14 ++- po/ja.po | 7 +- po/nb.po | 5 +- po/pl.po | 7 +- po/pt.po | 14 ++- po/pt_BR.po | 17 ++- po/ro.po | 14 ++- po/ru.po | 7 +- po/sk.po | 14 ++- po/sv.po | 7 +- po/tr.po | 7 +- po/uk.po | 7 +- po/zh_CN.po | 14 ++- po/zh_TW.po | 12 ++- tools/gpgconf-comp.c | 8 ++- 38 files changed, 771 insertions(+), 139 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jul 3 16:04:00 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 03 Jul 2013 16:04:00 +0200 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.20-20-gc3a57d7 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via c3a57d767719a58ec791a0791842bcc80c859081 (commit) via ebbce67489b8d0eded74be66cbd6bf42f5147725 (commit) via 90b419f3e9d05e509348d047e05fcc79e87be6cf (commit) from 8b0cf1f59e660b1562ca3421b784172df84b1c5d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c3a57d767719a58ec791a0791842bcc80c859081 Author: Werner Koch Date: Wed Jul 3 15:22:00 2013 +0200 po: Auto updates. -- diff --git a/po/be.po b/po/be.po index da9d281..3b64370 100644 --- a/po/be.po +++ b/po/be.po @@ -283,10 +283,10 @@ msgstr "" "????????????:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -338,7 +338,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/ca.po b/po/ca.po index b4957ad..ef417f7 100644 --- a/po/ca.po +++ b/po/ca.po @@ -308,10 +308,10 @@ msgstr "" "Opcions:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" # Un dels dos ??s en la llista d'opcions amb --help. Urgh. jm @@ -368,7 +368,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/cs.po b/po/cs.po index 688bcfd..7b21586 100644 --- a/po/cs.po +++ b/po/cs.po @@ -313,12 +313,12 @@ msgstr "" "@Volby:\n" " " -msgid "run in server mode (foreground)" -msgstr "b????et v??re??imu serveru (na pop??ed??)" - msgid "run in daemon mode (background)" msgstr "b????en v??re??imu d??mona (na pozad??)" +msgid "run in server mode (foreground)" +msgstr "b????et v??re??imu serveru (na pop??ed??)" + msgid "verbose" msgstr "s dodate??n??mi informacemi" @@ -367,7 +367,9 @@ msgstr "|N|zahodit zapamatovan?? PINy po N sekund??ch" msgid "do not use the PIN cache when signing" msgstr "nepou????vat pam???? PIN?? na podepisov??n??" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "dovolit klient??m ozna??it kl????e za ???d??v??ryhodn?????" msgid "allow presetting passphrase" diff --git a/po/da.po b/po/da.po index 365f6bd..f64b87c 100644 --- a/po/da.po +++ b/po/da.po @@ -298,12 +298,12 @@ msgstr "" "@Indstillinger:\n" " " -msgid "run in server mode (foreground)" -msgstr "k??r i servertilstand (forgrunden)" - msgid "run in daemon mode (background)" msgstr "k??r i d??montilstand (baggrunden)" +msgid "run in server mode (foreground)" +msgstr "k??r i servertilstand (forgrunden)" + msgid "verbose" msgstr "uddybende" @@ -352,7 +352,9 @@ msgstr "|N|udl??b mellemlagrede PIN'er efter N sekunder" msgid "do not use the PIN cache when signing" msgstr "brug ikke PIN-mellemlageret n??r der underskrives" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "tillad klienter at markere n??gler som ??trusted?? (trov??rdige)" msgid "allow presetting passphrase" diff --git a/po/de.po b/po/de.po index de55432..8c37ac6 100644 --- a/po/de.po +++ b/po/de.po @@ -299,12 +299,12 @@ msgstr "" "@Optionen:\n" " " -msgid "run in server mode (foreground)" -msgstr "Im Server Modus ausf??hren" - msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausf??hren" +msgid "run in server mode (foreground)" +msgstr "Im Server Modus ausf??hren" + msgid "verbose" msgstr "Detaillierte Informationen" diff --git a/po/el.po b/po/el.po index afc6a69..321ff3b 100644 --- a/po/el.po +++ b/po/el.po @@ -286,10 +286,10 @@ msgstr "" "????????:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -345,7 +345,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/eo.po b/po/eo.po index c3f568d..17f035c 100644 --- a/po/eo.po +++ b/po/eo.po @@ -287,10 +287,10 @@ msgstr "" "Opcioj:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -345,7 +345,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/es.po b/po/es.po index b3e9654..ba9aa7b 100644 --- a/po/es.po +++ b/po/es.po @@ -312,12 +312,12 @@ msgstr "" "@Opciones:\n" " " -msgid "run in server mode (foreground)" -msgstr "ejecutar en modo servidor (primer plano)" - msgid "run in daemon mode (background)" msgstr "ejecutar en modo demonio (segundo plano)" +msgid "run in server mode (foreground)" +msgstr "ejecutar en modo servidor (primer plano)" + msgid "verbose" msgstr "prolijo" @@ -366,7 +366,9 @@ msgstr "|N|los PINs en la cach msgid "do not use the PIN cache when signing" msgstr "no usar el cach? de PINs al firmar" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "permitir que los clientes marquen claves como \"fiables\"" msgid "allow presetting passphrase" diff --git a/po/et.po b/po/et.po index 6a047e9..dcdd036 100644 --- a/po/et.po +++ b/po/et.po @@ -284,10 +284,10 @@ msgstr "" "V?tmed:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -342,7 +342,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/fi.po b/po/fi.po index 15d22f4..b530eea 100644 --- a/po/fi.po +++ b/po/fi.po @@ -300,10 +300,10 @@ msgstr "" "Valitsimet:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -358,7 +358,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/fr.po b/po/fr.po index 61faa9b..17afec7 100644 --- a/po/fr.po +++ b/po/fr.po @@ -296,12 +296,12 @@ msgstr "" "@Options??:\n" " " -msgid "run in server mode (foreground)" -msgstr "ex??cuter en mode serveur (premier plan)" - msgid "run in daemon mode (background)" msgstr "ex??cuter en mode d??mon (arri??re-plan)" +msgid "run in server mode (foreground)" +msgstr "ex??cuter en mode serveur (premier plan)" + msgid "verbose" msgstr "bavard" @@ -350,7 +350,9 @@ msgstr "|N|oublier les codes personnels apr??s N??secondes" msgid "do not use the PIN cache when signing" msgstr "ne pas utiliser le cache de code pour signer" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "permettre de marquer la confiance des clefs" msgid "allow presetting passphrase" diff --git a/po/gl.po b/po/gl.po index fb7a180..fb5f358 100644 --- a/po/gl.po +++ b/po/gl.po @@ -285,10 +285,10 @@ msgstr "" "Opci?ns:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -345,7 +345,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/hu.po b/po/hu.po index 2aa53f6..086fff2 100644 --- a/po/hu.po +++ b/po/hu.po @@ -284,10 +284,10 @@ msgstr "" "Opci?k:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -342,7 +342,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/id.po b/po/id.po index 8cf6765..86b5ee0 100644 --- a/po/id.po +++ b/po/id.po @@ -289,10 +289,10 @@ msgstr "" "Pilihan:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -347,7 +347,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/it.po b/po/it.po index eed6c30..0f7159f 100644 --- a/po/it.po +++ b/po/it.po @@ -284,10 +284,10 @@ msgstr "" "Opzioni:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -342,7 +342,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/ja.po b/po/ja.po index 6944f33..c7f585e 100644 --- a/po/ja.po +++ b/po/ja.po @@ -282,12 +282,12 @@ msgstr "" "@???????????????:\n" " " -msgid "run in server mode (foreground)" -msgstr "?????????????????????????????? (????????????????????????)" - msgid "run in daemon mode (background)" msgstr "????????????????????????????????? (????????????????????????)" +msgid "run in server mode (foreground)" +msgstr "?????????????????????????????? (????????????????????????)" + msgid "verbose" msgstr "??????" @@ -336,7 +336,9 @@ msgstr "|N|N?????????????????????PIN??????????????????" msgid "do not use the PIN cache when signing" msgstr "??????????????????PIN????????????????????????" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "???????????????????????????\"trusted\"???????????????????????????????????????" msgid "allow presetting passphrase" diff --git a/po/nb.po b/po/nb.po index 809016d..6849dc7 100644 --- a/po/nb.po +++ b/po/nb.po @@ -296,10 +296,10 @@ msgstr "" "Valg:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -354,7 +354,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/pl.po b/po/pl.po index 62abfa5..d1ee871 100644 --- a/po/pl.po +++ b/po/pl.po @@ -292,12 +292,12 @@ msgstr "" "@Opcje:\n" " " -msgid "run in server mode (foreground)" -msgstr "uruchomienie w trybie serwera (pierwszoplanowo)" - msgid "run in daemon mode (background)" msgstr "uruchomienie w trybie demona (w tle)" +msgid "run in server mode (foreground)" +msgstr "uruchomienie w trybie serwera (pierwszoplanowo)" + msgid "verbose" msgstr "z dodatkowymi informacjami" @@ -346,7 +346,9 @@ msgstr "|N|przedawnienie pami msgid "do not use the PIN cache when signing" msgstr "nie u?ywanie pami?ci PIN-?w przy podpisywaniu" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "zezwolenie klientom na oznaczanie kluczy jako \"zaufanych\"" msgid "allow presetting passphrase" diff --git a/po/pt.po b/po/pt.po index 302399f..6f1eb46 100644 --- a/po/pt.po +++ b/po/pt.po @@ -287,10 +287,10 @@ msgstr "" "Op??es:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -346,7 +346,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/pt_BR.po b/po/pt_BR.po index 0a1aff5..067566b 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -292,10 +292,10 @@ msgstr "" "Op??es:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -350,7 +350,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/ro.po b/po/ro.po index 6583ef9..0227d3e 100644 --- a/po/ro.po +++ b/po/ro.po @@ -298,10 +298,10 @@ msgstr "" "Op?iuni:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -356,7 +356,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/ru.po b/po/ru.po index 0d6e3b2..a264d78 100644 --- a/po/ru.po +++ b/po/ru.po @@ -295,12 +295,12 @@ msgstr "" "@??????????????????:\n" " " -msgid "run in server mode (foreground)" -msgstr "???????????? ?? ???????????? ?????????????? (foreground)" - msgid "run in daemon mode (background)" msgstr "???????????? ?? ???????????? ???????????? (background)" +msgid "run in server mode (foreground)" +msgstr "???????????? ?? ???????????? ?????????????? (foreground)" + msgid "verbose" msgstr "????????????????" @@ -349,7 +349,9 @@ msgstr "|N|?????? PIN ?????????????????? ?????????? N ????????????" msgid "do not use the PIN cache when signing" msgstr "???? ???????????????????????? ?????? PIN ?????? ????????????????????????" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "?????????????????? ???????????????? ???????????????? ?????????? ?????? \"????????????????????\"" msgid "allow presetting passphrase" diff --git a/po/sk.po b/po/sk.po index 12be517..3a57da1 100644 --- a/po/sk.po +++ b/po/sk.po @@ -287,10 +287,10 @@ msgstr "" "Mo?nosti:\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -345,7 +345,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/sv.po b/po/sv.po index 9a62da2..383e329 100644 --- a/po/sv.po +++ b/po/sv.po @@ -311,12 +311,12 @@ msgstr "" "@Flaggor:\n" " " -msgid "run in server mode (foreground)" -msgstr "k??r i serverl??ge (f??rgrund)" - msgid "run in daemon mode (background)" msgstr "k??r i demonl??ge (bakgrund)" +msgid "run in server mode (foreground)" +msgstr "k??r i serverl??ge (f??rgrund)" + msgid "verbose" msgstr "utf??rlig" @@ -366,7 +366,9 @@ msgid "do not use the PIN cache when signing" msgstr "anv??nd inte mellanlagring av PIN-kod vid signering" # Antar att v??rdet inte ska ??vers??ttas. -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "till??t klienter att markera nycklar som \"trusted\"" msgid "allow presetting passphrase" diff --git a/po/tr.po b/po/tr.po index 1c73672..4d99c82 100644 --- a/po/tr.po +++ b/po/tr.po @@ -287,12 +287,12 @@ msgstr "" "@Se??enekler:\n" " " -msgid "run in server mode (foreground)" -msgstr "sunucu olarak (??nalanda) ??al??????r" - msgid "run in daemon mode (background)" msgstr "artalan s??reci olarak ??al??????r" +msgid "run in server mode (foreground)" +msgstr "sunucu olarak (??nalanda) ??al??????r" + msgid "verbose" msgstr "ayr??nt??l??" @@ -341,7 +341,9 @@ msgstr "|N|arabellekteki PINler N saniyede zamana????m??na u??rar" msgid "do not use the PIN cache when signing" msgstr "imzalarken PIN arabelle??i kullan??lmaz" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "istemcilerin anahtarlar?? \"g??venilir\" olarak imlemesine izin verilir" msgid "allow presetting passphrase" diff --git a/po/uk.po b/po/uk.po index 571c754..903d2c5 100644 --- a/po/uk.po +++ b/po/uk.po @@ -297,12 +297,12 @@ msgstr "" "@??????????????????:\n" " " -msgid "run in server mode (foreground)" -msgstr "?????????????????? ?? ???????????? ?????????????? (??????????????????)" - msgid "run in daemon mode (background)" msgstr "?????????????????? ?? ???????????? ?????????????? ???????????? (??????????????)" +msgid "run in server mode (foreground)" +msgstr "?????????????????? ?? ???????????? ?????????????? (??????????????????)" + msgid "verbose" msgstr "?????????????????? ??????????" @@ -351,7 +351,9 @@ msgstr "?????????????? ???????????????? ?????????????? ???? ?????????????? ???? msgid "do not use the PIN cache when signing" msgstr "???? ?????????????????????????????? ?????? ??????-?????????? ?????? ????????????????????????" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "?????????????????? ???????????????? ?????????????????? ?????????? ???? ??????????????" msgid "allow presetting passphrase" diff --git a/po/zh_CN.po b/po/zh_CN.po index 7f1a90f..fe86621 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -296,10 +296,10 @@ msgstr "" "?????????\n" " " -msgid "run in server mode (foreground)" +msgid "run in daemon mode (background)" msgstr "" -msgid "run in daemon mode (background)" +msgid "run in server mode (foreground)" msgstr "" msgid "verbose" @@ -354,7 +354,7 @@ msgstr "" msgid "do not use the PIN cache when signing" msgstr "" -msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "" #, fuzzy diff --git a/po/zh_TW.po b/po/zh_TW.po index 7c6df10..4ac3df2 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -276,12 +276,12 @@ msgstr "" "@??????:\n" " " -msgid "run in server mode (foreground)" -msgstr "???????????????????????? (??????)" - msgid "run in daemon mode (background)" msgstr "????????????????????? (??????)" +msgid "run in server mode (foreground)" +msgstr "???????????????????????? (??????)" + msgid "verbose" msgstr "????????????" @@ -330,7 +330,9 @@ msgstr "|N|?????????????????????????????? (PIN) ??? N ????????????" msgid "do not use the PIN cache when signing" msgstr "???????????????????????????????????? (PIN) ??????" -msgid "allow clients to mark keys as \"trusted\"" +#, fuzzy +#| msgid "allow clients to mark keys as \"trusted\"" +msgid "disallow clients to mark keys as \"trusted\"" msgstr "????????????????????????????????? \"?????????\"" msgid "allow presetting passphrase" commit ebbce67489b8d0eded74be66cbd6bf42f5147725 Author: Werner Koch Date: Wed Jul 3 15:21:33 2013 +0200 Update the German translation. diff --git a/po/de.po b/po/de.po index 14ff5f1..de55432 100644 --- a/po/de.po +++ b/po/de.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg-2.0.18\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"PO-Revision-Date: 2013-07-03 13:32+0200\n" +"PO-Revision-Date: 2013-07-03 15:03+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: German \n" "Language: de\n" @@ -353,8 +353,8 @@ msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht beim Signieren" -msgid "allow clients to mark keys as \"trusted\"" -msgstr "erlaube Aufrufern Schl??ssel als \"vertrauensw??rdig\" zu markieren" +msgid "disallow clients to mark keys as \"trusted\"" +msgstr "verbite Aufrufern Schl??ssel als \"vertrauensw??rdig\" zu markieren" msgid "allow presetting passphrase" msgstr "erlaube ein \"preset\" von Passphrases" commit 90b419f3e9d05e509348d047e05fcc79e87be6cf Author: Werner Koch Date: Wed Jul 3 15:20:25 2013 +0200 agent: Make --allow-mark-trusted the default. * agent/gpg-agent.c (opts, main): Add option --no-allow-mark-trusted. Put this option into the gpgconf-list. (main): Enable opt.allow_mark_trusted by default. * tools/gpgconf-comp.c (gc_options_gpg_agent): Replace allow-mark-trusted by no-allow-mark-trusted. * agent/trustlist.c (agent_marktrusted): Always set the "relax" flag. -- These changes have been in effect for the Gpg4win Windows version since 2011-01-24 and thus first released with Gpg4win 2.1.0. Given the current state of PKIX it does not make any sense to lure the Unix user into false security by making it harder to trust self-signed or CAcert certificates. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index adaa257..782a54b 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,15 @@ Noteworthy changes in version 2.0.21 (unreleased) ------------------------------------------------- + * gpg-agent: By default the users are now asked via the Pinentry + whether they trust an X.509 root key. To prohibit interactive + marking of such keys, the new option --no-allow-mark-trusted may + be used. + * The included ssh agent does now support ECDSA keys. - * New option --enable-putty-support to allow gpg-agent to act as a - Pageant replacement including full smartcard support. + * The new option --enable-putty-support allows gpg-agent on Windows + to act as a Pageant replacement with full smartcard support. Noteworthy changes in version 2.0.20 (2013-05-10) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 9d53de9..1f53a37 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -112,6 +112,7 @@ enum cmd_and_opt_values oIgnoreCacheForSigning, oAllowMarkTrusted, + oNoAllowMarkTrusted, oAllowPresetPassphrase, oKeepTTY, oKeepDISPLAY, @@ -131,8 +132,8 @@ 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)") }, + { oServer, "server", 0, N_("run in server mode (foreground)") }, { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oSh, "sh", 0, N_("sh-style command output") }, @@ -184,8 +185,9 @@ static ARGPARSE_OPTS opts[] = { { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, - { oAllowMarkTrusted, "allow-mark-trusted", 0, - N_("allow clients to mark keys as \"trusted\"")}, + { oNoAllowMarkTrusted, "no-allow-mark-trusted", 0, + N_("disallow clients to mark keys as \"trusted\"")}, + { oAllowMarkTrusted, "allow-mark-trusted", 0, "@"}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh support") }, @@ -503,7 +505,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.max_passphrase_days = MAX_PASSPHRASE_DAYS; opt.enable_passhrase_history = 0; opt.ignore_cache_for_signing = 0; - opt.allow_mark_trusted = 0; + opt.allow_mark_trusted = 1; opt.disable_scdaemon = 0; return 1; } @@ -563,6 +565,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break; + case oNoAllowMarkTrusted: opt.allow_mark_trusted = 0; break; case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break; @@ -960,7 +963,7 @@ main (int argc, char **argv ) GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("ignore-cache-for-signing:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); - printf ("allow-mark-trusted:%lu:\n", + printf ("no-allow-mark-trusted:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("disable-scdaemon:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); diff --git a/agent/trustlist.c b/agent/trustlist.c index be5406b..ef9c661 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -731,7 +731,8 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag) } else es_fputs (nameformatted, fp); - es_fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag); + es_fprintf (fp, "\n%s%s %c%s\n", yes_i_trust?"":"!", fprformatted, flag, + flag == 'S'? " relax":""); if (es_ferror (fp)) err = gpg_error_from_syserror (); diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 72e7134..078dcea 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -532,8 +532,8 @@ static gc_option_t gc_options_gpg_agent[] = { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, - { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME, - GC_LEVEL_ADVANCED, "gnupg", "allow clients to mark keys as \"trusted\"", + { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME, + GC_LEVEL_ADVANCED, "gnupg", "disallow clients to mark keys as \"trusted\"", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", ----------------------------------------------------------------------- Summary of changes: NEWS | 9 +++++++-- agent/gpg-agent.c | 13 ++++++++----- agent/trustlist.c | 3 ++- po/be.po | 6 +++--- po/ca.po | 6 +++--- po/cs.po | 10 ++++++---- po/da.po | 10 ++++++---- po/de.po | 12 ++++++------ po/el.po | 6 +++--- po/eo.po | 6 +++--- po/es.po | 10 ++++++---- po/et.po | 6 +++--- po/fi.po | 6 +++--- po/fr.po | 10 ++++++---- po/gl.po | 6 +++--- po/hu.po | 6 +++--- po/id.po | 6 +++--- po/it.po | 6 +++--- po/ja.po | 10 ++++++---- po/nb.po | 6 +++--- po/pl.po | 10 ++++++---- po/pt.po | 6 +++--- po/pt_BR.po | 6 +++--- po/ro.po | 6 +++--- po/ru.po | 10 ++++++---- po/sk.po | 6 +++--- po/sv.po | 10 ++++++---- po/tr.po | 10 ++++++---- po/uk.po | 10 ++++++---- po/zh_CN.po | 6 +++--- po/zh_TW.po | 10 ++++++---- tools/gpgconf-comp.c | 4 ++-- 32 files changed, 139 insertions(+), 108 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jul 4 16:45:45 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 04 Jul 2013 16:45:45 +0200 Subject: [git] GpgEX - branch, master, updated. gpgex-0.9.7-26-gb5d1172 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GnupG extension for the Windows Explorer". The branch, master has been updated via b5d1172f5fc2cddfbdfeb473c65b6508c5a73287 (commit) via 7329e9a8d0ef661d8c306cc2f996bac718990f14 (commit) from e84489cd5e3b2e6c6c8a8a252cb5b2028dbf3dd9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b5d1172f5fc2cddfbdfeb473c65b6508c5a73287 Author: Werner Koch Date: Thu Jun 27 17:39:01 2013 +0200 Minor fixes to the help texts. -- We definitely need beter help texts. diff --git a/doc/gpgex-de.html b/doc/gpgex-de.html index a54778c..e7fce25 100644 --- a/doc/gpgex-de.html +++ b/doc/gpgex-de.html @@ -1,4 +1,4 @@ - + @@ -18,47 +18,46 @@

Entschl?sseln und ?berpr?fen, Entschl?sseln, ?berpr?fen

Entschl?sselt und/oder ?berpr?ft die ausgew?hlten Dateien. - FIXME: Hier wird ein Link zur Kleopatra-Dokumentation f?r die - Entschl?ssel- und Verifizier-Funktionen eingestellt. + FIXME: Einen Link zur Gpg4win Dokumentation f?r die + Entschl?ssel- und Verifizier-Funktionen einbauen.

Signieren und verschl?sseln, Signieren, Verschl?sseln

Signiert und/oder verschl?sselt die ausgew?hlten Dateien. - FIXME: Hier wird ein Link zur Kleopatra-Dokumentation f?r die - Verschl?ssel- und Signier-Funktionen eingestellt. + FIXME: Einen Link zur Gpg4win Dokumentation f?r die + Verschl?ssel- und Signier-Funktionen einbauen.

Zertifikate importieren

- Import die Zertifikate in den ausgew?hlten Dateien. FIXME: Hier - wird ein Link zur Kleopatra-Dokumentation f?r die - Import-Funktion eingestellt. + Import die Zertifikate in den ausgew?hlten Dateien.

Hilfe zu GpgEX

Stellt diese Hilfe dar.

+

Über GpgEX

+

+ Zeigt die Version von GpgEX an. +

+

Debugging

- Falls nicht auf Kleopatra zugegriffen werden kann, wird ein + Falls nicht auf die GnuPG Benutzerschnittstelle zugegriffen werden kann, wird ein Nachrichtenfenster mit einer Fehlermeldung angezeigt. Um mehr Informationen zu erhalten, kann der Fehlerbericht von Kleopatra - eingesehen werden (Anleitung siehe Gpg4win-Kompendium), + oder GPA eingesehen werden (Anleitung siehe Gpg4win-Kompendium), oder es kann eine GpgEX-Diagnosedatei angegeben werden. Dazu im Registrierungs-Editor den Schl?ssel HKLM\Software\GNU\GnuPG - ausw?hlen, eine neue "Zeichenfolge" mit dem Namen GpgEX Debug File - anlegen und als Wert einen Dateinamen (z.B. c:\temp\gpgex-debug-file.log) - angeben. Informationen zum Protokoll werden dann nach - einem Neustart von Windows an diese Datei angehangen. + ausw?hlen, eine neue "Zeichenfolge" mit dem Namen GpgEX + Debug File anlegen und als Wert einen Dateinamen + (z.B. c:\temp\gpgex-debug-file.log) + angeben. Informationen zum Protokoll werden dann nach einem + Neustart von Windows an diese Datei angehangen.

Hinweis

- Mehr Informationen ?ber die Krypto-Operationen befinden sich im - Kleopatra Handbuch - (Englisch). -

-

- Mehr Informationen und aktuelle Programmversionen sind auf der + Mehr Informationen und aktuelle Programmversionen sind auf der Gpg4win Webpr?senz verf?gbar.

diff --git a/doc/gpgex-en.html b/doc/gpgex-en.html index 95c799f..7e7f255 100644 --- a/doc/gpgex-en.html +++ b/doc/gpgex-en.html @@ -11,37 +11,43 @@

The GNU Privacy Guard extensions for the Windows Explorer shell - allow you to access cryptographic functions in Kleopatra using - the context menu to files. + allow you to access cryptographic functions of the GnuPG user + interface using the context menu to files.

Commands

Decrypt and verify, Decrypt, Verify

- Decrypt and/or verify the selected files. FIXME: Here will be a - link to the Kleopatra documentation for the decrypt and verify + Decrypt and/or verify the selected files. FIXME: Add a link + to the Gpg4win documentation for the decrypt and verify functions.

Encrypt and sign, Encrypt, Sign

- Encrypt and/or sign the selected files. FIXME: Here will be a - link to the Kleopatra documentation for the sign and encrypt + Encrypt and/or sign the selected files. FIXME: Add a link to the + Gpg4win documentation for the sign and encrypt functions.

Import keys

- Import certificates in the selected files. FIXME: Here will be - a link to the Kleopatra documentation for the import function. + Import certificates in the selected files. FIXME: Add a link to the + Gpg4win documentation for the import function.

Help on GpgEX

Display this help.

+

About GpgEX

+

+ Display the version number. +

+

Debugging

- If Kleopatra can not be accessed, a message box with an error - message will be displayed. To get more information, you can - either check the error log of Kleopatra, or specify a debug - file: Select the key HKLM\Software\GNU\GnuPG + If the GnuPG user interface (either GPA or Kleopatra) can not be + accessed, a message box with an error message will be displayed. + To get more information, you can either check the error log, or + specify a debug file: Select the + key HKLM\Software\GNU\GnuPG in the registry editor, create a new string value with the name GpgEX Debug File and the value of the debug filename (e.g. c:\temp\gpgex-debug-file.log). To this file @@ -49,10 +55,6 @@

Reference

- More information about these crypto operations can be found in - the Kleopatra - manual. - Please find more information and new software versions at the Gpg4win website.

commit 7329e9a8d0ef661d8c306cc2f996bac718990f14 Author: Werner Koch Date: Thu Jun 27 17:38:25 2013 +0200 Improve error message from the UI-server. * client.cc (call_assuan): Distinguish between connection and and server errors. -- I consider it better not to use the term "server" here. To the user it is a user interface and not a server. diff --git a/src/ChangeLog b/src/ChangeLog index a6f7a7c..05ecb0c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2013-06-27 Werner Koch + + * client.cc (call_assuan): Distinguish between connection and and + server errors. + 2013-06-26 Werner Koch * client.cc (default_uiserver_cmdline): Replace code with code diff --git a/src/client.cc b/src/client.cc index 6fc9162..37fe7ef 100644 --- a/src/client.cc +++ b/src/client.cc @@ -356,6 +356,8 @@ bool client_t::call_assuan (const char *cmd, vector &filenames) { int rc = 0; + int connect_failed = 0; + assuan_context_t ctx = NULL; string msg; @@ -364,7 +366,10 @@ client_t::call_assuan (const char *cmd, vector &filenames) rc = uiserver_connect (&ctx, this->window); if (rc) - goto leave; + { + connect_failed = 1; + goto leave; + } try { @@ -405,12 +410,21 @@ client_t::call_assuan (const char *cmd, vector &filenames) if (rc) { char buf[256]; - snprintf (buf, sizeof (buf), - _("Can not access the UI-server%s%s%s:\r\n%s"), - gpgex_server::ui_server? " (":"", - gpgex_server::ui_server? gpgex_server::ui_server:"", - gpgex_server::ui_server? ")":"", - gpg_strerror (rc)); + + if (connect_failed) + snprintf (buf, sizeof (buf), + _("Can not connect to the GnuPG user interface%s%s%s:\r\n%s"), + gpgex_server::ui_server? " (":"", + gpgex_server::ui_server? gpgex_server::ui_server:"", + gpgex_server::ui_server? ")":"", + gpg_strerror (rc)); + else + snprintf (buf, sizeof (buf), + _("Error returned by the GnuPG user interface%s%s%s:\r\n%s"), + gpgex_server::ui_server? " (":"", + gpgex_server::ui_server? gpgex_server::ui_server:"", + gpgex_server::ui_server? ")":"", + gpg_strerror (rc)); MessageBox (this->window, buf, "GpgEX", MB_ICONINFORMATION); } ----------------------------------------------------------------------- Summary of changes: doc/gpgex-de.html | 39 +++++++++++++++++++-------------------- doc/gpgex-en.html | 34 ++++++++++++++++++---------------- src/ChangeLog | 5 +++++ src/client.cc | 28 +++++++++++++++++++++------- 4 files changed, 63 insertions(+), 43 deletions(-) hooks/post-receive -- GnupG extension for the Windows Explorer http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jul 5 10:25:55 2013 From: cvs at cvs.gnupg.org (by Andre Heinecke) Date: Fri, 05 Jul 2013 10:25:55 +0200 Subject: [git] GpgOL - branch, outlook14, created. gpgol-1.1.3-4-ge185317 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GnuPG extension for MS Outlook". The branch, outlook14 has been created at e1853176eaf2e0411f471f1cc30a783676a5d912 (commit) - Log ----------------------------------------------------------------- commit e1853176eaf2e0411f471f1cc30a783676a5d912 Author: Andre Heinecke Date: Fri Jul 5 08:00:58 2013 +0000 Prototype Outlook 14 support This adds a prototype "Save and decrypt" action for attachments. The main advancement is that gpgOl can now interact with Outlook 14 using the Ribbon extension interface. * src/gpgoladdin.cpp, src/gpgoladdin.h: New. Classes implementing the COM Objects to interact with outlook. * src/gpgoladdin.cpp, src/gpgol.def (DllGetClassObject), (DllCanUnloadNow): New entry points into the library. * src/olflange.cpp (DllRegisterServer, DllUnregisterServer): Register / Unregister gpgOl as an Outlook Addin. (GpgolExt): Use VERSION macro. (install_sinks, install_forms): Expose for other classes. * src/olflange.h: Move GUID and some string definitions into header. Add function declarations. -- In outlook 14 the exchange extension interface was removed. Now we have to use the IDT_EXTENSIBILITY2 interface to interact with outlook (or other office applications). Similarly the context menu events in the OOM have been removed now we must use the Ribbon Extensibility Interface to extend context Menus. This is also the only way to avoid having all added buttons placed in a generic "Addins" tab and gives us some more flexibility how we can modify the UI. There are still some fixmes and todos in there but basically it works. Not tested with older outlook versions where the Exchange interface also works. In that case it might be best to check the Version in OnConnection and disable all functionality in case it is < 14. diff --git a/src/Makefile.am b/src/Makefile.am index 220a013..3f73dba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -79,7 +79,8 @@ gpgol_SOURCES = \ inspectors.cpp inspectors.h \ mailitem.cpp mailitem.h \ cmdbarcontrols.cpp cmdbarcontrols.h \ - w32-gettext.c w32-gettext.h + w32-gettext.c w32-gettext.h \ + gpgoladdin.cpp gpgoladdin.h #treeview_SOURCES = treeview.c @@ -110,7 +111,8 @@ clean-local: gpgol_LDADD = $(srcdir)/gpgol.def \ -L . -lgpgme -lassuan -lgpg-error \ -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \ - -lole32 -loleaut32 -lws2_32 -ladvapi32 + -lole32 -loleaut32 -lws2_32 -ladvapi32 \ + -luuid resource.o: resource.rc versioninfo.rc dialogs.rc diff --git a/src/gpgol-ids.h b/src/gpgol-ids.h index 0c02123..ff8f206 100644 --- a/src/gpgol-ids.h +++ b/src/gpgol-ids.h @@ -1,6 +1,6 @@ /* gpgol-ids.h - Resource IDs used by gpgol-rsrcs.rc. + Resource IDs used by gpgol resource files */ #ifndef GPGOL_IDS_H @@ -32,6 +32,7 @@ #define IDC_OPT_HOMEDIR 1027 #define IDC_OPT_SELHOMEDIR 1028 +#define IDR_XML_EXPLORER 203 #endif /*GPGOL_IDS_H*/ diff --git a/src/gpgol.def b/src/gpgol.def index 4d319ed..79cf727 100644 --- a/src/gpgol.def +++ b/src/gpgol.def @@ -6,6 +6,8 @@ EXPORTS ExchEntryPoint = ExchEntryPoint at 0 @1 DllRegisterServer = DllRegisterServer at 0 @2 PRIVATE DllUnregisterServer = DllUnregisterServer at 0 @3 PRIVATE + DllGetClassObject = DllGetClassObject at 12 @4 PRIVATE + DllCanUnloadNow = DllCanUnloadNow at 0 @5 PRIVATE gpgol_check_version = gpgol_check_version at 4 @11 gpgol_message_revert = gpgol_message_revert at 12 @12 diff --git a/src/gpgoladdin.cpp b/src/gpgoladdin.cpp new file mode 100644 index 0000000..7f55b69 --- /dev/null +++ b/src/gpgoladdin.cpp @@ -0,0 +1,636 @@ +/* gpgoladdin.cpp - Connect GpgOL to Outlook as an addin + * Copyright (C) 2013 Intevation GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "util.h" +#include "gpgoladdin.h" + +#include "mymapi.h" +#include "mymapitags.h" +#include "myexchext.h" + +#include "common.h" +#include "display.h" +#include "msgcache.h" +#include "engine.h" +#include "engine-assuan.h" +#include "mapihelp.h" + +#include "oomhelp.h" + +#include "olflange.h" + +#include "gpgol-ids.h" + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + +/* Id's of our callbacks */ +#define ID_CMD_DECRYPT_VERIFY 1 +#define ID_CMD_DECRYPT 2 +#define ID_CMD_VERIFY 3 + +ULONG addinLocks = 0; + +/* This is the main entry point for the addin + Outlook uses this function to query for an Object implementing + the IClassFactory interface. +*/ +STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppvObj) +{ + if (!ppvObj) + return E_POINTER; + + *ppvObj = NULL; + if (rclsid != CLSID_GPGOL) + return CLASS_E_CLASSNOTAVAILABLE; + + /* Let the factory give the requested interface. */ + GpgolAddinFactory* factory = new GpgolAddinFactory(); + if (!factory) + return E_OUTOFMEMORY; + + HRESULT hr = factory->QueryInterface (riid, ppvObj); + if(FAILED(hr)) + { + *ppvObj = NULL; + delete factory; + } + + return hr; +} + + +STDAPI DllCanUnloadNow() +{ + return addinLocks == 0 ? S_OK : S_FALSE; +} + +/* Class factory */ +STDMETHODIMP GpgolAddinFactory::QueryInterface (REFIID riid, LPVOID* ppvObj) +{ + HRESULT hr = S_OK; + + *ppvObj = NULL; + + if ((IID_IUnknown == riid) || (IID_IClassFactory == riid)) + *ppvObj = static_cast(this); + else + { + hr = E_NOINTERFACE; + LPOLESTR sRiid = NULL; + StringFromIID (riid, &sRiid); + /* Should not happen */ + log_debug ("GpgolAddinFactory queried for unknown interface: %S \n", sRiid); + } + + if (*ppvObj) + ((LPUNKNOWN)*ppvObj)->AddRef(); + + return hr; +} + + +/* This actually creates the instance of our COM object */ +STDMETHODIMP GpgolAddinFactory::CreateInstance (LPUNKNOWN punk, REFIID riid, + LPVOID* ppvObj) +{ + *ppvObj = NULL; + + GpgolAddin* obj = new GpgolAddin(); + if (NULL == obj) + return E_OUTOFMEMORY; + + HRESULT hr = obj->QueryInterface (riid, ppvObj); + + if (FAILED(hr)) + { + LPOLESTR sRiid = NULL; + StringFromIID (riid, &sRiid); + fprintf(stderr, "failed to create instance for: %S", sRiid); + } + + return hr; +} + +/* GpgolAddin definition */ + + +/* Constructor of GpgolAddin + + Initializes members and creates the interface objects for the new + context. Does the DLL initialization if it has not been done + before. + + The ref count is set by the factory after creation. +*/ +GpgolAddin::GpgolAddin (void) : m_lRef(0), m_application(0), m_addin(0) +{ + /* Create the COM Extension Object that handles the startup and + endinge initialization + */ + m_gpgolext = new GpgolExt(); + + /* RibbonExtender is it's own object to avoid the pitfalls of + multiple inheritance + */ + m_ribbonExtender = new GpgolRibbonExtender(); +} + +GpgolAddin::~GpgolAddin (void) +{ + log_debug ("%s:%s: cleaning up GpgolAddin object;", + SRCNAME, __func__); + + engine_deinit (); + write_options (); + delete m_gpgolext; + delete m_ribbonExtender; + + log_debug ("%s:%s: Object deleted\n", SRCNAME, __func__); +} + +STDMETHODIMP +GpgolAddin::QueryInterface (REFIID riid, LPVOID* ppvObj) +{ + HRESULT hr = S_OK; + + *ppvObj = NULL; + + if ((riid == IID_IUnknown) || (riid == IID_IDTExtensibility2) || + (riid == IID_IDispatch)) + { + *ppvObj = (LPUNKNOWN) this; + } + else if (riid == IID_IRibbonExtensibility) + { + return m_ribbonExtender->QueryInterface (riid, ppvObj); + } + else + { + hr = m_gpgolext->QueryInterface (riid, ppvObj); +#if 0 + if (FAILED(hr)) + { + LPOLESTR sRiid = NULL; + StringFromIID(riid, &sRiid); + log_debug ("%s:%s: queried for unimplmented interface: %S", + SRCNAME, __func__, sRiid); + } +#endif + } + + if (*ppvObj) + ((LPUNKNOWN)*ppvObj)->AddRef(); + + return hr; +} + +STDMETHODIMP +GpgolAddin::OnConnection (LPDISPATCH Application, ext_ConnectMode ConnectMode, + LPDISPATCH AddInInst, SAFEARRAY ** custom) +{ + (void)custom; + TRACEPOINT(); + + if (!m_application) + { + m_application = Application; + m_application->AddRef(); + m_addin = AddInInst; + } + else + { + /* This should not happen but happened during development when + the vtable was incorrect and the wrong function was called */ + log_debug ("%s:%s: Application already set. Ignoring new value.", + SRCNAME, __func__); + return S_OK; + } + + if (ConnectMode != ext_cm_Startup) + { + OnStartupComplete (custom); + } + return S_OK; +} + +STDMETHODIMP +GpgolAddin::OnDisconnection (ext_DisconnectMode RemoveMode, + SAFEARRAY** custom) +{ + (void)custom; + return S_OK; +} + +STDMETHODIMP +GpgolAddin::OnAddInsUpdate (SAFEARRAY** custom) +{ + (void)custom; + return S_OK; +} + +STDMETHODIMP +GpgolAddin::OnStartupComplete (SAFEARRAY** custom) +{ + (void)custom; + TRACEPOINT(); + + if (m_application) + { + /* + An install_sinks here works this but we + don't implement all the old extension feature + in the addin yet. + install_sinks ((LPEXCHEXTCALLBACK)m_application); + */ + return S_OK; + } + /* Should not happen as OnConnection should be called before */ + log_error ("%s:%s: no application set;", + SRCNAME, __func__); + return E_NOINTERFACE; +} + +STDMETHODIMP +GpgolAddin::OnBeginShutdown (SAFEARRAY * * custom) +{ + (void)custom; + TRACEPOINT(); + return S_OK; +} + +STDMETHODIMP +GpgolAddin::GetTypeInfoCount (UINT *r_count) +{ + *r_count = 0; + TRACEPOINT(); /* Should not happen */ + return S_OK; +} + +STDMETHODIMP +GpgolAddin::GetTypeInfo (UINT iTypeInfo, LCID lcid, + LPTYPEINFO *r_typeinfo) +{ + (void)iTypeInfo; + (void)lcid; + (void)r_typeinfo; + TRACEPOINT(); /* Should not happen */ + return S_OK; +} + +STDMETHODIMP +GpgolAddin::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, + DISPID *rgDispId) +{ + (void)riid; + (void)rgszNames; + (void)cNames; + (void)lcid; + (void)rgDispId; + TRACEPOINT(); /* Should not happen */ + return E_NOINTERFACE; +} + +STDMETHODIMP +GpgolAddin::Invoke (DISPID dispid, REFIID riid, LCID lcid, + WORD flags, DISPPARAMS *parms, VARIANT *result, + EXCEPINFO *exepinfo, UINT *argerr) +{ + TRACEPOINT(); /* Should not happen */ + return DISP_E_MEMBERNOTFOUND; +} + + + +/* Definition of GpgolRibbonExtender */ + +GpgolRibbonExtender::GpgolRibbonExtender (void) : m_lRef(0) +{ +} + +GpgolRibbonExtender::~GpgolRibbonExtender (void) +{ + log_debug ("%s:%s: cleaning up GpgolRibbonExtender object;", + SRCNAME, __func__); + log_debug ("%s:%s: Object deleted\n", SRCNAME, __func__); +} + +STDMETHODIMP +GpgolRibbonExtender::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + HRESULT hr = S_OK; + + *ppvObj = NULL; + + if ((riid == IID_IUnknown) || (riid == IID_IRibbonExtensibility) || + (riid == IID_IDispatch)) + { + *ppvObj = (LPUNKNOWN) this; + } + else + { + LPOLESTR sRiid = NULL; + StringFromIID (riid, &sRiid); + log_debug ("%s:%s: queried for unknown interface: %S", + SRCNAME, __func__, sRiid); + } + + if (*ppvObj) + ((LPUNKNOWN)*ppvObj)->AddRef(); + + return hr; +} + +STDMETHODIMP +GpgolRibbonExtender::GetTypeInfoCount (UINT *r_count) +{ + *r_count = 0; + TRACEPOINT(); /* Should not happen */ + return S_OK; +} + +STDMETHODIMP +GpgolRibbonExtender::GetTypeInfo (UINT iTypeInfo, LCID lcid, + LPTYPEINFO *r_typeinfo) +{ + (void)iTypeInfo; + (void)lcid; + (void)r_typeinfo; + TRACEPOINT(); /* Should not happen */ + return S_OK; +} + +/* Good documentation of what this function is supposed to do can + be found at: http://msdn.microsoft.com/en-us/library/cc237568.aspx + + There is also a very good blog explaining how Ribbon Extensibility + is supposed to work. + http://blogs.msdn.com/b/andreww/archive/2007/03/09/ +why-is-it-so-hard-to-shim-iribbonextensibility.aspx + */ +STDMETHODIMP +GpgolRibbonExtender::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, + DISPID *rgDispId) +{ + (void)riid; + (void)lcid; + bool found = false; + + if (!rgszNames || !cNames || !rgDispId) + { + return E_POINTER; + } + + for (unsigned int i = 0; i < cNames; i++) + { + log_debug ("%s:%s: GetIDsOfNames for: %S", + SRCNAME, __func__, rgszNames[0]); + /* How this is supposed to work with cNames > 1 is unknown, + but we can just say that we won't support callbacks with + different parameters and just match the name (the first element) + and we give it one of our own dispIds's that are later handled in + the invoke part */ + if (!wcscmp (rgszNames[i], L"AttachmentDecryptCallback")) + { + found = true; + rgDispId[i] = ID_CMD_DECRYPT; + } + } + + if (cNames > 1) + { + log_debug ("More then one name provided. Should not happen"); + } + + return found ? S_OK : E_NOINTERFACE; +} + +HRESULT +GpgolRibbonExtender::decryptAttachments(LPRIBBONCONTROL ctrl) +{ + BSTR idStr = NULL; + LPDISPATCH context = NULL; + int attachmentCount; + HRESULT hr = 0; + int i = 0; + HWND curWindow; + LPOLEWINDOW actExplorer; + int err; + + /* We got the vtable right so we can save us the invoke and + property lookup hassle and call it directly */ + hr = ctrl->get_Id (&idStr); + hr |= ctrl->get_Context (&context); + + if (FAILED(hr)) + { + log_debug ("%s:%s:Context / ID lookup failed. hr: %x", + SRCNAME, __func__, (unsigned int) hr); + SysFreeString (idStr); + return E_FAIL; + } + else + { + log_debug ("%s:%s: contextId: %S, contextObj: %s", + SRCNAME, __func__, idStr, get_object_name (context)); + SysFreeString (idStr); + } + + attachmentCount = get_oom_int (context, "Count"); + log_debug ("Count: %i ", attachmentCount); + + actExplorer = (LPOLEWINDOW) get_oom_object(context, + "Application.ActiveExplorer"); + if (actExplorer) + actExplorer->GetWindow (&curWindow); + else + { + log_debug ("%s:%s: Could not find active window", + SRCNAME, __func__); + curWindow = NULL; + } + + char *filenames[attachmentCount + 1]; + filenames[attachmentCount] = NULL; + /* Yes the items start at 1! */ + for (i = 1; i <= attachmentCount; i++) + { + char buf[16]; + char *filename; + wchar_t *wcsOutFilename; + DISPPARAMS saveParams; + VARIANT aVariant[1]; + LPDISPATCH attachmentObj; + DISPID saveID; + + snprintf (buf, sizeof (buf), "Item(%i)", i); + attachmentObj = get_oom_object (context, buf); + filename = get_oom_string (attachmentObj, "FileName"); + + saveID = lookup_oom_dispid (attachmentObj, "SaveAsFile"); + + saveParams.rgvarg = aVariant; + saveParams.rgvarg[0].vt = VT_BSTR; + filenames[i-1] = get_save_filename (NULL, filename); + xfree (filename); + + wcsOutFilename = utf8_to_wchar2 (filenames[i-1], + strlen(filenames[i-1])); + saveParams.rgvarg[0].bstrVal = SysAllocString (wcsOutFilename); + saveParams.cArgs = 1; + saveParams.cNamedArgs = 0; + + hr = attachmentObj->Invoke (saveID, IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_METHOD, &saveParams, + NULL, NULL, NULL); + SysFreeString (saveParams.rgvarg[0].bstrVal); + if (FAILED(hr)) + { + int j; + log_debug ("%s:%s: Saving to file failed. hr: %x", + SRCNAME, __func__, (unsigned int) hr); + for (j = 0; j < i; j++) + xfree (filenames[j]); + return hr; + } + } + err = op_assuan_start_decrypt_files (curWindow, filenames); + + for (i = 0; i < attachmentCount; i++) + xfree (filenames[i]); + + return err ? E_FAIL : S_OK; +} + +STDMETHODIMP +GpgolRibbonExtender::Invoke (DISPID dispid, REFIID riid, LCID lcid, + WORD flags, DISPPARAMS *parms, VARIANT *result, + EXCEPINFO *exepinfo, UINT *argerr) +{ + log_debug ("%s:%s: enter with dispid: %x", + SRCNAME, __func__, (int)dispid); + + if (!(flags & DISPATCH_METHOD)) + { + log_debug ("%s:%s: not called in method mode. Bailing out.", + SRCNAME, __func__); + return DISP_E_MEMBERNOTFOUND; + } + + switch (dispid) + { + case ID_CMD_DECRYPT: + /* We can assume that this points to an implementation of + IRibbonControl as we know the callback dispid. */ + return decryptAttachments ((LPRIBBONCONTROL) + parms->rgvarg[0].pdispVal); + } + + log_debug ("%s:%s: leave", SRCNAME, __func__); + + return DISP_E_MEMBERNOTFOUND; +} + +BSTR +loadXMLResource (int id) +{ + /* XXX I do not know how to get the handle of the currently + executed code as we never had a chance in DllMain to save + that handle. */ + + /* FIXME this does not work as intended */ + HMODULE hModule = GetModuleHandle("gpgol.dll"); + + HRSRC hRsrc = FindResourceEx (hModule, MAKEINTRESOURCE(id), TEXT("XML"), + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); + + if (!hRsrc) + { + log_error_w32 (-1, "%s:%s: FindResource(%d) failed\n", + SRCNAME, __func__, id); + return NULL; + } + + HGLOBAL hGlobal = LoadResource(hModule, hRsrc); + + if (!hGlobal) + { + log_error_w32 (-1, "%s:%s: LoadResource(%d) failed\n", + SRCNAME, __func__, id); + return NULL; + } + + LPVOID xmlData = LockResource (hGlobal); + + return SysAllocString (reinterpret_cast(xmlData)); +} + +STDMETHODIMP +GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml) +{ + log_debug ("%s:%s: GetCustomUI for id: %S", SRCNAME, __func__, RibbonID); + + if (!RibbonXml) + return E_POINTER; + + /*if (!wcscmp (RibbonID, L"Microsoft.Outlook.Explorer")) + {*/ + // *RibbonXml = loadXMLResource (IDR_XML_EXPLORER); + /* TODO use callback for label's and Icons, load xml from resource */ + *RibbonXml = SysAllocString ( + L"" + L" " + L" " + L" " + L" " + L"