2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
35 #include "pwmd-error.h"
36 #include "util-misc.h"
42 #include "util-string.h"
49 #define STATUS_TIMEOUT_INIT(crypto) \
51 crypto->status_timeout = time (NULL); \
52 crypto->progress_rc = 0; \
55 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
57 time_t now = time (NULL); \
58 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
59 rc = send_status (crypto->client_ctx, s, line); \
60 crypto->status_timeout = now; \
66 show_key_output (gpgme_key_t key
)
68 gpgme_subkey_t keyp
; // first is primary
70 for (keyp
= key
->subkeys
; keyp
; keyp
= keyp
->next
)
72 fprintf(stderr
, "keyid: %s, revoked: %i, expired: %i, disabled: %i, invalid: %i,"
73 "encrypt: %i, sign: %i, cert: %i, auth: %i, secret: %i\n",
74 keyp
->keyid
, keyp
->revoked
, keyp
->expired
, keyp
->disabled
,
75 keyp
->invalid
, keyp
->can_encrypt
, keyp
->can_sign
,
76 keyp
->can_certify
, keyp
->can_authenticate
, keyp
->secret
);
84 get_password (const char *keyfile
, unsigned char **result
, size_t *len
)
88 unsigned char *buf
= NULL
;
91 log_write (_ ("obtaining passphrase from passphrase file"));
92 if (stat (keyfile
, &st
) == -1)
93 return gpg_error_from_syserror ();
95 fd
= open (keyfile
, O_RDONLY
);
97 return gpg_error_from_syserror ();
99 buf
= xmalloc (st
.st_size
+1);
102 size_t rlen
= read (fd
, buf
, st
.st_size
);
104 if (rlen
!= st
.st_size
)
105 rc
= GPG_ERR_ASS_READ_ERROR
;
109 if (rlen
&& strlen ((char *)buf
) != rlen
)
110 rc
= GPG_ERR_INV_PASSPHRASE
;
130 status_cb (void *data
, const char *keyword
, const char *args
)
132 struct crypto_s
*crypto
= data
;
135 if (!crypto
->client_ctx
)
138 if (!strcmp (keyword
, "INQUIRE_MAXLEN") &&
139 (crypto
->flags
& CRYPTO_FLAG_KEYFILE
))
142 return assuan_write_status (crypto
->client_ctx
, keyword
, args
);
146 passphrase_cb (void *data
, const char *hint
, const char *info
, int bad
, int fd
)
148 struct crypto_s
*crypto
= data
;
149 unsigned char *result
= NULL
;
153 if (crypto
->flags
& CRYPTO_FLAG_KEYFILE
)
154 rc
= get_password (crypto
->keyfile
, &result
, &len
);
158 rc
= assuan_write_status (crypto
->client_ctx
, "PASSPHRASE_HINT", hint
);
161 rc
= assuan_write_status (crypto
->client_ctx
, "PASSPHRASE_INFO", info
);
165 char *keyword
= "PASSPHRASE";
167 /* FIXME: how to handle multiple signers */
168 if (!bad
&& crypto
->flags
& CRYPTO_FLAG_PASSWD_SIGN
)
169 keyword
= "SIGN_PASSPHRASE";
170 else if (!bad
&& crypto
->flags
& CRYPTO_FLAG_PASSWD_NEW
)
172 crypto
->flags
|= CRYPTO_FLAG_PASSWD_SIGN
;
173 keyword
= "NEW_PASSPHRASE";
175 else if (!bad
&& crypto
->flags
& CRYPTO_FLAG_PASSWD
)
176 crypto
->flags
|= CRYPTO_FLAG_PASSWD_NEW
;
177 else if (!bad
&& crypto
->flags
& CRYPTO_FLAG_NEWFILE
)
179 keyword
= "NEW_PASSPHRASE";
180 if (crypto
->save
.sigkey
)
181 crypto
->flags
|= CRYPTO_FLAG_PASSWD_SIGN
;
184 rc
= assuan_inquire (crypto
->client_ctx
, keyword
, &result
, &len
, 0);
190 pthread_cleanup_push ((void *)xfree
, result
);
193 gpgme_io_writen (fd
, "\n", 1);
196 int nl
= result
[len
-1] == '\n';
199 ret
= gpgme_io_writen (fd
, result
, len
);
201 gpgme_io_writen (fd
, "\n", 1);
203 rc
= GPG_ERR_CANCELED
;
206 pthread_cleanup_pop (1);
213 progress_cb (void *data
, const char *what
, int type
, int current
, int total
)
215 struct crypto_s
*crypto
= data
;
217 crypto
->progress_rc
= send_status (crypto
->client_ctx
, STATUS_GPGME
,
218 "%s %i %i %i", what
, type
, current
, total
);
222 crypto_data_to_buf (const gpgme_data_t data
, unsigned char **result
,
225 off_t ret
= gpgme_data_seek (data
, 0, SEEK_SET
);
227 size_t total
= 0, size
= BUFSIZE
;
231 return gpg_error_from_syserror ();
233 buf
= xmalloc (size
);
235 return GPG_ERR_ENOMEM
;
239 pthread_cleanup_push ((void *)xfree
, buf
);
240 ret
= gpgme_data_read (data
, &buf
[total
], BUFSIZE
);
241 pthread_cleanup_pop (0);
248 p
= xrealloc (buf
, size
* sizeof(char));
252 return GPG_ERR_ENOMEM
;
261 rc
= gpgme_err_code_from_syserror ();
272 crypto_cancel_gpgme (void *data
)
274 struct crypto_s
*crypto
= data
;
275 struct client_s
*client
= assuan_get_pointer (crypto
->client_ctx
);
276 gpgme_error_t rc
= 0;
279 update_client_state (client
, CLIENT_STATE_DISCON
);
281 gpgme_cancel_async (crypto
->ctx
);
282 while (!gpgme_wait (crypto
->ctx
, &rc
, 0) && !rc
)
283 log_write1 (_ ("waiting for operation to finish"));
287 crypto_list_keys (struct crypto_s
*crypto
, char *keys
[], int secret
,
288 gpgme_key_t
**result
)
291 gpgme_key_t key
= NULL
, *res
= NULL
;
294 STATUS_TIMEOUT_INIT (crypto
);
295 rc
= gpgme_op_keylist_ext_start (crypto
->ctx
, (const char **)keys
, secret
, 0);
299 pthread_cleanup_push ((void *)crypto_cancel_gpgme
, crypto
);
305 pthread_cleanup_push ((void *)crypto_free_key_list
, res
);
306 rc
= gpgme_op_keylist_next (crypto
->ctx
, &key
);
307 pthread_cleanup_pop (0);
308 if (rc
&& gpgme_err_code(rc
) != GPG_ERR_EOF
)
317 p
= xrealloc (res
, (total
+2) * sizeof (gpgme_key_t
));
327 pthread_cleanup_push ((void *)crypto_free_key_list
, res
);
328 STATUS_TIMEOUT_TEST (crypto
, rc
, STATUS_KEEPALIVE
, NULL
);
329 pthread_cleanup_pop (0);
332 pthread_cleanup_pop (0);
336 rc
= gpgme_op_keylist_end (crypto
->ctx
);
340 rc
= total
? 0 : secret
? GPG_ERR_NO_SECKEY
: GPG_ERR_NO_PUBKEY
;
344 crypto_free_key_list (res
);
350 crypto_free_save (struct save_s
*save
)
355 strv_free (save
->pubkey
);
356 strv_free (save
->sigkey
);
357 memset (save
, 0, sizeof (struct save_s
));
363 return cache_kill_scd ();
367 free_gpgme_data_cb (void *data
)
369 gpgme_data_t d
= data
;
376 t
= gpgme_data_release_and_get_mem (d
, &len
);
378 wipememory (t
, 0, len
);
384 crypto_free_non_keys (struct crypto_s
*crypto
)
390 gpgme_release (crypto
->ctx
);
393 xfree (crypto
->plaintext
);
394 crypto
->plaintext
= NULL
;
395 crypto
->plaintext_size
= 0;
398 free_gpgme_data_cb (crypto
->cipher
);
400 crypto
->cipher
= NULL
;
401 crypto_free_save (&crypto
->save
);
402 xfree (crypto
->keyfile
);
403 crypto
->keyfile
= NULL
;
404 crypto
->flags
&= ~CRYPTO_FLAG_KEYFILE
;
405 (void)crypto_kill_scd ();
409 crypto_free (struct crypto_s
*crypto
)
414 crypto_free_non_keys (crypto
);
415 strv_free (crypto
->pubkey
);
416 strv_free (crypto
->sigkey
);
417 xfree (crypto
->filename
);
422 crypto_init_ctx (struct crypto_s
*crypto
, int no_pinentry
,
423 char *passphrase_file
)
426 gpgme_keylist_mode_t keylist_mode
;
429 rc
= gpgme_new (&ctx
);
433 rc
= gpgme_set_protocol (ctx
, GPGME_PROTOCOL_OPENPGP
);
436 keylist_mode
= gpgme_get_keylist_mode (ctx
);
437 keylist_mode
|= GPGME_KEYLIST_MODE_LOCAL
|GPGME_KEYLIST_MODE_WITH_SECRET
;
438 rc
= gpgme_set_keylist_mode (ctx
, keylist_mode
);
441 if (no_pinentry
|| passphrase_file
)
442 rc
= gpgme_set_pinentry_mode (ctx
, GPGME_PINENTRY_MODE_LOOPBACK
);
444 rc
= gpgme_set_pinentry_mode (ctx
, GPGME_PINENTRY_MODE_DEFAULT
);
448 gpgme_set_passphrase_cb (ctx
, passphrase_cb
, crypto
);
449 gpgme_set_progress_cb (ctx
, progress_cb
, crypto
);
450 gpgme_set_status_cb (ctx
, status_cb
, crypto
);
457 crypto
->keyfile
= passphrase_file
;
458 crypto
->flags
|= CRYPTO_FLAG_KEYFILE
;
470 crypto_set_keepalive ()
472 keepalive
= config_get_integer ("global", "keepalive_interval");
476 crypto_init (struct crypto_s
**crypto
, void *ctx
, const char *filename
,
477 int no_pinentry
, char *passphrase_file
)
479 struct crypto_s
*new = xcalloc (1, sizeof (struct crypto_s
));
482 crypto_set_keepalive ();
485 return GPG_ERR_ENOMEM
;
487 rc
= crypto_init_ctx (new, no_pinentry
, passphrase_file
);
493 new->filename
= str_dup (filename
);
501 new->client_ctx
= ctx
;
510 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
511 * gpgme_recipient_t.keyid. */
513 crypto_keyid_to_16b (char **keys
)
517 for (p
= keys
; p
&& *p
; p
++)
520 size_t len
= strlen (t
);
523 return GPG_ERR_INV_ARG
;
525 memmove (&t
[0], &t
[len
-16], 16);
533 crypto_decrypt (struct client_s
*client
, struct crypto_s
*crypto
)
539 char **new_recipients
= NULL
;
540 char **new_signers
= NULL
;
542 gpgme_decrypt_result_t result
;
544 rc
= gpgme_data_new (&plain
);
548 pthread_cleanup_push ((void *)free_gpgme_data_cb
, plain
);
549 fd
= open (crypto
->filename
, O_RDONLY
);
552 pthread_cleanup_push ((void *)close_fd_cb
, &fd
);
553 rc
= gpgme_data_new_from_fd (&cipher
, fd
);
556 pthread_cleanup_push ((void *)free_gpgme_data_cb
, cipher
);
557 STATUS_TIMEOUT_INIT(crypto
);
558 rc
= send_status (client
? client
->ctx
: NULL
, STATUS_DECRYPT
, NULL
);
560 rc
= gpgme_op_decrypt_verify_start (crypto
->ctx
, cipher
, plain
);
564 pthread_cleanup_push ((void *)crypto_cancel_gpgme
, crypto
);
568 if (!rc
&& crypto
->progress_rc
)
569 rc
= crypto
->progress_rc
;
572 STATUS_TIMEOUT_TEST (crypto
, rc
, STATUS_DECRYPT
, NULL
);
576 } while (!gpgme_wait (crypto
->ctx
, &rc
, 0) && !rc
);
578 pthread_cleanup_pop (0); // cancellation
581 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
584 pthread_cleanup_pop (1); // close (fd)
587 rc
= gpgme_err_code_from_syserror ();
589 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
593 free_gpgme_data_cb (plain
);
597 pthread_cleanup_push ((void *)free_gpgme_data_cb
, plain
);
598 result
= gpgme_op_decrypt_result (crypto
->ctx
);
599 if (!result
->unsupported_algorithm
&& !result
->wrong_key_usage
)
603 for (r
= result
->recipients
; r
; r
= r
->next
)
605 pthread_cleanup_push ((void *)strv_free
, new_recipients
);
606 log_write1 (_ ("%s: recipient: %s, status=%u"),
607 crypto
->filename
, r
->keyid
, r
->status
);
608 pthread_cleanup_pop (0);
609 pp
= strv_cat(new_recipients
, str_dup (r
->keyid
));
619 else if (result
->wrong_key_usage
)
620 rc
= GPG_ERR_WRONG_KEY_USAGE
;
621 else if (result
->unsupported_algorithm
)
622 rc
= GPG_ERR_UNSUPPORTED_ALGORITHM
;
626 gpgme_verify_result_t result
;
629 result
= gpgme_op_verify_result (crypto
->ctx
);
631 for (s
= result
->signatures
; s
; s
= s
->next
)
633 pthread_cleanup_push ((void *)strv_free
, new_signers
);
634 log_write1 (_ ("%s: signer: %s, status=%u"),
635 crypto
->filename
, s
->fpr
, s
->status
);
636 pthread_cleanup_pop (0);
637 if (s
->status
|| s
->wrong_key_usage
638 || !(s
->summary
& GPGME_SIGSUM_VALID
))
641 pp
= strv_cat (new_signers
, str_dup (s
->fpr
));
651 if (result
->signatures
&& !new_signers
)
652 rc
= GPG_ERR_BAD_SIGNATURE
;
656 xfree (crypto
->plaintext
);
657 crypto
->plaintext
= NULL
;
658 crypto
->plaintext_size
= 0;
659 pthread_cleanup_push ((void *)strv_free
, new_recipients
);
660 pthread_cleanup_push ((void *)strv_free
, new_signers
);
661 rc
= crypto_data_to_buf (plain
, &crypto
->plaintext
,
662 &crypto
->plaintext_size
);
663 pthread_cleanup_pop (0);
664 pthread_cleanup_pop (0);
667 strv_free (crypto
->pubkey
);
668 crypto
->pubkey
= new_recipients
;
669 crypto_keyid_to_16b (crypto
->pubkey
);
670 strv_free (crypto
->sigkey
);
671 crypto
->sigkey
= new_signers
;
672 crypto_keyid_to_16b (crypto
->sigkey
);
679 strv_free (new_recipients
);
680 strv_free (new_signers
);
683 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
688 crypto_free_key_list (gpgme_key_t
*keys
)
692 for (i
= 0; keys
&& keys
[i
]; i
++)
693 gpgme_key_unref (keys
[i
]);
698 /* Removes strings in 'prune' from 'a'. */
700 prune_keys (char **a
, char **prune
)
704 for (p
= prune
; p
&& *p
; p
++)
708 for (ap
= a
; ap
&& *ap
; ap
++)
710 if (!strcmp (*ap
, *p
))
725 remove_duplicates (char **a
)
729 for (p
= a
; p
&& *p
; p
++)
733 for (t
= p
+1; t
&& *t
; t
++)
735 if (!strcmp (*p
, *t
))
747 remove_duplicates (a
);
755 crypto_encrypt (struct client_s
*client
, struct crypto_s
*crypto
)
758 gpgme_data_t cipher
= NULL
;
759 gpgme_key_t
*keys
= NULL
;
760 gpgme_key_t
*sigkeys
= NULL
;
762 STATUS_TIMEOUT_INIT (crypto
);
763 if (!(crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
))
765 crypto_keyid_to_16b (crypto
->save
.pubkey
);
766 remove_duplicates (crypto
->save
.pubkey
);
767 rc
= crypto_list_keys (crypto
, crypto
->save
.pubkey
, 0, &keys
);
772 pthread_cleanup_push ((void *)crypto_free_key_list
, keys
);
773 rc
= gpgme_data_new (&cipher
);
774 pthread_cleanup_push ((void *)free_gpgme_data_cb
, cipher
);
776 rc
= gpgme_data_set_file_name (cipher
, crypto
->filename
);
778 if (!rc
&& (crypto
->save
.sigkey
779 || !(crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
)))
781 crypto_keyid_to_16b (crypto
->save
.sigkey
);
782 remove_duplicates (crypto
->save
.sigkey
);
783 rc
= crypto_list_keys (crypto
, crypto
->save
.sigkey
, 1, &sigkeys
);
784 if (gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
790 gpgme_data_t plain
= NULL
;
792 pthread_cleanup_push ((void *)crypto_free_key_list
, sigkeys
);
793 rc
= gpgme_data_new_from_mem (&plain
, (char *)crypto
->plaintext
,
794 crypto
->plaintext_size
, 0);
795 pthread_cleanup_push ((void *)free_gpgme_data_cb
, plain
);
800 gpgme_signers_clear (crypto
->ctx
);
802 for (i
= 0; sigkeys
&& sigkeys
[i
]; i
++)
803 gpgme_signers_add (crypto
->ctx
, sigkeys
[i
]);
805 if (!i
&& !(crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
))
806 rc
= GPG_ERR_NO_SIGNATURE_SCHEME
;
811 gpgme_data_set_encoding (cipher
, GPGME_DATA_ENCODING_ARMOR
);
813 rc
= send_status (client
? client
->ctx
: NULL
, STATUS_ENCRYPT
, NULL
);
817 int f
= config_get_boolean ("global", "encrypt_to");
820 flags
|= GPGME_ENCRYPT_NO_ENCRYPT_TO
;
822 f
= config_get_boolean ("global", "always_trust");
824 flags
|= GPGME_ENCRYPT_ALWAYS_TRUST
;
826 if (!(crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
)
827 || (crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
&& sigkeys
))
828 rc
= gpgme_op_encrypt_sign_start (crypto
->ctx
,
829 (crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
) ? NULL
: keys
,
830 flags
, plain
, cipher
);
832 rc
= gpgme_op_encrypt_start (crypto
->ctx
, NULL
, flags
,
839 pthread_cleanup_push ((void *)crypto_cancel_gpgme
, crypto
);
843 if (!rc
&& crypto
->progress_rc
)
844 rc
= crypto
->progress_rc
;
847 STATUS_TIMEOUT_TEST (crypto
, rc
, STATUS_ENCRYPT
, NULL
);
851 } while (!gpgme_wait (crypto
->ctx
, &rc
, 0) && !rc
);
853 pthread_cleanup_pop (0);
857 gpgme_encrypt_result_t result
;
858 gpgme_sign_result_t sresult
;
859 gpgme_invalid_key_t inv
;
860 gpgme_new_signature_t sigs
;
864 result
= gpgme_op_encrypt_result (crypto
->ctx
);
865 inv
= result
->invalid_recipients
;
868 pthread_cleanup_push ((void *)strv_free
, prune
);
869 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
870 crypto
->filename
, inv
->fpr
, inv
->reason
);
871 pthread_cleanup_pop (0);
872 p
= strv_cat (prune
, str_dup(inv
->fpr
));
886 p
= prune_keys (crypto
->save
.pubkey
, prune
);
887 crypto
->save
.pubkey
= p
;
890 crypto_keyid_to_16b (crypto
->save
.pubkey
);
891 sresult
= gpgme_op_sign_result (crypto
->ctx
);
892 inv
= sresult
? sresult
->invalid_signers
: NULL
;
895 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
896 crypto
->filename
, inv
->fpr
, inv
->reason
);
900 sigs
= sresult
? sresult
->signatures
: NULL
;
909 pthread_cleanup_push ((void *)strv_free
, p
);
910 log_write1 (_ ("%s: signer: %s"), crypto
->filename
,
912 pthread_cleanup_pop (0);
914 pp
= strv_cat (p
, str_dup (sigs
->fpr
));
928 strv_free (crypto
->save
.sigkey
);
929 crypto
->save
.sigkey
= p
;
930 crypto_keyid_to_16b (crypto
->save
.sigkey
);
931 crypto
->cipher
= cipher
;
934 else if (!rc
&& crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
)
936 crypto
->cipher
= cipher
;
940 if (!(crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
)
941 || (crypto
->flags
& CRYPTO_FLAG_SYMMETRIC
&& sigkeys
))
942 rc
= GPG_ERR_NO_SIGNATURE_SCHEME
;
947 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
948 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
951 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
952 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
955 free_gpgme_data_cb (cipher
);
961 crypto_passwd (struct client_s
*client
, struct crypto_s
*crypto
)
964 gpgme_key_t
*keys
= NULL
;
966 /* Use SAVE instead for symmetric files. */
967 rc
= crypto_is_symmetric (client
->filename
);
968 if (!rc
|| rc
!= GPG_ERR_BAD_DATA
)
969 return !rc
? GPG_ERR_NOT_SUPPORTED
: rc
;
971 rc
= crypto_list_keys (crypto
, crypto
->pubkey
, 1, &keys
);
975 crypto
->flags
|= CRYPTO_FLAG_PASSWD
;
976 pthread_cleanup_push ((void *)crypto_free_key_list
, keys
);
977 STATUS_TIMEOUT_INIT (crypto
);
978 rc
= send_status (client
->ctx
, STATUS_KEEPALIVE
, NULL
);
980 rc
= gpgme_op_passwd_start (crypto
->ctx
, keys
[0], 0);
984 pthread_cleanup_push ((void *)crypto_cancel_gpgme
, crypto
);
988 if (!rc
&& crypto
->progress_rc
)
989 rc
= crypto
->progress_rc
;
992 STATUS_TIMEOUT_TEST (crypto
, rc
, STATUS_KEEPALIVE
, NULL
);
996 } while (!gpgme_wait (crypto
->ctx
, &rc
, 0) && !rc
);
998 pthread_cleanup_pop (0);
1001 pthread_cleanup_pop (1);
1005 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1008 crypto_genkey (struct client_s
*client
, struct crypto_s
*crypto
,
1009 const unsigned char *params
)
1011 gpgme_genkey_result_t result
;
1014 if (strstr ((char *) params
, "%pubring")
1015 || strstr ((char *) params
, "%secring"))
1016 return GPG_ERR_INV_VALUE
;
1018 STATUS_TIMEOUT_INIT (crypto
);
1019 rc
= send_status (client
? client
->ctx
: NULL
, STATUS_GENKEY
, NULL
);
1021 rc
= gpgme_op_genkey_start (crypto
->ctx
, (const char *)params
, NULL
, NULL
);
1026 pthread_cleanup_push ((void *)crypto_cancel_gpgme
, crypto
);
1030 if (!rc
&& crypto
->progress_rc
)
1031 rc
= crypto
->progress_rc
;
1034 STATUS_TIMEOUT_TEST (crypto
, rc
, STATUS_GENKEY
, NULL
);
1038 } while (!gpgme_wait (crypto
->ctx
, &rc
, 0) && !rc
);
1040 pthread_cleanup_pop (0);
1044 gpgme_key_t
*keys
= NULL
;
1046 result
= gpgme_op_genkey_result (crypto
->ctx
);
1047 crypto
->save
.sigkey
= strv_cat (crypto
->save
.sigkey
,
1048 str_dup (result
->fpr
));
1049 crypto_keyid_to_16b (crypto
->save
.sigkey
);
1051 rc
= crypto_list_keys (crypto
, crypto
->save
.sigkey
, 1, &keys
);
1054 gpgme_subkey_t key
= keys
[0]->subkeys
;
1056 for (; key
; key
= key
->next
)
1058 if (key
->can_encrypt
)
1062 pthread_cleanup_push ((void *)crypto_free_key_list
, keys
);
1063 rc
= send_status (client
? client
->ctx
: NULL
, STATUS_GENKEY
, "%s %s",
1064 crypto
->save
.sigkey
[0], key
? key
->fpr
: "");
1067 crypto
->save
.pubkey
= strv_cat (crypto
->save
.pubkey
,
1068 str_dup (key
->fpr
));
1069 crypto_keyid_to_16b (crypto
->save
.pubkey
);
1072 pthread_cleanup_pop (1);
1080 crypto_default_key_params ()
1082 char *user
= get_username (getuid());
1083 char *params
= str_asprintf(
1084 "<GnupgKeyParms format=\"internal\">\n"
1085 " Key-Type: default\n"
1086 " Subkey-Type: default\n"
1091 getenv ("REALNAME") ? getenv ("REALNAME") : user
,
1092 getenv ("EMAIL") ? getenv ("EMAIL") : user
);
1100 acl_free_cb (void *arg
)
1102 acl_t acl
= arg
? (acl_t
) arg
: NULL
;
1109 /* The advisory lock should be obtained before calling this function. */
1111 crypto_write_file (struct crypto_s
*crypto
)
1124 if (crypto
->filename
)
1126 if (lstat (crypto
->filename
, &st
) == 0)
1128 mode
= st
.st_mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
);
1130 if (!(mode
& S_IWUSR
))
1131 return GPG_ERR_EACCES
;
1133 else if (errno
!= ENOENT
)
1134 return gpg_error_from_errno (errno
);
1136 snprintf (tmp
, sizeof (tmp
), "%s.XXXXXX", crypto
->filename
);
1137 mode_t tmode
= umask (0600);
1141 rc
= gpg_error_from_errno (errno
);
1143 log_write ("%s: %s", tmp
, pwmd_strerror (rc
));
1152 rc
= crypto_data_to_buf (crypto
->cipher
, &buf
, &size
);
1155 if (crypto
->filename
)
1160 pthread_cleanup_push ((void *)close_fd_cb
, &fd
);
1161 pthread_cleanup_push ((void *)xfree
, buf
);
1162 len
= write (fd
, buf
, size
);
1163 pthread_cleanup_pop (1);
1165 rc
= gpg_error_from_errno (errno
);
1169 if (fsync (fd
) != -1)
1171 if (crypto
->filename
&& close (fd
) != -1)
1174 acl
= acl_get_file (crypto
->filename
, ACL_TYPE_ACCESS
);
1175 if (!acl
&& errno
== ENOENT
)
1176 acl
= acl_get_file (".", ACL_TYPE_DEFAULT
);
1178 log_write ("ACL: %s: %s", crypto
->filename
,
1179 pwmd_strerror (gpg_error_from_errno (errno
)));
1180 pthread_cleanup_push ((void *)acl_free_cb
, acl
);
1184 if (config_get_boolean (crypto
->filename
, "backup"))
1186 char tmp2
[PATH_MAX
];
1188 snprintf (tmp2
, sizeof (tmp2
), "%s.backup", crypto
->filename
);
1189 if (rename (crypto
->filename
, tmp2
) == -1)
1190 if (errno
!= ENOENT
)
1191 rc
= gpg_error_from_errno (errno
);
1194 if (!rc
&& rename (tmp
, crypto
->filename
) == -1)
1195 rc
= gpg_error_from_errno (errno
);
1198 chmod (crypto
->filename
, mode
);
1200 if (!rc
&& acl
&& acl_set_file (crypto
->filename
,
1201 ACL_TYPE_ACCESS
, acl
))
1202 log_write ("ACL: %s: %s", crypto
->filename
,
1203 pwmd_strerror (gpg_error_from_errno (errno
)));
1204 pthread_cleanup_pop (1);
1207 else if (crypto
->filename
)
1208 rc
= gpg_error_from_errno (errno
);
1210 if (!rc
&& fd
!= -1)
1212 char *tmp
= str_asprintf ("%s/data", homedir
);
1216 int dfd
= open (tmp
, O_RDONLY
);
1220 if (fsync (dfd
) == -1)
1221 log_write ("%s %d: %s", __FILE__
, __LINE__
,
1222 pwmd_strerror (errno
));
1227 log_write ("%s %d: %s", __FILE__
, __LINE__
,
1228 pwmd_strerror (errno
));
1235 rc
= gpg_error_from_errno (errno
);
1238 pthread_cleanup_pop (0); // close (fd)
1245 crypto_key_info (const gpgme_key_t key
)
1247 struct string_s
*string
= string_new (NULL
), *s
;
1250 gpgme_subkey_t subkey
;
1251 gpgme_user_id_t uid
;
1256 for (u
= 0, uid
= key
->uids
; uid
; uid
= uid
->next
)
1259 for (n
= 0, subkey
= key
->subkeys
; subkey
; subkey
= subkey
->next
)
1262 s
= string_append_printf (string
, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1263 key
->revoked
, key
->expired
, key
->disabled
,
1264 key
->invalid
, key
->can_encrypt
, key
->can_sign
,
1265 key
->can_certify
, key
->secret
,
1266 key
->can_authenticate
, key
->is_qualified
,
1268 key
->issuer_serial
? key
->issuer_serial
: "",
1269 key
->issuer_name
? key
->issuer_name
: "",
1270 key
->chain_id
? key
->chain_id
: "",
1271 key
->owner_trust
, u
, n
);
1274 string_free (string
, 1);
1279 for (subkey
= key
->subkeys
; subkey
; subkey
= subkey
->next
)
1283 s
= string_append_printf (string
, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1284 subkey
->revoked
, subkey
->expired
,
1285 subkey
->disabled
, subkey
->invalid
,
1286 subkey
->can_encrypt
, subkey
->can_sign
,
1287 subkey
->can_certify
, subkey
->secret
,
1288 subkey
->can_authenticate
, subkey
->is_qualified
,
1289 subkey
->is_cardkey
, subkey
->pubkey_algo
,
1293 string_free (string
, 1);
1298 s
= string_append_printf (string
, ":%s:%s:%s:%li:%li:%s",
1299 subkey
->keyid
, subkey
->fpr
,
1300 subkey
->keygrip
? subkey
->keygrip
: "",
1301 subkey
->timestamp
, subkey
->expires
,
1302 subkey
->card_number
? subkey
->card_number
: "0");
1305 string_free (string
, 1);
1310 tmp
= gnupg_escape (subkey
->curve
);
1311 s
= string_append_printf (string
, ":%s", tmp
? tmp
: "");
1315 string_free (string
, 1);
1322 for (uid
= key
->uids
; uid
; uid
= uid
->next
)
1324 char *userid
, *name
, *email
, *comment
;
1326 userid
= gnupg_escape (uid
->uid
);
1327 name
= gnupg_escape (uid
->name
);
1328 email
= gnupg_escape (uid
->email
);
1329 comment
= gnupg_escape (uid
->comment
);
1330 s
= string_append_printf (string
, ":%u:%u:%u:%s:%s:%s:%s",
1331 uid
->revoked
, uid
->invalid
, uid
->validity
,
1332 userid
? userid
: "",
1335 comment
? comment
: "");
1342 string_free (string
, 1);
1350 string_free (string
, 0);
1355 crypto_try_decrypt (struct client_s
*client
, int no_pinentry
)
1357 struct crypto_s
*crypto
;
1359 char *keyfile
= config_get_string (client
->filename
, "passphrase_file");
1361 rc
= crypto_init (&crypto
, client
->ctx
, client
->filename
, no_pinentry
,
1365 pthread_cleanup_push ((void *)crypto_free
, crypto
);
1366 rc
= crypto_decrypt (client
, crypto
);
1367 pthread_cleanup_pop (1);
1375 /* The advisory lock should be obtained before calling this function. */
1377 crypto_is_symmetric (const char *filename
)
1383 fd
= open (filename
, O_RDONLY
);
1385 return gpg_error_from_errno (errno
);
1387 len
= read (fd
, &magic
, sizeof(magic
));
1389 if (len
!= sizeof (magic
))
1390 return GPG_ERR_INV_VALUE
;
1392 // Always read as big endian.
1393 if (magic
[0] != 0x8c || magic
[1] != 0x0d)
1394 return GPG_ERR_BAD_DATA
;