mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-03 22:48:03 +02:00
Compare commits
271 Commits
gnupg-2.4.
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
ed118e2ed5 | ||
|
d2dca58338 | ||
|
42b0e9558a | ||
|
253a701ed7 | ||
|
fc3fde1bde | ||
|
34045ed9e1 | ||
|
aedeef6acf | ||
|
9adaa79ab4 | ||
|
dcb0b6fd48 | ||
|
28c705a3be | ||
|
4c1b007035 | ||
|
379fc5569d | ||
|
bdbf5cee2f | ||
|
fdc5003956 | ||
|
021c27510b | ||
|
bcc002cd45 | ||
|
d631c8198c | ||
|
2e4b1f7850 | ||
|
610a452bb5 | ||
|
cdc798db5c | ||
|
287e717b55 | ||
|
5355d08855 | ||
|
7f661aa129 | ||
|
758cd4ccfc | ||
|
6b2ebc36a9 | ||
|
0eefa08295 | ||
|
3bbfcab606 | ||
|
b36e557c5b | ||
|
e0543f97be | ||
|
0cb7f6fbb7 | ||
|
14534e72e1 | ||
|
351fc6e6fa | ||
|
473f37a53e | ||
|
467239dccb | ||
|
f415d96fac | ||
|
516b530126 | ||
|
c8a3b711f0 | ||
|
c1d62418d5 | ||
|
351f5e814b | ||
|
9128d81bb7 | ||
|
83e2dede0a | ||
|
d3b41e7611 | ||
|
02b056ef77 | ||
|
2593dcbceb | ||
|
2958e5e4cf | ||
|
a45243548e | ||
|
d1f8caafb4 | ||
|
ab703eacf7 | ||
|
dd650b2c7b | ||
|
32ec480024 | ||
|
54741685ce | ||
|
f325d3277e | ||
|
e591fd25ad | ||
|
f305e703d5 | ||
|
af98a3e5fa | ||
|
65833eefb2 | ||
|
d5c6b52e59 | ||
|
aa15272ba1 | ||
|
7728a179e0 | ||
|
f119444e64 | ||
|
ba3c873934 | ||
|
2a0a706eb2 | ||
|
967678d972 | ||
|
7d6ad28667 | ||
|
21f7ad563d | ||
|
2a71c3cf97 | ||
|
4e32ff209d | ||
|
c736052e9c | ||
|
4c20d2d273 | ||
|
35ef87d8d9 | ||
|
b48476bbef | ||
|
6f94fe01a9 | ||
|
813f8d1b8e | ||
|
61717fb0a7 | ||
|
869d1df270 | ||
|
f2fd4f1a9e | ||
|
172d53d636 | ||
|
6737e07a9b | ||
|
87025e5da6 | ||
|
84ddb24e30 | ||
|
c21237ac27 | ||
|
aee6b1131b | ||
|
04b81ec236 | ||
|
52c4b09080 | ||
|
1a37f0080b | ||
|
3a344d6236 | ||
|
f7a26aa8ad | ||
|
c5d7a332c8 | ||
|
03d53c88cc | ||
|
68d9bc9c35 | ||
|
b261478c06 | ||
|
53c6b1e858 | ||
|
ce8b25270b | ||
|
548fd7bca7 | ||
|
131dd2a351 | ||
|
0b1f7427b3 | ||
|
98e287ba6d | ||
|
97f5159495 | ||
|
6c1dd3afd1 | ||
|
4b981e415f | ||
|
fa33b18940 | ||
|
c69363e8c7 | ||
|
1fa24e2841 | ||
|
571a768ac6 | ||
|
984a0c6982 | ||
|
f9919bcc48 | ||
|
cec1fde1bc | ||
|
a0bfbdaaa2 | ||
|
fb3fe38d28 | ||
|
759adb2493 | ||
|
122803bf1a | ||
|
50e81ad38d | ||
|
f78501c545 | ||
|
c27534de95 | ||
|
14c1b73093 | ||
|
81536535f8 | ||
|
4485930f9f | ||
|
609b1ec0c6 | ||
|
79d0e52b2d | ||
|
40227e42ea | ||
|
874918ab91 | ||
|
27f66148f7 | ||
|
dfa60c09f5 | ||
|
af6ac2ac02 | ||
|
ccfbb9ebdf | ||
|
6ddaf2be9f | ||
|
7cde533ce8 | ||
|
c44f0bc91e | ||
|
2764ee309a | ||
|
853f36e596 | ||
|
4dd4e9d2f1 | ||
|
4e94b004a6 | ||
|
37fa36a329 | ||
|
1ded50dd5b | ||
|
548d4aad5f | ||
|
42ee841976 | ||
|
2600047470 | ||
|
6fab7b075a | ||
|
ec1446f944 | ||
|
64f5f7b74e | ||
|
65607fb81d | ||
|
e6b3d53db3 | ||
|
387ee7dcbd | ||
|
337de21f4b | ||
|
00da0e9f93 | ||
|
c2812a9bbc | ||
|
05ef8c0cc0 | ||
|
16b6b77532 | ||
|
227b3b14f4 | ||
|
98dd6f7af6 | ||
|
08e529fa7c | ||
|
f2ca727978 | ||
|
25c84ffd10 | ||
|
321f9c0a3f | ||
|
4206d89003 | ||
|
78afc209cc | ||
|
1da40db03e | ||
|
eda3997b43 | ||
|
459bd577fc | ||
|
a8618fdccd | ||
|
26939ea222 | ||
|
34f812475e | ||
|
1be7882344 | ||
|
d90f1e5fa4 | ||
|
28364affa6 | ||
|
5e47d5edd8 | ||
|
57125d3f5a | ||
|
92de0387f0 | ||
|
76a2f18028 | ||
|
7025375e8b | ||
|
76896e2339 | ||
|
b2826924ee | ||
|
95186ae92f | ||
|
9dd8fd4ae4 | ||
|
a430f22549 | ||
|
716e59b0b6 | ||
|
9e4d522239 | ||
|
1d73806972 | ||
|
ed4050e011 | ||
|
0821ceebfb | ||
|
5cad5f903e | ||
|
0d20b79ab7 | ||
|
dad880155e | ||
|
1ddd69935d | ||
|
95d9761509 | ||
|
30fc365124 | ||
|
eceba4f207 | ||
|
6e2412e74a | ||
|
6524becf28 | ||
|
ea1935252e | ||
|
521ec40aea | ||
|
ae188a3357 | ||
|
81055baf5c | ||
|
b849c930e9 | ||
|
ee9e3578ce | ||
|
5d375bb168 | ||
|
cf270b0d30 | ||
|
ea625c74f0 | ||
|
69c1d81284 | ||
|
fb046ccd93 | ||
|
23bcb78d27 | ||
|
b07b5144ff | ||
|
067bc2ed4c | ||
|
16d135c396 | ||
|
250733c0d8 | ||
|
37343db08f | ||
|
5bc949d230 | ||
|
9f39e4da29 | ||
|
8cacfce898 | ||
|
2abea42d9c | ||
|
f2dcd158a5 | ||
|
577baf4af3 | ||
|
3fb69641e8 | ||
|
2c2516f03a | ||
|
68d3a73ea7 | ||
|
dc13361524 | ||
|
2c5a93e66e | ||
|
334f5d95c8 | ||
|
b5efb52d43 | ||
|
a0ff2919f7 | ||
|
250fff0f6e | ||
|
6049d61991 | ||
|
3672c29156 | ||
|
cacb018992 | ||
|
7cfbf0dd72 | ||
|
631c23b664 | ||
|
b9b0c18320 | ||
|
72ac77c4fa | ||
|
76df934929 | ||
|
1f9a4fbc7e | ||
|
f0ecc07c4e | ||
|
87a73e8eb0 | ||
|
2756147e39 | ||
|
04d0851cca | ||
|
e9e7b5425f | ||
|
28a4d0d4f5 | ||
|
be77c05532 | ||
|
e16fc3e19c | ||
|
3c57aee263 | ||
|
5170c366ee | ||
|
1b0ce9918c | ||
|
f5656ff363 | ||
|
9433dfa5dd | ||
|
22350d0768 | ||
|
ef4f22b9d9 | ||
|
0fba0bbc62 | ||
|
6ed61d98a0 | ||
|
2783b786a9 | ||
|
a216e9c028 | ||
|
1d23dc9389 | ||
|
ec0c35d1b8 | ||
|
f15a643a2d | ||
|
09a96c9e1b | ||
|
e9dd47d789 | ||
|
39a4373780 | ||
|
6984ddc6eb | ||
|
000b82ade7 | ||
|
8295fb3f0b | ||
|
3a438a1cc3 | ||
|
42bea7de16 | ||
|
7e681da1b2 | ||
|
097701e698 | ||
|
faf0a97b2e | ||
|
2f872fa68c | ||
|
b789ada2b0 | ||
|
d221062769 | ||
|
86cdb49097 | ||
|
5c7c6065f3 | ||
|
23bb92b755 | ||
|
a035938216 | ||
|
1e41878bf2 |
|
@ -2,3 +2,5 @@
|
|||
6a80d6f9206eae2c867c45daa5cd3e7d6c6ad114
|
||||
# doc: Fix spelling errors found by lintian.
|
||||
2ed1f68b48db7b5503045386de0500fddf70077e
|
||||
# indent: Re-indent a function
|
||||
869d1df270c0ccc3a9f792167b96d678a932b37e
|
||||
|
|
3
AUTHORS
3
AUTHORS
|
@ -220,6 +220,9 @@ Jussi Kivilinna <jussi.kivilinna@iki.fi>
|
|||
Kyle Butt <kylebutt@gmail.com>
|
||||
2013-05-29:CAAODAYLbCtqOG6msLLL0UTdASKWT6u2ptxsgUQ1JpusBESBoNQ@mail.gmail.com:
|
||||
|
||||
Mario Haustein <mario.haustein@hrz.tu-chemnitz.de>
|
||||
2022-09-26:8149069.T7Z3S40VBb@localdomain:
|
||||
|
||||
Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
|
||||
2018-07-13:c397e637-f1ce-34f0-7e6a-df04a76e1c35@ssi-schaefer.com:
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ WITH_MSI=1
|
|||
# Location of the released tarball archives. This is prefixed by
|
||||
# the variable RELEASE_ARCHIVE in ~/.gnupg-autogen.rc. For example:
|
||||
# RELEASE_ARCHIVE=user@host:archive/tarballs
|
||||
RELEASE_ARCHIVE_SUFFIX = gnupg/v2.4
|
||||
RELEASE_ARCHIVE_SUFFIX = gnupg/v2.5
|
||||
# The variable RELEASE_SIGNKEY in ~/.gnupg-autogen.rc is used
|
||||
# to specify the key for signing. For example:
|
||||
# RELEASE_SIGNKEY=D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
|
||||
|
|
53
NEWS
53
NEWS
|
@ -1,6 +1,28 @@
|
|||
Noteworthy changes in version 2.4.5 (2024-03-07)
|
||||
Noteworthy changes in version 2.5.0 (unreleased)
|
||||
------------------------------------------------
|
||||
|
||||
Changes also found in 2.4.6:
|
||||
|
||||
* gpg: New command --quick-set-ownertrust. [rG967678d972]
|
||||
|
||||
* gpg: Indicate disabled keys in key listings and add list option
|
||||
"show-ownertrust". [rG2a0a706eb2]
|
||||
|
||||
* gpg: Make sure a DECRYPTION_OKAY is never issued for a bad OCB
|
||||
tag. [T7042]
|
||||
|
||||
* gpg: Do not allow to accidently set the RENC usage. [T7072]
|
||||
|
||||
* agent: Consider an empty pattern file as valid. [rGc27534de95]
|
||||
|
||||
* agent: Fix error handling of READKEY. [T6012]
|
||||
|
||||
* gpgconf: Check readability of some files with -X and change its
|
||||
output format. [rG759adb2493]
|
||||
|
||||
|
||||
Changes also found in 2.4.5:
|
||||
|
||||
* gpg,gpgv: New option --assert-pubkey-algo. [T6946]
|
||||
|
||||
* gpg: Emit status lines for errors in the compression layer.
|
||||
|
@ -40,11 +62,8 @@ Noteworthy changes in version 2.4.5 (2024-03-07)
|
|||
|
||||
* Make the getswdb.sh tool usable outside the GnuPG tree.
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6960
|
||||
|
||||
|
||||
Noteworthy changes in version 2.4.4 (2024-01-25)
|
||||
------------------------------------------------
|
||||
Changes also found in 2.4.4:
|
||||
|
||||
* gpg: Do not keep an unprotected smartcard backup key on disk. See
|
||||
https://gnupg.org/blog/20240125-smartcard-backup-key.html for a
|
||||
|
@ -145,11 +164,7 @@ Noteworthy changes in version 2.4.4 (2024-01-25)
|
|||
* Improve the speedo build system for Unix. [T6710]
|
||||
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6578
|
||||
|
||||
|
||||
Noteworthy changes in version 2.4.3 (2023-07-04)
|
||||
------------------------------------------------
|
||||
Changes also found in 2.4.3:
|
||||
|
||||
* gpg: Set default expiration date to 3 years. [T2701]
|
||||
|
||||
|
@ -198,12 +213,8 @@ Noteworthy changes in version 2.4.3 (2023-07-04)
|
|||
|
||||
* Fix garbled time output in non-English Windows. [T6741]
|
||||
|
||||
See-also: gnupg-announce/2023q3/000480.html
|
||||
Release-info: https://dev.gnupg.org/T6509
|
||||
|
||||
|
||||
Noteworthy changes in version 2.4.2 (2023-05-30)
|
||||
------------------------------------------------
|
||||
Changes also found in 2.4.2:
|
||||
|
||||
* gpg: Print a warning if no more encryption subkeys are left over
|
||||
after changing the expiration date. [rGef2c3d50fa]
|
||||
|
@ -225,8 +236,16 @@ Noteworthy changes in version 2.4.2 (2023-05-30)
|
|||
|
||||
* w32: Avoid using the VirtualStore. [T6403]
|
||||
|
||||
See-also: gnupg-announce/2023q2/000479.html
|
||||
Release-info: https://dev.gnupg.org/T6506
|
||||
|
||||
Release dates of 2.4 versions
|
||||
-----------------------------
|
||||
|
||||
Version 2.4.5 (2024-03-07) https://dev.gnupg.org/T6960
|
||||
Version 2.4.4 (2024-01-25) https://dev.gnupg.org/T6578
|
||||
Version 2.4.3 (2023-07-04) https://dev.gnupg.org/T6509
|
||||
Version 2.4.2 (2023-05-30) https://dev.gnupg.org/T6506
|
||||
Version 2.4.1 (2023-04-28) https://dev.gnupg.org/T6454
|
||||
Version 2.4.0 (2022-12-16) https://dev.gnupg.org/T6302
|
||||
|
||||
|
||||
Noteworthy changes in version 2.4.1 (2023-04-28)
|
||||
|
|
2
README
2
README
|
@ -1,6 +1,6 @@
|
|||
The GNU Privacy Guard
|
||||
=======================
|
||||
Version 2.4
|
||||
Version 2.5 (devel)
|
||||
|
||||
Copyright 1997-2019 Werner Koch
|
||||
Copyright 1998-2021 Free Software Foundation, Inc.
|
||||
|
|
|
@ -121,7 +121,7 @@ struct
|
|||
/* Flag disallowing bypassing of the warning. */
|
||||
int enforce_passphrase_constraints;
|
||||
|
||||
/* The require minmum length of a passphrase. */
|
||||
/* The required minimum length of a passphrase. */
|
||||
unsigned int min_passphrase_len;
|
||||
|
||||
/* The minimum number of non-alpha characters in a passphrase. */
|
||||
|
@ -286,10 +286,13 @@ struct server_control_s
|
|||
int algo;
|
||||
unsigned char value[MAX_DIGEST_LEN];
|
||||
unsigned int raw_value: 1;
|
||||
unsigned int is_pss: 1; /* DATA holds PSS formated data. */
|
||||
unsigned int is_pss: 1; /* DATA holds PSS formatted data. */
|
||||
} digest;
|
||||
unsigned int have_keygrip: 1;
|
||||
unsigned int have_keygrip1: 1;
|
||||
unsigned char keygrip[20];
|
||||
int have_keygrip;
|
||||
unsigned char keygrip1[20]; /* Another keygrip for hybrid crypto. */
|
||||
|
||||
|
||||
/* A flag to enable a hack to send the PKAUTH command instead of the
|
||||
PKSIGN command to the scdaemon. */
|
||||
|
@ -428,6 +431,7 @@ void *get_agent_daemon_notify_event (void);
|
|||
#endif
|
||||
void agent_sighup_action (void);
|
||||
int map_pk_openpgp_to_gcry (int openpgp_algo);
|
||||
void agent_kick_the_loop (void);
|
||||
|
||||
/*-- command.c --*/
|
||||
gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid,
|
||||
|
@ -533,7 +537,7 @@ int agent_clear_passphrase (ctrl_t ctrl,
|
|||
/*-- cache.c --*/
|
||||
void initialize_module_cache (void);
|
||||
void deinitialize_module_cache (void);
|
||||
void agent_cache_housekeeping (void);
|
||||
struct timespec *agent_cache_expiration (void);
|
||||
void agent_flush_cache (int pincache_only);
|
||||
int agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
||||
const char *data, int ttl);
|
||||
|
@ -556,6 +560,18 @@ gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||
const unsigned char *ciphertext, size_t ciphertextlen,
|
||||
membuf_t *outbuf, int *r_padding);
|
||||
|
||||
enum kemids
|
||||
{
|
||||
KEM_PQC_PGP,
|
||||
KEM_PGP,
|
||||
KEM_CMS
|
||||
};
|
||||
|
||||
gpg_error_t agent_kem_decrypt (ctrl_t ctrl, const char *desc_text, int kemid,
|
||||
const unsigned char *ct, size_t ctlen,
|
||||
const unsigned char *option, size_t optionlen,
|
||||
membuf_t *outbuf);
|
||||
|
||||
/*-- genkey.c --*/
|
||||
#define CHECK_CONSTRAINTS_NOT_EMPTY 1
|
||||
#define CHECK_CONSTRAINTS_NEW_SYMKEY 2
|
||||
|
@ -689,6 +705,9 @@ gpg_error_t divert_writekey (ctrl_t ctrl, int force, const char *serialno,
|
|||
const char *keyref,
|
||||
const char *keydata, size_t keydatalen);
|
||||
|
||||
gpg_error_t agent_card_ecc_kem (ctrl_t ctrl, const unsigned char *ecc_ct,
|
||||
size_t ecc_point_len, unsigned char *ecc_ecdh);
|
||||
|
||||
/*-- call-daemon.c --*/
|
||||
gpg_error_t daemon_start (enum daemon_type type, ctrl_t ctrl);
|
||||
assuan_context_t daemon_type_ctx (enum daemon_type type, ctrl_t ctrl);
|
||||
|
@ -737,6 +756,7 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
|
|||
const char *desc_text,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen, int *r_padding);
|
||||
|
||||
int agent_card_readcert (ctrl_t ctrl,
|
||||
const char *id, char **r_buf, size_t *r_buflen);
|
||||
int agent_card_readkey (ctrl_t ctrl, const char *id,
|
||||
|
@ -758,7 +778,6 @@ void agent_card_free_keyinfo (struct card_key_info_s *l);
|
|||
gpg_error_t agent_card_keyinfo (ctrl_t ctrl, const char *keygrip,
|
||||
int cap, struct card_key_info_s **result);
|
||||
|
||||
|
||||
/*-- learncard.c --*/
|
||||
int agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force);
|
||||
|
||||
|
|
364
agent/cache.c
364
agent/cache.c
|
@ -53,8 +53,20 @@ struct secret_data_s {
|
|||
char data[1]; /* A string. */
|
||||
};
|
||||
|
||||
/* The cache object. */
|
||||
/* The type of cache object. */
|
||||
typedef struct cache_item_s *ITEM;
|
||||
|
||||
/* The timer entry in a linked list. */
|
||||
struct timer_s {
|
||||
ITEM next;
|
||||
int tv_sec;
|
||||
int reason;
|
||||
};
|
||||
#define CACHE_EXPIRE_UNUSED 0
|
||||
#define CACHE_EXPIRE_LAST_ACCESS 1
|
||||
#define CACHE_EXPIRE_CREATION 2
|
||||
|
||||
/* The cache object. */
|
||||
struct cache_item_s {
|
||||
ITEM next;
|
||||
time_t created;
|
||||
|
@ -63,12 +75,18 @@ struct cache_item_s {
|
|||
struct secret_data_s *pw;
|
||||
cache_mode_t cache_mode;
|
||||
int restricted; /* The value of ctrl->restricted is part of the key. */
|
||||
struct timer_s t;
|
||||
char key[1];
|
||||
};
|
||||
|
||||
/* The cache himself. */
|
||||
static ITEM thecache;
|
||||
|
||||
/* The timer list of expiration, in active. */
|
||||
static ITEM the_timer_list;
|
||||
/* Newly created entries, to be inserted into the timer list. */
|
||||
static ITEM the_timer_list_new;
|
||||
|
||||
/* NULL or the last cache key stored by agent_store_cache_hit. */
|
||||
static char *last_stored_cache_key;
|
||||
|
||||
|
@ -193,100 +211,302 @@ new_data (const char *string, struct secret_data_s **r_data)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* Check whether there are items to expire. */
|
||||
static void
|
||||
housekeeping (void)
|
||||
insert_to_timer_list_new (ITEM entry)
|
||||
{
|
||||
ITEM r, rprev;
|
||||
entry->t.next = the_timer_list_new;
|
||||
the_timer_list_new = entry;
|
||||
}
|
||||
|
||||
/* Insert to the active timer list. */
|
||||
static void
|
||||
insert_to_timer_list (struct timespec *ts, ITEM entry)
|
||||
{
|
||||
ITEM e, eprev;
|
||||
|
||||
if (!the_timer_list || ts->tv_sec >= entry->t.tv_sec)
|
||||
{
|
||||
if (the_timer_list)
|
||||
{
|
||||
the_timer_list->t.tv_sec += ts->tv_sec - entry->t.tv_sec;
|
||||
if (ts->tv_nsec >= 500000000)
|
||||
the_timer_list->t.tv_sec++;
|
||||
}
|
||||
|
||||
ts->tv_sec = entry->t.tv_sec;
|
||||
ts->tv_nsec = 0;
|
||||
|
||||
entry->t.tv_sec = 0;
|
||||
entry->t.next = the_timer_list;
|
||||
the_timer_list = entry;
|
||||
return;
|
||||
}
|
||||
|
||||
entry->t.tv_sec -= ts->tv_sec;
|
||||
eprev = NULL;
|
||||
for (e = the_timer_list; e; e = e->t.next)
|
||||
{
|
||||
if (e->t.tv_sec > entry->t.tv_sec)
|
||||
break;
|
||||
|
||||
eprev = e;
|
||||
entry->t.tv_sec -= e->t.tv_sec;
|
||||
}
|
||||
|
||||
entry->t.next = e;
|
||||
if (e)
|
||||
e->t.tv_sec -= entry->t.tv_sec;
|
||||
|
||||
if (eprev)
|
||||
eprev->t.next = entry;
|
||||
else
|
||||
the_timer_list = entry;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_from_timer_list (ITEM entry)
|
||||
{
|
||||
ITEM e, eprev;
|
||||
|
||||
eprev = NULL;
|
||||
for (e = the_timer_list; e; e = e->t.next)
|
||||
if (e != entry)
|
||||
eprev = e;
|
||||
else
|
||||
{
|
||||
if (e->t.next)
|
||||
e->t.next->t.tv_sec += e->t.tv_sec;
|
||||
|
||||
if (eprev)
|
||||
eprev->t.next = e->t.next;
|
||||
else
|
||||
the_timer_list = e->t.next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
entry->t.next = NULL;
|
||||
entry->t.tv_sec = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_from_timer_list_new (ITEM entry)
|
||||
{
|
||||
ITEM e, eprev;
|
||||
|
||||
eprev = NULL;
|
||||
for (e = the_timer_list_new; e; e = e->t.next)
|
||||
if (e != entry)
|
||||
eprev = e;
|
||||
else
|
||||
{
|
||||
if (eprev)
|
||||
eprev->t.next = e->t.next;
|
||||
else
|
||||
the_timer_list_new = e->t.next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
entry->t.next = NULL;
|
||||
entry->t.tv_sec = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
compute_expiration (ITEM r)
|
||||
{
|
||||
unsigned long maxttl;
|
||||
time_t current = gnupg_get_time ();
|
||||
time_t next;
|
||||
|
||||
/* First expire the actual data */
|
||||
for (r=thecache; r; r = r->next)
|
||||
if (r->cache_mode == CACHE_MODE_PIN)
|
||||
return 0; /* Don't let it expire - scdaemon explicitly flushes them. */
|
||||
|
||||
if (!r->pw)
|
||||
{
|
||||
if (r->cache_mode == CACHE_MODE_PIN)
|
||||
; /* Don't let it expire - scdaemon explicitly flushes them. */
|
||||
else if (r->pw && r->ttl >= 0 && r->accessed + r->ttl < current)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired '%s'.%d (%ds after last access)\n",
|
||||
r->key, r->restricted, r->ttl);
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = current;
|
||||
}
|
||||
/* Expire an old and unused entry after 30 minutes. */
|
||||
r->t.tv_sec = 60*30;
|
||||
r->t.reason = CACHE_EXPIRE_UNUSED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Second, make sure that we also remove them based on the created
|
||||
* stamp so that the user has to enter it from time to time. We
|
||||
* don't do this for data items which are used to storage secrets in
|
||||
* meory and are not user entered passphrases etc. */
|
||||
for (r=thecache; r; r = r->next)
|
||||
switch (r->cache_mode)
|
||||
{
|
||||
unsigned long maxttl;
|
||||
|
||||
switch (r->cache_mode)
|
||||
{
|
||||
case CACHE_MODE_DATA:
|
||||
case CACHE_MODE_PIN:
|
||||
continue; /* No MAX TTL here. */
|
||||
case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
|
||||
default: maxttl = opt.max_cache_ttl; break;
|
||||
}
|
||||
if (r->pw && r->created + maxttl < current)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired '%s'.%d (%lus after creation)\n",
|
||||
r->key, r->restricted, opt.max_cache_ttl);
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = current;
|
||||
}
|
||||
case CACHE_MODE_DATA:
|
||||
case CACHE_MODE_PIN:
|
||||
maxttl = 0; /* No MAX TTL here. */
|
||||
break;
|
||||
case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break;
|
||||
default: maxttl = opt.max_cache_ttl; break;
|
||||
}
|
||||
|
||||
/* Third, make sure that we don't have too many items in the list.
|
||||
* Expire old and unused entries after 30 minutes. */
|
||||
for (rprev=NULL, r=thecache; r; )
|
||||
if (maxttl)
|
||||
{
|
||||
if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current)
|
||||
if (r->created + maxttl < current)
|
||||
{
|
||||
ITEM r2 = r->next;
|
||||
if (DBG_CACHE)
|
||||
log_debug (" removed '%s'.%d (mode %d) (slot not used for 30m)\n",
|
||||
r->key, r->restricted, r->cache_mode);
|
||||
xfree (r);
|
||||
if (!rprev)
|
||||
thecache = r2;
|
||||
else
|
||||
rprev->next = r2;
|
||||
r = r2;
|
||||
}
|
||||
else
|
||||
{
|
||||
rprev = r;
|
||||
r = r->next;
|
||||
r->t.tv_sec = 0;
|
||||
r->t.reason = CACHE_EXPIRE_CREATION;
|
||||
return 1;
|
||||
}
|
||||
|
||||
next = r->created + maxttl - current;
|
||||
}
|
||||
else
|
||||
next = 0;
|
||||
|
||||
if (r->ttl >= 0 && (next == 0 || r->ttl < next))
|
||||
{
|
||||
r->t.tv_sec = r->ttl;
|
||||
r->t.reason = CACHE_EXPIRE_LAST_ACCESS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (next)
|
||||
{
|
||||
r->t.tv_sec = next;
|
||||
r->t.reason = CACHE_EXPIRE_CREATION;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
update_expiration (ITEM entry, int is_new_entry)
|
||||
{
|
||||
if (!is_new_entry)
|
||||
{
|
||||
remove_from_timer_list (entry);
|
||||
remove_from_timer_list_new (entry);
|
||||
}
|
||||
|
||||
if (compute_expiration (entry))
|
||||
{
|
||||
insert_to_timer_list_new (entry);
|
||||
agent_kick_the_loop ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
agent_cache_housekeeping (void)
|
||||
/* Expire the cache entry. Returns 1 when the entry should be removed
|
||||
* from the cache. */
|
||||
static int
|
||||
do_expire (ITEM e)
|
||||
{
|
||||
int res;
|
||||
if (!e->pw)
|
||||
/* Unused entry after 30 minutes. */
|
||||
return 1;
|
||||
|
||||
if (DBG_CACHE)
|
||||
log_debug ("agent_cache_housekeeping\n");
|
||||
if (e->t.reason == CACHE_EXPIRE_LAST_ACCESS)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired '%s'.%d (%ds after last access)\n",
|
||||
e->key, e->restricted, e->ttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired '%s'.%d (%lus after creation)\n",
|
||||
e->key, e->restricted, opt.max_cache_ttl);
|
||||
}
|
||||
|
||||
release_data (e->pw);
|
||||
e->pw = NULL;
|
||||
e->accessed = 0;
|
||||
|
||||
if (compute_expiration (e))
|
||||
insert_to_timer_list_new (e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct timespec *
|
||||
agent_cache_expiration (void)
|
||||
{
|
||||
static struct timespec abstime;
|
||||
static struct timespec timeout;
|
||||
struct timespec *tp;
|
||||
struct timespec curtime;
|
||||
int res;
|
||||
int expired = 0;
|
||||
ITEM e, enext;
|
||||
|
||||
res = npth_mutex_lock (&cache_lock);
|
||||
if (res)
|
||||
log_fatal ("failed to acquire cache mutex: %s\n", strerror (res));
|
||||
|
||||
housekeeping ();
|
||||
npth_clock_gettime (&curtime);
|
||||
if (the_timer_list)
|
||||
{
|
||||
if (npth_timercmp (&abstime, &curtime, <))
|
||||
expired = 1;
|
||||
else
|
||||
npth_timersub (&abstime, &curtime, &timeout);
|
||||
}
|
||||
|
||||
if (expired && (e = the_timer_list) && e->t.tv_sec == 0)
|
||||
{
|
||||
the_timer_list = e->t.next;
|
||||
e->t.next = NULL;
|
||||
|
||||
if (do_expire (e))
|
||||
{
|
||||
ITEM r, rprev;
|
||||
|
||||
if (DBG_CACHE)
|
||||
log_debug (" removed '%s'.%d (mode %d) (slot not used for 30m)\n",
|
||||
e->key, e->restricted, e->cache_mode);
|
||||
|
||||
rprev = NULL;
|
||||
for (r = thecache; r; r = r->next)
|
||||
if (r == e)
|
||||
{
|
||||
if (!rprev)
|
||||
thecache = r->next;
|
||||
else
|
||||
rprev->next = r->next;
|
||||
break;
|
||||
}
|
||||
else
|
||||
rprev = r;
|
||||
|
||||
remove_from_timer_list_new (e);
|
||||
|
||||
xfree (e);
|
||||
}
|
||||
}
|
||||
|
||||
if (expired || !the_timer_list)
|
||||
timeout.tv_sec = timeout.tv_nsec = 0;
|
||||
|
||||
for (e = the_timer_list_new; e; e = enext)
|
||||
{
|
||||
enext = e->t.next;
|
||||
e->t.next = NULL;
|
||||
insert_to_timer_list (&timeout, e);
|
||||
}
|
||||
the_timer_list_new = NULL;
|
||||
|
||||
if (!the_timer_list)
|
||||
tp = NULL;
|
||||
else
|
||||
{
|
||||
if (the_timer_list->t.tv_sec != 0)
|
||||
{
|
||||
timeout.tv_sec += the_timer_list->t.tv_sec;
|
||||
the_timer_list->t.tv_sec = 0;
|
||||
}
|
||||
|
||||
npth_timeradd (&timeout, &curtime, &abstime);
|
||||
tp = &timeout;
|
||||
}
|
||||
|
||||
res = npth_mutex_unlock (&cache_lock);
|
||||
if (res)
|
||||
log_fatal ("failed to release cache mutex: %s\n", strerror (res));
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,6 +534,7 @@ agent_flush_cache (int pincache_only)
|
|||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = 0;
|
||||
update_expiration (r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,7 +579,6 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
|||
if (DBG_CACHE)
|
||||
log_debug ("agent_put_cache '%s'.%d (mode %d) requested ttl=%d\n",
|
||||
key, restricted, cache_mode, ttl);
|
||||
housekeeping ();
|
||||
|
||||
if (!ttl)
|
||||
{
|
||||
|
@ -410,6 +630,7 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
|||
err = new_data (data, &r->pw);
|
||||
if (err)
|
||||
log_error ("error replacing cache item: %s\n", gpg_strerror (err));
|
||||
update_expiration (r, 0);
|
||||
}
|
||||
}
|
||||
else if (data) /* Insert. */
|
||||
|
@ -431,6 +652,7 @@ agent_put_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode,
|
|||
{
|
||||
r->next = thecache;
|
||||
thecache = r;
|
||||
update_expiration (r, 1);
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
|
@ -478,7 +700,6 @@ agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
|
|||
log_debug ("agent_get_cache '%s'.%d (mode %d)%s ...\n",
|
||||
key, restricted, cache_mode,
|
||||
last_stored? " (stored cache key)":"");
|
||||
housekeeping ();
|
||||
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
|
@ -500,7 +721,10 @@ agent_get_cache (ctrl_t ctrl, const char *key, cache_mode_t cache_mode)
|
|||
* below. Note also that we don't update the accessed time
|
||||
* for data items. */
|
||||
if (r->cache_mode != CACHE_MODE_DATA)
|
||||
r->accessed = gnupg_get_time ();
|
||||
{
|
||||
r->accessed = gnupg_get_time ();
|
||||
update_expiration (r, 0);
|
||||
}
|
||||
if (DBG_CACHE)
|
||||
log_debug ("... hit\n");
|
||||
if (r->pw->totallen < 32)
|
||||
|
|
|
@ -98,7 +98,6 @@ static npth_mutex_t start_daemon_lock;
|
|||
struct wait_child_thread_parm_s
|
||||
{
|
||||
enum daemon_type type;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
|
||||
|
@ -109,54 +108,14 @@ wait_child_thread (void *arg)
|
|||
int err;
|
||||
struct wait_child_thread_parm_s *parm = arg;
|
||||
enum daemon_type type = parm->type;
|
||||
pid_t pid = parm->pid;
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
int wstatus;
|
||||
#endif
|
||||
const char *name = opt.daemon_program[type];
|
||||
struct daemon_global_s *g = &daemon_global[type];
|
||||
struct daemon_local_s *sl;
|
||||
|
||||
xfree (parm); /* We have copied all data to the stack. */
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
npth_unprotect ();
|
||||
/* Note that although we use a pid_t here, it is actually a HANDLE. */
|
||||
WaitForSingleObject ((HANDLE)pid, INFINITE);
|
||||
npth_protect ();
|
||||
assuan_pipe_wait_server_termination (g->primary_ctx, NULL, 0);
|
||||
log_info ("daemon %s finished\n", name);
|
||||
#else /* !HAVE_W32_SYSTEM*/
|
||||
|
||||
again:
|
||||
npth_unprotect ();
|
||||
err = waitpid (pid, &wstatus, 0);
|
||||
npth_protect ();
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
log_error ("waitpid for %s failed: %s\n", name, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WIFEXITED (wstatus))
|
||||
log_info ("daemon %s finished (status %d)\n",
|
||||
name, WEXITSTATUS (wstatus));
|
||||
else if (WIFSIGNALED (wstatus))
|
||||
log_info ("daemon %s killed by signal %d\n", name, WTERMSIG (wstatus));
|
||||
else
|
||||
{
|
||||
if (WIFSTOPPED (wstatus))
|
||||
log_info ("daemon %s stopped by signal %d\n",
|
||||
name, WSTOPSIG (wstatus));
|
||||
goto again;
|
||||
}
|
||||
|
||||
assuan_set_flag (g->primary_ctx, ASSUAN_NO_WAITPID, 1);
|
||||
}
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
|
||||
agent_flush_cache (1); /* Flush the PIN cache. */
|
||||
|
||||
|
@ -471,8 +430,8 @@ daemon_start (enum daemon_type type, ctrl_t ctrl)
|
|||
char buf[100];
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
snprintf (buf, sizeof buf, "OPTION event-signal=%lx",
|
||||
(unsigned long)get_agent_daemon_notify_event ());
|
||||
snprintf (buf, sizeof buf, "OPTION event-signal=%p",
|
||||
get_agent_daemon_notify_event ());
|
||||
#else
|
||||
snprintf (buf, sizeof buf, "OPTION event-signal=%d", SIGUSR2);
|
||||
#endif
|
||||
|
@ -496,7 +455,6 @@ daemon_start (enum daemon_type type, ctrl_t ctrl)
|
|||
}
|
||||
|
||||
wctp->type = type;
|
||||
wctp->pid = assuan_get_pid (g->primary_ctx);
|
||||
err = npth_attr_init (&tattr);
|
||||
if (!err)
|
||||
{
|
||||
|
@ -561,10 +519,9 @@ agent_daemon_dump_state (void)
|
|||
for (i = 0; i < DAEMON_MAX_TYPE; i++) {
|
||||
struct daemon_global_s *g = &daemon_global[i];
|
||||
|
||||
log_info ("%s: name %s primary_ctx=%p pid=%ld reusable=%d\n", __func__,
|
||||
log_info ("%s: name %s primary_ctx=%p reusable=%d\n", __func__,
|
||||
gnupg_module_name (daemon_modules[i]),
|
||||
g->primary_ctx,
|
||||
(long)assuan_get_pid (g->primary_ctx),
|
||||
g->primary_ctx_reusable);
|
||||
if (g->socket_name)
|
||||
log_info ("%s: socket='%s'\n", __func__, g->socket_name);
|
||||
|
|
|
@ -128,8 +128,9 @@ initialize_module_call_pinentry (void)
|
|||
void
|
||||
agent_query_dump_state (void)
|
||||
{
|
||||
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
|
||||
entry_ctx, (long)assuan_get_pid (entry_ctx), (void*)popup_tid);
|
||||
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%lx\n",
|
||||
entry_ctx, (long)assuan_get_pid (entry_ctx),
|
||||
(unsigned long)popup_tid);
|
||||
}
|
||||
|
||||
/* Called to make sure that a popup window owned by the current
|
||||
|
@ -883,7 +884,7 @@ struct inq_cb_parm_s
|
|||
};
|
||||
|
||||
|
||||
/* Return true if PIN is indentical to the last generated pin. */
|
||||
/* Return true if PIN is identical to the last generated pin. */
|
||||
static int
|
||||
is_generated_pin (struct inq_cb_parm_s *parm, const char *pin)
|
||||
{
|
||||
|
@ -1288,8 +1289,6 @@ build_cmd_setdesc (char *line, size_t linelen, const char *desc)
|
|||
static void *
|
||||
watch_sock (void *arg)
|
||||
{
|
||||
pid_t pid = assuan_get_pid (entry_ctx);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int err;
|
||||
|
@ -1302,7 +1301,7 @@ watch_sock (void *arg)
|
|||
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (FD2INT (sock), &fdset);
|
||||
err = npth_select (FD2INT (sock)+1, &fdset, NULL, NULL, &timeout);
|
||||
err = npth_select (FD2NUM (sock)+1, &fdset, NULL, NULL, &timeout);
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
|
@ -1317,17 +1316,7 @@ watch_sock (void *arg)
|
|||
break;
|
||||
}
|
||||
|
||||
if (pid == (pid_t)(-1))
|
||||
; /* No pid available can't send a kill. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* Older versions of assuan set PID to 0 on Windows to indicate an
|
||||
invalid value. */
|
||||
else if (pid != (pid_t) INVALID_HANDLE_VALUE && pid != 0)
|
||||
TerminateProcess ((HANDLE)pid, 1);
|
||||
#else
|
||||
else if (pid > 0)
|
||||
kill (pid, SIGINT);
|
||||
#endif
|
||||
assuan_pipe_kill_server (entry_ctx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2124,7 +2113,6 @@ void
|
|||
agent_popup_message_stop (ctrl_t ctrl)
|
||||
{
|
||||
int rc;
|
||||
pid_t pid;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
|
@ -2137,26 +2125,10 @@ agent_popup_message_stop (ctrl_t ctrl)
|
|||
return;
|
||||
}
|
||||
|
||||
pid = assuan_get_pid (entry_ctx);
|
||||
if (pid == (pid_t)(-1))
|
||||
; /* No pid available can't send a kill. */
|
||||
else if (popup_finished)
|
||||
if (popup_finished)
|
||||
; /* Already finished and ready for joining. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* Older versions of assuan set PID to 0 on Windows to indicate an
|
||||
invalid value. */
|
||||
else if (pid != (pid_t) INVALID_HANDLE_VALUE
|
||||
&& pid != 0)
|
||||
{
|
||||
HANDLE process = (HANDLE) pid;
|
||||
|
||||
/* Arbitrary error code. */
|
||||
TerminateProcess (process, 1);
|
||||
}
|
||||
#else
|
||||
else if (pid > 0)
|
||||
kill (pid, SIGINT);
|
||||
#endif
|
||||
else
|
||||
assuan_pipe_kill_server (entry_ctx);
|
||||
|
||||
/* Now wait for the thread to terminate. */
|
||||
rc = npth_join (popup_tid, NULL);
|
||||
|
|
|
@ -196,7 +196,8 @@ handle_pincache_get (const char *args, assuan_context_t ctx)
|
|||
const char *key;
|
||||
char *pin = NULL;
|
||||
|
||||
log_debug ("%s: enter '%s'\n", __func__, args);
|
||||
if (DBG_CACHE)
|
||||
log_debug ("%s: enter '%s'\n", __func__, args);
|
||||
key = args;
|
||||
if (strlen (key) < 5)
|
||||
{
|
||||
|
@ -210,11 +211,14 @@ handle_pincache_get (const char *args, assuan_context_t ctx)
|
|||
if (!pin || !*pin)
|
||||
{
|
||||
xfree (pin);
|
||||
pin = NULL;
|
||||
err = 0; /* Not found is indicated by sending no data back. */
|
||||
log_debug ("%s: not cached\n", __func__);
|
||||
if (DBG_CACHE)
|
||||
log_debug ("%s: not cached\n", __func__);
|
||||
goto leave;
|
||||
}
|
||||
log_debug ("%s: cache returned '%s'\n", __func__, pin);
|
||||
if (DBG_CACHE)
|
||||
log_debug ("%s: cache returned '%s'\n", __func__, "[hidden]"/*pin*/);
|
||||
err = assuan_send_data (ctx, pin, strlen (pin));
|
||||
|
||||
leave:
|
||||
|
@ -548,7 +552,8 @@ padding_info_cb (void *opaque, const char *line)
|
|||
|
||||
if ((s=has_leading_keyword (line, "PADDING")))
|
||||
{
|
||||
*r_padding = atoi (s);
|
||||
if (r_padding)
|
||||
*r_padding = atoi (s);
|
||||
}
|
||||
else if ((s=has_leading_keyword (line, "PINCACHE_PUT")))
|
||||
err = handle_pincache_put (s);
|
||||
|
@ -560,8 +565,8 @@ padding_info_cb (void *opaque, const char *line)
|
|||
/* Decipher INDATA using the current card. Note that the returned
|
||||
* value is not an s-expression but the raw data as returned by
|
||||
* scdaemon. The padding information is stored at R_PADDING with -1
|
||||
* for not known. DESC_TEXT is an additional parameter passed to
|
||||
* GETPIN_CB. */
|
||||
* for not known, when it's not NULL. DESC_TEXT is an additional
|
||||
* parameter passed to GETPIN_CB. */
|
||||
int
|
||||
agent_card_pkdecrypt (ctrl_t ctrl,
|
||||
const char *keyid,
|
||||
|
@ -579,7 +584,8 @@ agent_card_pkdecrypt (ctrl_t ctrl,
|
|||
size_t len;
|
||||
|
||||
*r_buf = NULL;
|
||||
*r_padding = -1; /* Unknown. */
|
||||
if (r_padding)
|
||||
*r_padding = -1; /* Unknown. */
|
||||
rc = start_scd (ctrl);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
|
|
@ -3952,7 +3952,11 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
|
|||
es_syshd_t syshd;
|
||||
|
||||
syshd.type = ES_SYSHD_SOCK;
|
||||
#ifdef HAVE_SOCKET
|
||||
syshd.u.sock = (SOCKET)sock_client;
|
||||
#else
|
||||
syshd.u.sock = sock_client;
|
||||
#endif
|
||||
|
||||
get_client_info (sock_client, &peer_info);
|
||||
ctrl->client_pid = peer_info.pid;
|
||||
|
|
|
@ -241,7 +241,7 @@ reset_notify (assuan_context_t ctx, char *line)
|
|||
(void) line;
|
||||
|
||||
memset (ctrl->keygrip, 0, 20);
|
||||
ctrl->have_keygrip = 0;
|
||||
ctrl->have_keygrip = ctrl->have_keygrip1 = 0;
|
||||
ctrl->digest.valuelen = 0;
|
||||
xfree (ctrl->digest.data);
|
||||
ctrl->digest.data = NULL;
|
||||
|
@ -251,7 +251,7 @@ reset_notify (assuan_context_t ctx, char *line)
|
|||
|
||||
clear_nonce_cache (ctrl);
|
||||
|
||||
/* Note that a RESET does not clear the ephemeral store becuase
|
||||
/* Note that a RESET does not clear the ephemeral store because
|
||||
* clients are used to issue a RESET on a connection. */
|
||||
|
||||
return 0;
|
||||
|
@ -796,8 +796,8 @@ cmd_havekey (assuan_context_t ctx, char *line)
|
|||
|
||||
|
||||
static const char hlp_sigkey[] =
|
||||
"SIGKEY <hexstring_with_keygrip>\n"
|
||||
"SETKEY <hexstring_with_keygrip>\n"
|
||||
"SIGKEY [--another] <hexstring_with_keygrip>\n"
|
||||
"SETKEY [--another] <hexstring_with_keygrip>\n"
|
||||
"\n"
|
||||
"Set the key used for a sign or decrypt operation.";
|
||||
static gpg_error_t
|
||||
|
@ -805,11 +805,17 @@ cmd_sigkey (assuan_context_t ctx, char *line)
|
|||
{
|
||||
int rc;
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int opt_another;
|
||||
|
||||
rc = parse_keygrip (ctx, line, ctrl->keygrip);
|
||||
opt_another = has_option (line, "--another");
|
||||
line = skip_options (line);
|
||||
rc = parse_keygrip (ctx, line, opt_another? ctrl->keygrip1 : ctrl->keygrip);
|
||||
if (rc)
|
||||
return rc;
|
||||
ctrl->have_keygrip = 1;
|
||||
if (opt_another)
|
||||
ctrl->have_keygrip1 = 1;
|
||||
else
|
||||
ctrl->have_keygrip = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1043,10 +1049,14 @@ cmd_pksign (assuan_context_t ctx, char *line)
|
|||
|
||||
|
||||
static const char hlp_pkdecrypt[] =
|
||||
"PKDECRYPT [<options>]\n"
|
||||
"PKDECRYPT [--kem[=<kemid>] [<options>]\n"
|
||||
"\n"
|
||||
"Perform the actual decrypt operation. Input is not\n"
|
||||
"sensitive to eavesdropping.";
|
||||
"sensitive to eavesdropping.\n"
|
||||
"If the --kem option is used, decryption is done with the KEM,\n"
|
||||
"inquiring upper-layer option, when needed. KEMID can be\n"
|
||||
"specified with --kem option; Valid value is: PQC-PGP, PGP, or CMS.\n"
|
||||
"Default is PQC-PGP.";
|
||||
static gpg_error_t
|
||||
cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
||||
{
|
||||
|
@ -1055,22 +1065,52 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
|
|||
unsigned char *value;
|
||||
size_t valuelen;
|
||||
membuf_t outbuf;
|
||||
int padding;
|
||||
int padding = -1;
|
||||
unsigned char *option = NULL;
|
||||
size_t optionlen = 0;
|
||||
const char *p;
|
||||
int kemid = -1;
|
||||
|
||||
(void)line;
|
||||
p = has_option_name (line, "--kem");
|
||||
if (p)
|
||||
{
|
||||
kemid = KEM_PQC_PGP;
|
||||
if (*p == '=')
|
||||
{
|
||||
p++;
|
||||
if (!strcmp (p, "PQC-PGP"))
|
||||
kemid = KEM_PQC_PGP;
|
||||
else if (!strcmp (p, "PGP"))
|
||||
kemid = KEM_PGP;
|
||||
else if (!strcmp (p, "CMS"))
|
||||
kemid = KEM_CMS;
|
||||
else
|
||||
return set_error (GPG_ERR_ASS_PARAMETER, "invalid KEM algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
/* First inquire the data to decrypt */
|
||||
rc = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%u", MAXLEN_CIPHERTEXT);
|
||||
if (!rc)
|
||||
rc = assuan_inquire (ctx, "CIPHERTEXT",
|
||||
&value, &valuelen, MAXLEN_CIPHERTEXT);
|
||||
if (!rc && kemid > KEM_PQC_PGP)
|
||||
rc = assuan_inquire (ctx, "OPTION",
|
||||
&option, &optionlen, MAXLEN_CIPHERTEXT);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
init_membuf (&outbuf, 512);
|
||||
|
||||
rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
|
||||
value, valuelen, &outbuf, &padding);
|
||||
if (kemid < 0)
|
||||
rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
|
||||
value, valuelen, &outbuf, &padding);
|
||||
else
|
||||
{
|
||||
rc = agent_kem_decrypt (ctrl, ctrl->server_local->keydesc, kemid,
|
||||
value, valuelen, option, optionlen, &outbuf);
|
||||
xfree (option);
|
||||
}
|
||||
xfree (value);
|
||||
if (rc)
|
||||
clear_outbuf (&outbuf);
|
||||
|
@ -1130,6 +1170,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||
int c;
|
||||
unsigned int flags = 0;
|
||||
|
||||
init_membuf (&outbuf, 512);
|
||||
|
||||
if (ctrl->restricted)
|
||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||
|
||||
|
@ -1187,8 +1229,6 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||
if (rc)
|
||||
goto leave;
|
||||
|
||||
init_membuf (&outbuf, 512);
|
||||
|
||||
/* If requested, ask for the password to be used for the key. If
|
||||
this is not used the regular Pinentry mechanism is used. */
|
||||
if (opt_inq_passwd && !(flags & GENKEY_FLAG_NO_PROTECTION))
|
||||
|
@ -1418,7 +1458,9 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||
goto leave;
|
||||
|
||||
rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
|
||||
if (!rc)
|
||||
if (rc)
|
||||
goto leave;
|
||||
else
|
||||
{
|
||||
if (opt_format_ssh)
|
||||
{
|
||||
|
|
|
@ -1384,6 +1384,17 @@ extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
|
|||
err = gcry_sexp_extract_param (list, NULL, format,
|
||||
array+0, array+1, NULL);
|
||||
}
|
||||
else if ( !strcmp (name, (algoname = "kyber512"))
|
||||
|| !strcmp (name, (algoname = "kyber768"))
|
||||
|| !strcmp (name, (algoname = "kyber1024")))
|
||||
{
|
||||
format = "/ps?";
|
||||
elems = "ps?";
|
||||
npkey = 1;
|
||||
nskey = 2;
|
||||
err = gcry_sexp_extract_param (list, NULL, format,
|
||||
array+0, array+1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||
|
|
|
@ -90,7 +90,7 @@ has_percent0A_suffix (const char *string)
|
|||
|
||||
INFO gets displayed as part of a generic string. However if the
|
||||
first character of INFO is a vertical bar all up to the next
|
||||
verical bar are considered flags and only everything after the
|
||||
vertical bar are considered flags and only everything after the
|
||||
second vertical bar gets displayed as the full prompt.
|
||||
|
||||
Flags:
|
||||
|
@ -377,10 +377,10 @@ divert_pksign (ctrl_t ctrl, const unsigned char *grip,
|
|||
}
|
||||
|
||||
|
||||
/* Decrypt the value given asn an S-expression in CIPHER using the
|
||||
/* Decrypt the value given as an s-expression in CIPHER using the
|
||||
key identified by SHADOW_INFO and return the plaintext in an
|
||||
allocated buffer in R_BUF. The padding information is stored at
|
||||
R_PADDING with -1 for not known. */
|
||||
R_PADDING with -1 for not known, when it's not NULL. */
|
||||
int
|
||||
divert_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
|
@ -399,7 +399,8 @@ divert_pkdecrypt (ctrl_t ctrl,
|
|||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
|
||||
*r_padding = -1;
|
||||
if (r_padding)
|
||||
*r_padding = -1;
|
||||
s = cipher;
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
|
@ -485,6 +486,34 @@ divert_pkdecrypt (ctrl_t ctrl,
|
|||
return rc;
|
||||
}
|
||||
|
||||
gpg_error_t
|
||||
agent_card_ecc_kem (ctrl_t ctrl, const unsigned char *ecc_ct,
|
||||
size_t ecc_point_len, unsigned char *ecc_ecdh)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
char *ecdh = NULL;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
rc = agent_card_pkdecrypt (ctrl, ctrl->keygrip, getpin_cb, ctrl, NULL,
|
||||
ecc_ct, ecc_point_len, &ecdh, &len, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (len != ecc_point_len)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: ECC result length invalid (%zu != %zu)\n",
|
||||
__func__, len, ecc_point_len);
|
||||
return gpg_error (GPG_ERR_INV_DATA);
|
||||
}
|
||||
else
|
||||
memcpy (ecc_ecdh, ecdh, len);
|
||||
|
||||
xfree (ecdh);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
divert_writekey (ctrl_t ctrl, int force, const char *serialno,
|
||||
|
|
|
@ -106,7 +106,8 @@ divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
|||
const unsigned char *s;
|
||||
size_t n;
|
||||
|
||||
*r_padding = -1;
|
||||
if (r_padding)
|
||||
*r_padding = -1;
|
||||
|
||||
s = cipher;
|
||||
if (*s != '(')
|
||||
|
@ -125,7 +126,8 @@ divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
|||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
if (smatch (&s, n, "rsa"))
|
||||
{
|
||||
*r_padding = 0;
|
||||
if (r_padding)
|
||||
*r_padding = 0;
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
s++;
|
||||
|
|
|
@ -1550,7 +1550,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||
{
|
||||
memcpy (*shadow_info, s, n);
|
||||
/*
|
||||
* When it's a key on card (not on tpm2), maks sure
|
||||
* When it's a key on card (not on tpm2), make sure
|
||||
* it's available.
|
||||
*/
|
||||
if (strcmp (shadow_type, "t1-v1") == 0 && !grip)
|
||||
|
|
|
@ -116,6 +116,7 @@ store_key (ctrl_t ctrl, gcry_sexp_t private,
|
|||
ek->keybuf = buf;
|
||||
buf = NULL;
|
||||
ek->keybuflen = len;
|
||||
err = 0;
|
||||
}
|
||||
else
|
||||
err = agent_write_private_key (ctrl, grip, buf, len, force,
|
||||
|
@ -161,7 +162,7 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
|
|||
const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN);
|
||||
estream_t stream_to_check_pattern = NULL;
|
||||
const char *argv[10];
|
||||
pid_t pid;
|
||||
gnupg_process_t proc;
|
||||
int result, i;
|
||||
const char *pattern;
|
||||
char *patternfname;
|
||||
|
@ -204,11 +205,17 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
|
|||
argv[i] = NULL;
|
||||
log_assert (i < sizeof argv);
|
||||
|
||||
if (gnupg_spawn_process (pgmname, argv, NULL, 0,
|
||||
&stream_to_check_pattern, NULL, NULL, &pid))
|
||||
if (gnupg_process_spawn (pgmname, argv,
|
||||
GNUPG_PROCESS_STDIN_PIPE,
|
||||
NULL, &proc))
|
||||
result = 1; /* Execute error - assume password should no be used. */
|
||||
else
|
||||
{
|
||||
int status;
|
||||
|
||||
gnupg_process_get_streams (proc, 0, &stream_to_check_pattern,
|
||||
NULL, NULL);
|
||||
|
||||
es_set_binary (stream_to_check_pattern);
|
||||
if (es_fwrite (pw, strlen (pw), 1, stream_to_check_pattern) != 1)
|
||||
{
|
||||
|
@ -219,11 +226,13 @@ do_check_passphrase_pattern (ctrl_t ctrl, const char *pw, unsigned int flags)
|
|||
else
|
||||
es_fflush (stream_to_check_pattern);
|
||||
es_fclose (stream_to_check_pattern);
|
||||
if (gnupg_wait_process (pgmname, pid, 1, NULL))
|
||||
gnupg_process_wait (proc, 1);
|
||||
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
|
||||
if (status)
|
||||
result = 1; /* Helper returned an error - probably a match. */
|
||||
else
|
||||
result = 0; /* Success; i.e. no match. */
|
||||
gnupg_release_process (pid);
|
||||
gnupg_process_release (proc);
|
||||
}
|
||||
|
||||
xfree (patternfname);
|
||||
|
|
|
@ -341,15 +341,13 @@ static struct debug_flags_s debug_flags [] =
|
|||
#define MIN_PASSPHRASE_NONALPHA (1)
|
||||
#define MAX_PASSPHRASE_DAYS (0)
|
||||
|
||||
/* The timer tick used for housekeeping stuff. Note that on Windows
|
||||
* we use a SetWaitableTimer seems to signal earlier than about 2
|
||||
* seconds. Thus we use 4 seconds on all platforms.
|
||||
* CHECK_OWN_SOCKET_INTERVAL defines how often we check
|
||||
* our own socket in standard socket mode. If that value is 0 we
|
||||
* don't check at all. All values are in seconds. */
|
||||
#define TIMERTICK_INTERVAL (4)
|
||||
/* CHECK_OWN_SOCKET_INTERVAL defines how often we check our own socket
|
||||
* in standard socket mode. If that value is 0 we don't check at all.
|
||||
* Values is in seconds. */
|
||||
#define CHECK_OWN_SOCKET_INTERVAL (60)
|
||||
|
||||
/* CHECK_PROBLEMS_INTERVAL defines how often we check the existence of
|
||||
* parent process and homedir. Value is in seconds. */
|
||||
#define CHECK_PROBLEMS_INTERVAL (4)
|
||||
|
||||
/* Flag indicating that the ssh-agent subsystem has been enabled. */
|
||||
static int ssh_support;
|
||||
|
@ -384,9 +382,6 @@ static int startup_signal_mask_valid;
|
|||
/* Flag to indicate that a shutdown was requested. */
|
||||
static int shutdown_pending;
|
||||
|
||||
/* Counter for the currently running own socket checks. */
|
||||
static int check_own_socket_running;
|
||||
|
||||
/* Flags to indicate that check_own_socket shall not be called. */
|
||||
static int disable_check_own_socket;
|
||||
|
||||
|
@ -396,6 +391,12 @@ static int is_supervised;
|
|||
/* Flag indicating to start the daemon even if one already runs. */
|
||||
static int steal_socket;
|
||||
|
||||
/* Flag to monitor problems. */
|
||||
static int problem_detected;
|
||||
#define AGENT_PROBLEM_SOCKET_TAKEOVER (1 << 0)
|
||||
#define AGENT_PROBLEM_PARENT_HAS_GONE (1 << 1)
|
||||
#define AGENT_PROBLEM_HOMEDIR_REMOVED (1 << 2)
|
||||
|
||||
/* Flag to inhibit socket removal in cleanup. */
|
||||
static int inhibit_socket_removal;
|
||||
|
||||
|
@ -432,6 +433,17 @@ static assuan_sock_nonce_t socket_nonce_ssh;
|
|||
* Let's try this as default. Change at runtime with --listen-backlog. */
|
||||
static int listen_backlog = 64;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* The event to break the select call. */
|
||||
static HANDLE the_event2;
|
||||
#elif defined(HAVE_PSELECT_NO_EINTR)
|
||||
/* An FD to break the select call. */
|
||||
static int event_pipe_fd;
|
||||
#else
|
||||
/* PID of the main thread. */
|
||||
static pid_t main_thread_pid;
|
||||
#endif
|
||||
|
||||
/* Default values for options passed to the pinentry. */
|
||||
static char *default_display;
|
||||
static char *default_ttyname;
|
||||
|
@ -452,9 +464,14 @@ static const char *debug_level;
|
|||
the log file after a SIGHUP if it didn't changed. Malloced. */
|
||||
static char *current_logfile;
|
||||
|
||||
/* The handle_tick() function may test whether a parent is still
|
||||
* running. We record the PID of the parent here or -1 if it should
|
||||
* be watched. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#define HAVE_PARENT_PID_SUPPORT 0
|
||||
#else
|
||||
#define HAVE_PARENT_PID_SUPPORT 1
|
||||
#endif
|
||||
/* The check_others_thread() function may test whether a parent is
|
||||
* still running. We record the PID of the parent here or -1 if it
|
||||
* should be watched. */
|
||||
static pid_t parent_pid = (pid_t)(-1);
|
||||
|
||||
/* This flag is true if the inotify mechanism for detecting the
|
||||
|
@ -462,11 +479,6 @@ static pid_t parent_pid = (pid_t)(-1);
|
|||
* alternative but portable stat based check. */
|
||||
static int have_homedir_inotify;
|
||||
|
||||
/* Depending on how gpg-agent was started, the homedir inotify watch
|
||||
* may not be reliable. This flag is set if we assume that inotify
|
||||
* works reliable. */
|
||||
static int reliable_homedir_inotify;
|
||||
|
||||
/* Number of active connections. */
|
||||
static int active_connections;
|
||||
|
||||
|
@ -516,13 +528,13 @@ static void agent_deinit_default_ctrl (ctrl_t ctrl);
|
|||
static void handle_connections (gnupg_fd_t listen_fd,
|
||||
gnupg_fd_t listen_fd_extra,
|
||||
gnupg_fd_t listen_fd_browser,
|
||||
gnupg_fd_t listen_fd_ssh);
|
||||
static void check_own_socket (void);
|
||||
gnupg_fd_t listen_fd_ssh,
|
||||
int reliable_homedir_inotify);
|
||||
static int check_for_running_agent (int silent);
|
||||
|
||||
/* Pth wrapper function definitions. */
|
||||
ASSUAN_SYSTEM_NPTH_IMPL;
|
||||
|
||||
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||
static void *check_own_socket_thread (void *arg);
|
||||
#endif
|
||||
static void *check_others_thread (void *arg);
|
||||
|
||||
/*
|
||||
Functions.
|
||||
|
@ -1050,6 +1062,7 @@ thread_init_once (void)
|
|||
* initialized and thus Libgcrypt could not set its system call
|
||||
* clamp. */
|
||||
gcry_control (GCRYCTL_REINIT_SYSCALL_CLAMP, 0, 0);
|
||||
assuan_control (ASSUAN_CONTROL_REINIT_SYSCALL_CLAMP, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1057,7 +1070,6 @@ static void
|
|||
initialize_modules (void)
|
||||
{
|
||||
thread_init_once ();
|
||||
assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
|
||||
initialize_module_cache ();
|
||||
initialize_module_call_pinentry ();
|
||||
initialize_module_daemon ();
|
||||
|
@ -1085,6 +1097,7 @@ main (int argc, char **argv)
|
|||
int gpgconf_list = 0;
|
||||
gpg_error_t err;
|
||||
struct assuan_malloc_hooks malloc_hooks;
|
||||
int reliable_homedir_inotify = 1;
|
||||
|
||||
early_system_init ();
|
||||
|
||||
|
@ -1117,7 +1130,6 @@ main (int argc, char **argv)
|
|||
assuan_set_malloc_hooks (&malloc_hooks);
|
||||
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
|
||||
assuan_sock_init ();
|
||||
assuan_sock_set_system_hooks (ASSUAN_SYSTEM_NPTH);
|
||||
setup_libassuan_logging (&opt.debug, NULL);
|
||||
|
||||
setup_libgcrypt_logging ();
|
||||
|
@ -1204,7 +1216,7 @@ main (int argc, char **argv)
|
|||
* Now we are now working under our real uid
|
||||
*/
|
||||
|
||||
/* The configuraton directories for use by gpgrt_argparser. */
|
||||
/* The configuration directories for use by gpgrt_argparser. */
|
||||
gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
|
||||
gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
|
||||
|
||||
|
@ -1213,7 +1225,7 @@ main (int argc, char **argv)
|
|||
pargs.argc = &argc;
|
||||
pargs.argv = &argv;
|
||||
/* We are re-using the struct, thus the reset flag. We OR the
|
||||
* flags so that the internal intialized flag won't be cleared. */
|
||||
* flags so that the internal initialized flag won't be cleared. */
|
||||
pargs.flags |= (ARGPARSE_FLAG_RESET
|
||||
| ARGPARSE_FLAG_KEEP
|
||||
| ARGPARSE_FLAG_SYS
|
||||
|
@ -1583,7 +1595,7 @@ main (int argc, char **argv)
|
|||
|
||||
log_info ("listening on: std=%d extra=%d browser=%d ssh=%d\n",
|
||||
fd, fd_extra, fd_browser, fd_ssh);
|
||||
handle_connections (fd, fd_extra, fd_browser, fd_ssh);
|
||||
handle_connections (fd, fd_extra, fd_browser, fd_ssh, 1);
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
}
|
||||
else if (!is_daemon)
|
||||
|
@ -1811,14 +1823,14 @@ main (int argc, char **argv)
|
|||
log_get_prefix (&oldflags);
|
||||
log_set_prefix (NULL, oldflags | GPGRT_LOG_RUN_DETACHED);
|
||||
opt.running_detached = 1;
|
||||
|
||||
/* Unless we are running with a program given on the command
|
||||
* line we can assume that the inotify things works and thus
|
||||
* we can avoid the regular stat calls. */
|
||||
if (!argc)
|
||||
reliable_homedir_inotify = 1;
|
||||
}
|
||||
|
||||
/* When we are running with a program given on the command
|
||||
* line, the inotify things may not work well and thus
|
||||
* we cannot avoid the regular stat calls. */
|
||||
if (argc)
|
||||
reliable_homedir_inotify = 0;
|
||||
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
|
@ -1837,7 +1849,8 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
log_info ("%s %s started\n", gpgrt_strusage(11), gpgrt_strusage(13) );
|
||||
handle_connections (fd, fd_extra, fd_browser, fd_ssh);
|
||||
handle_connections (fd, fd_extra, fd_browser, fd_ssh,
|
||||
reliable_homedir_inotify);
|
||||
assuan_sock_close (fd);
|
||||
}
|
||||
|
||||
|
@ -2139,39 +2152,45 @@ get_agent_active_connection_count (void)
|
|||
notification event. Calling it the first time creates that
|
||||
event. */
|
||||
#if defined(HAVE_W32_SYSTEM)
|
||||
static void *
|
||||
create_an_event (void)
|
||||
{
|
||||
HANDLE h, h2;
|
||||
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
|
||||
|
||||
/* We need to use a manual reset event object due to the way our
|
||||
w32-pth wait function works: If we would use an automatic
|
||||
reset event we are not able to figure out which handle has
|
||||
been signaled because at the time we single out the signaled
|
||||
handles using WFSO the event has already been reset due to
|
||||
the WFMO. */
|
||||
h = CreateEvent (&sa, TRUE, FALSE, NULL);
|
||||
if (!h)
|
||||
log_error ("can't create an event: %s\n", w32_strerror (-1) );
|
||||
else if (!DuplicateHandle (GetCurrentProcess(), h,
|
||||
GetCurrentProcess(), &h2,
|
||||
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
|
||||
{
|
||||
log_error ("setting synchronize for an event failed: %s\n",
|
||||
w32_strerror (-1) );
|
||||
CloseHandle (h);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle (h);
|
||||
return h2;
|
||||
}
|
||||
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
void *
|
||||
get_agent_daemon_notify_event (void)
|
||||
{
|
||||
static HANDLE the_event = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (the_event == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HANDLE h, h2;
|
||||
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
|
||||
|
||||
/* We need to use a manual reset event object due to the way our
|
||||
w32-pth wait function works: If we would use an automatic
|
||||
reset event we are not able to figure out which handle has
|
||||
been signaled because at the time we single out the signaled
|
||||
handles using WFSO the event has already been reset due to
|
||||
the WFMO. */
|
||||
h = CreateEvent (&sa, TRUE, FALSE, NULL);
|
||||
if (!h)
|
||||
log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
|
||||
else if (!DuplicateHandle (GetCurrentProcess(), h,
|
||||
GetCurrentProcess(), &h2,
|
||||
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
|
||||
{
|
||||
log_error ("setting synchronize for scd notify event failed: %s\n",
|
||||
w32_strerror (-1) );
|
||||
CloseHandle (h);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle (h);
|
||||
the_event = h2;
|
||||
}
|
||||
}
|
||||
the_event = create_an_event ();
|
||||
|
||||
return the_event;
|
||||
}
|
||||
|
@ -2428,57 +2447,6 @@ create_directories (void)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* This is the worker for the ticker. It is called every few seconds
|
||||
and may only do fast operations. */
|
||||
static void
|
||||
handle_tick (void)
|
||||
{
|
||||
static time_t last_minute;
|
||||
struct stat statbuf;
|
||||
|
||||
if (!last_minute)
|
||||
last_minute = time (NULL);
|
||||
|
||||
/* If we are running as a child of another process, check whether
|
||||
the parent is still alive and shutdown if not. */
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
if (parent_pid != (pid_t)(-1))
|
||||
{
|
||||
if (kill (parent_pid, 0))
|
||||
{
|
||||
shutdown_pending = 2;
|
||||
log_info ("parent process died - shutting down\n");
|
||||
log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
|
||||
cleanup ();
|
||||
agent_exit (0);
|
||||
}
|
||||
}
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
/* Code to be run from time to time. */
|
||||
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||
if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
|
||||
{
|
||||
check_own_socket ();
|
||||
last_minute = time (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Need to check for expired cache entries. */
|
||||
agent_cache_housekeeping ();
|
||||
|
||||
/* Check whether the homedir is still available. */
|
||||
if (!shutdown_pending
|
||||
&& (!have_homedir_inotify || !reliable_homedir_inotify)
|
||||
&& gnupg_stat (gnupg_homedir (), &statbuf) && errno == ENOENT)
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
log_info ("homedir has been removed - shutting down\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* A global function which allows us to call the reload stuff from
|
||||
other places too. This is only used when build for W32. */
|
||||
void
|
||||
|
@ -2537,6 +2505,11 @@ handle_signal (int signo)
|
|||
agent_sigusr2_action ();
|
||||
break;
|
||||
|
||||
case SIGCONT:
|
||||
/* Do nothing, but break the syscall. */
|
||||
log_debug ("SIGCONT received - breaking select\n");
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
if (!shutdown_pending)
|
||||
log_info ("SIGTERM received - shutting down ...\n");
|
||||
|
@ -2574,7 +2547,7 @@ check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
|
|||
if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce))
|
||||
{
|
||||
log_info (_("error reading nonce on fd %d: %s\n"),
|
||||
FD2INT(ctrl->thread_startup.fd), strerror (errno));
|
||||
FD_DBG (ctrl->thread_startup.fd), strerror (errno));
|
||||
assuan_sock_close (ctrl->thread_startup.fd);
|
||||
xfree (ctrl);
|
||||
return -1;
|
||||
|
@ -2874,12 +2847,12 @@ do_start_connection_thread (ctrl_t ctrl)
|
|||
agent_init_default_ctrl (ctrl);
|
||||
if (opt.verbose > 1 && !DBG_IPC)
|
||||
log_info (_("handler 0x%lx for fd %d started\n"),
|
||||
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
|
||||
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
|
||||
|
||||
start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
|
||||
if (opt.verbose > 1 && !DBG_IPC)
|
||||
log_info (_("handler 0x%lx for fd %d terminated\n"),
|
||||
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
|
||||
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
|
||||
|
||||
agent_deinit_default_ctrl (ctrl);
|
||||
xfree (ctrl);
|
||||
|
@ -2954,12 +2927,12 @@ start_connection_thread_ssh (void *arg)
|
|||
agent_init_default_ctrl (ctrl);
|
||||
if (opt.verbose)
|
||||
log_info (_("ssh handler 0x%lx for fd %d started\n"),
|
||||
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
|
||||
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
|
||||
|
||||
start_command_handler_ssh (ctrl, ctrl->thread_startup.fd);
|
||||
if (opt.verbose)
|
||||
log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
|
||||
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
|
||||
(unsigned long) npth_self(), FD_DBG (ctrl->thread_startup.fd));
|
||||
|
||||
agent_deinit_default_ctrl (ctrl);
|
||||
xfree (ctrl);
|
||||
|
@ -2968,13 +2941,36 @@ start_connection_thread_ssh (void *arg)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
agent_kick_the_loop (void)
|
||||
{
|
||||
/* Kick the select loop. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
int ret = SetEvent (the_event2);
|
||||
if (ret == 0)
|
||||
log_error ("SetEvent for agent_kick_the_loop failed: %s\n",
|
||||
w32_strerror (-1));
|
||||
#else
|
||||
# ifdef HAVE_PSELECT_NO_EINTR
|
||||
write (event_pipe_fd, "", 1);
|
||||
# else
|
||||
int ret = kill (main_thread_pid, SIGCONT);
|
||||
if (ret < 0)
|
||||
log_error ("sending signal for agent_kick_the_loop failed: %s\n",
|
||||
gpg_strerror (gpg_error_from_syserror ()));
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Connection handler loop. Wait for connection requests and spawn a
|
||||
thread after accepting a connection. */
|
||||
static void
|
||||
handle_connections (gnupg_fd_t listen_fd,
|
||||
gnupg_fd_t listen_fd_extra,
|
||||
gnupg_fd_t listen_fd_browser,
|
||||
gnupg_fd_t listen_fd_ssh)
|
||||
gnupg_fd_t listen_fd_ssh,
|
||||
int reliable_homedir_inotify)
|
||||
{
|
||||
gpg_error_t err;
|
||||
npth_attr_t tattr;
|
||||
|
@ -2985,12 +2981,15 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
gnupg_fd_t fd;
|
||||
int nfd;
|
||||
int saved_errno;
|
||||
struct timespec abstime;
|
||||
struct timespec curtime;
|
||||
struct timespec timeout;
|
||||
struct timespec *tp;
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
HANDLE events[2];
|
||||
HANDLE events[3];
|
||||
unsigned int events_set;
|
||||
#else
|
||||
int signo;
|
||||
# ifdef HAVE_PSELECT_NO_EINTR
|
||||
int pipe_fd[2];
|
||||
# endif
|
||||
#endif
|
||||
int sock_inotify_fd = -1;
|
||||
int home_inotify_fd = -1;
|
||||
|
@ -3018,11 +3017,24 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
npth_sigev_add (SIGUSR1);
|
||||
npth_sigev_add (SIGUSR2);
|
||||
npth_sigev_add (SIGINT);
|
||||
npth_sigev_add (SIGCONT);
|
||||
npth_sigev_add (SIGTERM);
|
||||
npth_sigev_fini ();
|
||||
# ifdef HAVE_PSELECT_NO_EINTR
|
||||
ret = gnupg_create_pipe (pipe_fd);
|
||||
if (ret)
|
||||
{
|
||||
log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
|
||||
return;
|
||||
}
|
||||
event_pipe_fd = pipe_fd[1];
|
||||
# else
|
||||
main_thread_pid = getpid ();
|
||||
# endif
|
||||
#else
|
||||
events[0] = get_agent_daemon_notify_event ();
|
||||
events[1] = INVALID_HANDLE_VALUE;
|
||||
events[1] = the_event2 = create_an_event ();
|
||||
events[2] = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
if (disable_check_own_socket)
|
||||
|
@ -3034,7 +3046,7 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
gpg_strerror (err));
|
||||
}
|
||||
|
||||
if (disable_check_own_socket)
|
||||
if (!reliable_homedir_inotify)
|
||||
home_inotify_fd = -1;
|
||||
else if ((err = gnupg_inotify_watch_delete_self (&home_inotify_fd,
|
||||
gnupg_homedir ())))
|
||||
|
@ -3046,6 +3058,27 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
else
|
||||
have_homedir_inotify = 1;
|
||||
|
||||
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||
if (!disable_check_own_socket && sock_inotify_fd == -1)
|
||||
{
|
||||
npth_t thread;
|
||||
|
||||
err = npth_create (&thread, &tattr, check_own_socket_thread, NULL);
|
||||
if (err)
|
||||
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((HAVE_PARENT_PID_SUPPORT && parent_pid != (pid_t)(-1))
|
||||
|| !have_homedir_inotify)
|
||||
{
|
||||
npth_t thread;
|
||||
|
||||
err = npth_create (&thread, &tattr, check_others_thread, NULL);
|
||||
if (err)
|
||||
log_error ("error spawning check_others_thread: %s\n", strerror (err));
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
@ -3075,24 +3108,24 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (FD2INT (listen_fd), &fdset);
|
||||
nfd = FD2INT (listen_fd);
|
||||
nfd = FD2NUM (listen_fd);
|
||||
if (listen_fd_extra != GNUPG_INVALID_FD)
|
||||
{
|
||||
FD_SET ( FD2INT(listen_fd_extra), &fdset);
|
||||
if (FD2INT (listen_fd_extra) > nfd)
|
||||
nfd = FD2INT (listen_fd_extra);
|
||||
nfd = FD2NUM (listen_fd_extra);
|
||||
}
|
||||
if (listen_fd_browser != GNUPG_INVALID_FD)
|
||||
{
|
||||
FD_SET ( FD2INT(listen_fd_browser), &fdset);
|
||||
if (FD2INT (listen_fd_browser) > nfd)
|
||||
nfd = FD2INT (listen_fd_browser);
|
||||
nfd = FD2NUM (listen_fd_browser);
|
||||
}
|
||||
if (listen_fd_ssh != GNUPG_INVALID_FD)
|
||||
{
|
||||
FD_SET ( FD2INT(listen_fd_ssh), &fdset);
|
||||
if (FD2INT (listen_fd_ssh) > nfd)
|
||||
nfd = FD2INT (listen_fd_ssh);
|
||||
nfd = FD2NUM (listen_fd_ssh);
|
||||
}
|
||||
if (sock_inotify_fd != -1)
|
||||
{
|
||||
|
@ -3112,15 +3145,12 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
listentbl[2].l_fd = listen_fd_browser;
|
||||
listentbl[3].l_fd = listen_fd_ssh;
|
||||
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Shutdown test. */
|
||||
if (shutdown_pending)
|
||||
{
|
||||
if (active_connections == 0)
|
||||
if (active_connections == 0 || is_supervised)
|
||||
break; /* ready */
|
||||
|
||||
/* Do not accept new connections but keep on running the
|
||||
|
@ -3149,28 +3179,23 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
thus a simple assignment is fine to copy the entire set. */
|
||||
read_fdset = fdset;
|
||||
|
||||
npth_clock_gettime (&curtime);
|
||||
if (!(npth_timercmp (&curtime, &abstime, <)))
|
||||
{
|
||||
/* Timeout. */
|
||||
handle_tick ();
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
}
|
||||
npth_timersub (&abstime, &curtime, &timeout);
|
||||
#ifdef HAVE_PSELECT_NO_EINTR
|
||||
FD_SET (pipe_fd[0], &read_fdset);
|
||||
if (nfd < pipe_fd[0])
|
||||
nfd = pipe_fd[0];
|
||||
#endif
|
||||
|
||||
tp = agent_cache_expiration ();
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
|
||||
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, tp,
|
||||
npth_sigev_sigmask ());
|
||||
saved_errno = errno;
|
||||
|
||||
{
|
||||
int signo;
|
||||
while (npth_sigev_get_pending (&signo))
|
||||
handle_signal (signo);
|
||||
}
|
||||
while (npth_sigev_get_pending (&signo))
|
||||
handle_signal (signo);
|
||||
#else
|
||||
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
|
||||
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, tp,
|
||||
events, &events_set);
|
||||
saved_errno = errno;
|
||||
|
||||
|
@ -3186,11 +3211,47 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
gnupg_sleep (1);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
if ((problem_detected & AGENT_PROBLEM_PARENT_HAS_GONE))
|
||||
{
|
||||
shutdown_pending = 2;
|
||||
log_info ("parent process died - shutting down\n");
|
||||
log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
|
||||
cleanup ();
|
||||
agent_exit (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((problem_detected & AGENT_PROBLEM_SOCKET_TAKEOVER))
|
||||
{
|
||||
/* We may not remove the socket as it is now in use by another
|
||||
server. */
|
||||
inhibit_socket_removal = 1;
|
||||
shutdown_pending = 2;
|
||||
log_info ("this process is useless - shutting down\n");
|
||||
}
|
||||
|
||||
if ((problem_detected & AGENT_PROBLEM_HOMEDIR_REMOVED))
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
log_info ("homedir has been removed - shutting down\n");
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
/* Interrupt or timeout. Will be handled when calculating the
|
||||
next timeout. */
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_PSELECT_NO_EINTR
|
||||
if (FD_ISSET (pipe_fd[0], &read_fdset))
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
read (pipe_fd[0], buf, sizeof buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The inotify fds are set even when a shutdown is pending (see
|
||||
* above). So we must handle them in any case. To avoid that
|
||||
* they trigger a second time we close them immediately. */
|
||||
|
@ -3198,7 +3259,10 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
&& FD_ISSET (sock_inotify_fd, &read_fdset)
|
||||
&& gnupg_inotify_has_name (sock_inotify_fd, GPG_AGENT_SOCK_NAME))
|
||||
{
|
||||
shutdown_pending = 1;
|
||||
/* We may not remove the socket (if any), as it may be now
|
||||
in use by another server. */
|
||||
inhibit_socket_removal = 1;
|
||||
shutdown_pending = 2;
|
||||
close (sock_inotify_fd);
|
||||
sock_inotify_fd = -1;
|
||||
log_info ("socket file has been removed - shutting down\n");
|
||||
|
@ -3227,8 +3291,8 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
continue;
|
||||
|
||||
plen = sizeof paddr;
|
||||
fd = INT2FD (npth_accept (FD2INT(listentbl[idx].l_fd),
|
||||
(struct sockaddr *)&paddr, &plen));
|
||||
fd = assuan_sock_accept (listentbl[idx].l_fd,
|
||||
(struct sockaddr *)&paddr, &plen);
|
||||
if (fd == GNUPG_INVALID_FD)
|
||||
{
|
||||
log_error ("accept failed for %s: %s\n",
|
||||
|
@ -3268,13 +3332,21 @@ handle_connections (gnupg_fd_t listen_fd,
|
|||
close (sock_inotify_fd);
|
||||
if (home_inotify_fd != -1)
|
||||
close (home_inotify_fd);
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if (the_event2 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (the_event2);
|
||||
#endif
|
||||
#ifdef HAVE_PSELECT_NO_EINTR
|
||||
close (pipe_fd[0]);
|
||||
close (pipe_fd[1]);
|
||||
#endif
|
||||
cleanup ();
|
||||
log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
|
||||
npth_attr_destroy (&tattr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||
/* Helper for check_own_socket. */
|
||||
static gpg_error_t
|
||||
check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
|
||||
|
@ -3285,20 +3357,18 @@ check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
|
|||
}
|
||||
|
||||
|
||||
/* The thread running the actual check. We need to run this in a
|
||||
separate thread so that check_own_thread can be called from the
|
||||
timer tick. */
|
||||
static void *
|
||||
check_own_socket_thread (void *arg)
|
||||
/* Check whether we are still listening on our own socket. In case
|
||||
another gpg-agent process started after us has taken ownership of
|
||||
our socket, we would linger around without any real task. Thus we
|
||||
better check once in a while whether we are really needed. */
|
||||
static int
|
||||
do_check_own_socket (const char *sockname)
|
||||
{
|
||||
int rc;
|
||||
char *sockname = arg;
|
||||
assuan_context_t ctx = NULL;
|
||||
membuf_t mb;
|
||||
char *buffer;
|
||||
|
||||
check_own_socket_running++;
|
||||
|
||||
rc = assuan_new (&ctx);
|
||||
if (rc)
|
||||
{
|
||||
|
@ -3336,58 +3406,78 @@ check_own_socket_thread (void *arg)
|
|||
xfree (buffer);
|
||||
|
||||
leave:
|
||||
xfree (sockname);
|
||||
if (ctx)
|
||||
assuan_release (ctx);
|
||||
if (rc)
|
||||
{
|
||||
/* We may not remove the socket as it is now in use by another
|
||||
server. */
|
||||
inhibit_socket_removal = 1;
|
||||
shutdown_pending = 2;
|
||||
log_info ("this process is useless - shutting down\n");
|
||||
}
|
||||
check_own_socket_running--;
|
||||
return NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether we are still listening on our own socket. In case
|
||||
another gpg-agent process started after us has taken ownership of
|
||||
our socket, we would linger around without any real task. Thus we
|
||||
better check once in a while whether we are really needed. */
|
||||
static void
|
||||
check_own_socket (void)
|
||||
/* The thread running the actual check. */
|
||||
static void *
|
||||
check_own_socket_thread (void *arg)
|
||||
{
|
||||
char *sockname;
|
||||
npth_t thread;
|
||||
npth_attr_t tattr;
|
||||
int err;
|
||||
|
||||
if (disable_check_own_socket)
|
||||
return;
|
||||
|
||||
if (check_own_socket_running || shutdown_pending)
|
||||
return; /* Still running or already shutting down. */
|
||||
(void)arg;
|
||||
|
||||
sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
|
||||
if (!sockname)
|
||||
return; /* Out of memory. */
|
||||
return NULL; /* Out of memory. */
|
||||
|
||||
err = npth_attr_init (&tattr);
|
||||
if (err)
|
||||
while (!problem_detected)
|
||||
{
|
||||
xfree (sockname);
|
||||
return;
|
||||
if (shutdown_pending)
|
||||
goto leave;
|
||||
|
||||
gnupg_sleep (CHECK_OWN_SOCKET_INTERVAL);
|
||||
|
||||
if (do_check_own_socket (sockname))
|
||||
problem_detected |= AGENT_PROBLEM_SOCKET_TAKEOVER;
|
||||
}
|
||||
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
|
||||
err = npth_create (&thread, &tattr, check_own_socket_thread, sockname);
|
||||
if (err)
|
||||
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
|
||||
npth_attr_destroy (&tattr);
|
||||
|
||||
agent_kick_the_loop ();
|
||||
|
||||
leave:
|
||||
xfree (sockname);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The thread running other checks. */
|
||||
static void *
|
||||
check_others_thread (void *arg)
|
||||
{
|
||||
const char *homedir = gnupg_homedir ();
|
||||
|
||||
(void)arg;
|
||||
|
||||
while (!problem_detected)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (shutdown_pending)
|
||||
goto leave;
|
||||
|
||||
gnupg_sleep (CHECK_PROBLEMS_INTERVAL);
|
||||
|
||||
/* If we are running as a child of another process, check whether
|
||||
the parent is still alive and shutdown if not. */
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
if (parent_pid != (pid_t)(-1) && kill (parent_pid, 0))
|
||||
problem_detected |= AGENT_PROBLEM_PARENT_HAS_GONE;
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
/* Check whether the homedir is still available. */
|
||||
if (!have_homedir_inotify
|
||||
&& gnupg_stat (homedir, &statbuf) && errno == ENOENT)
|
||||
problem_detected |= AGENT_PROBLEM_HOMEDIR_REMOVED;
|
||||
}
|
||||
|
||||
agent_kick_the_loop ();
|
||||
|
||||
leave:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Figure out whether an agent is available and running. Prints an
|
||||
error if not. If SILENT is true, no messages are printed.
|
||||
|
|
|
@ -27,8 +27,83 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "../common/openpgpdefs.h"
|
||||
|
||||
|
||||
/* Table with parameters for KEM decryption. Use get_ecc_parms to
|
||||
* find an entry. */
|
||||
struct ecc_params
|
||||
{
|
||||
const char *curve; /* Canonical name of the curve. */
|
||||
size_t pubkey_len; /* Pubkey in the SEXP representation. */
|
||||
size_t scalar_len;
|
||||
size_t point_len;
|
||||
size_t shared_len;
|
||||
int hash_algo;
|
||||
int kem_algo;
|
||||
int scalar_reverse;
|
||||
};
|
||||
|
||||
static const struct ecc_params ecc_table[] =
|
||||
{
|
||||
{
|
||||
"Curve25519",
|
||||
33, 32, 32, 32,
|
||||
GCRY_MD_SHA3_256, GCRY_KEM_RAW_X25519,
|
||||
1
|
||||
},
|
||||
{
|
||||
"X448",
|
||||
56, 56, 56, 64,
|
||||
GCRY_MD_SHA3_512, GCRY_KEM_RAW_X448,
|
||||
0
|
||||
},
|
||||
{
|
||||
"brainpoolP256r1",
|
||||
65, 32, 65, 32,
|
||||
GCRY_MD_SHA3_256, GCRY_KEM_RAW_BP256,
|
||||
0
|
||||
},
|
||||
{
|
||||
"brainpoolP384r1",
|
||||
97, 48, 97, 64,
|
||||
GCRY_MD_SHA3_512, GCRY_KEM_RAW_BP384,
|
||||
0
|
||||
},
|
||||
{
|
||||
"brainpoolP512r1",
|
||||
129, 64, 129, 64,
|
||||
GCRY_MD_SHA3_512, GCRY_KEM_RAW_BP512,
|
||||
0
|
||||
},
|
||||
{ NULL, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
/* Maximum buffer sizes required for ECC KEM. Keep this aligned to
|
||||
* the ecc_table above. */
|
||||
#define ECC_SCALAR_LEN_MAX 64
|
||||
#define ECC_POINT_LEN_MAX (1+2*64)
|
||||
#define ECC_HASH_LEN_MAX 64
|
||||
|
||||
|
||||
|
||||
/* Return the ECC parameters for CURVE. CURVE is expected to be the
|
||||
* canonical name. */
|
||||
static const struct ecc_params *
|
||||
get_ecc_params (const char *curve)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ecc_table[i].curve; i++)
|
||||
if (!strcmp (ecc_table[i].curve, curve))
|
||||
return &ecc_table[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp.
|
||||
Try to get the key from CTRL and write the decoded stuff back to
|
||||
OUTFP. The padding information is stored at R_PADDING with -1
|
||||
|
@ -41,7 +116,6 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||
gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL;
|
||||
unsigned char *shadow_info = NULL;
|
||||
gpg_error_t err = 0;
|
||||
int no_shadow_info = 0;
|
||||
char *buf = NULL;
|
||||
size_t len;
|
||||
|
||||
|
@ -70,17 +144,13 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||
err = agent_key_from_file (ctrl, NULL, desc_text,
|
||||
NULL, &shadow_info,
|
||||
CACHE_MODE_NORMAL, NULL, &s_skey, NULL, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_NO_SECKEY)
|
||||
no_shadow_info = 1;
|
||||
else if (err)
|
||||
if (err && gpg_err_code (err) != GPG_ERR_NO_SECKEY)
|
||||
{
|
||||
log_error ("failed to read the secret key\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (shadow_info || no_shadow_info)
|
||||
else if (shadow_info
|
||||
|| err /* gpg_err_code (err) == GPG_ERR_NO_SECKEY */)
|
||||
{ /* divert operation to the smartcard */
|
||||
|
||||
if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_SEXP);
|
||||
|
@ -95,12 +165,12 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||
&buf, &len, r_padding);
|
||||
if (err)
|
||||
{
|
||||
/* We restore the original error (ie. no seckey) is no card
|
||||
/* We restore the original error (ie. no seckey) as no card
|
||||
* has been found and we have no shadow key. This avoids a
|
||||
* surprising "card removed" error code. */
|
||||
if ((gpg_err_code (err) == GPG_ERR_CARD_REMOVED
|
||||
|| gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
|
||||
&& no_shadow_info)
|
||||
&& !shadow_info)
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
else
|
||||
log_error ("smartcard decryption failed: %s\n", gpg_strerror (err));
|
||||
|
@ -157,3 +227,597 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||
xfree (shadow_info);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Reverse BUFFER to change the endianness. */
|
||||
static void
|
||||
reverse_buffer (unsigned char *buffer, unsigned int length)
|
||||
{
|
||||
unsigned int tmp, i;
|
||||
|
||||
for (i=0; i < length/2; i++)
|
||||
{
|
||||
tmp = buffer[i];
|
||||
buffer[i] = buffer[length-1-i];
|
||||
buffer[length-1-i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
ecc_extract_pk_from_key (const struct ecc_params *ecc, gcry_sexp_t s_skey,
|
||||
unsigned char *ecc_pk)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned int nbits;
|
||||
const unsigned char *p;
|
||||
size_t len;
|
||||
gcry_mpi_t ecc_pk_mpi = NULL;
|
||||
|
||||
err = gcry_sexp_extract_param (s_skey, NULL, "/q", &ecc_pk_mpi, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: extracting q and d from ECC key failed\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
p = gcry_mpi_get_opaque (ecc_pk_mpi, &nbits);
|
||||
len = (nbits+7)/8;
|
||||
if (len != ecc->pubkey_len)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: ECC public key length invalid (%zu)\n", __func__, len);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
else if (len == ecc->point_len)
|
||||
memcpy (ecc_pk, p, ecc->point_len);
|
||||
else if (len == ecc->point_len + 1 && p[0] == 0x40)
|
||||
/* Remove the 0x40 prefix (for Curve25519) */
|
||||
memcpy (ecc_pk, p+1, ecc->point_len);
|
||||
else
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex (ecc_pk, ecc->pubkey_len, "ECC pubkey:");
|
||||
|
||||
leave:
|
||||
mpi_release (ecc_pk_mpi);
|
||||
return err;
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
ecc_extract_sk_from_key (const struct ecc_params *ecc, gcry_sexp_t s_skey,
|
||||
unsigned char *ecc_sk)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned int nbits;
|
||||
const unsigned char *p;
|
||||
size_t len;
|
||||
gcry_mpi_t ecc_sk_mpi = NULL;
|
||||
|
||||
err = gcry_sexp_extract_param (s_skey, NULL, "/d", &ecc_sk_mpi, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: extracting d from ECC key failed\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
p = gcry_mpi_get_opaque (ecc_sk_mpi, &nbits);
|
||||
len = (nbits+7)/8;
|
||||
if (len > ecc->scalar_len)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: ECC secret key too long (%zu)\n", __func__, len);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
memset (ecc_sk, 0, ecc->scalar_len - len);
|
||||
memcpy (ecc_sk + ecc->scalar_len - len, p, len);
|
||||
if (ecc->scalar_reverse)
|
||||
reverse_buffer (ecc_sk, ecc->scalar_len);
|
||||
mpi_release (ecc_sk_mpi);
|
||||
ecc_sk_mpi = NULL;
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex (ecc_sk, ecc->scalar_len, "ECC seckey:");
|
||||
|
||||
leave:
|
||||
mpi_release (ecc_sk_mpi);
|
||||
return err;
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
ecc_raw_kem (const struct ecc_params *ecc, gcry_sexp_t s_skey,
|
||||
const unsigned char *ecc_ct, unsigned char *ecc_ecdh)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
unsigned char ecc_sk[ECC_SCALAR_LEN_MAX];
|
||||
|
||||
if (ecc->scalar_len > ECC_SCALAR_LEN_MAX)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: ECC scalar length invalid (%zu)\n",
|
||||
__func__, ecc->scalar_len);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = ecc_extract_sk_from_key (ecc, s_skey, ecc_sk);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
err = gcry_kem_decap (ecc->kem_algo, ecc_sk, ecc->scalar_len,
|
||||
ecc_ct, ecc->point_len, ecc_ecdh, ecc->point_len,
|
||||
NULL, 0);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: gcry_kem_decap for ECC failed\n", __func__);
|
||||
}
|
||||
|
||||
leave:
|
||||
wipememory (ecc_sk, sizeof ecc_sk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
get_cardkey (ctrl_t ctrl, const char *keygrip, gcry_sexp_t *r_s_pk)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned char *pkbuf;
|
||||
size_t pkbuflen;
|
||||
|
||||
err = agent_card_readkey (ctrl, keygrip, &pkbuf, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
|
||||
err = gcry_sexp_sscan (r_s_pk, NULL, (char*)pkbuf, pkbuflen);
|
||||
if (err)
|
||||
log_error ("failed to build S-Exp from received card key: %s\n",
|
||||
gpg_strerror (err));
|
||||
|
||||
xfree (pkbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static gpg_error_t
|
||||
ecc_get_curve (ctrl_t ctrl, gcry_sexp_t s_skey, const char **r_curve)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
gcry_sexp_t s_skey_card = NULL;
|
||||
const char *curve = NULL;
|
||||
gcry_sexp_t key;
|
||||
|
||||
*r_curve = NULL;
|
||||
|
||||
if (!s_skey)
|
||||
{
|
||||
err = get_cardkey (ctrl, ctrl->keygrip, &s_skey_card);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
key = s_skey_card;
|
||||
}
|
||||
else
|
||||
key = s_skey;
|
||||
|
||||
curve = get_ecc_curve_from_key (key);
|
||||
if (!curve)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
*r_curve = curve;
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (s_skey_card);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Given a private key in SEXP by S_SKEY0 and a cipher text by ECC_CT
|
||||
* with length ECC_POINT_LEN, do ECC-KEM operation. Result is
|
||||
* returned in the memory referred by ECC_SS. Shared secret length is
|
||||
* returned in the memory referred by R_SHARED_LEN. CTRL is used to
|
||||
* access smartcard, internally. */
|
||||
static gpg_error_t
|
||||
ecc_pgp_kem_decrypt (ctrl_t ctrl, gcry_sexp_t s_skey0,
|
||||
unsigned char *shadow_info0,
|
||||
const unsigned char *ecc_ct, size_t ecc_point_len,
|
||||
unsigned char *ecc_ss, size_t *r_shared_len)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned char ecc_ecdh[ECC_POINT_LEN_MAX];
|
||||
unsigned char ecc_pk[ECC_POINT_LEN_MAX];
|
||||
const char *curve;
|
||||
const struct ecc_params *ecc = NULL;
|
||||
|
||||
if (ecc_point_len > ECC_POINT_LEN_MAX)
|
||||
return gpg_error (GPG_ERR_INV_DATA);
|
||||
|
||||
err = ecc_get_curve (ctrl, s_skey0, &curve);
|
||||
if (err)
|
||||
{
|
||||
if ((gpg_err_code (err) == GPG_ERR_CARD_REMOVED
|
||||
|| gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
|
||||
&& !s_skey0)
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
return err;
|
||||
}
|
||||
|
||||
ecc = get_ecc_params (curve);
|
||||
if (!ecc)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: curve '%s' not supported\n", __func__, curve);
|
||||
return gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
}
|
||||
|
||||
*r_shared_len = ecc->shared_len;
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_debug ("ECC curve: %s\n", curve);
|
||||
|
||||
if (ecc->point_len != ecc_point_len)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: ECC cipher text length invalid (%zu != %zu)\n",
|
||||
__func__, ecc->point_len, ecc_point_len);
|
||||
return gpg_error (GPG_ERR_INV_DATA);
|
||||
}
|
||||
|
||||
err = ecc_extract_pk_from_key (ecc, s_skey0, ecc_pk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex (ecc_ct, ecc->point_len, "ECC ephem:");
|
||||
|
||||
if (shadow_info0 || !s_skey0)
|
||||
{
|
||||
if (s_skey0 && agent_is_tpm2_key (s_skey0))
|
||||
{
|
||||
log_error ("TPM decryption failed: %s\n", gpg_strerror (err));
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = agent_card_ecc_kem (ctrl, ecc_ct, ecc->point_len, ecc_ecdh);
|
||||
if (err)
|
||||
{
|
||||
log_error ("smartcard decryption failed: %s\n",
|
||||
gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
err = ecc_raw_kem (ecc, s_skey0, ecc_ct, ecc_ecdh);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex (ecc_ecdh, ecc_point_len, "ECC ecdh:");
|
||||
|
||||
err = gnupg_ecc_kem_kdf (ecc_ss, ecc->shared_len, ecc->hash_algo,
|
||||
ecc_ecdh, ecc->point_len, ecc_ct, ecc->point_len,
|
||||
ecc_pk, ecc->point_len);
|
||||
|
||||
wipememory (ecc_ecdh, sizeof ecc_ecdh);
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: kdf for ECC failed\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex (ecc_ss, ecc->shared_len, "ECC shared:");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For composite PGP KEM (ECC+ML-KEM), decrypt CIPHERTEXT using KEM API.
|
||||
First keygrip is for ECC, second keygrip is for PQC. CIPHERTEXT
|
||||
should follow the format of:
|
||||
|
||||
(enc-val(pqc(c%d)(e%m)(k%m)(s%m)(fixed-info&)))
|
||||
c: cipher identifier (symmetric)
|
||||
e: ECDH ciphertext
|
||||
k: ML-KEM ciphertext
|
||||
s: encrypted session key
|
||||
fixed-info: A buffer with the fixed info.
|
||||
|
||||
FIXME: For now, possible keys on smartcard are not supported.
|
||||
*/
|
||||
static gpg_error_t
|
||||
composite_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
||||
gcry_sexp_t s_cipher, membuf_t *outbuf)
|
||||
{
|
||||
gcry_sexp_t s_skey0 = NULL;
|
||||
gcry_sexp_t s_skey1 = NULL;
|
||||
unsigned char *shadow_info0 = NULL;
|
||||
unsigned char *shadow_info1 = NULL;
|
||||
gpg_error_t err = 0;
|
||||
|
||||
unsigned int nbits;
|
||||
size_t len;
|
||||
|
||||
int algo;
|
||||
gcry_mpi_t encrypted_sessionkey_mpi = NULL;
|
||||
const unsigned char *encrypted_sessionkey;
|
||||
size_t encrypted_sessionkey_len;
|
||||
|
||||
gcry_mpi_t ecc_ct_mpi = NULL;
|
||||
const unsigned char *ecc_ct;
|
||||
size_t ecc_ct_len;
|
||||
unsigned char ecc_ss[ECC_HASH_LEN_MAX];
|
||||
size_t ecc_shared_len, ecc_point_len;
|
||||
|
||||
enum gcry_kem_algos mlkem_kem_algo;
|
||||
gcry_mpi_t mlkem_sk_mpi = NULL;
|
||||
gcry_mpi_t mlkem_ct_mpi = NULL;
|
||||
const unsigned char *mlkem_sk;
|
||||
size_t mlkem_sk_len;
|
||||
const unsigned char *mlkem_ct;
|
||||
size_t mlkem_ct_len;
|
||||
unsigned char mlkem_ss[GCRY_KEM_MLKEM1024_SHARED_LEN];
|
||||
size_t mlkem_ss_len;
|
||||
|
||||
unsigned char kek[32];
|
||||
size_t kek_len = 32; /* AES-256 is mandatory */
|
||||
|
||||
gcry_cipher_hd_t hd;
|
||||
unsigned char sessionkey[256];
|
||||
size_t sessionkey_len;
|
||||
gcry_buffer_t fixed_info = { 0, 0, 0, NULL };
|
||||
|
||||
err = agent_key_from_file (ctrl, NULL, desc_text,
|
||||
ctrl->keygrip, &shadow_info0,
|
||||
CACHE_MODE_NORMAL, NULL, &s_skey0, NULL, NULL);
|
||||
if (err && gpg_err_code (err) != GPG_ERR_NO_SECKEY)
|
||||
{
|
||||
log_error ("failed to read the secret key\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = agent_key_from_file (ctrl, NULL, desc_text,
|
||||
ctrl->keygrip1, &shadow_info1,
|
||||
CACHE_MODE_NORMAL, NULL, &s_skey1, NULL, NULL);
|
||||
/* Here assumes no smartcard for ML-KEM, but private key in a file. */
|
||||
if (err)
|
||||
{
|
||||
log_error ("failed to read the another secret key\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = gcry_sexp_extract_param (s_cipher, NULL, "%dc/eks&'fixed-info'",
|
||||
&algo, &ecc_ct_mpi, &mlkem_ct_mpi,
|
||||
&encrypted_sessionkey_mpi, &fixed_info, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: extracting parameters failed\n", __func__);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ecc_ct = gcry_mpi_get_opaque (ecc_ct_mpi, &nbits);
|
||||
ecc_ct_len = (nbits+7)/8;
|
||||
|
||||
len = gcry_cipher_get_algo_keylen (algo);
|
||||
encrypted_sessionkey = gcry_mpi_get_opaque (encrypted_sessionkey_mpi, &nbits);
|
||||
encrypted_sessionkey_len = (nbits+7)/8;
|
||||
if (len == 0 || encrypted_sessionkey_len != len + 8)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: encrypted session key length %zu"
|
||||
" does not match the length for algo %d\n",
|
||||
__func__, encrypted_sessionkey_len, algo);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Firstly, ECC part. */
|
||||
ecc_point_len = ecc_ct_len;
|
||||
err = ecc_pgp_kem_decrypt (ctrl, s_skey0, shadow_info0, ecc_ct, ecc_point_len,
|
||||
ecc_ss, &ecc_shared_len);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Secondly, PQC part. For now, we assume ML-KEM. */
|
||||
err = gcry_sexp_extract_param (s_skey1, NULL, "/s", &mlkem_sk_mpi, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: extracting s from PQ key failed\n", __func__);
|
||||
goto leave;
|
||||
}
|
||||
mlkem_sk = gcry_mpi_get_opaque (mlkem_sk_mpi, &nbits);
|
||||
mlkem_sk_len = (nbits+7)/8;
|
||||
if (mlkem_sk_len == GCRY_KEM_MLKEM512_SECKEY_LEN)
|
||||
{
|
||||
mlkem_kem_algo = GCRY_KEM_MLKEM512;
|
||||
mlkem_ss_len = GCRY_KEM_MLKEM512_SHARED_LEN;
|
||||
mlkem_ct_len = GCRY_KEM_MLKEM512_CIPHER_LEN;
|
||||
}
|
||||
else if (mlkem_sk_len == GCRY_KEM_MLKEM768_SECKEY_LEN)
|
||||
{
|
||||
mlkem_kem_algo = GCRY_KEM_MLKEM768;
|
||||
mlkem_ss_len = GCRY_KEM_MLKEM768_SHARED_LEN;
|
||||
mlkem_ct_len = GCRY_KEM_MLKEM768_CIPHER_LEN;
|
||||
}
|
||||
else if (mlkem_sk_len == GCRY_KEM_MLKEM1024_SECKEY_LEN)
|
||||
{
|
||||
mlkem_kem_algo = GCRY_KEM_MLKEM1024;
|
||||
mlkem_ss_len = GCRY_KEM_MLKEM1024_SHARED_LEN;
|
||||
mlkem_ct_len = GCRY_KEM_MLKEM1024_CIPHER_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: PQ key length invalid (%zu)\n", __func__, mlkem_sk_len);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mlkem_ct = gcry_mpi_get_opaque (mlkem_ct_mpi, &nbits);
|
||||
len = (nbits+7)/8;
|
||||
if (len != mlkem_ct_len)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: PQ cipher text length invalid (%zu)\n",
|
||||
__func__, mlkem_ct_len);
|
||||
err = gpg_error (GPG_ERR_INV_DATA);
|
||||
goto leave;
|
||||
}
|
||||
err = gcry_kem_decap (mlkem_kem_algo, mlkem_sk, mlkem_sk_len,
|
||||
mlkem_ct, mlkem_ct_len, mlkem_ss, mlkem_ss_len,
|
||||
NULL, 0);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: gcry_kem_decap for PQ failed\n", __func__);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mpi_release (mlkem_sk_mpi);
|
||||
mlkem_sk_mpi = NULL;
|
||||
|
||||
/* Then, combine two shared secrets and ciphertexts into one KEK */
|
||||
err = gnupg_kem_combiner (kek, kek_len,
|
||||
ecc_ss, ecc_shared_len, ecc_ct, ecc_point_len,
|
||||
mlkem_ss, mlkem_ss_len, mlkem_ct, mlkem_ct_len,
|
||||
fixed_info.data, fixed_info.size);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_info ("%s: KEM combiner failed\n", __func__);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mpi_release (ecc_ct_mpi);
|
||||
ecc_ct_mpi = NULL;
|
||||
mpi_release (mlkem_ct_mpi);
|
||||
mlkem_ct_mpi = NULL;
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_printhex (kek, kek_len, "KEK key: ");
|
||||
}
|
||||
|
||||
err = gcry_cipher_open (&hd, GCRY_CIPHER_AES256,
|
||||
GCRY_CIPHER_MODE_AESWRAP, 0);
|
||||
if (err)
|
||||
{
|
||||
if (opt.verbose)
|
||||
log_error ("ecdh failed to initialize AESWRAP: %s\n",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = gcry_cipher_setkey (hd, kek, kek_len);
|
||||
|
||||
sessionkey_len = encrypted_sessionkey_len - 8;
|
||||
err = gcry_cipher_decrypt (hd, sessionkey, sessionkey_len,
|
||||
encrypted_sessionkey, encrypted_sessionkey_len);
|
||||
gcry_cipher_close (hd);
|
||||
|
||||
mpi_release (encrypted_sessionkey_mpi);
|
||||
encrypted_sessionkey_mpi = NULL;
|
||||
|
||||
if (err)
|
||||
{
|
||||
log_error ("KEM decrypt failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
put_membuf_printf (outbuf,
|
||||
"(5:value%u:", (unsigned int)sessionkey_len);
|
||||
put_membuf (outbuf, sessionkey, sessionkey_len);
|
||||
put_membuf (outbuf, ")", 2);
|
||||
|
||||
leave:
|
||||
wipememory (ecc_ss, sizeof ecc_ss);
|
||||
wipememory (mlkem_ss, sizeof mlkem_ss);
|
||||
wipememory (kek, sizeof kek);
|
||||
wipememory (sessionkey, sizeof sessionkey);
|
||||
|
||||
mpi_release (ecc_ct_mpi);
|
||||
mpi_release (mlkem_sk_mpi);
|
||||
mpi_release (mlkem_ct_mpi);
|
||||
mpi_release (encrypted_sessionkey_mpi);
|
||||
gcry_free (fixed_info.data);
|
||||
gcry_sexp_release (s_skey0);
|
||||
gcry_sexp_release (s_skey1);
|
||||
xfree (shadow_info0);
|
||||
xfree (shadow_info1);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* DECRYPT the encrypted stuff (like encrypted session key) in
|
||||
CIPHERTEXT using KEM API, with KEMID. Keys (or a key) are
|
||||
specified in CTRL. DESC_TEXT is used to retrieve private key.
|
||||
OPTION can be specified for upper layer option for KEM. Decrypted
|
||||
stuff (like session key) is written to OUTBUF.
|
||||
*/
|
||||
gpg_error_t
|
||||
agent_kem_decrypt (ctrl_t ctrl, const char *desc_text, int kemid,
|
||||
const unsigned char *ciphertext, size_t ciphertextlen,
|
||||
const unsigned char *option, size_t optionlen,
|
||||
membuf_t *outbuf)
|
||||
{
|
||||
gcry_sexp_t s_cipher = NULL;
|
||||
gpg_error_t err = 0;
|
||||
|
||||
/* For now, only PQC-PGP is supported. */
|
||||
if (kemid != KEM_PQC_PGP)
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
||||
|
||||
(void)optionlen;
|
||||
if (kemid == KEM_PQC_PGP && option)
|
||||
{
|
||||
log_error ("PQC-PGP requires no option\n");
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
}
|
||||
|
||||
if (!ctrl->have_keygrip)
|
||||
{
|
||||
log_error ("speculative decryption not yet supported\n");
|
||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
||||
}
|
||||
|
||||
if (!ctrl->have_keygrip1)
|
||||
{
|
||||
log_error ("Composite KEM requires two KEYGRIPs\n");
|
||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
||||
}
|
||||
|
||||
err = gcry_sexp_sscan (&s_cipher, NULL, (char*)ciphertext, ciphertextlen);
|
||||
if (err)
|
||||
{
|
||||
log_error ("failed to convert ciphertext: %s\n", gpg_strerror (err));
|
||||
return gpg_error (GPG_ERR_INV_DATA);
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_printhex (ctrl->keygrip, 20, "keygrip0:");
|
||||
log_printhex (ctrl->keygrip1, 20, "keygrip1:");
|
||||
gcry_log_debugsxp ("cipher", s_cipher);
|
||||
}
|
||||
|
||||
err = composite_pgp_kem_decrypt (ctrl, desc_text, s_cipher, outbuf);
|
||||
|
||||
gcry_sexp_release (s_cipher);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -509,7 +509,7 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
|
|||
((sha1 salt no_of_iterations) 16byte_iv)
|
||||
encrypted_octet_string)
|
||||
|
||||
in canoncical format of course. We use asprintf and %n modifier
|
||||
in canonical format of course. We use asprintf and %n modifier
|
||||
and dummy values as placeholders. */
|
||||
{
|
||||
char countbuf[35];
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "../common/sexp-parse.h"
|
||||
|
||||
/*
|
||||
* When it's for ECC, fixup private key part in the cannonical SEXP
|
||||
* When it's for ECC, fixup private key part in the canonical SEXP
|
||||
* representation in BUF. If not ECC, do nothing.
|
||||
*/
|
||||
gpg_error_t
|
||||
|
|
|
@ -38,14 +38,14 @@ struct trustitem_s
|
|||
{
|
||||
struct
|
||||
{
|
||||
int disabled:1; /* This entry is disabled. */
|
||||
int for_pgp:1; /* Set by '*' or 'P' as first flag. */
|
||||
int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
||||
int relax:1; /* Relax checking of root certificate
|
||||
unsigned int disabled:1; /* This entry is disabled. */
|
||||
unsigned int for_pgp:1; /* Set by '*' or 'P' as first flag. */
|
||||
unsigned int for_smime:1; /* Set by '*' or 'S' as first flag. */
|
||||
unsigned int relax:1; /* Relax checking of root certificate
|
||||
constraints. */
|
||||
int cm:1; /* Use chain model for validation. */
|
||||
int qual:1; /* Root CA for qualified signatures. */
|
||||
int de_vs:1; /* Root CA for de-vs compliant PKI. */
|
||||
unsigned int cm:1; /* Use chain model for validation. */
|
||||
unsigned int qual:1; /* Root CA for qualified signatures. */
|
||||
unsigned int de_vs:1; /* Root CA for de-vs compliant PKI. */
|
||||
} flags;
|
||||
unsigned char fpr[20]; /* The binary fingerprint. */
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ static const char headerblurb[] =
|
|||
"# well as empty lines are ignored. Lines have a length limit but this\n"
|
||||
"# is not a serious limitation as the format of the entries is fixed and\n"
|
||||
"# checked by gpg-agent. A non-comment line starts with optional white\n"
|
||||
"# space, followed by the SHA-1 fingerpint in hex, followed by a flag\n"
|
||||
"# space, followed by the SHA-1 fingerprint in hex, followed by a flag\n"
|
||||
"# which may be one of 'P', 'S' or '*' and optionally followed by a list of\n"
|
||||
"# other flags. The fingerprint may be prefixed with a '!' to mark the\n"
|
||||
"# key as not trusted. You should give the gpg-agent a HUP or run the\n"
|
||||
|
@ -736,7 +736,7 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
|
|||
insert a line break. The double percent sign is actually
|
||||
needed because it is also a printf format string. If you
|
||||
need to insert a plain % sign, you need to encode it as
|
||||
"%%25". The second "%s" gets replaced by a hexdecimal
|
||||
"%%25". The second "%s" gets replaced by a hexadecimal
|
||||
fingerprint string whereas the first one receives the name
|
||||
as stored in the certificate. */
|
||||
L_("Please verify that the certificate identified as:%%0A"
|
||||
|
|
|
@ -43,58 +43,7 @@
|
|||
#
|
||||
# The information required to sign the tarballs and binaries
|
||||
# are expected in the developer specific file ~/.gnupg-autogen.rc".
|
||||
# Here is an example:
|
||||
#--8<---------------cut here---------------start------------->8---
|
||||
# # Location of the released tarball archives. Note that this is an
|
||||
# # internal archive and before uploading this to the public server,
|
||||
# # manual tests should be run and the git release tagged and pushed.
|
||||
# # This is greped by the Makefile.
|
||||
# RELEASE_ARCHIVE=foo@somehost:tarball-archive
|
||||
#
|
||||
# # The key used to sign the GnuPG sources.
|
||||
# # This is greped by the Makefile.
|
||||
# RELEASE_SIGNKEY=6DAA6E64A76D2840571B4902528897B826403ADA
|
||||
#
|
||||
# # The key used to sign the VERSION files of some MSI installers.
|
||||
# VERSION_SIGNKEY=02F38DFF731FF97CB039A1DA549E695E905BA208
|
||||
#
|
||||
# # For signing Windows binaries we need to employ a Windows machine.
|
||||
# # We connect to this machine via ssh and take the connection
|
||||
# # parameters via .ssh/config. For example a VM could be specified
|
||||
# # like this:
|
||||
# #
|
||||
# # Host authenticode-signhost
|
||||
# # HostName localhost
|
||||
# # Port 27042
|
||||
# # User gpgsign
|
||||
# #
|
||||
# # Depending on the used token it might be necessary to allow single
|
||||
# # signon and unlock the token before running the make. The following
|
||||
# # variable references this entry. This is greped by the Makefile.
|
||||
# AUTHENTICODE_SIGNHOST=authenticode-signhost
|
||||
#
|
||||
# # The name of the signtool as used on Windows.
|
||||
# # This is greped by the Makefile.
|
||||
# AUTHENTICODE_TOOL="C:\Program Files (x86)\Windows Kits\10\bin\signtool.exe"
|
||||
#
|
||||
# # The URL for the timestamping service
|
||||
# AUTHENTICODE_TSURL=http://rfc3161timestamp.globalsign.com/advanced
|
||||
#
|
||||
# # To use osslsigncode the follwing entries are required and
|
||||
# # an empty string must be given for AUTHENTICODE_SIGNHOST.
|
||||
# # They are greped by the Makefile.
|
||||
# AUTHENTICODE_KEY=/home/foo/.gnupg/my-authenticode-key.p12
|
||||
# AUTHENTICODE_CERTS=/home/foo/.gnupg/my-authenticode-certs.pem
|
||||
#
|
||||
# # If a smartcard is used for the Authenticode signature these
|
||||
# # entries are required instead:
|
||||
# AUTHENTICODE_KEY=card
|
||||
# AUTHENTICODE_CERTS=/home/foo/.gnupg/my_authenticode_cert.pem
|
||||
# OSSLSIGNCODE=/usr/bin/osslsigncode
|
||||
# OSSLPKCS11ENGINE=/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so
|
||||
# SCUTEMODULE=/usr/local/lib/scute.so
|
||||
#
|
||||
#--8<---------------cut here---------------end--------------->8---
|
||||
# Use "gpg-authcode-sign.sh --template" to create a template.
|
||||
|
||||
|
||||
# We need to know our own name.
|
||||
|
@ -124,6 +73,7 @@ help:
|
|||
@echo 'Use WIXPREFIX to provide the WIX binaries for the MSI package.'
|
||||
@echo ' Using WIX also requires wine with installed wine mono.'
|
||||
@echo ' See help-wixlib for more information'
|
||||
@echo 'Set W32VERSION=w64 to build a 64 bit Windows version.'
|
||||
|
||||
help-wixlib:
|
||||
@echo 'The buildsystem can create a wixlib to build MSI packages.'
|
||||
|
@ -208,9 +158,12 @@ w32-release-offline: check-tools
|
|||
# to "this" from the unpacked sources.
|
||||
WHAT=git
|
||||
|
||||
# Set target to "native" or "w32"
|
||||
# Set target to "native" or "w32".
|
||||
TARGETOS=
|
||||
|
||||
# To build a 64 bit Windows version also change this to "w64"
|
||||
W32VERSION=w32
|
||||
|
||||
# Set to 1 to use a pre-installed swdb.lst instead of the online version.
|
||||
CUSTOM_SWDB=0
|
||||
|
||||
|
@ -231,29 +184,23 @@ TARBALLS=$(shell pwd)/../tarballs
|
|||
MAKE_J=6
|
||||
|
||||
# Name to use for the w32 installer and sources
|
||||
|
||||
|
||||
INST_NAME=gnupg-w32
|
||||
|
||||
# Use this to override the installaion directory for native builds.
|
||||
# Use this to override the installation directory for native builds.
|
||||
INSTALL_PREFIX=none
|
||||
|
||||
# Set this to the location of wixtools
|
||||
WIXPREFIX=$(shell readlink -f ~/w32root/wixtools)
|
||||
|
||||
# If patchelf(1) is not availale disable the command.
|
||||
# If patchelf(1) is not available disable the command.
|
||||
PATCHELF := $(shell patchelf --version 2>/dev/null >/dev/null || echo "echo please run: ")patchelf
|
||||
|
||||
# Read signing information from ~/.gnupg-autogen.rc
|
||||
define READ_AUTOGEN_template
|
||||
$(1) = $$(shell grep '^[[:blank:]]*$(1)[[:blank:]]*=' $$$$HOME/.gnupg-autogen.rc|cut -d= -f2|xargs)
|
||||
endef
|
||||
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_SIGNHOST))
|
||||
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_TOOL))
|
||||
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_TSURL))
|
||||
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_KEY))
|
||||
$(eval $(call READ_AUTOGEN_template,AUTHENTICODE_CERTS))
|
||||
$(eval $(call READ_AUTOGEN_template,OSSLSIGNCODE))
|
||||
$(eval $(call READ_AUTOGEN_template,OSSLPKCS11ENGINE))
|
||||
$(eval $(call READ_AUTOGEN_template,SCUTEMODULE))
|
||||
$(eval $(call READ_AUTOGEN_template,OVERRIDE_TARBALLS))
|
||||
|
||||
|
||||
|
@ -330,7 +277,12 @@ endif
|
|||
# Packages which are additionally build for 64 bit Windows. They are
|
||||
# only used for gpgex and thus we need to build them only if we want
|
||||
# a full installer.
|
||||
speedo_w64_spkgs =
|
||||
ifeq ($(W32VERSION),w64)
|
||||
# Keep this empty
|
||||
speedo_w64_spkgs =
|
||||
else
|
||||
speedo_w64_spkgs =
|
||||
endif
|
||||
|
||||
# Packages which use the gnupg autogen.sh build style
|
||||
speedo_gnupg_style = \
|
||||
|
@ -362,7 +314,7 @@ endif
|
|||
# Version numbers of the released packages
|
||||
gnupg_ver_this = $(shell cat $(topsrc)/VERSION)
|
||||
|
||||
gnupg_ver := $(shell awk '$$1=="gnupg24_ver" {print $$2}' swdb.lst)
|
||||
gnupg_ver := $(shell awk '$$1=="gnupg26_ver" {print $$2}' swdb.lst)
|
||||
|
||||
libgpg_error_ver := $(shell awk '$$1=="libgpg_error_ver" {print $$2}' swdb.lst)
|
||||
libgpg_error_sha1:= $(shell awk '$$1=="libgpg_error_sha1" {print $$2}' swdb.lst)
|
||||
|
@ -409,7 +361,7 @@ sqlite_sha1 := $(shell awk '$$1=="sqlite_sha1_gz" {print $$2}' swdb.lst)
|
|||
sqlite_sha2 := $(shell awk '$$1=="sqlite_sha2_gz" {print $$2}' swdb.lst)
|
||||
|
||||
|
||||
$(info Information from the version database)
|
||||
$(info Information from the version database:)
|
||||
$(info GnuPG ..........: $(gnupg_ver) (building $(gnupg_ver_this)))
|
||||
$(info GpgRT ..........: $(libgpg_error_ver))
|
||||
$(info Npth ...........: $(npth_ver))
|
||||
|
@ -424,6 +376,21 @@ $(info GPGME ..........: $(gpgme_ver))
|
|||
$(info Pinentry .......: $(pinentry_ver))
|
||||
endif
|
||||
|
||||
$(info Information for this run:)
|
||||
$(info Build type .....: $(WHAT))
|
||||
$(info Target .........: $(TARGETOS))
|
||||
ifeq ($(TARGETOS),w32)
|
||||
ifeq ($(W32VERSION),w64)
|
||||
$(info Windows version : 64 bit)
|
||||
else
|
||||
$(info Windows version : 32 bit)
|
||||
ifneq ($(W32VERSION),w32)
|
||||
$(error W32VERSION is not set to a proper value: Use only w32 or w64)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
# Version number for external packages
|
||||
pkg_config_ver = 0.23
|
||||
libiconv_ver = 1.14
|
||||
|
@ -514,8 +481,8 @@ speedo_pkg_gettext_tar = $(pkg2rep)/gettext-$(gettext_ver).tar.gz
|
|||
|
||||
speedo_pkg_npth_configure = --enable-static
|
||||
|
||||
speedo_pkg_libgpg_error_configure = --enable-static --enable-install-gpg-error-config
|
||||
speedo_pkg_w64_libgpg_error_configure = --enable-static --enable-install-gpg-error-config
|
||||
speedo_pkg_libgpg_error_configure = --enable-static
|
||||
speedo_pkg_w64_libgpg_error_configure = --enable-static
|
||||
|
||||
speedo_pkg_libassuan_configure = --enable-static
|
||||
speedo_pkg_w64_libassuan_configure = --enable-static
|
||||
|
@ -651,12 +618,21 @@ report: report-speedo
|
|||
|
||||
clean: clean-speedo
|
||||
|
||||
|
||||
ifeq ($(W32VERSION),w64)
|
||||
W32CC_PREFIX = x86_64
|
||||
else
|
||||
W32CC_PREFIX = i686
|
||||
endif
|
||||
|
||||
ifeq ($(TARGETOS),w32)
|
||||
STRIP = i686-w64-mingw32-strip
|
||||
STRIP = $(W32CC_PREFIX)-w64-mingw32-strip
|
||||
W32STRIP32 = i686-w64-mingw32-strip
|
||||
else
|
||||
STRIP = strip
|
||||
endif
|
||||
W32CC = i686-w64-mingw32-gcc
|
||||
W32CC = $(W32CC_PREFIX)-w64-mingw32-gcc
|
||||
W32CC32 = i686-w64-mingw32-gcc
|
||||
|
||||
-include config.mk
|
||||
|
||||
|
@ -698,9 +674,9 @@ ifneq ($(TARGETOS),)
|
|||
# Determine build and host system
|
||||
build := $(shell $(topsrc)/autogen.sh --silent --print-build)
|
||||
ifeq ($(TARGETOS),w32)
|
||||
speedo_autogen_buildopt := --build-w32
|
||||
speedo_autogen_buildopt := --build-$(W32VERSION)
|
||||
speedo_autogen_buildopt6 := --build-w64
|
||||
host := $(shell $(topsrc)/autogen.sh --silent --print-host --build-w32)
|
||||
host := $(shell $(topsrc)/autogen.sh --silent --print-host --build-$(W32VERSION))
|
||||
host6:= $(shell $(topsrc)/autogen.sh --silent --print-host --build-w64)
|
||||
speedo_host_build_option := --host=$(host) --build=$(build)
|
||||
speedo_host_build_option6 := --host=$(host6) --build=$(build)
|
||||
|
@ -924,7 +900,7 @@ else ifneq ($(findstring $(1),$(speedo_gnupg_style)),)
|
|||
mkdir "$$$${pkgbdir}"; \
|
||||
cd "$$$${pkgbdir}"; \
|
||||
if [ -n "$(speedo_autogen_buildopt)" ]; then \
|
||||
eval AUTOGEN_SH_SILENT=1 w32root="$(idir)" \
|
||||
eval AUTOGEN_SH_SILENT=1 $(W32VERSION)root="$(idir)" \
|
||||
"$$$${pkgsdir}/autogen.sh" \
|
||||
$(speedo_autogen_buildopt) \
|
||||
$$$${pkgcfg} $$$${pkgextracflags}; \
|
||||
|
@ -1133,8 +1109,8 @@ ifneq ($(TARGETOS),w32)
|
|||
echo "speedo: * Now copy $(idir)/ to the final location and" ;\
|
||||
echo "speedo: * adjust $(idir)/bin/gpgconf.ctl accordingly" ;\
|
||||
echo "speedo: * Or run:" ;\
|
||||
echo "speedo: * make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24" ;\
|
||||
echo "speedo: * ldconfig -n /usr/local/gnupg24/lib";\
|
||||
echo "speedo: * make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg26" ;\
|
||||
echo "speedo: * ldconfig -n /usr/local/gnupg26/lib";\
|
||||
echo "speedo: */")
|
||||
endif
|
||||
|
||||
|
@ -1149,8 +1125,8 @@ ifneq ($(TARGETOS),w32)
|
|||
echo "speedo: ERROR: SYSROOT has not been given";\
|
||||
echo "speedo: Set SYSROOT to the desired install directory";\
|
||||
echo "speedo: Example:";\
|
||||
echo "speedo: make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg24";\
|
||||
echo "speedo: ldconfig -n /usr/local/gnupg24/lib";\
|
||||
echo "speedo: make -f $(topsrc)/build-aux/speedo.mk install SYSROOT=/usr/local/gnupg26";\
|
||||
echo "speedo: ldconfig -n /usr/local/gnupg26/lib";\
|
||||
exit 1;\
|
||||
fi;\
|
||||
if [ ! -d "$$SYSROOT"/bin ]; then if ! mkdir "$$SYSROOT"/bin; then \
|
||||
|
@ -1238,13 +1214,13 @@ $(bdir)/README.txt: $(bdir)/NEWS.tmp $(topsrc)/README $(w32src)/README.txt \
|
|||
|
||||
$(bdir)/g4wihelp.dll: $(w32src)/g4wihelp.c $(w32src)/exdll.h $(w32src)/exdll.c
|
||||
(set -e; cd $(bdir); \
|
||||
$(W32CC) -DUNICODE -static-libgcc -I . -O2 -c \
|
||||
$(W32CC32) -DUNICODE -static-libgcc -I . -O2 -c \
|
||||
-o exdll.o $(w32src)/exdll.c; \
|
||||
$(W32CC) -DUNICODE -static-libgcc -I. -shared -O2 \
|
||||
$(W32CC32) -DUNICODE -static-libgcc -I. -shared -O2 \
|
||||
-o g4wihelp.dll $(w32src)/g4wihelp.c exdll.o \
|
||||
-lwinmm -lgdi32 -luserenv \
|
||||
-lshell32 -loleaut32 -lshlwapi -lmsimg32; \
|
||||
$(STRIP) g4wihelp.dll)
|
||||
$(W32STRIP32) g4wihelp.dll)
|
||||
|
||||
w32_insthelpers: $(bdir)/g4wihelp.dll
|
||||
|
||||
|
@ -1340,7 +1316,7 @@ wixlib: installer $(bdir)/README.txt $(w32src)/wixlib.wxs
|
|||
)
|
||||
|
||||
define MKSWDB_commands
|
||||
( pref="#+macro: gnupg24_w32_$(3)" ;\
|
||||
( pref="#+macro: gnupg26_w32_$(3)" ;\
|
||||
echo "$${pref}ver $(INST_VERSION)_$(BUILD_DATESTR)" ;\
|
||||
echo "$${pref}date $(2)" ;\
|
||||
echo "$${pref}size $$(wc -c <$(1)|awk '{print int($$1/1024)}')k";\
|
||||
|
@ -1351,35 +1327,13 @@ endef
|
|||
|
||||
# Sign the file $1 and save the result as $2
|
||||
define AUTHENTICODE_sign
|
||||
set -e;\
|
||||
if [ -n "$(AUTHENTICODE_SIGNHOST)" ]; then \
|
||||
echo "speedo: Signing via host $(AUTHENTICODE_SIGNHOST)";\
|
||||
scp $(1) "$(AUTHENTICODE_SIGNHOST):a.exe" ;\
|
||||
ssh "$(AUTHENTICODE_SIGNHOST)" '$(AUTHENTICODE_TOOL)' sign \
|
||||
/a /n '"g10 Code GmbH"' \
|
||||
/tr '$(AUTHENTICODE_TSURL)' /td sha256 \
|
||||
/fd sha256 /du https://gnupg.org a.exe ;\
|
||||
scp "$(AUTHENTICODE_SIGNHOST):a.exe" $(2);\
|
||||
echo "speedo: signed file is '$(2)'" ;\
|
||||
elif [ "$(AUTHENTICODE_KEY)" = card ]; then \
|
||||
echo "speedo: Signing using a card: '$(1)'";\
|
||||
$(OSSLSIGNCODE) sign \
|
||||
-pkcs11engine $(OSSLPKCS11ENGINE) \
|
||||
-pkcs11module $(SCUTEMODULE) \
|
||||
-certs $(AUTHENTICODE_CERTS) \
|
||||
-h sha256 -n GnuPG -i https://gnupg.org \
|
||||
-ts $(AUTHENTICODE_TSURL) \
|
||||
-in $(1) -out $(2).tmp ; mv $(2).tmp $(2) ; \
|
||||
elif [ -e "$(AUTHENTICODE_KEY)" ]; then \
|
||||
echo "speedo: Signing using key $(AUTHENTICODE_KEY)";\
|
||||
osslsigncode sign -certs $(AUTHENTICODE_CERTS) \
|
||||
-pkcs12 $(AUTHENTICODE_KEY) -askpass \
|
||||
-ts "$(AUTHENTICODE_TSURL)" \
|
||||
-h sha256 -n GnuPG -i https://gnupg.org \
|
||||
-in $(1) -out $(2) ;\
|
||||
(set -e; \
|
||||
if gpg-authcode-sign.sh --version >/dev/null; then \
|
||||
gpg-authcode-sign.sh "$(1)" "$(2)"; \
|
||||
else \
|
||||
echo "speedo: WARNING: Binaries are not signed"; \
|
||||
fi
|
||||
echo 2>&1 "warning: Please install gpg-authcode-sign.sh to sign files." ;\
|
||||
[ "$(1)" != "$(2)" ] && cp "$(1)" "$(2)" ;\
|
||||
fi)
|
||||
endef
|
||||
|
||||
# Help target for testing to sign a file.
|
||||
|
@ -1447,7 +1401,7 @@ endif
|
|||
|
||||
|
||||
#
|
||||
# Check availibility of standard tools and prepare everything.
|
||||
# Check availability of standard tools and prepare everything.
|
||||
#
|
||||
check-tools: $(stampdir)/stamp-directories
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ Below is the README file as distributed with the GnuPG source.
|
|||
4. Software Versions of the Included Packages
|
||||
=============================================
|
||||
|
||||
GnuPG for Windows depends on several independet developed packages
|
||||
GnuPG for Windows depends on several independent developed packages
|
||||
which are part of the installation. These packages along with their
|
||||
version numbers and the SHA-1 checksums of their compressed tarballs
|
||||
are listed here:
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
************************************************************
|
||||
* The code for the splash screen has been taken from the Splash
|
||||
* plugin of the NSIS 2.04 distribution. That code comes without
|
||||
* explicit copyright notices in tyhe source files or author names, it
|
||||
* explicit copyright notices in the source files or author names, it
|
||||
* seems that it has been written by Justin Frankel; not sure about
|
||||
* the year, though. [wk 2005-11-28]
|
||||
*
|
||||
|
|
|
@ -46,7 +46,7 @@ Unicode true
|
|||
!define PRETTY_PACKAGE "GNU Privacy Guard"
|
||||
!define PRETTY_PACKAGE_SHORT "GnuPG"
|
||||
!define COMPANY "The GnuPG Project"
|
||||
!define COPYRIGHT "Copyright (C) 2021 g10 Code GmbH"
|
||||
!define COPYRIGHT "Copyright (C) 2024 g10 Code GmbH"
|
||||
!define DESCRIPTION "GnuPG: The GNU Privacy Guard for Windows"
|
||||
|
||||
!define INSTALL_DIR "GnuPG"
|
||||
|
@ -63,13 +63,13 @@ Unicode true
|
|||
GnuPG includes an advanced key management facility and is compliant \
|
||||
with the OpenPGP Internet standard as described in RFC-4880. \
|
||||
\r\n\r\n$_CLICK \
|
||||
\r\n\r\n\r\n\r\n\r\nThis is GnuPG version ${VERSION}.\r\n\
|
||||
\r\n\r\n\r\n\r\n\r\nThis is GnuPG version ${VERSION} (64 bit).\r\n\
|
||||
File version: ${PROD_VERSION}\r\n\
|
||||
Release date: ${BUILD_ISODATE}"
|
||||
!define ABOUT_GERMAN \
|
||||
"GnuPG is die häufigst verwendete Software zur Mail- und Datenverschlüsselung.\
|
||||
\r\n\r\n$_CLICK \
|
||||
\r\n\r\n\r\n\r\n\r\nDies ist GnuPG Version ${VERSION}.\r\n\
|
||||
\r\n\r\n\r\n\r\n\r\nDies ist GnuPG Version ${VERSION} (64 bit).\r\n\
|
||||
Dateiversion: ${PROD_VERSION}\r\n\
|
||||
Releasedatum: ${BUILD_ISODATE}"
|
||||
|
||||
|
@ -119,7 +119,7 @@ OutFile "${NAME}-${VERSION}_${BUILD_DATESTR}.exe"
|
|||
!ifndef INSTALL_DIR
|
||||
!define INSTALL_DIR "GnuPG"
|
||||
!endif
|
||||
InstallDir "$PROGRAMFILES\${INSTALL_DIR}"
|
||||
InstallDir "$PROGRAMFILES64\${INSTALL_DIR}"
|
||||
|
||||
# Add version information to the file properties.
|
||||
VIProductVersion "${PROD_VERSION}"
|
||||
|
@ -1465,7 +1465,12 @@ Function .onInit
|
|||
|
||||
Call G4wRunOnce
|
||||
|
||||
SetOutPath $TEMP
|
||||
${IfNot} ${RunningX64}
|
||||
MessageBox MB_OK "Sorry this version runs only on x64 machines"
|
||||
Abort
|
||||
${EndIf}
|
||||
|
||||
SetOutPath $TEMP
|
||||
#!ifdef SOURCES
|
||||
# File /oname=gpgspltmp.bmp "${TOP_SRCDIR}/doc/logo/gnupg-logo-400px.bmp"
|
||||
# # We play the tune only for the soruce installer
|
||||
|
@ -1486,7 +1491,7 @@ Function .onInit
|
|||
|
||||
Var /GLOBAL changed_dir
|
||||
# Check if the install directory was modified on the command line
|
||||
StrCmp "$INSTDIR" "$PROGRAMFILES\${INSTALL_DIR}" unmodified 0
|
||||
StrCmp "$INSTDIR" "$PROGRAMFILES64\${INSTALL_DIR}" unmodified 0
|
||||
# It is modified. Save that value.
|
||||
StrCpy $changed_dir "$INSTDIR"
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ common_sources = \
|
|||
homedir.c \
|
||||
gettime.c gettime.h \
|
||||
yesno.c \
|
||||
b64enc.c b64dec.c zb32.c zb32.h \
|
||||
zb32.c zb32.h \
|
||||
convert.c \
|
||||
percent.c \
|
||||
mbox-util.c mbox-util.h \
|
||||
|
@ -97,8 +97,8 @@ common_sources = \
|
|||
openpgp-fpr.c \
|
||||
comopt.c comopt.h \
|
||||
compliance.c compliance.h \
|
||||
pkscreening.c pkscreening.h
|
||||
|
||||
pkscreening.c pkscreening.h \
|
||||
kem.c
|
||||
|
||||
if HAVE_W32_SYSTEM
|
||||
common_sources += w32-reg.c w32-cmdline.c
|
||||
|
@ -161,11 +161,12 @@ module_tests = t-stringhelp t-timestuff \
|
|||
t-convert t-percent t-gettime t-sysutils t-sexputil \
|
||||
t-session-env t-openpgp-oid t-ssh-utils \
|
||||
t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \
|
||||
t-name-value t-ccparray t-recsel t-w32-cmdline t-b64
|
||||
t-name-value t-ccparray t-recsel t-w32-cmdline t-exechelp
|
||||
|
||||
if HAVE_W32_SYSTEM
|
||||
module_tests += t-w32-reg
|
||||
else
|
||||
module_tests += t-exechelp t-exectool
|
||||
module_tests += t-exectool
|
||||
endif
|
||||
|
||||
if MAINTAINER_MODE
|
||||
|
@ -196,7 +197,6 @@ t_gettime_LDADD = $(t_common_ldadd)
|
|||
t_sysutils_LDADD = $(t_common_ldadd)
|
||||
t_helpfile_LDADD = $(t_common_ldadd)
|
||||
t_sexputil_LDADD = $(t_common_ldadd)
|
||||
t_b64_LDADD = $(t_common_ldadd)
|
||||
t_exechelp_LDADD = $(t_common_ldadd)
|
||||
t_exectool_LDADD = $(t_common_ldadd)
|
||||
t_session_env_LDADD = $(t_common_ldadd)
|
||||
|
|
|
@ -386,7 +386,8 @@ start_new_service (assuan_context_t *r_ctx,
|
|||
const char *opt_lc_ctype,
|
||||
const char *opt_lc_messages,
|
||||
session_env_t session_env,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg)
|
||||
{
|
||||
|
@ -445,7 +446,7 @@ start_new_service (assuan_context_t *r_ctx,
|
|||
}
|
||||
|
||||
err = assuan_socket_connect (ctx, sockname, 0, connect_flags);
|
||||
if (err && autostart)
|
||||
if (err && (flags & ASSHELP_FLAG_AUTOSTART))
|
||||
{
|
||||
char *abs_homedir;
|
||||
lock_spawn_t lock;
|
||||
|
@ -523,16 +524,11 @@ start_new_service (assuan_context_t *r_ctx,
|
|||
&& assuan_socket_connect (ctx, sockname, 0, connect_flags))
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
err = gnupg_spawn_process_detached (program? program : program_name,
|
||||
argv, NULL);
|
||||
err = gnupg_process_spawn (program? program : program_name, argv,
|
||||
GNUPG_PROCESS_DETACHED, NULL, NULL);
|
||||
#else /*!W32*/
|
||||
pid_t pid;
|
||||
|
||||
err = gnupg_spawn_process_fd (program? program : program_name,
|
||||
argv, -1, -1, -1, &pid);
|
||||
if (!err)
|
||||
err = gnupg_wait_process (program? program : program_name,
|
||||
pid, 1, NULL);
|
||||
err = gnupg_process_spawn (program? program : program_name, argv,
|
||||
0, NULL, NULL);
|
||||
#endif /*!W32*/
|
||||
if (err)
|
||||
log_error ("failed to start %s '%s': %s\n",
|
||||
|
@ -551,7 +547,8 @@ start_new_service (assuan_context_t *r_ctx,
|
|||
xfree (sockname);
|
||||
if (err)
|
||||
{
|
||||
if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
|
||||
if ((flags & ASSHELP_FLAG_AUTOSTART)
|
||||
|| gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
|
||||
log_error ("can't connect to the %s: %s\n",
|
||||
printed_name, gpg_strerror (err));
|
||||
assuan_release (ctx);
|
||||
|
@ -603,55 +600,58 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
|
|||
const char *opt_lc_ctype,
|
||||
const char *opt_lc_messages,
|
||||
session_env_t session_env,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg)
|
||||
{
|
||||
return start_new_service (r_ctx, GNUPG_MODULE_NAME_AGENT,
|
||||
errsource, agent_program,
|
||||
opt_lc_ctype, opt_lc_messages, session_env,
|
||||
autostart, verbose, debug,
|
||||
flags, verbose, debug,
|
||||
status_cb, status_cb_arg);
|
||||
}
|
||||
|
||||
|
||||
/* Try to connect to the dirmngr via a socket. On platforms
|
||||
supporting it, start it up if needed and if AUTOSTART is true.
|
||||
supporting it, start it up if needed and if ASSHELP_FLAG_AUTOSTART is set.
|
||||
Returns a new assuan context at R_CTX or an error code. */
|
||||
gpg_error_t
|
||||
start_new_keyboxd (assuan_context_t *r_ctx,
|
||||
gpg_err_source_t errsource,
|
||||
const char *keyboxd_program,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg)
|
||||
{
|
||||
return start_new_service (r_ctx, GNUPG_MODULE_NAME_KEYBOXD,
|
||||
errsource, keyboxd_program,
|
||||
NULL, NULL, NULL,
|
||||
autostart, verbose, debug,
|
||||
flags, verbose, debug,
|
||||
status_cb, status_cb_arg);
|
||||
}
|
||||
|
||||
|
||||
/* Try to connect to the dirmngr via a socket. On platforms
|
||||
supporting it, start it up if needed and if AUTOSTART is true.
|
||||
supporting it, start it up if needed and if ASSHELP_FLAG_AUTOSTART is set.
|
||||
Returns a new assuan context at R_CTX or an error code. */
|
||||
gpg_error_t
|
||||
start_new_dirmngr (assuan_context_t *r_ctx,
|
||||
gpg_err_source_t errsource,
|
||||
const char *dirmngr_program,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg)
|
||||
{
|
||||
#ifndef USE_DIRMNGR_AUTO_START
|
||||
autostart = 0;
|
||||
flags &= ~ASSHELP_FLAG_AUTOSTART; /* Clear flag. */
|
||||
#endif
|
||||
return start_new_service (r_ctx, GNUPG_MODULE_NAME_DIRMNGR,
|
||||
errsource, dirmngr_program,
|
||||
NULL, NULL, NULL,
|
||||
autostart, verbose, debug,
|
||||
flags, verbose, debug,
|
||||
status_cb, status_cb_arg);
|
||||
}
|
||||
|
||||
|
@ -695,7 +695,7 @@ get_assuan_server_version (assuan_context_t ctx, int mode, char **r_version)
|
|||
|
||||
/* Print a warning if the server's version number is less than our
|
||||
* version number. Returns an error code on a connection problem.
|
||||
* CTX is the Assuan context, SERVERNAME is the name of teh server,
|
||||
* CTX is the Assuan context, SERVERNAME is the name of the server,
|
||||
* STATUS_FUNC and STATUS_FUNC_DATA is a callback to emit status
|
||||
* messages. If PRINT_HINTS is set additional hints are printed. For
|
||||
* MODE see get_assuan_server_version. */
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "util.h"
|
||||
|
||||
/*-- asshelp.c --*/
|
||||
#define ASSHELP_FLAG_AUTOSTART 1 /* Autostart the new service. */
|
||||
|
||||
|
||||
void setup_libassuan_logging (unsigned int *debug_var_address,
|
||||
int (*log_monitor)(assuan_context_t ctx,
|
||||
|
@ -61,7 +63,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
|
|||
const char *opt_lc_ctype,
|
||||
const char *opt_lc_messages,
|
||||
session_env_t session_env,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg);
|
||||
|
||||
|
@ -71,7 +74,8 @@ gpg_error_t
|
|||
start_new_keyboxd (assuan_context_t *r_ctx,
|
||||
gpg_err_source_t errsource,
|
||||
const char *keyboxd_program,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg);
|
||||
|
||||
|
@ -81,7 +85,8 @@ gpg_error_t
|
|||
start_new_dirmngr (assuan_context_t *r_ctx,
|
||||
gpg_err_source_t errsource,
|
||||
const char *dirmngr_program,
|
||||
int autostart, int verbose, int debug,
|
||||
unsigned int flags,
|
||||
int verbose, int debug,
|
||||
gpg_error_t (*status_cb)(ctrl_t, int, ...),
|
||||
ctrl_t status_cb_arg);
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ struct log_item_s
|
|||
gpg_error_t err; /* The logged error code. */
|
||||
int intvalue; /* A logged integer value. */
|
||||
char *string; /* A malloced string or NULL. */
|
||||
ksba_cert_t cert; /* A certifciate or NULL. */
|
||||
int have_err:1;
|
||||
int have_intvalue:1;
|
||||
ksba_cert_t cert; /* A certificate or NULL. */
|
||||
unsigned int have_err:1;
|
||||
unsigned int have_intvalue:1;
|
||||
};
|
||||
typedef struct log_item_s *log_item_t;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ typedef enum
|
|||
/* The signature is a detached one. */
|
||||
|
||||
AUDIT_CERT_ONLY_SIG,
|
||||
/* A certifciate only signature has been detected. */
|
||||
/* A certificate only signature has been detected. */
|
||||
|
||||
AUDIT_DATA_HASH_ALGO, /* int */
|
||||
/* The hash algo given as argument is used for the data. This
|
||||
|
|
299
common/b64dec.c
299
common/b64dec.c
|
@ -1,299 +0,0 @@
|
|||
/* b64dec.c - Simple Base64 decoder.
|
||||
* Copyright (C) 2008, 2011 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2008, 2011, 2016 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/* The reverse base-64 list used for base-64 decoding. */
|
||||
static unsigned char const asctobin[128] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
enum decoder_states
|
||||
{
|
||||
s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
|
||||
s_b64_0, s_b64_1, s_b64_2, s_b64_3,
|
||||
s_waitendtitle, s_waitend
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Initialize the context for the base64 decoder. If TITLE is NULL a
|
||||
plain base64 decoding is done. If it is the empty string the
|
||||
decoder will skip everything until a "-----BEGIN " line has been
|
||||
seen, decoding ends at a "----END " line. */
|
||||
gpg_error_t
|
||||
b64dec_start (struct b64state *state, const char *title)
|
||||
{
|
||||
memset (state, 0, sizeof *state);
|
||||
if (title)
|
||||
{
|
||||
state->title = xtrystrdup (title);
|
||||
if (!state->title)
|
||||
state->lasterr = gpg_error_from_syserror ();
|
||||
else
|
||||
state->idx = s_init;
|
||||
}
|
||||
else
|
||||
state->idx = s_b64_0;
|
||||
return state->lasterr;
|
||||
}
|
||||
|
||||
|
||||
/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
|
||||
new length of the buffer at R_NBYTES. */
|
||||
gpg_error_t
|
||||
b64dec_proc (struct b64state *state, void *buffer, size_t length,
|
||||
size_t *r_nbytes)
|
||||
{
|
||||
enum decoder_states ds = state->idx;
|
||||
unsigned char val = state->radbuf[0];
|
||||
int pos = state->quad_count;
|
||||
char *d, *s;
|
||||
|
||||
if (state->lasterr)
|
||||
return state->lasterr;
|
||||
|
||||
if (state->stop_seen)
|
||||
{
|
||||
*r_nbytes = 0;
|
||||
state->lasterr = gpg_error (GPG_ERR_EOF);
|
||||
xfree (state->title);
|
||||
state->title = NULL;
|
||||
return state->lasterr;
|
||||
}
|
||||
|
||||
for (s=d=buffer; length && !state->stop_seen; length--, s++)
|
||||
{
|
||||
again:
|
||||
switch (ds)
|
||||
{
|
||||
case s_idle:
|
||||
if (*s == '\n')
|
||||
{
|
||||
ds = s_lfseen;
|
||||
pos = 0;
|
||||
}
|
||||
break;
|
||||
case s_init:
|
||||
ds = s_lfseen;
|
||||
/* fall through */
|
||||
case s_lfseen:
|
||||
if (*s != "-----BEGIN "[pos])
|
||||
{
|
||||
ds = s_idle;
|
||||
goto again;
|
||||
}
|
||||
else if (pos == 10)
|
||||
{
|
||||
pos = 0;
|
||||
ds = s_beginseen;
|
||||
}
|
||||
else
|
||||
pos++;
|
||||
break;
|
||||
case s_beginseen:
|
||||
if (*s != "PGP "[pos])
|
||||
ds = s_begin; /* Not a PGP armor. */
|
||||
else if (pos == 3)
|
||||
ds = s_waitheader;
|
||||
else
|
||||
pos++;
|
||||
break;
|
||||
case s_waitheader:
|
||||
if (*s == '\n')
|
||||
ds = s_waitblank;
|
||||
break;
|
||||
case s_waitblank:
|
||||
if (*s == '\n')
|
||||
ds = s_b64_0; /* blank line found. */
|
||||
else if (*s == ' ' || *s == '\r' || *s == '\t')
|
||||
; /* Ignore spaces. */
|
||||
else
|
||||
{
|
||||
/* Armor header line. Note that we don't care that our
|
||||
* FSM accepts a header prefixed with spaces. */
|
||||
ds = s_waitheader; /* Wait for next header. */
|
||||
}
|
||||
break;
|
||||
case s_begin:
|
||||
if (*s == '\n')
|
||||
ds = s_b64_0;
|
||||
break;
|
||||
case s_b64_0:
|
||||
case s_b64_1:
|
||||
case s_b64_2:
|
||||
case s_b64_3:
|
||||
{
|
||||
int c;
|
||||
|
||||
if (*s == '-' && state->title)
|
||||
{
|
||||
/* Not a valid Base64 character: assume end
|
||||
header. */
|
||||
ds = s_waitend;
|
||||
}
|
||||
else if (*s == '=')
|
||||
{
|
||||
/* Pad character: stop */
|
||||
if (ds == s_b64_1)
|
||||
*d++ = val;
|
||||
ds = state->title? s_waitendtitle : s_waitend;
|
||||
}
|
||||
else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
|
||||
; /* Skip white spaces. */
|
||||
else if ( (*s & 0x80)
|
||||
|| (c = asctobin[*(unsigned char *)s]) == 255)
|
||||
{
|
||||
/* Skip invalid encodings. */
|
||||
state->invalid_encoding = 1;
|
||||
}
|
||||
else if (ds == s_b64_0)
|
||||
{
|
||||
val = c << 2;
|
||||
ds = s_b64_1;
|
||||
}
|
||||
else if (ds == s_b64_1)
|
||||
{
|
||||
val |= (c>>4)&3;
|
||||
*d++ = val;
|
||||
val = (c<<4)&0xf0;
|
||||
ds = s_b64_2;
|
||||
}
|
||||
else if (ds == s_b64_2)
|
||||
{
|
||||
val |= (c>>2)&15;
|
||||
*d++ = val;
|
||||
val = (c<<6)&0xc0;
|
||||
ds = s_b64_3;
|
||||
}
|
||||
else
|
||||
{
|
||||
val |= c&0x3f;
|
||||
*d++ = val;
|
||||
ds = s_b64_0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case s_waitendtitle:
|
||||
if (*s == '-')
|
||||
ds = s_waitend;
|
||||
break;
|
||||
case s_waitend:
|
||||
if ( *s == '\n')
|
||||
state->stop_seen = 1;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
state->idx = ds;
|
||||
state->radbuf[0] = val;
|
||||
state->quad_count = pos;
|
||||
*r_nbytes = (d -(char*) buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* This function needs to be called before releasing the decoder
|
||||
state. It may return an error code in case an encoding error has
|
||||
been found during decoding. */
|
||||
gpg_error_t
|
||||
b64dec_finish (struct b64state *state)
|
||||
{
|
||||
xfree (state->title);
|
||||
state->title = NULL;
|
||||
|
||||
if (state->lasterr)
|
||||
return state->lasterr;
|
||||
|
||||
return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert STRING consisting of base64 characters into its binary
|
||||
* representation and store the result in a newly allocated buffer at
|
||||
* R_BUFFER with its length at R_BUFLEN. If TITLE is NULL a plain
|
||||
* base64 decoding is done. If it is the empty string the decoder
|
||||
* will skip everything until a "-----BEGIN " line has been seen,
|
||||
* decoding then ends at a "----END " line. On failure the function
|
||||
* returns an error code and sets R_BUFFER to NULL. If the decoded
|
||||
* data has a length of 0 a dummy buffer will still be allocated and
|
||||
* the length is set to 0. */
|
||||
gpg_error_t
|
||||
b64decode (const char *string, const char *title,
|
||||
void **r_buffer, size_t *r_buflen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state state;
|
||||
size_t nbytes;
|
||||
char *buffer;
|
||||
|
||||
*r_buffer = NULL;
|
||||
*r_buflen = 0;
|
||||
|
||||
buffer = xtrystrdup (string);
|
||||
if (!buffer)
|
||||
return gpg_error_from_syserror();
|
||||
|
||||
err = b64dec_start (&state, title);
|
||||
if (err)
|
||||
{
|
||||
xfree (buffer);
|
||||
return err;
|
||||
}
|
||||
b64dec_proc (&state, buffer, strlen (buffer), &nbytes);
|
||||
err = b64dec_finish (&state);
|
||||
if (err)
|
||||
xfree (buffer);
|
||||
else
|
||||
{
|
||||
*r_buffer = buffer;
|
||||
*r_buflen = nbytes;
|
||||
}
|
||||
return err;
|
||||
}
|
423
common/b64enc.c
423
common/b64enc.c
|
@ -1,423 +0,0 @@
|
|||
/* b64enc.c - Simple Base64 encoder.
|
||||
* Copyright (C) 2001, 2003, 2004, 2008, 2010,
|
||||
* 2011 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2001, 2003, 2004, 2008, 2010,
|
||||
* 2011 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include "util.h"
|
||||
|
||||
#define B64ENC_DID_HEADER 1
|
||||
#define B64ENC_DID_TRAILER 2
|
||||
#define B64ENC_NO_LINEFEEDS 16
|
||||
#define B64ENC_USE_PGPCRC 32
|
||||
|
||||
/* The base-64 character list */
|
||||
static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
/* Stuff required to create the OpenPGP CRC. This crc_table has been
|
||||
created using this code:
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define CRCPOLY 0x864CFB
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int i, j;
|
||||
uint32_t t;
|
||||
uint32_t crc_table[256];
|
||||
|
||||
crc_table[0] = 0;
|
||||
for (i=j=0; j < 128; j++ )
|
||||
{
|
||||
t = crc_table[j];
|
||||
if ( (t & 0x00800000) )
|
||||
{
|
||||
t <<= 1;
|
||||
crc_table[i++] = t ^ CRCPOLY;
|
||||
crc_table[i++] = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
t <<= 1;
|
||||
crc_table[i++] = t;
|
||||
crc_table[i++] = t ^ CRCPOLY;
|
||||
}
|
||||
}
|
||||
|
||||
puts ("static const u32 crc_table[256] = {");
|
||||
for (i=j=0; i < 256; i++)
|
||||
{
|
||||
printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]);
|
||||
if (i != 255)
|
||||
{
|
||||
putchar (',');
|
||||
if ( ++j > 5)
|
||||
{
|
||||
j = 0;
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
puts ("\n};");
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
#define CRCINIT 0xB704CE
|
||||
static const u32 crc_table[256] = {
|
||||
0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a,
|
||||
0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf,
|
||||
0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272,
|
||||
0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e,
|
||||
0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa,
|
||||
0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f,
|
||||
0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b,
|
||||
0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7,
|
||||
0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a,
|
||||
0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af,
|
||||
0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29,
|
||||
0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5,
|
||||
0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1,
|
||||
0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad,
|
||||
0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099,
|
||||
0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375,
|
||||
0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821,
|
||||
0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4,
|
||||
0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049,
|
||||
0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5,
|
||||
0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791,
|
||||
0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52,
|
||||
0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66,
|
||||
0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a,
|
||||
0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337,
|
||||
0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2,
|
||||
0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6,
|
||||
0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a,
|
||||
0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e,
|
||||
0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132,
|
||||
0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506,
|
||||
0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea,
|
||||
0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c,
|
||||
0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9,
|
||||
0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604,
|
||||
0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8,
|
||||
0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc,
|
||||
0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69,
|
||||
0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d,
|
||||
0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1,
|
||||
0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
|
||||
0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9,
|
||||
0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538
|
||||
};
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
enc_start (struct b64state *state, FILE *fp, estream_t stream,
|
||||
const char *title)
|
||||
{
|
||||
memset (state, 0, sizeof *state);
|
||||
state->fp = fp;
|
||||
state->stream = stream;
|
||||
state->lasterr = 0;
|
||||
if (title && !*title)
|
||||
state->flags |= B64ENC_NO_LINEFEEDS;
|
||||
else if (title)
|
||||
{
|
||||
if (!strncmp (title, "PGP ", 4))
|
||||
{
|
||||
state->flags |= B64ENC_USE_PGPCRC;
|
||||
state->crc = CRCINIT;
|
||||
}
|
||||
state->title = xtrystrdup (title);
|
||||
if (!state->title)
|
||||
state->lasterr = gpg_error_from_syserror ();
|
||||
}
|
||||
return state->lasterr;
|
||||
}
|
||||
|
||||
|
||||
/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL
|
||||
and not an empty string, this string will be used as the title for
|
||||
the armor lines, with TITLE being an empty string, we don't write
|
||||
the header lines and furthermore even don't write any linefeeds.
|
||||
If TITLE starts with "PGP " the OpenPGP CRC checksum will be
|
||||
written as well. With TITLE being NULL, we merely don't write
|
||||
header but make sure that lines are not too long. Note, that we
|
||||
don't write any output unless at least one byte get written using
|
||||
b64enc_write. */
|
||||
gpg_error_t
|
||||
b64enc_start (struct b64state *state, FILE *fp, const char *title)
|
||||
{
|
||||
return enc_start (state, fp, NULL, title);
|
||||
}
|
||||
|
||||
/* Same as b64enc_start but takes an estream. */
|
||||
gpg_error_t
|
||||
b64enc_start_es (struct b64state *state, estream_t fp, const char *title)
|
||||
{
|
||||
return enc_start (state, NULL, fp, title);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
my_fputs (const char *string, struct b64state *state)
|
||||
{
|
||||
if (state->stream)
|
||||
return es_fputs (string, state->stream);
|
||||
else
|
||||
return fputs (string, state->fp);
|
||||
}
|
||||
|
||||
|
||||
/* Write NBYTES from BUFFER to the Base 64 stream identified by
|
||||
STATE. With BUFFER and NBYTES being 0, merely do a fflush on the
|
||||
stream. */
|
||||
gpg_error_t
|
||||
b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
|
||||
{
|
||||
unsigned char radbuf[4];
|
||||
int idx, quad_count;
|
||||
const unsigned char *p;
|
||||
|
||||
if (state->lasterr)
|
||||
return state->lasterr;
|
||||
|
||||
if (!nbytes)
|
||||
{
|
||||
if (buffer)
|
||||
if (state->stream? es_fflush (state->stream) : fflush (state->fp))
|
||||
goto write_error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(state->flags & B64ENC_DID_HEADER))
|
||||
{
|
||||
if (state->title)
|
||||
{
|
||||
if ( my_fputs ("-----BEGIN ", state) == EOF
|
||||
|| my_fputs (state->title, state) == EOF
|
||||
|| my_fputs ("-----\n", state) == EOF)
|
||||
goto write_error;
|
||||
if ( (state->flags & B64ENC_USE_PGPCRC)
|
||||
&& my_fputs ("\n", state) == EOF)
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
state->flags |= B64ENC_DID_HEADER;
|
||||
}
|
||||
|
||||
idx = state->idx;
|
||||
quad_count = state->quad_count;
|
||||
assert (idx < 4);
|
||||
memcpy (radbuf, state->radbuf, idx);
|
||||
|
||||
if ( (state->flags & B64ENC_USE_PGPCRC) )
|
||||
{
|
||||
size_t n;
|
||||
u32 crc = state->crc;
|
||||
|
||||
for (p=buffer, n=nbytes; n; p++, n-- )
|
||||
crc = ((u32)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p];
|
||||
state->crc = (crc & 0x00ffffff);
|
||||
}
|
||||
|
||||
for (p=buffer; nbytes; p++, nbytes--)
|
||||
{
|
||||
radbuf[idx++] = *p;
|
||||
if (idx > 2)
|
||||
{
|
||||
char tmp[4];
|
||||
|
||||
tmp[0] = bintoasc[(*radbuf >> 2) & 077];
|
||||
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
|
||||
tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
|
||||
tmp[3] = bintoasc[radbuf[2]&077];
|
||||
if (state->stream)
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
es_putc (tmp[idx], state->stream);
|
||||
idx = 0;
|
||||
if (es_ferror (state->stream))
|
||||
goto write_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
putc (tmp[idx], state->fp);
|
||||
idx = 0;
|
||||
if (ferror (state->fp))
|
||||
goto write_error;
|
||||
}
|
||||
if (++quad_count >= (64/4))
|
||||
{
|
||||
quad_count = 0;
|
||||
if (!(state->flags & B64ENC_NO_LINEFEEDS)
|
||||
&& my_fputs ("\n", state) == EOF)
|
||||
goto write_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy (state->radbuf, radbuf, idx);
|
||||
state->idx = idx;
|
||||
state->quad_count = quad_count;
|
||||
return 0;
|
||||
|
||||
write_error:
|
||||
state->lasterr = gpg_error_from_syserror ();
|
||||
if (state->title)
|
||||
{
|
||||
xfree (state->title);
|
||||
state->title = NULL;
|
||||
}
|
||||
return state->lasterr;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
b64enc_finish (struct b64state *state)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
unsigned char radbuf[4];
|
||||
int idx, quad_count;
|
||||
char tmp[4];
|
||||
|
||||
if (state->lasterr)
|
||||
return state->lasterr;
|
||||
|
||||
if (!(state->flags & B64ENC_DID_HEADER))
|
||||
goto cleanup;
|
||||
|
||||
/* Flush the base64 encoding */
|
||||
idx = state->idx;
|
||||
quad_count = state->quad_count;
|
||||
assert (idx < 4);
|
||||
memcpy (radbuf, state->radbuf, idx);
|
||||
|
||||
if (idx)
|
||||
{
|
||||
tmp[0] = bintoasc[(*radbuf>>2)&077];
|
||||
if (idx == 1)
|
||||
{
|
||||
tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077];
|
||||
tmp[2] = '=';
|
||||
tmp[3] = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
|
||||
tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077];
|
||||
tmp[3] = '=';
|
||||
}
|
||||
if (state->stream)
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
es_putc (tmp[idx], state->stream);
|
||||
if (es_ferror (state->stream))
|
||||
goto write_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
putc (tmp[idx], state->fp);
|
||||
if (ferror (state->fp))
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
if (++quad_count >= (64/4))
|
||||
{
|
||||
quad_count = 0;
|
||||
if (!(state->flags & B64ENC_NO_LINEFEEDS)
|
||||
&& my_fputs ("\n", state) == EOF)
|
||||
goto write_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish the last line and write the trailer. */
|
||||
if (quad_count
|
||||
&& !(state->flags & B64ENC_NO_LINEFEEDS)
|
||||
&& my_fputs ("\n", state) == EOF)
|
||||
goto write_error;
|
||||
|
||||
if ( (state->flags & B64ENC_USE_PGPCRC) )
|
||||
{
|
||||
/* Write the CRC. */
|
||||
my_fputs ("=", state);
|
||||
radbuf[0] = state->crc >>16;
|
||||
radbuf[1] = state->crc >> 8;
|
||||
radbuf[2] = state->crc;
|
||||
tmp[0] = bintoasc[(*radbuf>>2)&077];
|
||||
tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
|
||||
tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
|
||||
tmp[3] = bintoasc[radbuf[2]&077];
|
||||
if (state->stream)
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
es_putc (tmp[idx], state->stream);
|
||||
if (es_ferror (state->stream))
|
||||
goto write_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (idx=0; idx < 4; idx++)
|
||||
putc (tmp[idx], state->fp);
|
||||
if (ferror (state->fp))
|
||||
goto write_error;
|
||||
}
|
||||
if (!(state->flags & B64ENC_NO_LINEFEEDS)
|
||||
&& my_fputs ("\n", state) == EOF)
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
if (state->title)
|
||||
{
|
||||
if ( my_fputs ("-----END ", state) == EOF
|
||||
|| my_fputs (state->title, state) == EOF
|
||||
|| my_fputs ("-----\n", state) == EOF)
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
|
||||
write_error:
|
||||
err = gpg_error_from_syserror ();
|
||||
|
||||
cleanup:
|
||||
if (state->title)
|
||||
{
|
||||
xfree (state->title);
|
||||
state->title = NULL;
|
||||
}
|
||||
state->fp = NULL;
|
||||
state->stream = NULL;
|
||||
state->lasterr = err;
|
||||
return err;
|
||||
}
|
|
@ -42,7 +42,7 @@ static int module;
|
|||
|
||||
/* This value is used by DSA and RSA checks in addition to the hard
|
||||
* coded length checks. It allows one to increase the required key length
|
||||
* using a confue file. */
|
||||
* using a config file. */
|
||||
static unsigned int min_compliant_rsa_length;
|
||||
|
||||
/* Return the address of a compliance cache variable for COMPLIANCE.
|
||||
|
@ -139,7 +139,7 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||
gcry_mpi_t key[], unsigned int keylength,
|
||||
const char *curvename)
|
||||
{
|
||||
enum { is_rsa, is_dsa, is_elg, is_ecc } algotype;
|
||||
enum { is_rsa, is_dsa, is_elg, is_ecc, is_kem } algotype;
|
||||
int result = 0;
|
||||
|
||||
if (! initialized)
|
||||
|
@ -173,6 +173,10 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||
case PUBKEY_ALGO_ELGAMAL:
|
||||
return 0; /* Signing with Elgamal is not at all supported. */
|
||||
|
||||
case PUBKEY_ALGO_KYBER:
|
||||
algotype = is_kem;
|
||||
break;
|
||||
|
||||
default: /* Unknown. */
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,6 +231,10 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||
|| !strcmp (curvename, "brainpoolP512r1")));
|
||||
break;
|
||||
|
||||
case is_kem:
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = 0;
|
||||
}
|
||||
|
|
|
@ -1450,7 +1450,7 @@ dotlock_take_unix (dotlock_t h, long timeout)
|
|||
int wtimereal;
|
||||
|
||||
if (ownerchanged)
|
||||
wtime = 0; /* Reset because owner chnaged. */
|
||||
wtime = 0; /* Reset because owner changed. */
|
||||
|
||||
wtimereal = next_wait_interval (&wtime, &timeout);
|
||||
if (!timeout)
|
||||
|
|
|
@ -34,12 +34,15 @@
|
|||
#ifndef __MINGW32__
|
||||
# include <dlfcn.h>
|
||||
#else
|
||||
# include <errhandlingapi.h>
|
||||
# include <handleapi.h>
|
||||
# include <libloaderapi.h>
|
||||
# ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include "utf8conv.h"
|
||||
# include "mischelp.h"
|
||||
# define RTLD_LAZY 0
|
||||
# ifndef RTLD_LAZY
|
||||
# define RTLD_LAZY 0
|
||||
# endif
|
||||
|
||||
static inline void *
|
||||
dlopen (const char *name, int flag)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@ int get_max_fds (void);
|
|||
EXCEPT is not NULL, it is expected to be a list of file descriptors
|
||||
which are not to close. This list shall be sorted in ascending
|
||||
order with its end marked by -1. */
|
||||
void close_all_fds (int first, int *except);
|
||||
void close_all_fds (int first, const int *except);
|
||||
|
||||
|
||||
/* Returns an array with all currently open file descriptors. The end
|
||||
|
@ -73,140 +73,98 @@ gpg_error_t gnupg_create_pipe (int filedes[2]);
|
|||
void gnupg_close_pipe (int fd);
|
||||
|
||||
|
||||
#define GNUPG_SPAWN_NONBLOCK 16
|
||||
#define GNUPG_SPAWN_RUN_ASFW 64
|
||||
#define GNUPG_SPAWN_DETACHED 128
|
||||
#define GNUPG_SPAWN_KEEP_STDIN 256
|
||||
#define GNUPG_SPAWN_KEEP_STDOUT 512
|
||||
#define GNUPG_SPAWN_KEEP_STDERR 1024
|
||||
/* The opaque type for a subprocess. */
|
||||
typedef struct gnupg_process *gnupg_process_t;
|
||||
typedef struct gnupg_spawn_actions *gnupg_spawn_actions_t;
|
||||
gpg_err_code_t gnupg_spawn_actions_new (gnupg_spawn_actions_t *r_act);
|
||||
void gnupg_spawn_actions_release (gnupg_spawn_actions_t act);
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
void gnupg_spawn_actions_set_envvars (gnupg_spawn_actions_t, char *);
|
||||
void gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t,
|
||||
void *, void *, void *);
|
||||
void gnupg_spawn_actions_set_inherit_handles (gnupg_spawn_actions_t, void **);
|
||||
#else
|
||||
void gnupg_spawn_actions_set_environ (gnupg_spawn_actions_t, char **);
|
||||
void gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t, int, int, int);
|
||||
void gnupg_spawn_actions_set_inherit_fds (gnupg_spawn_actions_t,
|
||||
const int *);
|
||||
void gnupg_spawn_actions_set_atfork (gnupg_spawn_actions_t,
|
||||
void (*atfork)(void *), void *arg);
|
||||
#endif
|
||||
|
||||
/* Fork and exec the program PGMNAME.
|
||||
#define GNUPG_PROCESS_DETACHED (1 << 1)
|
||||
|
||||
If R_INFP is NULL connect stdin of the new process to /dev/null; if
|
||||
it is not NULL store the address of a pointer to a new estream
|
||||
there. If R_OUTFP is NULL connect stdout of the new process to
|
||||
/dev/null; if it is not NULL store the address of a pointer to a
|
||||
new estream there. If R_ERRFP is NULL connect stderr of the new
|
||||
process to /dev/null; if it is not NULL store the address of a
|
||||
pointer to a new estream there. On success the pid of the new
|
||||
process is stored at PID. On error -1 is stored at PID and if
|
||||
R_OUTFP or R_ERRFP are not NULL, NULL is stored there.
|
||||
/* Specify how to keep/connect standard fds. */
|
||||
#define GNUPG_PROCESS_STDIN_PIPE (1 << 8)
|
||||
#define GNUPG_PROCESS_STDOUT_PIPE (1 << 9)
|
||||
#define GNUPG_PROCESS_STDERR_PIPE (1 << 10)
|
||||
#define GNUPG_PROCESS_STDINOUT_SOCKETPAIR (1 << 11)
|
||||
#define GNUPG_PROCESS_STDIN_KEEP (1 << 12)
|
||||
#define GNUPG_PROCESS_STDOUT_KEEP (1 << 13)
|
||||
#define GNUPG_PROCESS_STDERR_KEEP (1 << 14)
|
||||
#define GNUPG_PROCESS_STDFDS_SETTING ( GNUPG_PROCESS_STDIN_PIPE \
|
||||
| GNUPG_PROCESS_STDOUT_PIPE | GNUPG_PROCESS_STDERR_PIPE \
|
||||
| GNUPG_PROCESS_STDINOUT_SOCKETPAIR | GNUPG_PROCESS_STDIN_KEEP \
|
||||
| GNUPG_PROCESS_STDOUT_KEEP | GNUPG_PROCESS_STDERR_KEEP)
|
||||
|
||||
The arguments for the process are expected in the NULL terminated
|
||||
array ARGV. The program name itself should not be included there.
|
||||
If PREEXEC is not NULL, the given function will be called right
|
||||
before the exec.
|
||||
#define GNUPG_PROCESS_STREAM_NONBLOCK (1 << 16)
|
||||
|
||||
IF EXCEPT is not NULL, it is expected to be an ordered list of file
|
||||
descriptors, terminated by an entry with the value (-1). These
|
||||
file descriptors won't be closed before spawning a new program.
|
||||
/* Spawn PGMNAME. */
|
||||
gpg_err_code_t gnupg_process_spawn (const char *pgmname, const char *argv1[],
|
||||
unsigned int flags,
|
||||
gnupg_spawn_actions_t act,
|
||||
gnupg_process_t *r_process);
|
||||
|
||||
Returns 0 on success or an error code. Calling gnupg_wait_process
|
||||
and gnupg_release_process is required if the function succeeded.
|
||||
/* Get FDs for subprocess I/O. It is the caller which should care
|
||||
FDs (closing FDs). */
|
||||
gpg_err_code_t gnupg_process_get_fds (gnupg_process_t process,
|
||||
unsigned int flags,
|
||||
int *r_fd_in, int *r_fd_out,
|
||||
int *r_fd_err);
|
||||
|
||||
FLAGS is a bit vector:
|
||||
/* Get STREAMs for subprocess I/O. It is the caller which should care
|
||||
STREAMs (closing STREAMs). */
|
||||
gpg_err_code_t gnupg_process_get_streams (gnupg_process_t process,
|
||||
unsigned int flags,
|
||||
gpgrt_stream_t *r_fp_in,
|
||||
gpgrt_stream_t *r_fp_out,
|
||||
gpgrt_stream_t *r_fp_err);
|
||||
|
||||
GNUPG_SPAWN_NONBLOCK
|
||||
If set the two output streams are created in non-blocking
|
||||
mode and the input stream is switched to non-blocking mode.
|
||||
This is merely a convenience feature because the caller
|
||||
could do the same with gpgrt_set_nonblock. Does not yet
|
||||
work for Windows.
|
||||
enum gnupg_process_requests
|
||||
{
|
||||
/* Portable requests */
|
||||
GNUPG_PROCESS_NOP = 0,
|
||||
GNUPG_PROCESS_GET_PROC_ID = 1,
|
||||
GNUPG_PROCESS_GET_EXIT_ID = 2,
|
||||
|
||||
GNUPG_SPAWN_DETACHED
|
||||
If set the process will be started as a background process.
|
||||
This flag is only useful under W32 (but not W32CE) systems,
|
||||
so that no new console is created and pops up a console
|
||||
window when starting the server. Does not work on W32CE.
|
||||
/* POSIX only */
|
||||
GNUPG_PROCESS_GET_PID = 16,
|
||||
GNUPG_PROCESS_GET_WSTATUS = 17,
|
||||
GNUPG_PROCESS_KILL = 18,
|
||||
|
||||
GNUPG_SPAWN_RUN_ASFW
|
||||
On W32 (but not on W32CE) run AllowSetForegroundWindow for
|
||||
the child. Note that due to unknown problems this actually
|
||||
allows SetForegroundWindow for all children of this process.
|
||||
/* Windows only */
|
||||
GNUPG_PROCESS_GET_P_HANDLE = 32,
|
||||
GNUPG_PROCESS_GET_HANDLES = 33,
|
||||
GNUPG_PROCESS_GET_EXIT_CODE = 34,
|
||||
GNUPG_PROCESS_KILL_WITH_EC = 35
|
||||
};
|
||||
|
||||
GNUPG_SPAWN_KEEP_STDIN
|
||||
GNUPG_SPAWN_KEEP_STDOUT
|
||||
GNUPG_SPAWN_KEEP_STDERR
|
||||
Do not assign /dev/null to a non-required standard file
|
||||
descriptor.
|
||||
/* Control of a process. */
|
||||
gpg_err_code_t gnupg_process_ctl (gnupg_process_t process,
|
||||
unsigned int request, ...);
|
||||
|
||||
*/
|
||||
gpg_error_t
|
||||
gnupg_spawn_process (const char *pgmname, const char *argv[],
|
||||
int *execpt, unsigned int flags,
|
||||
estream_t *r_infp,
|
||||
estream_t *r_outfp,
|
||||
estream_t *r_errfp,
|
||||
pid_t *pid);
|
||||
/* Wait for a single PROCESS. */
|
||||
gpg_err_code_t gnupg_process_wait (gnupg_process_t process, int hang);
|
||||
|
||||
/* Terminate a PROCESS. */
|
||||
gpg_err_code_t gnupg_process_terminate (gnupg_process_t process);
|
||||
|
||||
/* Simplified version of gnupg_spawn_process. This function forks and
|
||||
then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
|
||||
and ERRFD to stderr (any of them may be -1 to connect them to
|
||||
/dev/null). The arguments for the process are expected in the NULL
|
||||
terminated array ARGV. The program name itself should not be
|
||||
included there. Calling gnupg_wait_process and
|
||||
gnupg_release_process is required. Returns 0 on success or an
|
||||
error code. */
|
||||
gpg_error_t gnupg_spawn_process_fd (const char *pgmname,
|
||||
const char *argv[],
|
||||
int infd, int outfd, int errfd,
|
||||
pid_t *pid);
|
||||
|
||||
|
||||
/* If HANG is true, waits for the process identified by PID to exit;
|
||||
if HANG is false, checks whether the process has terminated.
|
||||
PGMNAME should be the same as supplied to the spawn function and is
|
||||
only used for diagnostics. Return values:
|
||||
|
||||
0
|
||||
The process exited successful. 0 is stored at R_EXITCODE.
|
||||
|
||||
GPG_ERR_GENERAL
|
||||
The process exited without success. The exit code of process
|
||||
is then stored at R_EXITCODE. An exit code of -1 indicates
|
||||
that the process terminated abnormally (e.g. due to a signal).
|
||||
|
||||
GPG_ERR_TIMEOUT
|
||||
The process is still running (returned only if HANG is false).
|
||||
|
||||
GPG_ERR_INV_VALUE
|
||||
An invalid PID has been specified.
|
||||
|
||||
Other error codes may be returned as well. Unless otherwise noted,
|
||||
-1 will be stored at R_EXITCODE. R_EXITCODE may be passed as NULL
|
||||
if the exit code is not required (in that case an error message will
|
||||
be printed). Note that under Windows PID is not the process id but
|
||||
the handle of the process. */
|
||||
gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int hang,
|
||||
int *r_exitcode);
|
||||
|
||||
/* Like gnupg_wait_process, but for COUNT processes. */
|
||||
gpg_error_t gnupg_wait_processes (const char **pgmnames, pid_t *pids,
|
||||
size_t count, int hang, int *r_exitcodes);
|
||||
|
||||
|
||||
/* Kill a process; that is send an appropriate signal to the process.
|
||||
gnupg_wait_process must be called to actually remove the process
|
||||
from the system. An invalid PID is ignored. */
|
||||
void gnupg_kill_process (pid_t pid);
|
||||
|
||||
/* Release the process identified by PID. This function is actually
|
||||
only required for Windows but it does not harm to always call it.
|
||||
It is a nop if PID is invalid. */
|
||||
void gnupg_release_process (pid_t pid);
|
||||
|
||||
|
||||
/* Spawn a new process and immediately detach from it. The name of
|
||||
the program to exec is PGMNAME and its arguments are in ARGV (the
|
||||
programname is automatically passed as first argument).
|
||||
Environment strings in ENVP are set. An error is returned if
|
||||
pgmname is not executable; to make this work it is necessary to
|
||||
provide an absolute file name. */
|
||||
gpg_error_t gnupg_spawn_process_detached (const char *pgmname,
|
||||
const char *argv[],
|
||||
const char *envp[] );
|
||||
/* Release PROCESS resources. */
|
||||
void gnupg_process_release (gnupg_process_t process);
|
||||
|
||||
/* Wait for a multiple processes. */
|
||||
gpg_err_code_t gnupg_process_wait_list (gnupg_process_t *process_list,
|
||||
int count, int hang);
|
||||
|
||||
|
||||
#endif /*GNUPG_COMMON_EXECHELP_H*/
|
||||
|
|
|
@ -38,10 +38,14 @@
|
|||
#include <gpg-error.h>
|
||||
|
||||
#include <assuan.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include "logging.h"
|
||||
#include "membuf.h"
|
||||
#include "mischelp.h"
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#define NEED_STRUCT_SPAWN_CB_ARG 1
|
||||
#endif
|
||||
#include "exechelp.h"
|
||||
#include "sysutils.h"
|
||||
#include "util.h"
|
||||
|
@ -301,7 +305,6 @@ copy_buffer_flush (struct copy_buffer *c, estream_t sink)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* Run the program PGMNAME with the command line arguments given in
|
||||
* the NULL terminates array ARGV. If INPUT is not NULL it will be
|
||||
* fed to stdin of the process. stderr is logged using log_info and
|
||||
|
@ -321,7 +324,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
|||
void *status_cb_value)
|
||||
{
|
||||
gpg_error_t err;
|
||||
pid_t pid = (pid_t) -1;
|
||||
gnupg_process_t proc = NULL;
|
||||
estream_t infp = NULL;
|
||||
estream_t extrafp = NULL;
|
||||
estream_t outfp = NULL, errfp = NULL;
|
||||
|
@ -335,7 +338,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
|||
read_and_log_buffer_t fderrstate;
|
||||
struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
|
||||
int quiet = 0;
|
||||
int dummy_exitcode;
|
||||
gnupg_spawn_actions_t act = NULL;
|
||||
|
||||
memset (fds, 0, sizeof fds);
|
||||
memset (&fderrstate, 0, sizeof fderrstate);
|
||||
|
@ -411,10 +414,23 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
|||
else
|
||||
exceptclose[0] = -1;
|
||||
|
||||
err = gnupg_spawn_process (pgmname, argv,
|
||||
exceptclose, GNUPG_SPAWN_NONBLOCK,
|
||||
input? &infp : NULL,
|
||||
&outfp, &errfp, &pid);
|
||||
err = gnupg_spawn_actions_new (&act);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
gnupg_spawn_actions_set_inherit_handles (act, exceptclose);
|
||||
#else
|
||||
gnupg_spawn_actions_set_inherit_fds (act, exceptclose);
|
||||
#endif
|
||||
err = gnupg_process_spawn (pgmname, argv,
|
||||
((input
|
||||
? GNUPG_PROCESS_STDIN_PIPE
|
||||
: 0)
|
||||
| GNUPG_PROCESS_STDOUT_PIPE
|
||||
| GNUPG_PROCESS_STDERR_PIPE), act, &proc);
|
||||
gnupg_process_get_streams (proc, GNUPG_PROCESS_STREAM_NONBLOCK,
|
||||
input? &infp : NULL, &outfp, &errfp);
|
||||
if (extrapipe[0] != -1)
|
||||
close (extrapipe[0]);
|
||||
if (argsave)
|
||||
|
@ -546,20 +562,26 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
|||
es_fclose (outfp); outfp = NULL;
|
||||
es_fclose (errfp); errfp = NULL;
|
||||
|
||||
err = gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
|
||||
pid = (pid_t)(-1);
|
||||
err = gnupg_process_wait (proc, 1);
|
||||
if (!err)
|
||||
{ /* To be compatible to old wait_process. */
|
||||
int status;
|
||||
|
||||
gnupg_process_ctl (proc, GNUPG_PROCESS_GET_EXIT_ID, &status);
|
||||
if (status)
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
leave:
|
||||
if (err && pid != (pid_t) -1)
|
||||
gnupg_kill_process (pid);
|
||||
if (err && proc)
|
||||
gnupg_process_terminate (proc);
|
||||
|
||||
es_fclose (infp);
|
||||
es_fclose (extrafp);
|
||||
es_fclose (outfp);
|
||||
es_fclose (errfp);
|
||||
if (pid != (pid_t)(-1))
|
||||
gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
|
||||
gnupg_release_process (pid);
|
||||
gnupg_process_release (proc);
|
||||
gnupg_spawn_actions_release (act);
|
||||
|
||||
copy_buffer_shred (cpbuf_in);
|
||||
xfree (cpbuf_in);
|
||||
|
|
|
@ -94,7 +94,8 @@ start_agent (void)
|
|||
agentargs.lc_ctype,
|
||||
agentargs.lc_messages,
|
||||
agentargs.session_env,
|
||||
1, agentargs.verbosity, 0, NULL, NULL);
|
||||
ASSHELP_FLAG_AUTOSTART,
|
||||
agentargs.verbosity, 0, NULL, NULL);
|
||||
if (!err)
|
||||
{
|
||||
/* Tell the agent that we support Pinentry notifications. No
|
||||
|
|
|
@ -124,7 +124,7 @@ timegm (struct tm *tm)
|
|||
|
||||
/* Version of the GNU timegm which returns an unsigned 64 bit integer
|
||||
* instead of the usually signed time_t. On error (uint64_t)(-1) is
|
||||
* returned. This function is mostly here becuase on 32 bit Windows
|
||||
* returned. This function is mostly here because on 32 bit Windows
|
||||
* we have an internal API to get the system time even after
|
||||
* 2023-01-19. For 32 bit Unix we need to suffer from the too short
|
||||
* time_t and no system function to construct the time from a tm. */
|
||||
|
|
590
common/homedir.c
590
common/homedir.c
|
@ -1,7 +1,7 @@
|
|||
/* homedir.c - Setup the home directory.
|
||||
* Copyright (C) 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2013, 2016 Werner Koch
|
||||
* Copyright (C) 2021 g10 Code GmbH
|
||||
* Copyright (C) 2021, 2024 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
|
@ -93,6 +93,22 @@ static char *the_gnupg_homedir;
|
|||
static byte non_default_homedir;
|
||||
|
||||
|
||||
/* An object to store information taken from a gpgconf.ctl file. This
|
||||
* is parsed early at startup time and never changed later. */
|
||||
static struct
|
||||
{
|
||||
unsigned int checked:1; /* True if we have checked for a gpgconf.ctl. */
|
||||
unsigned int found:1; /* True if a gpgconf.ctl was found. */
|
||||
unsigned int empty:1; /* The file is empty except for comments. */
|
||||
unsigned int valid:1; /* The entries in gpgconf.ctl are valid. */
|
||||
unsigned int portable:1;/* Windows portable installation. */
|
||||
char *gnupg; /* The "gnupg" directory part. */
|
||||
char *rootdir; /* rootdir or NULL */
|
||||
char *sysconfdir; /* sysconfdir or NULL */
|
||||
char *socketdir; /* socketdir or NULL */
|
||||
} gpgconf_ctl;
|
||||
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* A flag used to indicate that a control file for gpgconf has been
|
||||
* detected. Under Windows the presence of this file indicates a
|
||||
|
@ -119,6 +135,87 @@ static byte w32_bin_is_bin;
|
|||
static const char *w32_rootdir (void);
|
||||
#endif
|
||||
|
||||
/* Return the name of the gnupg dir. This is usually "gnupg". */
|
||||
static const char *
|
||||
my_gnupg_dirname (void)
|
||||
{
|
||||
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
|
||||
return gpgconf_ctl.gnupg;
|
||||
return "gnupg";
|
||||
}
|
||||
|
||||
/* Return the hardwired home directory which is not anymore so
|
||||
* hardwired because it may now be modified using the gpgconf.ctl
|
||||
* "gnupg" keyword. */
|
||||
static const char *
|
||||
my_fixed_default_homedir (void)
|
||||
{
|
||||
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
|
||||
{
|
||||
static char *name;
|
||||
char *p;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
name = xmalloc (strlen (GNUPG_DEFAULT_HOMEDIR)
|
||||
+ strlen (gpgconf_ctl.gnupg) + 1);
|
||||
strcpy (name, GNUPG_DEFAULT_HOMEDIR);
|
||||
p = strrchr (name, '/');
|
||||
if (p)
|
||||
p++;
|
||||
else
|
||||
p = name;
|
||||
if (*p == '.')
|
||||
p++; /* Keep a leading dot. */
|
||||
strcpy (p, gpgconf_ctl.gnupg);
|
||||
gpgrt_annotate_leaked_object (name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return GNUPG_DEFAULT_HOMEDIR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Under Windows we need to modify the standard registry key with the
|
||||
* "gnupg" keyword from a gpgconf.ctl. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
const char *
|
||||
gnupg_registry_dir (void)
|
||||
{
|
||||
if (gpgconf_ctl.valid && gpgconf_ctl.gnupg)
|
||||
{
|
||||
static char *name;
|
||||
char *p;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
name = xmalloc (strlen (GNUPG_REGISTRY_DIR)
|
||||
+ strlen (gpgconf_ctl.gnupg) + 1);
|
||||
strcpy (name, GNUPG_REGISTRY_DIR);
|
||||
p = strrchr (name, '\\');
|
||||
if (p)
|
||||
p++;
|
||||
else
|
||||
p = name;
|
||||
strcpy (p, gpgconf_ctl.gnupg);
|
||||
if (!strncmp (p, "gnupg", 5))
|
||||
{
|
||||
/* Registry keys are case-insensitive and we use a
|
||||
* capitalized version of gnupg by default. So, if the
|
||||
* new value starts with "gnupg" we apply the usual
|
||||
* capitalization for this first part. */
|
||||
p[0] = 'G';
|
||||
p[3] = 'P';
|
||||
p[4] = 'G';
|
||||
}
|
||||
gpgrt_annotate_leaked_object (name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return GNUPG_REGISTRY_DIR;
|
||||
}
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
|
||||
/* This is a helper function to load and call a Windows function from
|
||||
|
@ -324,7 +421,7 @@ standard_homedir (void)
|
|||
NULL, 0);
|
||||
if (path)
|
||||
{
|
||||
dir = xstrconcat (path, "\\gnupg", NULL);
|
||||
dir = xstrconcat (path, "\\", my_gnupg_dirname (), NULL);
|
||||
xfree (path);
|
||||
gpgrt_annotate_leaked_object (dir);
|
||||
|
||||
|
@ -335,12 +432,12 @@ standard_homedir (void)
|
|||
|
||||
}
|
||||
else
|
||||
dir = GNUPG_DEFAULT_HOMEDIR;
|
||||
dir = my_fixed_default_homedir ();
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
#else/*!HAVE_W32_SYSTEM*/
|
||||
return GNUPG_DEFAULT_HOMEDIR;
|
||||
return my_fixed_default_homedir ();
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
}
|
||||
|
||||
|
@ -374,7 +471,7 @@ default_homedir (void)
|
|||
* warning if the homedir has been taken from the
|
||||
* registry. */
|
||||
tmp = read_w32_registry_string (NULL,
|
||||
GNUPG_REGISTRY_DIR,
|
||||
gnupg_registry_dir (),
|
||||
"HomeDir");
|
||||
if (tmp && !*tmp)
|
||||
{
|
||||
|
@ -399,7 +496,7 @@ default_homedir (void)
|
|||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
if (!dir || !*dir)
|
||||
dir = GNUPG_DEFAULT_HOMEDIR;
|
||||
dir = my_fixed_default_homedir ();
|
||||
else
|
||||
{
|
||||
char *p;
|
||||
|
@ -427,6 +524,234 @@ default_homedir (void)
|
|||
}
|
||||
|
||||
|
||||
/* Return true if S can be inteprtated as true. This is uised for
|
||||
* keywords in gpgconf.ctl. Spaces must have been trimmed. */
|
||||
static int
|
||||
string_is_true (const char *s)
|
||||
{
|
||||
return (atoi (s)
|
||||
|| !ascii_strcasecmp (s, "yes")
|
||||
|| !ascii_strcasecmp (s, "true")
|
||||
|| !ascii_strcasecmp (s, "fact"));
|
||||
}
|
||||
|
||||
/* This function is used to parse the gpgconf.ctl file and set the
|
||||
* information ito the gpgconf_ctl structure. This is called once
|
||||
* with the full filename of gpgconf.ctl. There are two callers: One
|
||||
* used on Windows and one on Unix. No error return but diagnostics
|
||||
* are printed. */
|
||||
static void
|
||||
parse_gpgconf_ctl (const char *fname)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *p;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
ssize_t length;
|
||||
estream_t fp;
|
||||
const char *name;
|
||||
int anyitem = 0;
|
||||
int ignoreall = 0;
|
||||
char *gnupgval = NULL;
|
||||
char *rootdir = NULL;
|
||||
char *sysconfdir = NULL;
|
||||
char *socketdir = NULL;
|
||||
|
||||
if (gpgconf_ctl.checked)
|
||||
return; /* Just in case this is called a second time. */
|
||||
gpgconf_ctl.checked = 1;
|
||||
gpgconf_ctl.found = 0;
|
||||
gpgconf_ctl.valid = 0;
|
||||
gpgconf_ctl.empty = 0;
|
||||
|
||||
if (gnupg_access (fname, F_OK))
|
||||
return; /* No gpgconf.ctl file. */
|
||||
|
||||
/* log_info ("detected '%s'\n", buffer); */
|
||||
fp = es_fopen (fname, "r");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error opening '%s': %s\n", fname, gpg_strerror (err));
|
||||
return;
|
||||
}
|
||||
gpgconf_ctl.found = 1;
|
||||
|
||||
line = NULL;
|
||||
linelen = 0;
|
||||
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
|
||||
{
|
||||
static const char *names[] =
|
||||
{
|
||||
"gnupg",
|
||||
"rootdir",
|
||||
"sysconfdir",
|
||||
"socketdir",
|
||||
"portable",
|
||||
".enable"
|
||||
};
|
||||
int i;
|
||||
size_t n;
|
||||
|
||||
/* Strip NL and CR, if present. */
|
||||
while (length > 0
|
||||
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
|
||||
line[--length] = 0;
|
||||
trim_spaces (line);
|
||||
if (*line == '#' || !*line)
|
||||
continue;
|
||||
anyitem = 1;
|
||||
|
||||
/* Find the keyword. */
|
||||
name = NULL;
|
||||
p = NULL;
|
||||
for (i=0; i < DIM (names); i++)
|
||||
{
|
||||
n = strlen (names[i]);
|
||||
if (!strncmp (line, names[i], n))
|
||||
{
|
||||
while (line[n] == ' ' || line[n] == '\t')
|
||||
n++;
|
||||
if (line[n] == '=')
|
||||
{
|
||||
name = names[i];
|
||||
p = line + n + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
continue; /* Keyword not known. */
|
||||
|
||||
trim_spaces (p);
|
||||
p = substitute_envvars (p);
|
||||
if (!p)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error getting %s from gpgconf.ctl: %s\n",
|
||||
name, gpg_strerror (err));
|
||||
}
|
||||
else if (!strcmp (name, ".enable"))
|
||||
{
|
||||
if (string_is_true (p))
|
||||
; /* Yes, this file shall be used. */
|
||||
else
|
||||
ignoreall = 1; /* No, this file shall be ignored. */
|
||||
xfree (p);
|
||||
}
|
||||
else if (!strcmp (name, "gnupg"))
|
||||
{
|
||||
xfree (gnupgval);
|
||||
gnupgval = p;
|
||||
}
|
||||
else if (!strcmp (name, "sysconfdir"))
|
||||
{
|
||||
xfree (sysconfdir);
|
||||
sysconfdir = p;
|
||||
}
|
||||
else if (!strcmp (name, "socketdir"))
|
||||
{
|
||||
xfree (socketdir);
|
||||
socketdir = p;
|
||||
}
|
||||
else if (!strcmp (name, "rootdir"))
|
||||
{
|
||||
xfree (rootdir);
|
||||
rootdir = p;
|
||||
}
|
||||
else if (!strcmp (name, "portable"))
|
||||
{
|
||||
gpgconf_ctl.portable = string_is_true (p);
|
||||
xfree (p);
|
||||
}
|
||||
else /* Unknown keyword. */
|
||||
xfree (p);
|
||||
}
|
||||
if (es_ferror (fp))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error reading '%s': %s\n", fname, gpg_strerror (err));
|
||||
ignoreall = 1; /* Force all entries to invalid. */
|
||||
}
|
||||
es_fclose (fp);
|
||||
xfree (line);
|
||||
|
||||
if (ignoreall)
|
||||
; /* Forced error. Note that .found is still set. */
|
||||
else if (gnupgval && (!*gnupgval || strpbrk (gnupgval, "/\\")))
|
||||
{
|
||||
/* We don't allow a slash or backslash in the value because our
|
||||
* code assumes this is a single directory name. */
|
||||
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
|
||||
"gnupg", gnupgval);
|
||||
}
|
||||
else if (rootdir && (!*rootdir || *rootdir != '/'))
|
||||
{
|
||||
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
|
||||
"rootdir", rootdir);
|
||||
}
|
||||
else if (sysconfdir && (!*sysconfdir || *sysconfdir != '/'))
|
||||
{
|
||||
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
|
||||
"sysconfdir", sysconfdir);
|
||||
}
|
||||
else if (socketdir && (!*socketdir || *socketdir != '/'))
|
||||
{
|
||||
log_info ("invalid %s '%s' specified in gpgconf.ctl\n",
|
||||
"socketdir", socketdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gnupgval)
|
||||
{
|
||||
gpgconf_ctl.gnupg = gnupgval;
|
||||
gpgrt_annotate_leaked_object (gpgconf_ctl.gnupg);
|
||||
/* log_info ("want gnupg '%s'\n", dir); */
|
||||
}
|
||||
if (rootdir)
|
||||
{
|
||||
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
|
||||
rootdir[strlen (rootdir)-1] = 0;
|
||||
gpgconf_ctl.rootdir = rootdir;
|
||||
gpgrt_annotate_leaked_object (gpgconf_ctl.rootdir);
|
||||
/* log_info ("want rootdir '%s'\n", dir); */
|
||||
}
|
||||
if (sysconfdir)
|
||||
{
|
||||
while (*sysconfdir && sysconfdir[strlen (sysconfdir)-1] == '/')
|
||||
sysconfdir[strlen (sysconfdir)-1] = 0;
|
||||
gpgconf_ctl.sysconfdir = sysconfdir;
|
||||
gpgrt_annotate_leaked_object (gpgconf_ctl.sysconfdir);
|
||||
/* log_info ("want sysconfdir '%s'\n", sdir); */
|
||||
}
|
||||
if (socketdir)
|
||||
{
|
||||
while (*socketdir && socketdir[strlen (socketdir)-1] == '/')
|
||||
socketdir[strlen (socketdir)-1] = 0;
|
||||
gpgconf_ctl.socketdir = socketdir;
|
||||
gpgrt_annotate_leaked_object (gpgconf_ctl.socketdir);
|
||||
/* log_info ("want socketdir '%s'\n", s2dir); */
|
||||
}
|
||||
gpgconf_ctl.valid = 1;
|
||||
}
|
||||
|
||||
gpgconf_ctl.empty = !anyitem;
|
||||
if (!gpgconf_ctl.valid)
|
||||
{
|
||||
/* Error reading some entries - clear them all. */
|
||||
xfree (gnupgval);
|
||||
xfree (rootdir);
|
||||
xfree (sysconfdir);
|
||||
xfree (socketdir);
|
||||
gpgconf_ctl.gnupg = NULL;
|
||||
gpgconf_ctl.rootdir = NULL;
|
||||
gpgconf_ctl.sysconfdir = NULL;
|
||||
gpgconf_ctl.socketdir = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* Check whether gpgconf is installed and if so read the gpgconf.ctl
|
||||
file. */
|
||||
|
@ -439,17 +764,20 @@ check_portable_app (const char *dir)
|
|||
if (!gnupg_access (fname, F_OK))
|
||||
{
|
||||
strcpy (fname + strlen (fname) - 3, "ctl");
|
||||
if (!gnupg_access (fname, F_OK))
|
||||
parse_gpgconf_ctl (fname);
|
||||
if ((gpgconf_ctl.found && gpgconf_ctl.empty)
|
||||
|| (gpgconf_ctl.valid && gpgconf_ctl.portable))
|
||||
{
|
||||
/* gpgconf.ctl file found. Record this fact. */
|
||||
unsigned int flags;
|
||||
|
||||
/* Classic gpgconf.ctl file found. This is a portable
|
||||
* application. Note that if there are any items in that
|
||||
* file we don't consider this a portable application unless
|
||||
* the (later added) ".portable" keyword has also been
|
||||
* seen. */
|
||||
w32_portable_app = 1;
|
||||
{
|
||||
unsigned int flags;
|
||||
log_get_prefix (&flags);
|
||||
log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
|
||||
}
|
||||
/* FIXME: We should read the file to detect special flags
|
||||
and print a warning if we don't understand them */
|
||||
log_get_prefix (&flags);
|
||||
log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
|
||||
}
|
||||
}
|
||||
xfree (fname);
|
||||
|
@ -528,28 +856,14 @@ w32_rootdir (void)
|
|||
static const char *
|
||||
unix_rootdir (enum wantdir_values wantdir)
|
||||
{
|
||||
static int checked;
|
||||
static char *dir; /* for the rootdir */
|
||||
static char *sdir; /* for the sysconfdir */
|
||||
static char *s2dir; /* for the socketdir */
|
||||
|
||||
if (!checked)
|
||||
if (!gpgconf_ctl.checked)
|
||||
{
|
||||
char *p;
|
||||
char *buffer;
|
||||
size_t bufsize = 256-1;
|
||||
int nread;
|
||||
gpg_error_t err;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
ssize_t length;
|
||||
estream_t fp;
|
||||
char *rootdir;
|
||||
char *sysconfdir;
|
||||
char *socketdir;
|
||||
const char *name;
|
||||
int ignoreall = 0;
|
||||
int okay;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -589,7 +903,7 @@ unix_rootdir (enum wantdir_values wantdir)
|
|||
if (!*buffer)
|
||||
{
|
||||
xfree (buffer);
|
||||
checked = 1;
|
||||
gpgconf_ctl.checked = 1;
|
||||
return NULL; /* Error - assume no gpgconf.ctl. */
|
||||
}
|
||||
|
||||
|
@ -597,197 +911,36 @@ unix_rootdir (enum wantdir_values wantdir)
|
|||
if (!p)
|
||||
{
|
||||
xfree (buffer);
|
||||
checked = 1;
|
||||
gpgconf_ctl.checked = 1;
|
||||
return NULL; /* Erroneous /proc - assume no gpgconf.ctl. */
|
||||
}
|
||||
*p = 0; /* BUFFER has the directory. */
|
||||
if ((p = strrchr (buffer, '/')))
|
||||
{
|
||||
/* Strip one part and expect the file below a bin dir. */
|
||||
*p = 0;
|
||||
p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
|
||||
xfree (buffer);
|
||||
buffer = p;
|
||||
}
|
||||
else /* !p */
|
||||
if (!(p = strrchr (buffer, '/')))
|
||||
{
|
||||
/* Installed in the root which is not a good idea. Assume
|
||||
* no gpgconf.ctl. */
|
||||
xfree (buffer);
|
||||
checked = 1;
|
||||
gpgconf_ctl.checked = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gnupg_access (buffer, F_OK))
|
||||
{
|
||||
/* No gpgconf.ctl file. */
|
||||
xfree (buffer);
|
||||
checked = 1;
|
||||
return NULL;
|
||||
}
|
||||
/* log_info ("detected '%s'\n", buffer); */
|
||||
fp = es_fopen (buffer, "r");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error opening '%s': %s\n", buffer, gpg_strerror (err));
|
||||
xfree (buffer);
|
||||
checked = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = NULL;
|
||||
linelen = 0;
|
||||
rootdir = NULL;
|
||||
sysconfdir = NULL;
|
||||
socketdir = NULL;
|
||||
while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
|
||||
{
|
||||
static const char *names[] =
|
||||
{
|
||||
"rootdir",
|
||||
"sysconfdir",
|
||||
"socketdir",
|
||||
".enable"
|
||||
};
|
||||
int i;
|
||||
size_t n;
|
||||
|
||||
/* Strip NL and CR, if present. */
|
||||
while (length > 0
|
||||
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
|
||||
line[--length] = 0;
|
||||
trim_spaces (line);
|
||||
/* Find the stamement. */
|
||||
name = NULL;
|
||||
for (i=0; i < DIM (names); i++)
|
||||
{
|
||||
n = strlen (names[i]);
|
||||
if (!strncmp (line, names[i], n))
|
||||
{
|
||||
while (line[n] == ' ' || line[n] == '\t')
|
||||
n++;
|
||||
if (line[n] == '=')
|
||||
{
|
||||
name = names[i];
|
||||
p = line + n + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
continue; /* Statement not known. */
|
||||
|
||||
trim_spaces (p);
|
||||
p = substitute_envvars (p);
|
||||
if (!p)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error getting %s from gpgconf.ctl: %s\n",
|
||||
name, gpg_strerror (err));
|
||||
}
|
||||
else if (!strcmp (name, ".enable"))
|
||||
{
|
||||
if (atoi (p)
|
||||
|| !ascii_strcasecmp (p, "yes")
|
||||
|| !ascii_strcasecmp (p, "true")
|
||||
|| !ascii_strcasecmp (p, "fact"))
|
||||
; /* Yes, this file shall be used. */
|
||||
else
|
||||
ignoreall = 1; /* No, this file shall be ignored. */
|
||||
xfree (p);
|
||||
}
|
||||
else if (!strcmp (name, "sysconfdir"))
|
||||
{
|
||||
xfree (sysconfdir);
|
||||
sysconfdir = p;
|
||||
}
|
||||
else if (!strcmp (name, "socketdir"))
|
||||
{
|
||||
xfree (socketdir);
|
||||
socketdir = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
xfree (rootdir);
|
||||
rootdir = p;
|
||||
}
|
||||
}
|
||||
if (es_ferror (fp))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_info ("error reading '%s': %s\n", buffer, gpg_strerror (err));
|
||||
es_fclose (fp);
|
||||
xfree (buffer);
|
||||
xfree (line);
|
||||
xfree (rootdir);
|
||||
xfree (sysconfdir);
|
||||
xfree (socketdir);
|
||||
checked = 1;
|
||||
return NULL;
|
||||
}
|
||||
es_fclose (fp);
|
||||
/* Strip one part and expect the file below a bin dir. */
|
||||
*p = 0;
|
||||
p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
|
||||
xfree (buffer);
|
||||
buffer = p;
|
||||
parse_gpgconf_ctl (buffer);
|
||||
xfree (buffer);
|
||||
xfree (line);
|
||||
|
||||
okay = 0;
|
||||
if (ignoreall)
|
||||
;
|
||||
else if (!rootdir || !*rootdir || *rootdir != '/')
|
||||
{
|
||||
log_info ("invalid rootdir '%s' specified in gpgconf.ctl\n", rootdir);
|
||||
}
|
||||
else if (sysconfdir && (!*sysconfdir || *sysconfdir != '/'))
|
||||
{
|
||||
log_info ("invalid sysconfdir '%s' specified in gpgconf.ctl\n",
|
||||
sysconfdir);
|
||||
}
|
||||
else if (socketdir && (!*socketdir || *socketdir != '/'))
|
||||
{
|
||||
log_info ("invalid socketdir '%s' specified in gpgconf.ctl\n",
|
||||
socketdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
okay = 1;
|
||||
while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
|
||||
rootdir[strlen (rootdir)-1] = 0;
|
||||
dir = rootdir;
|
||||
gpgrt_annotate_leaked_object (dir);
|
||||
/* log_info ("want rootdir '%s'\n", dir); */
|
||||
if (sysconfdir)
|
||||
{
|
||||
while (*sysconfdir && sysconfdir[strlen (sysconfdir)-1] == '/')
|
||||
sysconfdir[strlen (sysconfdir)-1] = 0;
|
||||
sdir = sysconfdir;
|
||||
gpgrt_annotate_leaked_object (sdir);
|
||||
/* log_info ("want sysconfdir '%s'\n", sdir); */
|
||||
}
|
||||
if (socketdir)
|
||||
{
|
||||
while (*socketdir && socketdir[strlen (socketdir)-1] == '/')
|
||||
socketdir[strlen (socketdir)-1] = 0;
|
||||
s2dir = socketdir;
|
||||
gpgrt_annotate_leaked_object (s2dir);
|
||||
/* log_info ("want socketdir '%s'\n", s2dir); */
|
||||
}
|
||||
}
|
||||
|
||||
if (!okay)
|
||||
{
|
||||
xfree (rootdir);
|
||||
xfree (sysconfdir);
|
||||
xfree (socketdir);
|
||||
dir = sdir = s2dir = NULL;
|
||||
}
|
||||
checked = 1;
|
||||
}
|
||||
|
||||
if (!gpgconf_ctl.valid)
|
||||
return NULL; /* No valid entries in gpgconf.ctl */
|
||||
|
||||
switch (wantdir)
|
||||
{
|
||||
case WANTDIR_ROOT: return dir;
|
||||
case WANTDIR_SYSCONF: return sdir;
|
||||
case WANTDIR_SOCKET: return s2dir;
|
||||
case WANTDIR_ROOT: return gpgconf_ctl.rootdir;
|
||||
case WANTDIR_SYSCONF: return gpgconf_ctl.sysconfdir;
|
||||
case WANTDIR_SOCKET: return gpgconf_ctl.socketdir;
|
||||
}
|
||||
|
||||
return NULL; /* Not reached. */
|
||||
|
@ -936,7 +1089,7 @@ gnupg_daemon_rootdir (void)
|
|||
|
||||
n = GetSystemDirectoryA (path, sizeof path);
|
||||
if (!n || n >= sizeof path)
|
||||
name = xstrdup ("/"); /* Error - use the curret top dir instead. */
|
||||
name = xstrdup ("/"); /* Error - use the current top dir instead. */
|
||||
else
|
||||
name = xstrdup (path);
|
||||
gpgrt_annotate_leaked_object (name);
|
||||
|
@ -982,7 +1135,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
|
|||
|
||||
if (w32_portable_app)
|
||||
{
|
||||
name = xstrconcat (w32_rootdir (), DIRSEP_S, "gnupg", NULL);
|
||||
name = xstrconcat (w32_rootdir (), DIRSEP_S, my_gnupg_dirname (), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -993,7 +1146,7 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
|
|||
NULL, 0);
|
||||
if (path)
|
||||
{
|
||||
name = xstrconcat (path, "\\gnupg", NULL);
|
||||
name = xstrconcat (path, "\\", my_gnupg_dirname (), NULL);
|
||||
xfree (path);
|
||||
if (gnupg_access (name, F_OK))
|
||||
gnupg_mkdir (name, "-rwx");
|
||||
|
@ -1101,10 +1254,11 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
|
|||
};
|
||||
int i;
|
||||
struct stat sb;
|
||||
char prefixbuffer[19 + 1 + 20 + 6 + 1];
|
||||
char prefixbuffer[256];
|
||||
const char *prefix;
|
||||
const char *s;
|
||||
char *name = NULL;
|
||||
const char *gnupgname = my_gnupg_dirname ();
|
||||
|
||||
*r_info = 0;
|
||||
|
||||
|
@ -1143,15 +1297,16 @@ _gnupg_socketdir_internal (int skip_checks, unsigned *r_info)
|
|||
goto leave;
|
||||
}
|
||||
|
||||
if (strlen (prefix) + 7 >= sizeof prefixbuffer)
|
||||
if (strlen (prefix) + strlen (gnupgname) + 2 >= sizeof prefixbuffer)
|
||||
{
|
||||
*r_info |= 1; /* Ooops: Buffer too short to append "/gnupg". */
|
||||
goto leave;
|
||||
}
|
||||
strcat (prefixbuffer, "/gnupg");
|
||||
strcat (prefixbuffer, "/");
|
||||
strcat (prefixbuffer, gnupgname);
|
||||
}
|
||||
|
||||
/* Check whether the gnupg sub directory (or the specified diretory)
|
||||
/* Check whether the gnupg sub directory (or the specified directory)
|
||||
* has proper permissions. */
|
||||
if (stat (prefix, &sb))
|
||||
{
|
||||
|
@ -1303,11 +1458,8 @@ gnupg_sysconfdir (void)
|
|||
|
||||
if (!name)
|
||||
{
|
||||
const char *s1, *s2;
|
||||
s1 = w32_commondir ();
|
||||
s2 = DIRSEP_S "etc" DIRSEP_S "gnupg";
|
||||
name = xmalloc (strlen (s1) + strlen (s2) + 1);
|
||||
strcpy (stpcpy (name, s1), s2);
|
||||
name = xstrconcat (w32_commondir (), DIRSEP_S, "etc", DIRSEP_S,
|
||||
my_gnupg_dirname (), NULL);
|
||||
gpgrt_annotate_leaked_object (name);
|
||||
}
|
||||
return name;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
# include <winsock2.h>
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
|
|
@ -166,7 +166,8 @@ block_filter_ctx_t;
|
|||
/* Local prototypes. */
|
||||
static int underflow (iobuf_t a, int clear_pending_eof);
|
||||
static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target);
|
||||
static int translate_file_handle (int fd, int for_write);
|
||||
static iobuf_t do_iobuf_fdopen (gnupg_fd_t fp, const char *mode, int keep_open);
|
||||
|
||||
|
||||
/* Sends any pending data to the filter's FILTER function. Note: this
|
||||
works on the filter and not on the whole pipeline. That is,
|
||||
|
@ -389,7 +390,7 @@ fd_cache_close (const char *fname, gnupg_fd_t fp)
|
|||
close (fp);
|
||||
#endif
|
||||
if (DBG_IOBUF)
|
||||
log_debug ("fd_cache_close (%d) real\n", (int)fp);
|
||||
log_debug ("fd_cache_close (%d) real\n", FD_DBG (fp));
|
||||
return;
|
||||
}
|
||||
/* try to reuse a slot */
|
||||
|
@ -696,7 +697,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
|
|||
if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT)
|
||||
{
|
||||
if (DBG_IOBUF)
|
||||
log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f));
|
||||
log_debug ("%s: close fd/handle %d\n", a->fname, FD_DBG (f));
|
||||
if (!a->keep_open)
|
||||
fd_cache_close (a->no_cache ? NULL : a->fname, f);
|
||||
}
|
||||
|
@ -1410,7 +1411,7 @@ iobuf_is_pipe_filename (const char *fname)
|
|||
{
|
||||
if (!fname || (*fname=='-' && !fname[1]) )
|
||||
return 1;
|
||||
return check_special_filename (fname, 0, 1) != -1;
|
||||
return gnupg_check_special_filename (fname) != GNUPG_INVALID_FD;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1423,7 +1424,7 @@ do_open (const char *fname, int special_filenames,
|
|||
file_filter_ctx_t *fcx;
|
||||
size_t len = 0;
|
||||
int print_only = 0;
|
||||
int fd;
|
||||
gnupg_fd_t fd;
|
||||
byte desc[MAX_IOBUF_DESC];
|
||||
|
||||
log_assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
|
||||
|
@ -1447,9 +1448,8 @@ do_open (const char *fname, int special_filenames,
|
|||
else if (!fname)
|
||||
return NULL;
|
||||
else if (special_filenames
|
||||
&& (fd = check_special_filename (fname, 0, 1)) != -1)
|
||||
return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1),
|
||||
opentype);
|
||||
&& (fd = gnupg_check_special_filename (fname)) != GNUPG_INVALID_FD)
|
||||
return do_iobuf_fdopen (fd, opentype, 0);
|
||||
else
|
||||
{
|
||||
if (use == IOBUF_INPUT)
|
||||
|
@ -1472,7 +1472,8 @@ do_open (const char *fname, int special_filenames,
|
|||
file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
|
||||
if (DBG_IOBUF)
|
||||
log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n",
|
||||
a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp));
|
||||
a->no, a->subno, fname, iobuf_desc (a, desc),
|
||||
FD_DBG (fcx->fp));
|
||||
|
||||
return a;
|
||||
}
|
||||
|
@ -1497,22 +1498,19 @@ iobuf_openrw (const char *fname)
|
|||
|
||||
|
||||
static iobuf_t
|
||||
do_iobuf_fdopen (int fd, const char *mode, int keep_open)
|
||||
do_iobuf_fdopen (gnupg_fd_t fp, const char *mode, int keep_open)
|
||||
{
|
||||
iobuf_t a;
|
||||
gnupg_fd_t fp;
|
||||
file_filter_ctx_t *fcx;
|
||||
size_t len = 0;
|
||||
|
||||
fp = INT2FD (fd);
|
||||
|
||||
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
|
||||
iobuf_buffer_size);
|
||||
fcx = xmalloc (sizeof *fcx + 20);
|
||||
fcx->fp = fp;
|
||||
fcx->print_only_name = 1;
|
||||
fcx->keep_open = keep_open;
|
||||
sprintf (fcx->fname, "[fd %d]", fd);
|
||||
sprintf (fcx->fname, "[fd %d]", FD_DBG (fp));
|
||||
a->filter = file_filter;
|
||||
a->filter_ov = fcx;
|
||||
file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
|
||||
|
@ -1525,15 +1523,15 @@ do_iobuf_fdopen (int fd, const char *mode, int keep_open)
|
|||
|
||||
|
||||
iobuf_t
|
||||
iobuf_fdopen (int fd, const char *mode)
|
||||
iobuf_fdopen (gnupg_fd_t fp, const char *mode)
|
||||
{
|
||||
return do_iobuf_fdopen (fd, mode, 0);
|
||||
return do_iobuf_fdopen (fp, mode, 0);
|
||||
}
|
||||
|
||||
iobuf_t
|
||||
iobuf_fdopen_nc (int fd, const char *mode)
|
||||
iobuf_fdopen_nc (gnupg_fd_t fp, const char *mode)
|
||||
{
|
||||
return do_iobuf_fdopen (fd, mode, 1);
|
||||
return do_iobuf_fdopen (fp, mode, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1585,7 +1583,7 @@ iobuf_sockopen (int fd, const char *mode)
|
|||
log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname);
|
||||
iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
|
||||
#else
|
||||
a = iobuf_fdopen (fd, mode);
|
||||
a = do_iobuf_fdopen (fd, mode, 0);
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
@ -1672,7 +1670,7 @@ iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval)
|
|||
/* Peek at a justed opened file. Use this only directly after a
|
||||
* file has been opened for reading. Don't use it after you did
|
||||
* a seek. This works only if just file filter has been
|
||||
* pushed. Expects a buffer wit size INTVAL at PTRVAL and returns
|
||||
* pushed. Expects a buffer with size INTVAL at PTRVAL and returns
|
||||
* the number of bytes put into the buffer. */
|
||||
if (DBG_IOBUF)
|
||||
log_debug ("iobuf-%d.%d: ioctl '%s' peek\n",
|
||||
|
@ -2644,20 +2642,20 @@ iobuf_get_filelength (iobuf_t a)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
gnupg_fd_t
|
||||
iobuf_get_fd (iobuf_t a)
|
||||
{
|
||||
for (; a->chain; a = a->chain)
|
||||
;
|
||||
|
||||
if (a->filter != file_filter)
|
||||
return -1;
|
||||
return GNUPG_INVALID_FD;
|
||||
|
||||
{
|
||||
file_filter_ctx_t *b = a->filter_ov;
|
||||
gnupg_fd_t fp = b->fp;
|
||||
|
||||
return FD2INT (fp);
|
||||
return fp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2948,36 +2946,6 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
|
|||
return nbytes;
|
||||
}
|
||||
|
||||
static int
|
||||
translate_file_handle (int fd, int for_write)
|
||||
{
|
||||
#if defined(HAVE_W32_SYSTEM)
|
||||
{
|
||||
int x;
|
||||
|
||||
(void)for_write;
|
||||
|
||||
if (fd == 0)
|
||||
x = (int) GetStdHandle (STD_INPUT_HANDLE);
|
||||
else if (fd == 1)
|
||||
x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
else if (fd == 2)
|
||||
x = (int) GetStdHandle (STD_ERROR_HANDLE);
|
||||
else
|
||||
x = fd;
|
||||
|
||||
if (x == -1)
|
||||
log_debug ("GetStdHandle(%d) failed: ec=%d\n",
|
||||
fd, (int) GetLastError ());
|
||||
|
||||
fd = x;
|
||||
}
|
||||
#else
|
||||
(void)for_write;
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)
|
||||
|
|
|
@ -204,7 +204,7 @@ struct iobuf_struct
|
|||
byte *buf;
|
||||
} d;
|
||||
|
||||
/* A external drain buffer for reading/writting data skipping internal
|
||||
/* A external drain buffer for reading/writing data skipping internal
|
||||
draint buffer D.BUF. This allows zerocopy operation reducing
|
||||
processing overhead across filter stack.
|
||||
|
||||
|
@ -333,11 +333,11 @@ iobuf_t iobuf_openrw (const char *fname);
|
|||
creates an input filter. Note: MODE must reflect the file
|
||||
descriptors actual mode! When the filter is destroyed, the file
|
||||
descriptor is closed. */
|
||||
iobuf_t iobuf_fdopen (int fd, const char *mode);
|
||||
iobuf_t iobuf_fdopen (gnupg_fd_t fd, const char *mode);
|
||||
|
||||
/* Like iobuf_fdopen, but doesn't close the file descriptor when the
|
||||
filter is destroyed. */
|
||||
iobuf_t iobuf_fdopen_nc (int fd, const char *mode);
|
||||
iobuf_t iobuf_fdopen_nc (gnupg_fd_t fd, const char *mode);
|
||||
|
||||
/* Create a filter using an existing estream. If MODE contains the
|
||||
letter 'w', creates an output filter. Otherwise, creates an input
|
||||
|
@ -590,7 +590,7 @@ uint64_t iobuf_get_filelength (iobuf_t a);
|
|||
|
||||
/* Return the file descriptor designating the underlying file. This
|
||||
only works with file_filter based pipelines. */
|
||||
int iobuf_get_fd (iobuf_t a);
|
||||
gnupg_fd_t iobuf_get_fd (iobuf_t a);
|
||||
|
||||
/* Return the real filename, if available. This only supports
|
||||
pipelines that end in file filters. Returns NULL if not
|
||||
|
|
220
common/kem.c
Normal file
220
common/kem.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/* kem.c - KEM helper functions
|
||||
* Copyright (C) 2024 g10 Code GmbH.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute and/or modify this
|
||||
* part of GnuPG under the terms of either
|
||||
*
|
||||
* - the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* or
|
||||
*
|
||||
* - the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* or both in parallel, as here.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received copies of the GNU General Public License
|
||||
* and the GNU Lesser General Public License along with this program;
|
||||
* if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gpg-error.h>
|
||||
#include <gcrypt.h>
|
||||
#include "mischelp.h"
|
||||
|
||||
|
||||
/* domSeperation as per *PGP specs. */
|
||||
#define KMAC_KEY "OpenPGPCompositeKeyDerivationFunction"
|
||||
|
||||
/* customizationString as per *PGP specs. */
|
||||
#define KMAC_CUSTOM "KDF"
|
||||
|
||||
/* The blocksize used for Keccak by compute_kmac256. */
|
||||
#define KECCAK512_BLOCKSIZE 136
|
||||
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
compute_kmac256 (void *digest, size_t digestlen,
|
||||
const void *key, size_t keylen,
|
||||
const void *custom, size_t customlen,
|
||||
gcry_buffer_t *data_iov, int data_iovlen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gcry_buffer_t iov[20];
|
||||
const unsigned char headPAD[2] = { 1, KECCAK512_BLOCKSIZE };
|
||||
unsigned char headK[3];
|
||||
const unsigned char pad[KECCAK512_BLOCKSIZE] = { 0 };
|
||||
unsigned char right_encode_L[3];
|
||||
unsigned int len;
|
||||
int iovcnt;
|
||||
|
||||
if (data_iovlen >= DIM(iov) - 6)
|
||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||
|
||||
/* Check the validity conditions of NIST SP 800-185 */
|
||||
if (keylen >= 255 || customlen >= 255 || digestlen >= 255)
|
||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||
|
||||
iovcnt = 0;
|
||||
iov[iovcnt].data = "KMAC";
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = 4;
|
||||
iovcnt++;
|
||||
|
||||
iov[iovcnt].data = (void *)custom;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = customlen;
|
||||
iovcnt++;
|
||||
|
||||
iov[iovcnt].data = (void *)headPAD;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = sizeof (headPAD);
|
||||
iovcnt++;
|
||||
|
||||
if (keylen < 32)
|
||||
{
|
||||
headK[0] = 1;
|
||||
headK[1] = (keylen*8)&0xff;
|
||||
iov[iovcnt].data = headK;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
headK[0] = 2;
|
||||
headK[1] = (keylen*8)>>8;
|
||||
headK[2] = (keylen*8)&0xff;
|
||||
iov[iovcnt].data = headK;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = 3;
|
||||
}
|
||||
iovcnt++;
|
||||
|
||||
iov[iovcnt].data = (void *)key;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = keylen;
|
||||
iovcnt++;
|
||||
|
||||
len = iov[2].len + iov[3].len + iov[4].len;
|
||||
len %= KECCAK512_BLOCKSIZE;
|
||||
|
||||
iov[iovcnt].data = (unsigned char *)pad;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = sizeof (pad) - len;
|
||||
iovcnt++;
|
||||
|
||||
memcpy (&iov[iovcnt], data_iov, data_iovlen * sizeof (gcry_buffer_t));
|
||||
iovcnt += data_iovlen;
|
||||
|
||||
if (digestlen < 32)
|
||||
{
|
||||
right_encode_L[0] = (digestlen * 8) & 0xff;
|
||||
right_encode_L[1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
right_encode_L[0] = (digestlen * 8) >> 8;
|
||||
right_encode_L[1] = (digestlen * 8) & 0xff;
|
||||
right_encode_L[2] = 2;
|
||||
}
|
||||
|
||||
iov[iovcnt].data = right_encode_L;
|
||||
iov[iovcnt].off = 0;
|
||||
iov[iovcnt].len = 3;
|
||||
iovcnt++;
|
||||
|
||||
err = gcry_md_hash_buffers_ext (GCRY_MD_CSHAKE256, 0,
|
||||
digest, digestlen, iov, iovcnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Compute KEK (shared secret) for ECC with HASHALGO, ECDH result,
|
||||
ciphertext in ECC_CT, public key in ECC_PK. */
|
||||
gpg_error_t
|
||||
gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
||||
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||
const void *ecc_ct, size_t ecc_ct_len,
|
||||
const void *ecc_pk, size_t ecc_pk_len)
|
||||
{
|
||||
gcry_buffer_t iov[3];
|
||||
unsigned int dlen;
|
||||
|
||||
dlen = gcry_md_get_algo_dlen (hashalgo);
|
||||
if (kek_len != dlen)
|
||||
return gpg_error (GPG_ERR_INV_LENGTH);
|
||||
|
||||
memset (iov, 0, sizeof (iov));
|
||||
|
||||
iov[0].data = (unsigned char *)ecdh;
|
||||
iov[0].len = ecdh_len;
|
||||
iov[1].data = (unsigned char *)ecc_ct;
|
||||
iov[1].len = ecc_ct_len;
|
||||
iov[2].data = (unsigned char *)ecc_pk;
|
||||
iov[2].len = ecc_pk_len;
|
||||
gcry_md_hash_buffers (hashalgo, 0, kek, iov, 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute KEK by combining two KEMs. The caller provides a buffer
|
||||
* KEK allocated with size KEK_LEN which will receive the computed
|
||||
* KEK. (ECC_SS, ECC_SS_LEN) is the shared secret of the first key.
|
||||
* (ECC_CT, ECC_CT_LEN) is the ciphertext of the first key.
|
||||
* (MLKEM_SS, ECC_SS_LEN) is the shared secret of the second key.
|
||||
* (MLKEM_CT, MLKEM_CT_LEN) is the ciphertext of the second key.
|
||||
* (FIXEDINFO, FIXEDINFO_LEN) is an octet string used to bind the KEK
|
||||
* to a the key; for PGP we use the concatenation of the session key's
|
||||
* algorithm id and the v5 fingerprint of the key.
|
||||
*/
|
||||
gpg_error_t
|
||||
gnupg_kem_combiner (void *kek, size_t kek_len,
|
||||
const void *ecc_ss, size_t ecc_ss_len,
|
||||
const void *ecc_ct, size_t ecc_ct_len,
|
||||
const void *mlkem_ss, size_t mlkem_ss_len,
|
||||
const void *mlkem_ct, size_t mlkem_ct_len,
|
||||
const void *fixedinfo, size_t fixedinfo_len)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gcry_buffer_t iov[6];
|
||||
|
||||
memset (iov, 0, sizeof (iov));
|
||||
|
||||
iov[0].data = "\x00\x00\x00\x01"; /* Counter */
|
||||
iov[0].len = 4;
|
||||
|
||||
iov[1].data = (unsigned char *)ecc_ss;
|
||||
iov[1].len = ecc_ss_len;
|
||||
|
||||
iov[2].data = (unsigned char *)ecc_ct;
|
||||
iov[2].len = ecc_ct_len;
|
||||
|
||||
iov[3].data = (unsigned char *)mlkem_ss;
|
||||
iov[3].len = mlkem_ss_len;
|
||||
|
||||
iov[4].data = (unsigned char *)mlkem_ct;
|
||||
iov[4].len = mlkem_ct_len;
|
||||
|
||||
iov[5].data = (unsigned char *)fixedinfo;
|
||||
iov[5].len = fixedinfo_len;
|
||||
|
||||
err = compute_kmac256 (kek, kek_len,
|
||||
KMAC_KEY, strlen (KMAC_KEY),
|
||||
KMAC_CUSTOM, strlen (KMAC_CUSTOM), iov, 6);
|
||||
return err;
|
||||
}
|
|
@ -36,27 +36,6 @@
|
|||
#include "iobuf.h"
|
||||
#include "i18n.h"
|
||||
|
||||
/* Used by libgcrypt for logging. */
|
||||
static void
|
||||
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
|
||||
{
|
||||
(void)dummy;
|
||||
|
||||
/* Map the log levels. */
|
||||
switch (level)
|
||||
{
|
||||
case GCRY_LOG_CONT: level = GPGRT_LOGLVL_CONT; break;
|
||||
case GCRY_LOG_INFO: level = GPGRT_LOGLVL_INFO; break;
|
||||
case GCRY_LOG_WARN: level = GPGRT_LOGLVL_WARN; break;
|
||||
case GCRY_LOG_ERROR:level = GPGRT_LOGLVL_ERROR; break;
|
||||
case GCRY_LOG_FATAL:level = GPGRT_LOGLVL_FATAL; break;
|
||||
case GCRY_LOG_BUG: level = GPGRT_LOGLVL_BUG; break;
|
||||
case GCRY_LOG_DEBUG:level = GPGRT_LOGLVL_DEBUG; break;
|
||||
default: level = GPGRT_LOGLVL_ERROR; break;
|
||||
}
|
||||
log_logv (level, fmt, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* This function is called by libgcrypt on a fatal error. */
|
||||
static void
|
||||
|
@ -100,7 +79,6 @@ my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
|
|||
void
|
||||
setup_libgcrypt_logging (void)
|
||||
{
|
||||
gcry_set_log_handler (my_gcry_logger, NULL);
|
||||
gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
|
||||
gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
|
||||
}
|
||||
|
@ -687,3 +665,53 @@ parse_compatibility_flags (const char *string, unsigned int *flagvar,
|
|||
*flagvar |= result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert STRING consisting of base64 characters into its binary
|
||||
* representation and store the result in a newly allocated buffer at
|
||||
* R_BUFFER with its length at R_BUFLEN. If TITLE is NULL a plain
|
||||
* base64 decoding is done. If it is the empty string the decoder
|
||||
* will skip everything until a "-----BEGIN " line has been seen,
|
||||
* decoding then ends at a "----END " line. On failure the function
|
||||
* returns an error code and sets R_BUFFER to NULL. If the decoded
|
||||
* data has a length of 0 a dummy buffer will still be allocated and
|
||||
* the length is set to 0. */
|
||||
gpg_error_t
|
||||
b64decode (const char *string, const char *title,
|
||||
void **r_buffer, size_t *r_buflen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gpgrt_b64state_t state;
|
||||
size_t nbytes;
|
||||
char *buffer;
|
||||
|
||||
*r_buffer = NULL;
|
||||
*r_buflen = 0;
|
||||
|
||||
buffer = xtrystrdup (string);
|
||||
if (!buffer)
|
||||
return gpg_error_from_syserror();
|
||||
|
||||
state = gpgrt_b64dec_start (title);
|
||||
if (!state)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
xfree (buffer);
|
||||
return err;
|
||||
}
|
||||
err = gpgrt_b64dec_proc (state, buffer, strlen (buffer), &nbytes);
|
||||
if (!err)
|
||||
{
|
||||
err = gpgrt_b64dec_finish (state);
|
||||
state = NULL;
|
||||
}
|
||||
if (err)
|
||||
xfree (buffer);
|
||||
else
|
||||
{
|
||||
*r_buffer = buffer;
|
||||
*r_buflen = nbytes;
|
||||
}
|
||||
gpgrt_b64dec_finish (state); /* Make sure it is released. */
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
/* Create a directory as well as any missing parents.
|
||||
|
||||
The arguments must be NULL termianted. If DIRECTORY_COMPONENTS...
|
||||
The arguments must be NULL terminated. If DIRECTORY_COMPONENTS...
|
||||
consists of two elements, "foo/bar" and "xyzzy", this function will
|
||||
first try to create the directory "foo/bar" and then the directory
|
||||
"foo/bar/xyzzy". On success returns 0, otherwise an error code is
|
||||
|
|
|
@ -136,7 +136,7 @@ compute_openpgp_fpr (int keyversion, int pgpalgo, unsigned long timestamp,
|
|||
/* log_printhex (iov[i].data, iov[i].len, "cmpfpr i=%d: ", i); */
|
||||
|
||||
err = gcry_md_hash_buffers (hashalgo, 0, result, iov, iovcnt);
|
||||
/* log_printhex (result, 20, "fingerpint: "); */
|
||||
/* log_printhex (result, 20, "fingerprint: "); */
|
||||
|
||||
/* Better clear the first element because it was set by us. */
|
||||
iov[0].size = 0;
|
||||
|
|
|
@ -43,23 +43,34 @@ static struct {
|
|||
const char *oidstr; /* IETF formatted OID. */
|
||||
unsigned int nbits; /* Nominal bit length of the curve. */
|
||||
const char *alias; /* NULL or alternative name of the curve. */
|
||||
const char *abbr; /* NULL or abbreviated name of the curve. */
|
||||
int pubkey_algo; /* Required OpenPGP algo or 0 for ECDSA/ECDH. */
|
||||
enum gcry_kem_algos kem_algo; /* 0 or the KEM algorithm for PQC. */
|
||||
} oidtable[] = {
|
||||
|
||||
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
|
||||
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
|
||||
{ "Curve25519", "1.3.101.110", 255, "cv25519", PUBKEY_ALGO_ECDH },
|
||||
{ "Ed25519", "1.3.101.112", 255, "ed25519", PUBKEY_ALGO_EDDSA },
|
||||
{ "X448", "1.3.101.111", 448, "cv448", PUBKEY_ALGO_ECDH },
|
||||
{ "Ed448", "1.3.101.113", 456, "ed448", PUBKEY_ALGO_EDDSA },
|
||||
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", NULL,
|
||||
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X25519 /* only during development */},
|
||||
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", NULL,
|
||||
PUBKEY_ALGO_EDDSA },
|
||||
{ "Curve25519", "1.3.101.110", 255, "cv25519", NULL,
|
||||
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X25519 },
|
||||
{ "Ed25519", "1.3.101.112", 255, "ed25519", NULL,
|
||||
PUBKEY_ALGO_EDDSA },
|
||||
{ "X448", "1.3.101.111", 448, "cv448", NULL,
|
||||
PUBKEY_ALGO_ECDH, GCRY_KEM_RAW_X448 },
|
||||
{ "Ed448", "1.3.101.113", 456, "ed448", NULL,
|
||||
PUBKEY_ALGO_EDDSA },
|
||||
|
||||
{ "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
|
||||
{ "NIST P-384", "1.3.132.0.34", 384, "nistp384" },
|
||||
{ "NIST P-521", "1.3.132.0.35", 521, "nistp521" },
|
||||
|
||||
{ "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", 256 },
|
||||
{ "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", 384 },
|
||||
{ "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", 512 },
|
||||
{ "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", 256, NULL, "bp256",
|
||||
0, GCRY_KEM_RAW_BP256 },
|
||||
{ "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", 384, NULL, "bp384",
|
||||
0, GCRY_KEM_RAW_BP384 },
|
||||
{ "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", 512, NULL, "bp512",
|
||||
0, GCRY_KEM_RAW_BP512 },
|
||||
|
||||
{ "secp256k1", "1.3.132.0.10", 256 },
|
||||
|
||||
|
@ -118,7 +129,7 @@ make_flagged_int (unsigned long value, char *buf, size_t buflen)
|
|||
|
||||
/* fixme: figure out the number of bits in an ulong and start with
|
||||
that value as shift (after making it a multiple of 7) a more
|
||||
straigtforward implementation is to do it in reverse order using
|
||||
straightforward implementation is to do it in reverse order using
|
||||
a temporary buffer - saves a lot of compares */
|
||||
for (more=0, shift=28; shift > 0; shift -= 7)
|
||||
{
|
||||
|
@ -477,10 +488,20 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo)
|
|||
|
||||
|
||||
/* Map an OpenPGP OID to the Libgcrypt curve name. Returns NULL for
|
||||
* unknown curve names. Unless CANON is set we prefer an alias name
|
||||
* here which is more suitable for printing. */
|
||||
* unknown curve names. MODE defines which version of the curve name
|
||||
* is returned. For example:
|
||||
*
|
||||
* | OID | mode=0 | mode=1 | mode=2 |
|
||||
* |----------------------+-----------------+-----------------+----------|
|
||||
* | 1.2.840.10045.3.1.7 | nistp256 | NIST P-256 | nistp256 |
|
||||
* | 1.3.36.3.3.2.8.1.1.7 | brainpoolP256r1 | brainpoolP256r1 | bp256 |
|
||||
*
|
||||
* Thus mode 0 returns the name as commonly used gpg, mode 1 returns
|
||||
* the canonical name, and mode 2 prefers an abbreviated name over the
|
||||
* commonly used name.
|
||||
*/
|
||||
const char *
|
||||
openpgp_oid_to_curve (const char *oidstr, int canon)
|
||||
openpgp_oid_to_curve (const char *oidstr, int mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -489,7 +510,15 @@ openpgp_oid_to_curve (const char *oidstr, int canon)
|
|||
|
||||
for (i=0; oidtable[i].name; i++)
|
||||
if (!strcmp (oidtable[i].oidstr, oidstr))
|
||||
return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
|
||||
{
|
||||
if (mode == 2)
|
||||
{
|
||||
if (oidtable[i].abbr)
|
||||
return oidtable[i].abbr;
|
||||
mode = 0; /* No abbreviation - fallback to mode 0. */
|
||||
}
|
||||
return !mode && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -517,6 +546,29 @@ openpgp_oid_or_name_to_curve (const char *oidname, int canon)
|
|||
}
|
||||
|
||||
|
||||
/* Return the KEM algorithm id for the curve with OIDNAME. */
|
||||
enum gcry_kem_algos
|
||||
openpgp_oid_to_kem_algo (const char *oidname)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!oidname)
|
||||
return 0;
|
||||
|
||||
for (i=0; oidtable[i].name; i++)
|
||||
if (!strcmp (oidtable[i].oidstr, oidname))
|
||||
return oidtable[i].kem_algo;
|
||||
|
||||
for (i=0; oidtable[i].name; i++)
|
||||
if (!ascii_strcasecmp (oidtable[i].name, oidname)
|
||||
|| (oidtable[i].alias
|
||||
&& !ascii_strcasecmp (oidtable[i].alias, oidname)))
|
||||
return oidtable[i].kem_algo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the curve with NAME is supported. */
|
||||
static int
|
||||
curve_supported_p (const char *name)
|
||||
|
@ -574,7 +626,9 @@ openpgp_is_curve_supported (const char *name, int *r_algo,
|
|||
{
|
||||
if ((!ascii_strcasecmp (name, oidtable[idx].name)
|
||||
|| (oidtable[idx].alias
|
||||
&& !ascii_strcasecmp (name, (oidtable[idx].alias))))
|
||||
&& !ascii_strcasecmp (name, (oidtable[idx].alias)))
|
||||
|| (oidtable[idx].abbr
|
||||
&& !ascii_strcasecmp (name, (oidtable[idx].abbr))))
|
||||
&& curve_supported_p (oidtable[idx].name))
|
||||
{
|
||||
if (r_algo)
|
||||
|
@ -598,6 +652,7 @@ map_gcry_pk_to_openpgp (enum gcry_pk_algos algo)
|
|||
case GCRY_PK_EDDSA: return PUBKEY_ALGO_EDDSA;
|
||||
case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA;
|
||||
case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH;
|
||||
case GCRY_PK_KEM: return PUBKEY_ALGO_KYBER;
|
||||
default: return algo < 110 ? (pubkey_algo_t)algo : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,7 +171,11 @@ typedef enum
|
|||
PUBKEY_ALGO_ECDSA = 19, /* RFC-6637 */
|
||||
PUBKEY_ALGO_ELGAMAL = 20, /* Elgamal encrypt+sign (legacy). */
|
||||
/* 21 reserved by OpenPGP. */
|
||||
PUBKEY_ALGO_EDDSA = 22, /* EdDSA (not yet assigned). */
|
||||
PUBKEY_ALGO_EDDSA = 22, /* EdDSA. */
|
||||
PUBKEY_ALGO_KYBER = 29, /* Kyber */
|
||||
PUBKEY_ALGO_DIL3_25519 = 35, /* Dilithium3 + Ed25519 (aka ML-DSA-65) */
|
||||
PUBKEY_ALGO_DIL5_448 = 36, /* Dilithium5 + Ed448 (aka ML-DSA-87) */
|
||||
PUBKEY_ALGO_SPHINX_SHA2 = 41, /* SPHINX+-simple-SHA2 (aka SLH-DSA-SHA2) */
|
||||
PUBKEY_ALGO_PRIVATE10 = 110
|
||||
}
|
||||
pubkey_algo_t;
|
||||
|
@ -206,7 +210,7 @@ compress_algo_t;
|
|||
#define OPENPGP_MAX_NPKEY 5 /* Maximum number of public key parameters. */
|
||||
#define OPENPGP_MAX_NSKEY 7 /* Maximum number of secret key parameters. */
|
||||
#define OPENPGP_MAX_NSIG 2 /* Maximum number of signature parameters. */
|
||||
#define OPENPGP_MAX_NENC 2 /* Maximum number of encryption parameters. */
|
||||
#define OPENPGP_MAX_NENC 4 /* Maximum number of encryption parameters. */
|
||||
|
||||
|
||||
/* Decode an rfc4880 encoded S2K count. */
|
||||
|
|
|
@ -315,7 +315,7 @@ session_env_putenv (session_env_t se, const char *string)
|
|||
}
|
||||
|
||||
|
||||
/* Same as session_env_putenv but with name and value given as distict
|
||||
/* Same as session_env_putenv but with name and value given as distinct
|
||||
values. */
|
||||
gpg_error_t
|
||||
session_env_setenv (session_env_t se, const char *name, const char *value)
|
||||
|
@ -355,7 +355,7 @@ session_env_getenv (session_env_t se, const char *name)
|
|||
object. The returned value is valid as long as SE is valid and as
|
||||
long it has not been removed or updated by a call to
|
||||
session_env_putenv. If the variable does not exist, the function
|
||||
tries to return the value trough a call to getenv; if that returns
|
||||
tries to return the value through a call to getenv; if that returns
|
||||
a value, this value is recorded and used. If no value could be
|
||||
found, returns NULL. The caller must not change the returned
|
||||
value. */
|
||||
|
|
|
@ -104,7 +104,7 @@ smatch (unsigned char const **buf, size_t buflen, const char *token)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Format VALUE for use as the length indicatior of an S-expression.
|
||||
/* Format VALUE for use as the length indicator of an S-expression.
|
||||
The caller needs to provide a buffer HELP_BUFFER with a length of
|
||||
HELP_BUFLEN. The return value is a pointer into HELP_BUFFER with
|
||||
the formatted length string. The colon and a trailing nul are
|
||||
|
|
|
@ -199,7 +199,7 @@ make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
|
|||
}
|
||||
|
||||
/* Return the so called "keygrip" which is the SHA-1 hash of the
|
||||
public key parameters expressed in a way dependend on the algorithm.
|
||||
public key parameters expressed in a way dependent on the algorithm.
|
||||
|
||||
KEY is expected to be an canonical encoded S-expression with a
|
||||
public or private key. KEYLEN is the length of that buffer.
|
||||
|
@ -992,7 +992,7 @@ get_pk_algo_from_key (gcry_sexp_t key)
|
|||
gcry_sexp_t list;
|
||||
const char *s;
|
||||
size_t n;
|
||||
char algoname[6];
|
||||
char algoname[10];
|
||||
int algo = 0;
|
||||
|
||||
list = gcry_sexp_nth (key, 1);
|
||||
|
@ -1194,3 +1194,47 @@ cipher_mode_to_string (int mode)
|
|||
default: return "[?]";
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the canonical name of the ECC curve in KEY. */
|
||||
const char *
|
||||
get_ecc_curve_from_key (gcry_sexp_t key)
|
||||
{
|
||||
gcry_sexp_t list = NULL;
|
||||
gcry_sexp_t l2 = NULL;
|
||||
const char *curve_name = NULL;
|
||||
char *name = NULL;
|
||||
|
||||
/* Check that the first element is valid. */
|
||||
list = gcry_sexp_find_token (key, "public-key", 0);
|
||||
if (!list)
|
||||
list = gcry_sexp_find_token (key, "private-key", 0);
|
||||
if (!list)
|
||||
list = gcry_sexp_find_token (key, "protected-private-key", 0);
|
||||
if (!list)
|
||||
list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
|
||||
if (!list)
|
||||
goto leave;
|
||||
|
||||
l2 = gcry_sexp_cadr (list);
|
||||
gcry_sexp_release (list);
|
||||
list = l2;
|
||||
l2 = NULL;
|
||||
|
||||
name = gcry_sexp_nth_string (list, 0);
|
||||
if (!name)
|
||||
goto leave;
|
||||
|
||||
if (gcry_pk_map_name (name) != GCRY_PK_ECC)
|
||||
goto leave;
|
||||
|
||||
l2 = gcry_sexp_find_token (list, "curve", 0);
|
||||
xfree (name);
|
||||
name = gcry_sexp_nth_string (l2, 1);
|
||||
curve_name = openpgp_oid_or_name_to_curve (name, 1);
|
||||
gcry_sexp_release (l2);
|
||||
|
||||
leave:
|
||||
xfree (name);
|
||||
gcry_sexp_release (list);
|
||||
return curve_name;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
|
|||
}
|
||||
else
|
||||
{
|
||||
struct b64state b64s;
|
||||
gpgrt_b64state_t b64s;
|
||||
estream_t stream;
|
||||
char *p;
|
||||
long int len;
|
||||
|
@ -273,15 +273,15 @@ get_fingerprint (gcry_sexp_t key, int algo,
|
|||
goto leave;
|
||||
}
|
||||
|
||||
err = b64enc_start_es (&b64s, stream, "");
|
||||
if (err)
|
||||
b64s = gpgrt_b64enc_start (stream, "");
|
||||
if (!b64s)
|
||||
{
|
||||
es_fclose (stream);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = b64enc_write (&b64s,
|
||||
gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo));
|
||||
err = gpgrt_b64enc_write (b64s, gcry_md_read (md, algo),
|
||||
gcry_md_get_algo_dlen (algo));
|
||||
if (err)
|
||||
{
|
||||
es_fclose (stream);
|
||||
|
@ -289,7 +289,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
|
|||
}
|
||||
|
||||
/* Finish, get the length, and close the stream. */
|
||||
err = b64enc_finish (&b64s);
|
||||
err = gpgrt_b64enc_finish (b64s);
|
||||
len = es_ftell (stream);
|
||||
es_fclose (stream);
|
||||
if (err)
|
||||
|
@ -566,7 +566,7 @@ ssh_public_key_in_base64 (gcry_sexp_t key, estream_t stream,
|
|||
const char *identifier = NULL;
|
||||
void *blob = NULL;
|
||||
size_t bloblen;
|
||||
struct b64state b64_state;
|
||||
gpgrt_b64state_t b64_state;
|
||||
|
||||
algo = get_pk_algo_from_key (key);
|
||||
if (algo == 0)
|
||||
|
@ -624,15 +624,15 @@ ssh_public_key_in_base64 (gcry_sexp_t key, estream_t stream,
|
|||
|
||||
es_fprintf (stream, "%s ", identifier);
|
||||
|
||||
err = b64enc_start_es (&b64_state, stream, "");
|
||||
if (err)
|
||||
b64_state = gpgrt_b64enc_start (stream, "");
|
||||
if (!b64_state)
|
||||
{
|
||||
es_free (blob);
|
||||
return err;
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
err = b64enc_write (&b64_state, blob, bloblen);
|
||||
b64enc_finish (&b64_state);
|
||||
err = gpgrt_b64enc_write (b64_state, blob, bloblen);
|
||||
gpgrt_b64enc_finish (b64_state);
|
||||
es_free (blob);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
118
common/strlist.c
118
common/strlist.c
|
@ -1,6 +1,6 @@
|
|||
/* strlist.c - string helpers
|
||||
* Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2015 g10 Code GmbH
|
||||
* Copyright (C) 2015, 2024 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
|
@ -27,6 +27,7 @@
|
|||
* You should have received a copies of the GNU General Public License
|
||||
* and the GNU Lesser General Public License along with this program;
|
||||
* if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
@ -134,27 +135,39 @@ append_to_strlist( strlist_t *list, const char *string )
|
|||
}
|
||||
|
||||
|
||||
/* Core of append_to_strlist_try which take the length of the string.
|
||||
* Return the item added to the end of the list. Or NULL in case of
|
||||
* an error. */
|
||||
static strlist_t
|
||||
do_append_to_strlist (strlist_t *list, const char *string, size_t stringlen)
|
||||
{
|
||||
strlist_t r, sl;
|
||||
|
||||
sl = xtrymalloc (sizeof *sl + stringlen);
|
||||
if (!sl)
|
||||
return NULL;
|
||||
|
||||
sl->flags = 0;
|
||||
memcpy (sl->d, string, stringlen);
|
||||
sl->d[stringlen] = 0;
|
||||
sl->next = NULL;
|
||||
if (!*list)
|
||||
*list = sl;
|
||||
else
|
||||
{
|
||||
for (r = *list; r->next; r = r->next)
|
||||
;
|
||||
r->next = sl;
|
||||
}
|
||||
return sl;
|
||||
}
|
||||
|
||||
|
||||
/* Add STRING to the LIST at the end. */
|
||||
strlist_t
|
||||
append_to_strlist_try (strlist_t *list, const char *string)
|
||||
{
|
||||
strlist_t r, sl;
|
||||
|
||||
sl = xtrymalloc( sizeof *sl + strlen(string));
|
||||
if (sl == NULL)
|
||||
return NULL;
|
||||
|
||||
sl->flags = 0;
|
||||
strcpy(sl->d, string);
|
||||
sl->next = NULL;
|
||||
if( !*list )
|
||||
*list = sl;
|
||||
else {
|
||||
for( r = *list; r->next; r = r->next )
|
||||
;
|
||||
r->next = sl;
|
||||
}
|
||||
return sl;
|
||||
return do_append_to_strlist (list, string, strlen (string));
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,6 +188,75 @@ append_to_strlist2( strlist_t *list, const char *string, int is_utf8 )
|
|||
}
|
||||
|
||||
|
||||
/* Tokenize STRING using the delimiters from DELIM and append each
|
||||
* token to the string list LIST. On success a pinter into LIST with
|
||||
* the first new token is returned. Returns NULL on error and sets
|
||||
* ERRNO. Take care, an error with ENOENT set mean that no tokens
|
||||
* were found in STRING. */
|
||||
strlist_t
|
||||
tokenize_to_strlist (strlist_t *list, const char *string, const char *delim)
|
||||
{
|
||||
const char *s, *se;
|
||||
size_t n;
|
||||
strlist_t newlist = NULL;
|
||||
strlist_t tail;
|
||||
|
||||
s = string;
|
||||
do
|
||||
{
|
||||
se = strpbrk (s, delim);
|
||||
if (se)
|
||||
n = se - s;
|
||||
else
|
||||
n = strlen (s);
|
||||
if (!n)
|
||||
continue; /* Skip empty string. */
|
||||
tail = do_append_to_strlist (&newlist, s, n);
|
||||
if (!tail)
|
||||
{
|
||||
free_strlist (newlist);
|
||||
return NULL;
|
||||
}
|
||||
trim_spaces (tail->d);
|
||||
if (!*tail->d) /* Remove new but empty item from the list. */
|
||||
{
|
||||
tail = strlist_prev (newlist, tail);
|
||||
if (tail)
|
||||
{
|
||||
free_strlist (tail->next);
|
||||
tail->next = NULL;
|
||||
}
|
||||
else if (newlist)
|
||||
{
|
||||
free_strlist (newlist);
|
||||
newlist = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (se && (s = se + 1));
|
||||
|
||||
if (!newlist)
|
||||
{
|
||||
/* Not items found. Indicate this by returnning NULL with errno
|
||||
* set to ENOENT. */
|
||||
gpg_err_set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Append NEWLIST to LIST. */
|
||||
if (!*list)
|
||||
*list = newlist;
|
||||
else
|
||||
{
|
||||
for (tail = *list; tail->next; tail = tail->next)
|
||||
;
|
||||
tail->next = newlist;
|
||||
}
|
||||
return newlist;
|
||||
}
|
||||
|
||||
|
||||
/* Return a copy of LIST. This function terminates the process on
|
||||
memory shortage.*/
|
||||
strlist_t
|
||||
|
|
|
@ -52,6 +52,9 @@ strlist_t append_to_strlist_try (strlist_t *list, const char *string);
|
|||
strlist_t append_to_strlist2 (strlist_t *list, const char *string,
|
||||
int is_utf8);
|
||||
|
||||
strlist_t tokenize_to_strlist (strlist_t *list,
|
||||
const char *string, const char *delim);
|
||||
|
||||
strlist_t strlist_copy (strlist_t list);
|
||||
|
||||
strlist_t strlist_prev (strlist_t head, strlist_t node);
|
||||
|
|
|
@ -113,6 +113,8 @@ static int allow_special_filenames;
|
|||
#ifdef HAVE_W32_SYSTEM
|
||||
/* State of gnupg_inhibit_set_foregound_window. */
|
||||
static int inhibit_set_foregound_window;
|
||||
/* Disable the use of _open_osfhandle. */
|
||||
static int no_translate_sys2libc_fd;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -351,6 +353,16 @@ enable_special_filenames (void)
|
|||
}
|
||||
|
||||
|
||||
/* Disable the use use of _open_osfhandle on Windows. */
|
||||
void
|
||||
disable_translate_sys2libc_fd (void)
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
no_translate_sys2libc_fd = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Return a string which is used as a kind of process ID. */
|
||||
const byte *
|
||||
get_session_marker (size_t *rlen)
|
||||
|
@ -537,10 +549,10 @@ gnupg_usleep (unsigned int usecs)
|
|||
different from the libc file descriptors (like open). This function
|
||||
translates system file handles to libc file handles. FOR_WRITE
|
||||
gives the direction of the handle. */
|
||||
int
|
||||
#if defined(HAVE_W32_SYSTEM)
|
||||
static int
|
||||
translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
|
||||
{
|
||||
#if defined(HAVE_W32_SYSTEM)
|
||||
int x;
|
||||
|
||||
if (fd == GNUPG_INVALID_FD)
|
||||
|
@ -552,27 +564,87 @@ translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
|
|||
if (x == -1)
|
||||
log_error ("failed to translate osfhandle %p\n", (void *) fd);
|
||||
return x;
|
||||
#else /*!HAVE_W32_SYSTEM */
|
||||
}
|
||||
#endif /*!HAVE_W32_SYSTEM */
|
||||
|
||||
|
||||
/* This is the same as translate_sys2libc_fd but takes an integer
|
||||
which is assumed to be such an system handle. */
|
||||
int
|
||||
translate_sys2libc_fd_int (int fd, int for_write)
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if (fd <= 2 || no_translate_sys2libc_fd)
|
||||
return fd; /* Do not do this for stdin, stdout, and stderr. */
|
||||
|
||||
return translate_sys2libc_fd ((void*)(intptr_t)fd, for_write);
|
||||
#else
|
||||
(void)for_write;
|
||||
return fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is the same as translate_sys2libc_fd but takes an integer
|
||||
which is assumed to be such an system handle. On WindowsCE the
|
||||
passed FD is a rendezvous ID and the function finishes the pipe
|
||||
creation. */
|
||||
int
|
||||
translate_sys2libc_fd_int (int fd, int for_write)
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if (fd <= 2)
|
||||
return fd; /* Do not do this for error, stdin, stdout, stderr. */
|
||||
|
||||
return translate_sys2libc_fd ((void*)fd, for_write);
|
||||
/*
|
||||
* Parse the string representation of a file reference (file handle on
|
||||
* Windows or file descriptor on POSIX) in FDSTR. The string
|
||||
* representation may be either of following:
|
||||
|
||||
* (1) 0, 1, or 2 which means stdin, stdout, and stderr, respectively.
|
||||
* (2) Integer representation (by %d of printf).
|
||||
* (3) Hex representation which starts as "0x".
|
||||
*
|
||||
* Then, fill R_SYSHD, according to the value of a file reference.
|
||||
*
|
||||
*/
|
||||
gpg_error_t
|
||||
gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd)
|
||||
{
|
||||
int fd = -1;
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
gnupg_fd_t hd;
|
||||
char *endptr;
|
||||
int base;
|
||||
|
||||
if (!strcmp (fdstr, "0"))
|
||||
fd = 0;
|
||||
else if (!strcmp (fdstr, "1"))
|
||||
fd = 1;
|
||||
else if (!strcmp (fdstr, "2"))
|
||||
fd = 2;
|
||||
|
||||
if (fd >= 0)
|
||||
{
|
||||
r_syshd->type = ES_SYSHD_FD;
|
||||
r_syshd->u.fd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strncmp (fdstr, "0x", 2))
|
||||
{
|
||||
base = 16;
|
||||
fdstr += 2;
|
||||
}
|
||||
else
|
||||
base = 10;
|
||||
|
||||
gpg_err_set_errno (0);
|
||||
#ifdef _WIN64
|
||||
hd = (gnupg_fd_t)strtoll (fdstr, &endptr, base);
|
||||
#else
|
||||
(void)for_write;
|
||||
return fd;
|
||||
hd = (gnupg_fd_t)strtol (fdstr, &endptr, base);
|
||||
#endif
|
||||
if (errno != 0 || endptr == fdstr || *endptr != '\0')
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
r_syshd->type = ES_SYSHD_HANDLE;
|
||||
r_syshd->u.handle = hd;
|
||||
return 0;
|
||||
#else
|
||||
fd = atoi (fdstr);
|
||||
r_syshd->type = ES_SYSHD_FD;
|
||||
r_syshd->u.fd = fd;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -594,13 +666,74 @@ check_special_filename (const char *fname, int for_write, int notranslate)
|
|||
for (i=0; digitp (fname+i); i++ )
|
||||
;
|
||||
if (!fname[i])
|
||||
return notranslate? atoi (fname)
|
||||
/**/ : translate_sys2libc_fd_int (atoi (fname), for_write);
|
||||
{
|
||||
if (notranslate)
|
||||
return atoi (fname);
|
||||
else
|
||||
{
|
||||
es_syshd_t syshd;
|
||||
|
||||
if (gnupg_parse_fdstr (fname, &syshd))
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if (syshd.type == ES_SYSHD_FD)
|
||||
return syshd.u.fd;
|
||||
else
|
||||
return translate_sys2libc_fd ((gnupg_fd_t)syshd.u.handle, for_write);
|
||||
#else
|
||||
(void)for_write;
|
||||
return syshd.u.fd;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether FNAME has the form "-&nnnn", where N is a number
|
||||
* representing a file. Returns GNUPG_INVALID_FD if it is not the
|
||||
* case. Returns a file descriptor on POSIX, a system handle on
|
||||
* Windows. */
|
||||
gnupg_fd_t
|
||||
gnupg_check_special_filename (const char *fname)
|
||||
{
|
||||
if (allow_special_filenames
|
||||
&& fname && *fname == '-' && fname[1] == '&')
|
||||
{
|
||||
int i;
|
||||
|
||||
fname += 2;
|
||||
for (i=0; digitp (fname+i); i++ )
|
||||
;
|
||||
if (!fname[i])
|
||||
{
|
||||
es_syshd_t syshd;
|
||||
|
||||
if (gnupg_parse_fdstr (fname, &syshd))
|
||||
return GNUPG_INVALID_FD;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if (syshd.type == ES_SYSHD_FD)
|
||||
{
|
||||
if (syshd.u.fd == 0)
|
||||
return GetStdHandle (STD_INPUT_HANDLE);
|
||||
else if (syshd.u.fd == 1)
|
||||
return GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
else if (syshd.u.fd == 2)
|
||||
return GetStdHandle (STD_ERROR_HANDLE);
|
||||
}
|
||||
else
|
||||
return syshd.u.handle;
|
||||
#else
|
||||
return syshd.u.fd;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return GNUPG_INVALID_FD;
|
||||
}
|
||||
|
||||
/* Replacement for tmpfile(). This is required because the tmpfile
|
||||
function of Windows' runtime library is broken, insecure, ignores
|
||||
TMPDIR and so on. In addition we create a file with an inheritable
|
||||
|
@ -973,7 +1106,7 @@ modestr_to_mode (const char *modestr, mode_t oldmode)
|
|||
int
|
||||
gnupg_mkdir (const char *name, const char *modestr)
|
||||
{
|
||||
/* Note that gpgrt_mkdir also sets ERRNO in addition to returing an
|
||||
/* Note that gpgrt_mkdir also sets ERRNO in addition to returning an
|
||||
* gpg-error style error code. */
|
||||
return gpgrt_mkdir (name, modestr);
|
||||
}
|
||||
|
@ -1158,6 +1291,19 @@ gnupg_setenv (const char *name, const char *value, int overwrite)
|
|||
return setenv (name, value, overwrite);
|
||||
#else /*!HAVE_SETENV*/
|
||||
if (! getenv (name) || overwrite)
|
||||
#if defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||
{
|
||||
int e = _putenv_s (name, value);
|
||||
|
||||
if (e)
|
||||
{
|
||||
gpg_err_set_errno (e);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
{
|
||||
char *buf;
|
||||
|
||||
|
@ -1175,6 +1321,7 @@ gnupg_setenv (const char *name, const char *value, int overwrite)
|
|||
# endif
|
||||
return putenv (buf);
|
||||
}
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
return 0;
|
||||
#endif /*!HAVE_SETENV*/
|
||||
}
|
||||
|
@ -1199,6 +1346,18 @@ gnupg_unsetenv (const char *name)
|
|||
|
||||
#ifdef HAVE_UNSETENV
|
||||
return unsetenv (name);
|
||||
#elif defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||
{
|
||||
int e = _putenv_s (name, "");
|
||||
|
||||
if (e)
|
||||
{
|
||||
gpg_err_set_errno (e);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#else /*!HAVE_UNSETENV*/
|
||||
{
|
||||
char *buf;
|
||||
|
@ -1829,3 +1988,22 @@ gnupg_fd_valid (int fd)
|
|||
close (d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Open a stream from FD (a file descriptor on POSIX, a system
|
||||
handle on Windows), non-closed. */
|
||||
estream_t
|
||||
open_stream_nc (gnupg_fd_t fd, const char *mode)
|
||||
{
|
||||
es_syshd_t syshd;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
syshd.type = ES_SYSHD_HANDLE;
|
||||
syshd.u.handle = fd;
|
||||
#else
|
||||
syshd.type = ES_SYSHD_FD;
|
||||
syshd.u.fd = fd;
|
||||
#endif
|
||||
|
||||
return es_sysopen_nc (&syshd, mode);
|
||||
}
|
||||
|
|
|
@ -38,12 +38,20 @@
|
|||
typedef void *gnupg_fd_t;
|
||||
#define GNUPG_INVALID_FD ((void*)(-1))
|
||||
#define INT2FD(s) ((void *)(s))
|
||||
#define FD2INT(h) ((unsigned int)(h))
|
||||
# ifdef _WIN64
|
||||
# define FD2INT(h) ((intptr_t)(h))
|
||||
# else
|
||||
# define FD2INT(h) ((unsigned int)(h))
|
||||
# endif
|
||||
#define FD_DBG(h) ((int)(intptr_t)(h))
|
||||
#define FD2NUM(h) ((int)(intptr_t)(h))
|
||||
#else
|
||||
typedef int gnupg_fd_t;
|
||||
#define GNUPG_INVALID_FD (-1)
|
||||
#define INT2FD(s) (s)
|
||||
#define FD2INT(h) (h)
|
||||
#define FD_DBG(h) (h)
|
||||
#define FD2NUM(h) (h)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STAT
|
||||
|
@ -67,14 +75,17 @@ void trap_unaligned (void);
|
|||
int disable_core_dumps (void);
|
||||
int enable_core_dumps (void);
|
||||
void enable_special_filenames (void);
|
||||
void disable_translate_sys2libc_fd (void);
|
||||
|
||||
const unsigned char *get_session_marker (size_t *rlen);
|
||||
unsigned int get_uint_nonce (void);
|
||||
/*int check_permissions (const char *path,int extension,int checkonly);*/
|
||||
void gnupg_sleep (unsigned int seconds);
|
||||
void gnupg_usleep (unsigned int usecs);
|
||||
int translate_sys2libc_fd (gnupg_fd_t fd, int for_write);
|
||||
int translate_sys2libc_fd_int (int fd, int for_write);
|
||||
gpg_error_t gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd);
|
||||
int check_special_filename (const char *fname, int for_write, int notranslate);
|
||||
gnupg_fd_t gnupg_check_special_filename (const char *fname);
|
||||
FILE *gnupg_tmpfile (void);
|
||||
void gnupg_reopen_std (const char *pgmname);
|
||||
void gnupg_inhibit_set_foregound_window (int yes);
|
||||
|
@ -108,6 +119,7 @@ gpg_error_t gnupg_inotify_watch_delete_self (int *r_fd, const char *fname);
|
|||
gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name);
|
||||
int gnupg_inotify_has_name (int fd, const char *name);
|
||||
|
||||
estream_t open_stream_nc (gnupg_fd_t fd, const char *mode);
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
int gnupg_w32_set_errno (int ec);
|
||||
|
|
283
common/t-b64.c
283
common/t-b64.c
|
@ -1,283 +0,0 @@
|
|||
/* t-b64.c - Module tests for b64enc.c and b64dec.c
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2008, 2023 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#define pass() do { ; } while(0)
|
||||
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
|
||||
__FILE__,__LINE__, (a)); \
|
||||
errcount++; \
|
||||
} while(0)
|
||||
#define oops() do { fprintf (stderr, "%s:%d: ooops\n", \
|
||||
__FILE__,__LINE__); \
|
||||
exit (2); \
|
||||
} while(0)
|
||||
|
||||
static int verbose;
|
||||
static int errcount;
|
||||
|
||||
|
||||
/* Convert STRING consisting of hex characters into its binary
|
||||
* representation and return it as an allocated buffer. The valid
|
||||
* length of the buffer is returned at R_LENGTH. The string is
|
||||
* delimited by end of string. The function returns NULL on
|
||||
* error. */
|
||||
static void *
|
||||
hex2buffer (const char *string, size_t *r_length)
|
||||
{
|
||||
const char *s;
|
||||
unsigned char *buffer;
|
||||
size_t length;
|
||||
|
||||
buffer = xmalloc (strlen(string)/2+1);
|
||||
length = 0;
|
||||
for (s=string; *s; s +=2 )
|
||||
{
|
||||
if (!hexdigitp (s) || !hexdigitp (s+1))
|
||||
return NULL; /* Invalid hex digits. */
|
||||
((unsigned char*)buffer)[length++] = xtoi_2 (s);
|
||||
}
|
||||
*r_length = length;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_b64decode (void)
|
||||
{
|
||||
static struct {
|
||||
const char *string; /* String to test. */
|
||||
const char *title; /* title parameter. */
|
||||
gpg_error_t err; /* expected error. */
|
||||
const char *datastr; /* Expected data (hex encoded) */
|
||||
} tests[] = {
|
||||
{ "YQ==", NULL, 0,
|
||||
"61" },
|
||||
{ "YWE==", NULL, 0,
|
||||
"6161" },
|
||||
{ "YWFh", NULL, 0,
|
||||
"616161" },
|
||||
{ "YWFhYQ==", NULL, 0,
|
||||
"61616161" },
|
||||
{ "YWJjZA==", NULL, 0,
|
||||
"61626364" },
|
||||
{ "AA=", NULL, 0,
|
||||
"00" },
|
||||
{ "AAEA=", NULL, 0,
|
||||
"000100" },
|
||||
{ "/w==", NULL, 0,
|
||||
"ff" },
|
||||
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECAg==", NULL, 0,
|
||||
"a1143012a0030a0103a10b06092a864882f712010202" },
|
||||
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECA-==", NULL, GPG_ERR_BAD_DATA,
|
||||
"a1143012a0030a0103a10b06092a864882f712010202" },
|
||||
{ "oRQwEqADCgEDoQsGCSqGSIL3EgECAg==", "", 0,
|
||||
"" },
|
||||
{ "-----BEGIN PGP\n\n"
|
||||
"oRQwEqADCgEDoQsGCSqGSIL3EgECAg==\n"
|
||||
"-----END PGP\n", "", 0,
|
||||
"a1143012a0030a0103a10b06092a864882f712010202" },
|
||||
|
||||
{ "", NULL, 0,
|
||||
"" }
|
||||
};
|
||||
int tidx;
|
||||
gpg_error_t err;
|
||||
void *data = NULL;
|
||||
size_t datalen;
|
||||
char *wantdata = NULL;
|
||||
size_t wantdatalen;
|
||||
|
||||
for (tidx = 0; tidx < DIM(tests); tidx++)
|
||||
{
|
||||
xfree (wantdata);
|
||||
if (!(wantdata = hex2buffer (tests[tidx].datastr, &wantdatalen)))
|
||||
oops ();
|
||||
xfree (data);
|
||||
err = b64decode (tests[tidx].string, tests[tidx].title, &data, &datalen);
|
||||
if (verbose)
|
||||
fprintf (stderr, "%s:%d: test %d, err=%d, datalen=%zu\n",
|
||||
__FILE__, __LINE__, tidx, err, datalen);
|
||||
if (gpg_err_code (err) != tests[tidx].err)
|
||||
fail (tidx);
|
||||
else if (err)
|
||||
pass ();
|
||||
else if (wantdatalen != datalen)
|
||||
fail (tidx);
|
||||
else if (memcmp (wantdata, data, datalen))
|
||||
fail (tidx);
|
||||
else
|
||||
pass ();
|
||||
}
|
||||
xfree (wantdata);
|
||||
xfree (data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_b64enc_pgp (const char *string)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state state;
|
||||
|
||||
if (!string)
|
||||
string = "a";
|
||||
|
||||
err = b64enc_start (&state, stdout, "PGP MESSAGE");
|
||||
if (err)
|
||||
fail (1);
|
||||
|
||||
err = b64enc_write (&state, string, strlen (string));
|
||||
if (err)
|
||||
fail (2);
|
||||
|
||||
err = b64enc_finish (&state);
|
||||
if (err)
|
||||
fail (3);
|
||||
|
||||
pass ();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_b64enc_file (const char *fname)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state state;
|
||||
FILE *fp;
|
||||
char buffer[50];
|
||||
size_t nread;
|
||||
|
||||
fp = fname ? fopen (fname, "r") : stdin;
|
||||
if (!fp)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: can't open '%s': %s\n",
|
||||
__FILE__, __LINE__, fname? fname:"[stdin]", strerror (errno));
|
||||
fail (0);
|
||||
}
|
||||
|
||||
err = b64enc_start (&state, stdout, "DATA");
|
||||
if (err)
|
||||
fail (1);
|
||||
|
||||
while ( (nread = fread (buffer, 1, sizeof buffer, fp)) )
|
||||
{
|
||||
err = b64enc_write (&state, buffer, nread);
|
||||
if (err)
|
||||
fail (2);
|
||||
}
|
||||
|
||||
err = b64enc_finish (&state);
|
||||
if (err)
|
||||
fail (3);
|
||||
|
||||
fclose (fp);
|
||||
pass ();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_b64dec_file (const char *fname)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state state;
|
||||
FILE *fp;
|
||||
char buffer[50];
|
||||
size_t nread, nbytes;
|
||||
|
||||
fp = fname ? fopen (fname, "r") : stdin;
|
||||
if (!fp)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: can't open '%s': %s\n",
|
||||
__FILE__, __LINE__, fname? fname:"[stdin]", strerror (errno));
|
||||
fail (0);
|
||||
}
|
||||
|
||||
err = b64dec_start (&state, "");
|
||||
if (err)
|
||||
fail (1);
|
||||
|
||||
while ( (nread = fread (buffer, 1, sizeof buffer, fp)) )
|
||||
{
|
||||
err = b64dec_proc (&state, buffer, nread, &nbytes);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_EOF)
|
||||
break;
|
||||
fail (2);
|
||||
}
|
||||
else if (nbytes)
|
||||
fwrite (buffer, 1, nbytes, stdout);
|
||||
}
|
||||
|
||||
err = b64dec_finish (&state);
|
||||
if (err)
|
||||
fail (3);
|
||||
|
||||
fclose (fp);
|
||||
pass ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int do_encode = 0;
|
||||
int do_decode = 0;
|
||||
int do_pgpdecode = 0;
|
||||
|
||||
if (argc)
|
||||
{ argc--; argv++; }
|
||||
if (argc && !strcmp (argv[0], "--verbose"))
|
||||
{
|
||||
verbose = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (argc && !strcmp (argv[0], "--encode"))
|
||||
{
|
||||
do_encode = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (argc && !strcmp (argv[0], "--decode"))
|
||||
{
|
||||
do_decode = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
else if (argc)
|
||||
do_pgpdecode = 1;
|
||||
|
||||
if (do_encode)
|
||||
test_b64enc_file (argc? *argv: NULL);
|
||||
else if (do_decode)
|
||||
test_b64dec_file (argc? *argv: NULL);
|
||||
else if (do_pgpdecode)
|
||||
test_b64enc_pgp (argc? *argv: NULL);
|
||||
else
|
||||
test_b64decode ();
|
||||
|
||||
return !!errcount;
|
||||
}
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static int verbose;
|
||||
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
static void
|
||||
print_open_fds (int *array)
|
||||
{
|
||||
|
@ -169,20 +169,168 @@ test_close_all_fds (void)
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static char buff12k[1024*12];
|
||||
static char buff4k[1024*4];
|
||||
|
||||
static void
|
||||
run_server (void)
|
||||
{
|
||||
estream_t fp;
|
||||
int i;
|
||||
char *p;
|
||||
unsigned int len;
|
||||
int ret;
|
||||
es_syshd_t syshd;
|
||||
size_t n;
|
||||
off_t o;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
syshd.type = ES_SYSHD_HANDLE;
|
||||
syshd.u.handle = (HANDLE)_get_osfhandle (1);
|
||||
#else
|
||||
syshd.type = ES_SYSHD_FD;
|
||||
syshd.u.fd = 1;
|
||||
#endif
|
||||
|
||||
fp = es_sysopen_nc (&syshd, "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf (stderr, "es_fdopen failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Fill the buffer by ASCII chars. */
|
||||
p = buff12k;
|
||||
for (i = 0; i < sizeof (buff12k); i++)
|
||||
if ((i % 64) == 63)
|
||||
*p++ = '\n';
|
||||
else
|
||||
*p++ = (i % 64) + '@';
|
||||
|
||||
len = sizeof (buff12k);
|
||||
|
||||
ret = es_write (fp, (void *)&len, sizeof (len), NULL);
|
||||
if (ret)
|
||||
{
|
||||
fprintf (stderr, "es_write (1) failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
es_fflush (fp);
|
||||
|
||||
o = 0;
|
||||
n = len;
|
||||
|
||||
while (1)
|
||||
{
|
||||
size_t n0, n1;
|
||||
|
||||
n0 = n > 4096 ? 4096 : n;
|
||||
memcpy (buff4k, buff12k + o, n0);
|
||||
|
||||
ret = es_write (fp, buff4k, n0, &n1);
|
||||
if (ret || n0 != n1)
|
||||
{
|
||||
fprintf (stderr, "es_write (2) failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
o += n0;
|
||||
n -= n0;
|
||||
if (n == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
es_fclose (fp);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_pipe_stream (const char *pgmname)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gnupg_process_t proc;
|
||||
estream_t outfp;
|
||||
const char *argv[2];
|
||||
unsigned int len;
|
||||
size_t n;
|
||||
off_t o;
|
||||
int ret;
|
||||
|
||||
argv[0] = "--server";
|
||||
argv[1] = NULL;
|
||||
|
||||
err = gnupg_process_spawn (pgmname, argv,
|
||||
(GNUPG_PROCESS_STDOUT_PIPE
|
||||
|GNUPG_PROCESS_STDERR_KEEP),
|
||||
NULL, &proc);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, "gnupg_process_spawn failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gnupg_process_get_streams (proc, 0, NULL, &outfp, NULL);
|
||||
|
||||
ret = es_read (outfp, (void *)&len, sizeof (len), NULL);
|
||||
if (ret)
|
||||
{
|
||||
fprintf (stderr, "es_read (1) failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
o = 0;
|
||||
while (1)
|
||||
{
|
||||
if (es_feof (outfp))
|
||||
break;
|
||||
|
||||
ret = es_read (outfp, buff4k, sizeof (buff4k), &n);
|
||||
if (ret)
|
||||
{
|
||||
fprintf (stderr, "es_read (2) failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
memcpy (buff12k + o, buff4k, n);
|
||||
o += n;
|
||||
}
|
||||
|
||||
if (o != sizeof (buff12k))
|
||||
{
|
||||
fprintf (stderr, "received data with wrong length %d\n", (int)o);
|
||||
exit (1);
|
||||
}
|
||||
es_fclose (outfp);
|
||||
gnupg_process_release (proc);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const char *myname = "no-pgm";
|
||||
|
||||
if (argc)
|
||||
{ argc--; argv++; }
|
||||
{
|
||||
myname = argv[0];
|
||||
argc--; argv++;
|
||||
}
|
||||
if (argc && !strcmp (argv[0], "--verbose"))
|
||||
{
|
||||
verbose = 1;
|
||||
argc--; argv++;
|
||||
}
|
||||
if (argc && !strcmp (argv[0], "--server"))
|
||||
run_server ();
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
test_close_all_fds ();
|
||||
#endif
|
||||
test_pipe_stream (myname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
/* t-iobuf.c - Simple module test for iobuf.c
|
||||
* Copyright (C) 2015 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either
|
||||
*
|
||||
* - the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* or
|
||||
*
|
||||
* - the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* or both in parallel, as here.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
|
||||
*/
|
||||
|
||||
/* The whole code here does not very fill into our general test frame
|
||||
* work pattern. But let's keep it as it is. */
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -7,6 +40,20 @@
|
|||
#include "iobuf.h"
|
||||
#include "stringhelp.h"
|
||||
|
||||
|
||||
static void *
|
||||
xmalloc (size_t n)
|
||||
{
|
||||
void *p = malloc (n);
|
||||
if (!p)
|
||||
{
|
||||
fprintf (stderr, "t-iobuf: out of core\n");
|
||||
abort ();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Return every other byte. In particular, reads two bytes, returns
|
||||
the second one. */
|
||||
static int
|
||||
|
@ -86,7 +133,7 @@ static struct content_filter_state *
|
|||
content_filter_new (const char *buffer)
|
||||
{
|
||||
struct content_filter_state *state
|
||||
= malloc (sizeof (struct content_filter_state));
|
||||
= xmalloc (sizeof (struct content_filter_state));
|
||||
|
||||
state->pos = 0;
|
||||
state->len = strlen (buffer);
|
||||
|
@ -215,8 +262,7 @@ main (int argc, char *argv[])
|
|||
allocate a buffer that is 5 bytes long, then no reallocation
|
||||
should be required. */
|
||||
size = 5;
|
||||
buffer = malloc (size);
|
||||
assert (buffer);
|
||||
buffer = xmalloc (size);
|
||||
max_len = 100;
|
||||
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
|
||||
assert (n == 4);
|
||||
|
@ -229,7 +275,7 @@ main (int argc, char *argv[])
|
|||
requires 6 bytes of storage. We pass a buffer that is 5 bytes
|
||||
large and we allow the buffer to be grown. */
|
||||
size = 5;
|
||||
buffer = malloc (size);
|
||||
buffer = xmalloc (size);
|
||||
max_len = 100;
|
||||
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
|
||||
assert (n == 5);
|
||||
|
@ -243,7 +289,7 @@ main (int argc, char *argv[])
|
|||
requires 7 bytes of storage. We pass a buffer that is 5 bytes
|
||||
large and we don't allow the buffer to be grown. */
|
||||
size = 5;
|
||||
buffer = malloc (size);
|
||||
buffer = xmalloc (size);
|
||||
max_len = 5;
|
||||
n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
|
||||
assert (n == 4);
|
||||
|
|
|
@ -72,6 +72,194 @@ test_strlist_rev (void)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
test_tokenize_to_strlist (void)
|
||||
{
|
||||
struct {
|
||||
const char *s;
|
||||
const char *delim;
|
||||
int error_expected;
|
||||
const char *items_expected[10];
|
||||
} tv[] = {
|
||||
{
|
||||
"", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
"a", ":",
|
||||
0, { "a", NULL }
|
||||
},
|
||||
{
|
||||
":", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
"::", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
"a:b:c", ":",
|
||||
0, { "a", "b", "c", NULL }
|
||||
},
|
||||
{
|
||||
"a:b:", ":",
|
||||
0, { "a", "b", NULL }
|
||||
},
|
||||
{
|
||||
"a:b", ":",
|
||||
0, { "a", "b", NULL }
|
||||
},
|
||||
{
|
||||
"aa:b:cd", ":",
|
||||
0, { "aa", "b", "cd", NULL }
|
||||
},
|
||||
{
|
||||
"aa::b:cd", ":",
|
||||
0, { "aa", "b", "cd", NULL }
|
||||
},
|
||||
{
|
||||
"::b:cd", ":",
|
||||
0, { "b", "cd", NULL }
|
||||
},
|
||||
{
|
||||
"aa: : b:cd ", ":",
|
||||
0, { "aa", "b", "cd", NULL }
|
||||
},
|
||||
{
|
||||
" aa: : b: cd ", ":",
|
||||
0, { "aa", "b", "cd", NULL }
|
||||
},
|
||||
{
|
||||
" :", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
" : ", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
": ", ":",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
": x ", ":",
|
||||
0, { "x", NULL }
|
||||
},
|
||||
{
|
||||
"a:bc:cde:fghi:jklmn::foo:", ":",
|
||||
0, { "a", "bc", "cde", "fghi", "jklmn", "foo", NULL }
|
||||
},
|
||||
{
|
||||
",a,bc,,def,", ",",
|
||||
0, { "a", "bc", "def", NULL }
|
||||
},
|
||||
{
|
||||
" a ", " ",
|
||||
0, { "a", NULL }
|
||||
},
|
||||
{
|
||||
" ", " ",
|
||||
1, { NULL }
|
||||
},
|
||||
{
|
||||
"a:bc:c de:fg hi:jklmn::foo :", ":",
|
||||
0, { "a", "bc", "c de", "fg hi", "jklmn", "foo", NULL }
|
||||
},
|
||||
{
|
||||
"", " ",
|
||||
1, { NULL }
|
||||
}
|
||||
};
|
||||
const char *prefixes[3] = { "abc", "bcd", "efg" };
|
||||
int tidx;
|
||||
int nprefixes; /* Number of items in already in the list. */
|
||||
strlist_t list = NULL;
|
||||
|
||||
for (nprefixes = 0; nprefixes < DIM (prefixes); nprefixes++)
|
||||
for (tidx = 0; tidx < DIM(tv); tidx++)
|
||||
{
|
||||
int item_count_expected;
|
||||
int i;
|
||||
strlist_t sl, newitems;
|
||||
|
||||
for (item_count_expected = 0;
|
||||
tv[tidx].items_expected[item_count_expected];
|
||||
item_count_expected++)
|
||||
;
|
||||
|
||||
/* printf ("np=%d testing %d \"%s\" delim=\"%s\"\n", */
|
||||
/* nprefixes, tidx, tv[tidx].s, tv[tidx].delim); */
|
||||
for (i=0; i < nprefixes; i++)
|
||||
append_to_strlist (&list, prefixes[i]);
|
||||
|
||||
newitems = tokenize_to_strlist (&list, tv[tidx].s, tv[tidx].delim);
|
||||
if (!newitems)
|
||||
{
|
||||
if (gpg_err_code_from_syserror () == GPG_ERR_ENOENT
|
||||
&& tv[tidx].error_expected)
|
||||
{
|
||||
/* Good. But need to check the prefixes. */
|
||||
for (sl=list, i=0; i < nprefixes; i++, sl=sl->next)
|
||||
{
|
||||
if (!sl || strcmp (prefixes[i], sl->d))
|
||||
{
|
||||
printf ("For item %d prefix item %d, expected '%s'\n",
|
||||
tidx, i, prefixes[i]);
|
||||
fail (tidx * 1000 + 40 + i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
fail (tidx * 1000);
|
||||
}
|
||||
else if (tv[tidx].error_expected)
|
||||
{
|
||||
printf ("got items");
|
||||
for (sl = list; sl; sl = sl->next)
|
||||
printf (" \"%s\"", sl->d);
|
||||
printf ("\n");
|
||||
fail (tidx * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlist_length (list) != nprefixes + item_count_expected)
|
||||
fail (tidx * 1000);
|
||||
else
|
||||
{
|
||||
for (sl=list, i=0; i < nprefixes; i++, sl=sl->next)
|
||||
{
|
||||
if (!sl || strcmp (prefixes[i], sl->d))
|
||||
{
|
||||
printf ("For item %d prefix item %d, expected '%s'\n",
|
||||
tidx, i, prefixes[i]);
|
||||
fail (tidx * 1000 + 50 + i + 1);
|
||||
}
|
||||
}
|
||||
for (i=0; i < item_count_expected; i++, sl=sl->next)
|
||||
{
|
||||
if (!sl)
|
||||
{
|
||||
printf ("No item at item index %d\n", i);
|
||||
fail (tidx * 1000 + i + 0);
|
||||
break;
|
||||
}
|
||||
if (strcmp (tv[tidx].items_expected[i], sl->d))
|
||||
{
|
||||
printf ("For item %d, expected '%s', but got '%s'\n",
|
||||
i, tv[tidx].items_expected[i], sl->d);
|
||||
fail (tidx * 1000 + 10 + i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_strlist (list);
|
||||
list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
@ -79,6 +267,7 @@ main (int argc, char **argv)
|
|||
(void)argv;
|
||||
|
||||
test_strlist_rev ();
|
||||
test_tokenize_to_strlist ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ ensure_space (tlv_builder_t tb)
|
|||
* element is described by CLASS, TAG, VALUE, and VALUEEN. CLASS and
|
||||
* TAG must describe a primitive element and (VALUE,VALUELEN) specify
|
||||
* its value. The value is a pointer and its object must not be
|
||||
* changed as long as the instance TB exists. For a TAG_NULL no vlaue
|
||||
* changed as long as the instance TB exists. For a TAG_NULL no value
|
||||
* is expected. Errors are not returned but recorded for later
|
||||
* retrieval. */
|
||||
void
|
||||
|
|
|
@ -42,7 +42,7 @@ struct bufferlist_s
|
|||
/* An object to control the ASN.1 parsing. */
|
||||
struct tlv_parser_s
|
||||
{
|
||||
/* The orginal buffer with the entire pkcs#12 object and its length. */
|
||||
/* The original buffer with the entire pkcs#12 object and its length. */
|
||||
const unsigned char *origbuffer;
|
||||
size_t origbufsize;
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ void tlv_builder_add_end (tlv_builder_t tb);
|
|||
gpg_error_t tlv_builder_finalize (tlv_builder_t tb,
|
||||
void **r_obj, size_t *r_objlen);
|
||||
|
||||
/* Wite a TLV header to MEMBUF. */
|
||||
/* Write a TLV header to MEMBUF. */
|
||||
void put_tlv_to_membuf (membuf_t *membuf, int class, int tag,
|
||||
int constructed, size_t length);
|
||||
|
||||
|
|
|
@ -149,36 +149,6 @@ ssize_t read_line (FILE *fp,
|
|||
size_t *max_length);
|
||||
|
||||
|
||||
/*-- b64enc.c and b64dec.c --*/
|
||||
struct b64state
|
||||
{
|
||||
unsigned int flags;
|
||||
int idx;
|
||||
int quad_count;
|
||||
FILE *fp;
|
||||
estream_t stream;
|
||||
char *title;
|
||||
unsigned char radbuf[4];
|
||||
u32 crc;
|
||||
int stop_seen:1;
|
||||
int invalid_encoding:1;
|
||||
gpg_error_t lasterr;
|
||||
};
|
||||
|
||||
gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title);
|
||||
gpg_error_t b64enc_start_es (struct b64state *state, estream_t fp,
|
||||
const char *title);
|
||||
gpg_error_t b64enc_write (struct b64state *state,
|
||||
const void *buffer, size_t nbytes);
|
||||
gpg_error_t b64enc_finish (struct b64state *state);
|
||||
|
||||
gpg_error_t b64dec_start (struct b64state *state, const char *title);
|
||||
gpg_error_t b64dec_proc (struct b64state *state, void *buffer, size_t length,
|
||||
size_t *r_nbytes);
|
||||
gpg_error_t b64dec_finish (struct b64state *state);
|
||||
gpg_error_t b64decode (const char *string, const char *title,
|
||||
void **r_buffer, size_t *r_buflen);
|
||||
|
||||
/*-- sexputil.c */
|
||||
char *canon_sexp_to_string (const unsigned char *canon, size_t canonlen);
|
||||
void log_printcanon (const char *text,
|
||||
|
@ -226,6 +196,7 @@ char *pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid);
|
|||
const char *pubkey_algo_to_string (int algo);
|
||||
const char *hash_algo_to_string (int algo);
|
||||
const char *cipher_mode_to_string (int mode);
|
||||
const char *get_ecc_curve_from_key (gcry_sexp_t key);
|
||||
|
||||
/*-- convert.c --*/
|
||||
int hex2bin (const char *string, void *buffer, size_t length);
|
||||
|
@ -257,9 +228,10 @@ int openpgp_oidbuf_is_cv25519 (const void *buf, size_t len);
|
|||
int openpgp_oid_is_cv25519 (gcry_mpi_t a);
|
||||
int openpgp_oid_is_cv448 (gcry_mpi_t a);
|
||||
int openpgp_oid_is_ed448 (gcry_mpi_t a);
|
||||
enum gcry_kem_algos openpgp_oid_to_kem_algo (const char *oidname);
|
||||
const char *openpgp_curve_to_oid (const char *name,
|
||||
unsigned int *r_nbits, int *r_algo);
|
||||
const char *openpgp_oid_to_curve (const char *oid, int canon);
|
||||
const char *openpgp_oid_to_curve (const char *oid, int mode);
|
||||
const char *openpgp_oid_or_name_to_curve (const char *oidname, int canon);
|
||||
const char *openpgp_enum_curves (int *idxp);
|
||||
const char *openpgp_is_curve_supported (const char *name,
|
||||
|
@ -274,6 +246,7 @@ void gnupg_set_homedir (const char *newdir);
|
|||
void gnupg_maybe_make_homedir (const char *fname, int quiet);
|
||||
const char *gnupg_homedir (void);
|
||||
int gnupg_default_homedir_p (void);
|
||||
const char *gnupg_registry_dir (void);
|
||||
const char *gnupg_daemon_rootdir (void);
|
||||
const char *gnupg_socketdir (void);
|
||||
const char *gnupg_sysconfdir (void);
|
||||
|
@ -328,6 +301,19 @@ char *gnupg_get_help_string (const char *key, int only_current_locale);
|
|||
/*-- localename.c --*/
|
||||
const char *gnupg_messages_locale_name (void);
|
||||
|
||||
/*-- kem.c --*/
|
||||
gpg_error_t gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
||||
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||
const void *ecc_ct, size_t ecc_ct_len,
|
||||
const void *ecc_pk, size_t ecc_pk_len);
|
||||
|
||||
gpg_error_t gnupg_kem_combiner (void *kek, size_t kek_len,
|
||||
const void *ecc_ss, size_t ecc_ss_len,
|
||||
const void *ecc_ct, size_t ecc_ct_len,
|
||||
const void *mlkem_ss, size_t mlkem_ss_len,
|
||||
const void *mlkem_ct, size_t mlkem_ct_len,
|
||||
const void *fixedinfo, size_t fixedinfo_len);
|
||||
|
||||
/*-- miscellaneous.c --*/
|
||||
|
||||
/* This function is called at startup to tell libgcrypt to use our own
|
||||
|
@ -337,7 +323,7 @@ void setup_libgcrypt_logging (void);
|
|||
/* Print an out of core message and die. */
|
||||
void xoutofcore (void);
|
||||
|
||||
/* Wrapper aroung gpgrt_reallocarray. Uses the gpgrt alloc function
|
||||
/* Wrapper around gpgrt_reallocarray. Uses the gpgrt alloc function
|
||||
* which redirects to the Libgcrypt versions via
|
||||
* init_common_subsystems. Thus this can be used interchangeable with
|
||||
* the other alloc functions. */
|
||||
|
@ -388,6 +374,10 @@ struct compatibility_flags_s
|
|||
int parse_compatibility_flags (const char *string, unsigned int *flagvar,
|
||||
const struct compatibility_flags_s *flags);
|
||||
|
||||
gpg_error_t b64decode (const char *string, const char *title,
|
||||
void **r_buffer, size_t *r_buflen);
|
||||
|
||||
|
||||
|
||||
/*-- Simple replacement functions. */
|
||||
|
||||
|
|
18
configure.ac
18
configure.ac
|
@ -28,8 +28,8 @@ min_automake_version="1.16.3"
|
|||
# another commit and push so that the git magic is able to work.
|
||||
m4_define([mym4_package],[gnupg])
|
||||
m4_define([mym4_major], [2])
|
||||
m4_define([mym4_minor], [4])
|
||||
m4_define([mym4_micro], [5])
|
||||
m4_define([mym4_minor], [5])
|
||||
m4_define([mym4_micro], [0])
|
||||
|
||||
# To start a new development series, i.e a new major or minor number
|
||||
# you need to mark an arbitrary commit before the first beta release
|
||||
|
@ -53,15 +53,15 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
|
|||
# When changing the SWDB tag please also adjust the hard coded tags in
|
||||
# build-aux/speedo.mk, build-aux/getswdb.sh, and Makefile.am
|
||||
# As well as the source info for the man pages.
|
||||
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg24", [swdb tag for this branch])
|
||||
AC_DEFINE_UNQUOTED(GNUPG_SWDB_TAG, "gnupg26", [swdb tag for this branch])
|
||||
|
||||
NEED_GPGRT_VERSION=1.46
|
||||
|
||||
NEED_LIBGCRYPT_API=1
|
||||
NEED_LIBGCRYPT_VERSION=1.9.1
|
||||
NEED_LIBGCRYPT_VERSION=1.11.0
|
||||
|
||||
NEED_LIBASSUAN_API=2
|
||||
NEED_LIBASSUAN_VERSION=2.5.0
|
||||
NEED_LIBASSUAN_API=3
|
||||
NEED_LIBASSUAN_VERSION=3.0.0
|
||||
|
||||
NEED_KSBA_API=1
|
||||
NEED_KSBA_VERSION=1.6.3
|
||||
|
@ -1385,6 +1385,8 @@ AC_CHECK_SIZEOF(time_t,,[[
|
|||
]])
|
||||
GNUPG_TIME_T_UNSIGNED
|
||||
|
||||
# Check SOCKET type for Windows.
|
||||
AC_CHECK_TYPES([SOCKET], [], [], [[#include "winsock2.h"]])
|
||||
|
||||
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|
||||
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
|
||||
|
@ -1599,7 +1601,7 @@ if test "$build_tpm2d" = "yes"; then
|
|||
# until version 2.4.0.
|
||||
#
|
||||
# Note: the missing API is fairly serious and is also easily backportable
|
||||
# so keep the check below as is intead of going by library version number.
|
||||
# so keep the check below as is instead of going by library version number.
|
||||
##
|
||||
AC_CHECK_LIB(tss2-esys, Esys_TR_GetTpmHandle, [], [
|
||||
AC_MSG_WARN([Need Esys_TR_GetTpmHandle API (usually requires Intel TSS 2.4.0 or later, disabling TPM support)])
|
||||
|
@ -1636,7 +1638,7 @@ if test "$GCC" = yes; then
|
|||
mycflags=
|
||||
mycflags_save=$CFLAGS
|
||||
|
||||
# Check whether gcc does not emit a diagnositc for unknown -Wno-*
|
||||
# Check whether gcc does not emit a diagnostic for unknown -Wno-*
|
||||
# options. This is the case for gcc >= 4.6
|
||||
AC_MSG_CHECKING([if gcc ignores unknown -Wno-* options])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
|
|
|
@ -55,7 +55,7 @@ Noteworthy changes in version 1.0.1 (2007-08-16)
|
|||
Noteworthy changes in version 1.0.0 (2006-11-29)
|
||||
------------------------------------------------
|
||||
|
||||
* Bumbed the version number.
|
||||
* Bumped the version number.
|
||||
|
||||
* Removed included gettext. We now require the system to provide a
|
||||
suitable installation.
|
||||
|
@ -174,7 +174,7 @@ Noteworthy changes in version 0.5.4 (2004-04-29)
|
|||
------------------------------------------------
|
||||
|
||||
* New commands --ocsp-responder and --ocsp-signer to define a default
|
||||
OCSP reponder if a certificate does not contain an assigned OCSP
|
||||
OCSP responder if a certificate does not contain an assigned OCSP
|
||||
responder.
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,8 @@ static unsigned int any_cert_of_class;
|
|||
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* We load some functions dynamically. Provide typedefs for tehse
|
||||
#include <wincrypt.h>
|
||||
/* We load some functions dynamically. Provide typedefs for these
|
||||
* functions. */
|
||||
typedef HCERTSTORE (WINAPI *CERTOPENSYSTEMSTORE)
|
||||
(HCRYPTPROV hProv, LPCSTR szSubsystemProtocol);
|
||||
|
@ -224,7 +225,7 @@ cert_compute_fpr (ksba_cert_t cert, unsigned char *digest)
|
|||
|
||||
|
||||
|
||||
/* Cleanup one slot. This releases all resourses but keeps the actual
|
||||
/* Cleanup one slot. This releases all resources but keeps the actual
|
||||
slot in the cache marked for reuse. */
|
||||
static void
|
||||
clean_cache_slot (cert_item_t ci)
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
2008) we need a context in the reader callback. */
|
||||
struct reader_cb_context_s
|
||||
{
|
||||
estream_t fp; /* The stream used with the ksba reader. */
|
||||
int checked:1; /* PEM/binary detection ahs been done. */
|
||||
int is_pem:1; /* The file stream is PEM encoded. */
|
||||
struct b64state b64state; /* The state used for Base64 decoding. */
|
||||
estream_t fp; /* The stream used with the ksba reader. */
|
||||
unsigned int checked:1; /* PEM/binary detection ahs been done. */
|
||||
unsigned int is_pem:1; /* The file stream is PEM encoded. */
|
||||
gpgrt_b64state_t b64state; /* The state used for Base64 decoding. */
|
||||
};
|
||||
|
||||
|
||||
|
@ -126,14 +126,16 @@ my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
|
|||
else
|
||||
{
|
||||
cb_ctx->is_pem = 1;
|
||||
b64dec_start (&cb_ctx->b64state, "");
|
||||
cb_ctx->b64state = gpgrt_b64dec_start ("");
|
||||
if (!cb_ctx->b64state)
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
}
|
||||
if (cb_ctx->is_pem && *nread)
|
||||
{
|
||||
size_t nread2;
|
||||
|
||||
if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
|
||||
if (gpgrt_b64dec_proc (cb_ctx->b64state, buffer, *nread, &nread2))
|
||||
{
|
||||
/* EOF from decoder. */
|
||||
*nread = 0;
|
||||
|
@ -581,7 +583,7 @@ crl_close_reader (ksba_reader_t reader)
|
|||
es_fclose (cb_ctx->fp);
|
||||
/* Release the base64 decoder state. */
|
||||
if (cb_ctx->is_pem)
|
||||
b64dec_finish (&cb_ctx->b64state);
|
||||
gpgrt_b64dec_finish (cb_ctx->b64state);
|
||||
/* Release the callback context. */
|
||||
xfree (cb_ctx);
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@ main (int argc, char **argv )
|
|||
opt.dirmngr_program
|
||||
? opt.dirmngr_program
|
||||
: gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR),
|
||||
! cmd_ping,
|
||||
cmd_ping? 0 : ASSHELP_FLAG_AUTOSTART,
|
||||
opt.verbose,
|
||||
0,
|
||||
NULL, NULL);
|
||||
|
@ -441,11 +441,11 @@ static gpg_error_t
|
|||
data_cb (void *opaque, const void *buffer, size_t length)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state *state = opaque;
|
||||
gpgrt_b64state_t state = opaque;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
err = b64enc_write (state, buffer, length);
|
||||
err = gpgrt_b64enc_write (state, buffer, length);
|
||||
if (err)
|
||||
log_error (_("error writing base64 encoding: %s\n"),
|
||||
gpg_strerror (err));
|
||||
|
@ -853,14 +853,14 @@ do_lookup (assuan_context_t ctx, const char *pattern)
|
|||
gpg_error_t err;
|
||||
const unsigned char *s;
|
||||
char *line, *p;
|
||||
struct b64state state;
|
||||
gpgrt_b64state_t state;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (_("looking up '%s'\n"), pattern);
|
||||
|
||||
err = b64enc_start (&state, stdout, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
state = gpgrt_b64enc_start (es_stdout, NULL);
|
||||
if (!state)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
line = xmalloc (10 + 6 + 13 + strlen (pattern)*3 + 1);
|
||||
|
||||
|
@ -885,13 +885,13 @@ do_lookup (assuan_context_t ctx, const char *pattern)
|
|||
|
||||
|
||||
err = assuan_transact (ctx, line,
|
||||
data_cb, &state,
|
||||
data_cb, state,
|
||||
NULL, NULL,
|
||||
status_cb, NULL);
|
||||
if (opt.verbose > 1)
|
||||
log_info ("response of dirmngr: %s\n", err? gpg_strerror (err): "okay");
|
||||
|
||||
err = b64enc_finish (&state);
|
||||
err = gpgrt_b64enc_finish (state);
|
||||
|
||||
xfree (line);
|
||||
return err;
|
||||
|
|
|
@ -394,6 +394,9 @@ static enum
|
|||
} tor_mode;
|
||||
|
||||
|
||||
/* Flag indicating that we are in supervised mode. */
|
||||
static int is_supervised;
|
||||
|
||||
/* Counter for the active connections. */
|
||||
static int active_connections;
|
||||
|
||||
|
@ -450,9 +453,6 @@ static void handle_connections (assuan_fd_t listen_fd);
|
|||
static void gpgconf_versions (void);
|
||||
|
||||
|
||||
/* NPth wrapper function definitions. */
|
||||
ASSUAN_SYSTEM_NPTH_IMPL;
|
||||
|
||||
static const char *
|
||||
my_strusage( int level )
|
||||
{
|
||||
|
@ -980,7 +980,6 @@ static void
|
|||
thread_init (void)
|
||||
{
|
||||
npth_init ();
|
||||
assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
|
||||
gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
|
||||
|
||||
/* Now with NPth running we can set the logging callback. Our
|
||||
|
@ -1105,12 +1104,12 @@ main (int argc, char **argv)
|
|||
|
||||
socket_name = dirmngr_socket_name ();
|
||||
|
||||
/* The configuraton directories for use by gpgrt_argparser. */
|
||||
/* The configuration directories for use by gpgrt_argparser. */
|
||||
gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
|
||||
gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
|
||||
|
||||
/* We are re-using the struct, thus the reset flag. We OR the
|
||||
* flags so that the internal intialized flag won't be cleared. */
|
||||
* flags so that the internal initialized flag won't be cleared. */
|
||||
argc = orig_argc;
|
||||
argv = orig_argv;
|
||||
pargs.argc = &argc;
|
||||
|
@ -1335,6 +1334,8 @@ main (int argc, char **argv)
|
|||
if (!opt.quiet)
|
||||
log_info(_("WARNING: \"%s\" is a deprecated option\n"), "--supervised");
|
||||
|
||||
is_supervised = 1;
|
||||
|
||||
/* In supervised mode, we expect file descriptor 3 to be an
|
||||
already opened, listening socket.
|
||||
|
||||
|
@ -1747,7 +1748,7 @@ dirmngr_deinit_default_ctrl (ctrl_t ctrl)
|
|||
|
||||
The format of such a file is line oriented where empty lines and
|
||||
lines starting with a hash mark are ignored. All other lines are
|
||||
assumed to be colon seprated with these fields:
|
||||
assumed to be colon separated with these fields:
|
||||
|
||||
1. field: Hostname
|
||||
2. field: Portnumber
|
||||
|
@ -2233,7 +2234,7 @@ check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
|
|||
if (assuan_sock_check_nonce (fd, nonce))
|
||||
{
|
||||
log_info (_("error reading nonce on fd %d: %s\n"),
|
||||
FD2INT (fd), strerror (errno));
|
||||
FD_DBG (fd), strerror (errno));
|
||||
assuan_sock_close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -2267,7 +2268,7 @@ start_connection_thread (void *arg)
|
|||
|
||||
active_connections++;
|
||||
if (opt.verbose)
|
||||
log_info (_("handler for fd %d started\n"), FD2INT (fd));
|
||||
log_info (_("handler for fd %d started\n"), FD_DBG (fd));
|
||||
|
||||
session_id = ++last_session_id;
|
||||
if (!session_id)
|
||||
|
@ -2275,7 +2276,7 @@ start_connection_thread (void *arg)
|
|||
start_command_handler (fd, session_id);
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (_("handler for fd %d terminated\n"), FD2INT (fd));
|
||||
log_info (_("handler for fd %d terminated\n"), FD_DBG (fd));
|
||||
active_connections--;
|
||||
|
||||
workqueue_run_post_session_tasks (session_id);
|
||||
|
@ -2378,7 +2379,7 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
to full second. */
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (FD2INT (listen_fd), &fdset);
|
||||
nfd = FD2INT (listen_fd);
|
||||
nfd = FD2NUM (listen_fd);
|
||||
if (my_inotify_fd != -1)
|
||||
{
|
||||
FD_SET (my_inotify_fd, &fdset);
|
||||
|
@ -2395,7 +2396,7 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
/* Shutdown test. */
|
||||
if (shutdown_pending)
|
||||
{
|
||||
if (!active_connections)
|
||||
if (!active_connections || is_supervised)
|
||||
break; /* ready */
|
||||
|
||||
/* Do not accept new connections but keep on running the
|
||||
|
@ -2479,8 +2480,8 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
gnupg_fd_t fd;
|
||||
|
||||
plen = sizeof paddr;
|
||||
fd = INT2FD (npth_accept (FD2INT(listen_fd),
|
||||
(struct sockaddr *)&paddr, &plen));
|
||||
fd = assuan_sock_accept (listen_fd,
|
||||
(struct sockaddr *)&paddr, &plen);
|
||||
if (fd == GNUPG_INVALID_FD)
|
||||
{
|
||||
log_error ("accept failed: %s\n", strerror (errno));
|
||||
|
@ -2494,7 +2495,7 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
memset (&argval, 0, sizeof argval);
|
||||
argval.afd = fd;
|
||||
snprintf (threadname, sizeof threadname,
|
||||
"conn fd=%d", FD2INT(fd));
|
||||
"conn fd=%d", FD_DBG (fd));
|
||||
|
||||
ret = npth_create (&thread, &tattr,
|
||||
start_connection_thread, argval.aptr);
|
||||
|
|
|
@ -241,7 +241,7 @@ struct server_control_s
|
|||
int audit_events; /* Send audit events to client. */
|
||||
char *http_proxy; /* The used http_proxy or NULL. */
|
||||
|
||||
nvc_t rootdse; /* Container wit the rootDSE properties. */
|
||||
nvc_t rootdse; /* Container with the rootDSE properties. */
|
||||
|
||||
unsigned int timeout; /* Timeout for connect calls in ms. */
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
# define WIN32_LEAN_AND_MEAN
|
||||
# ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <iphlpapi.h>
|
||||
|
|
|
@ -9761,7 +9761,7 @@ struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_ty
|
|||
/*
|
||||
* FIXME: If an explicit A or AAAA record type conflicts with
|
||||
* .ai_family or with resconf.family (i.e. AAAA specified but
|
||||
* AF_INET6 not in interection of .ai_family and resconf.family),
|
||||
* AF_INET6 not in intersection of .ai_family and resconf.family),
|
||||
* then what?
|
||||
*/
|
||||
switch (ai->qtype) {
|
||||
|
|
|
@ -78,7 +78,7 @@ gnupg_http_tls_verify_cb (void *opaque,
|
|||
validate_flags = VALIDATE_FLAG_TLS;
|
||||
|
||||
/* If we are using the standard hkps:// pool use the dedicated root
|
||||
* certificate. Note that this differes from the GnuTLS
|
||||
* certificate. Note that this differs from the GnuTLS
|
||||
* implementation which uses this special certificate only if no
|
||||
* other certificates are configured. */
|
||||
/* Disabled for 2.3.2 to due problems with the standard hkps pool. */
|
||||
|
|
|
@ -295,7 +295,7 @@ struct http_session_s
|
|||
} verify;
|
||||
char *servername; /* Malloced server name. */
|
||||
|
||||
/* A callback function to log details of TLS certifciates. */
|
||||
/* A callback function to log details of TLS certificates. */
|
||||
void (*cert_log_cb) (http_session_t, gpg_error_t, const char *,
|
||||
const void **, size_t *);
|
||||
|
||||
|
@ -441,7 +441,7 @@ _my_socket_new (int lnr, assuan_fd_t fd)
|
|||
so->refcount = 1;
|
||||
if (opt_debug)
|
||||
log_debug ("http.c:%d:socket_new: object %p for fd %d created\n",
|
||||
lnr, so, (int)so->fd);
|
||||
lnr, so, FD_DBG (so->fd));
|
||||
return so;
|
||||
}
|
||||
#define my_socket_new(a) _my_socket_new (__LINE__, (a))
|
||||
|
@ -453,7 +453,7 @@ _my_socket_ref (int lnr, my_socket_t so)
|
|||
so->refcount++;
|
||||
if (opt_debug > 1)
|
||||
log_debug ("http.c:%d:socket_ref: object %p for fd %d refcount now %d\n",
|
||||
lnr, so, (int)so->fd, so->refcount);
|
||||
lnr, so, FD_DBG (so->fd), so->refcount);
|
||||
return so;
|
||||
}
|
||||
#define my_socket_ref(a) _my_socket_ref (__LINE__,(a))
|
||||
|
@ -471,7 +471,7 @@ _my_socket_unref (int lnr, my_socket_t so,
|
|||
so->refcount--;
|
||||
if (opt_debug > 1)
|
||||
log_debug ("http.c:%d:socket_unref: object %p for fd %d ref now %d\n",
|
||||
lnr, so, (int)so->fd, so->refcount);
|
||||
lnr, so, FD_DBG (so->fd), so->refcount);
|
||||
|
||||
if (!so->refcount)
|
||||
{
|
||||
|
@ -2018,7 +2018,7 @@ w32_get_proxy (const char *url)
|
|||
* If OVERRIDE_PROXY is not NULL and not empty, this proxy will be
|
||||
* used instead of any configured or dynamically determined proxy. If
|
||||
* the function runs into an error an error code is returned and NULL
|
||||
* is stored at R_PROXY. If the fucntion was successful and a proxy
|
||||
* is stored at R_PROXY. If the function was successful and a proxy
|
||||
* is to be used, information on the procy is stored at R_PROXY; if no
|
||||
* proxy shall be used R_PROXY is set to NULL. Caller should always
|
||||
* use release_proxy_info on the value stored at R_PROXY. */
|
||||
|
@ -2200,7 +2200,7 @@ run_ntbtls_handshake (http_t hd)
|
|||
/* Until we support send/recv in estream under Windows we need
|
||||
* to use es_fopencookie. */
|
||||
# ifdef HAVE_W32_SYSTEM
|
||||
in = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "rb",
|
||||
in = es_fopencookie (hd->sock->fd, "rb",
|
||||
simple_cookie_functions);
|
||||
# else
|
||||
in = es_fdopen_nc (hd->sock->fd, "rb");
|
||||
|
@ -2212,7 +2212,7 @@ run_ntbtls_handshake (http_t hd)
|
|||
}
|
||||
|
||||
# ifdef HAVE_W32_SYSTEM
|
||||
out = es_fopencookie ((void*)(unsigned int)hd->sock->fd, "wb",
|
||||
out = es_fopencookie (hd->sock->fd, "wb",
|
||||
simple_cookie_functions);
|
||||
# else
|
||||
out = es_fdopen_nc (hd->sock->fd, "wb");
|
||||
|
@ -2358,8 +2358,8 @@ run_gnutls_handshake (http_t hd, const char *server)
|
|||
#endif /*HTTP_USE_GNUTLS*/
|
||||
|
||||
|
||||
/* It INPUTSTRING is NULL get the intial token. If INPUTSTRING is not
|
||||
* NULL, decode the string and use this as input from teh server. On
|
||||
/* It INPUTSTRING is NULL get the initial token. If INPUTSTRING is not
|
||||
* NULL, decode the string and use this as input from the server. On
|
||||
* success the final output token is stored at PROXY->OUTTOKEN and
|
||||
* OUTTOKLEN. IF the authentication succeeded OUTTOKLEN is zero. */
|
||||
static gpg_error_t
|
||||
|
@ -2379,7 +2379,7 @@ proxy_get_token (proxy_info_t proxy, const char *inputstring)
|
|||
|
||||
if (inputstring)
|
||||
{
|
||||
/* The input is expected in the token parameter but the paremter
|
||||
/* The input is expected in the token parameter but the parameter
|
||||
* name is often forgotten. Thus we simply detect the parameter
|
||||
* name and skip it, assuming no other parameters are given. */
|
||||
if (!strncmp (inputstring, "token=", 6))
|
||||
|
@ -3571,7 +3571,7 @@ connect_with_timeout (assuan_fd_t sock,
|
|||
tval.tv_sec = timeout / 1000;
|
||||
tval.tv_usec = (timeout % 1000) * 1000;
|
||||
|
||||
n = my_select (FD2INT(sock)+1, &rset, &wset, NULL, &tval);
|
||||
n = my_select (FD2NUM(sock)+1, &rset, &wset, NULL, &tval);
|
||||
if (n < 0)
|
||||
{
|
||||
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
|
||||
|
@ -4424,8 +4424,8 @@ same_host_p (parsed_uri_t a, parsed_uri_t b)
|
|||
|
||||
/* Prepare a new URL for a HTTP redirect. INFO has flags controlling
|
||||
* the operation, STATUS_CODE is used for diagnostics, LOCATION is the
|
||||
* value of the "Location" header, and R_URL reveives the new URL on
|
||||
* success or NULL or error. Note that INFO->ORIG_URL is
|
||||
* value of the "Location" header, and R_URL receives the new URL on
|
||||
* success or NULL on error. Note that INFO->ORIG_URL is
|
||||
* required. */
|
||||
gpg_error_t
|
||||
http_prepare_redirect (http_redir_info_t *info, unsigned int status_code,
|
||||
|
@ -4596,7 +4596,7 @@ http_status2string (unsigned int status)
|
|||
}
|
||||
|
||||
|
||||
/* Fucntion called on SIGHUP to flush internal variables. */
|
||||
/* Function called on SIGHUP to flush internal variables. */
|
||||
void
|
||||
http_reinitialize (void)
|
||||
{
|
||||
|
|
|
@ -373,6 +373,8 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
|||
|| !strcmp (uri->parsed_uri->scheme, "ldaps")
|
||||
|| !strcmp (uri->parsed_uri->scheme, "ldapi")
|
||||
|| uri->parsed_uri->opaque);
|
||||
#else
|
||||
(void)newer;
|
||||
#endif
|
||||
|
||||
if (is_hkp_s || is_http_s || is_ldap)
|
||||
|
@ -590,6 +592,13 @@ ks_action_query (ctrl_t ctrl, const char *url, unsigned int ks_get_flags,
|
|||
return err;
|
||||
|
||||
#else /* !USE_LDAP */
|
||||
(void)ctrl;
|
||||
(void)url;
|
||||
(void)ks_get_flags;
|
||||
(void)filter;
|
||||
(void)attrs;
|
||||
(void)newer;
|
||||
(void)outfp;
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
# define WINVER 0x0500 /* Same as in common/sysutils.c */
|
||||
# endif
|
||||
# include <winsock2.h>
|
||||
# include <winldap.h>
|
||||
# include <winber.h>
|
||||
# include <sddl.h>
|
||||
#endif
|
||||
|
||||
|
@ -51,7 +53,7 @@
|
|||
#define SERVERINFO_PGPKEYV2 2 /* Needs "pgpKeyV2" instead of "pgpKey"*/
|
||||
#define SERVERINFO_SCHEMAV2 4 /* Version 2 of the Schema. */
|
||||
#define SERVERINFO_NTDS 8 /* Server is an Active Directory. */
|
||||
#define SERVERINFO_GENERIC 16 /* Connected in genric mode. */
|
||||
#define SERVERINFO_GENERIC 16 /* Connected in generic mode. */
|
||||
|
||||
|
||||
/* The page size requested from the server. */
|
||||
|
@ -1255,7 +1257,7 @@ return_all_attributes (LDAP *ld, LDAPMessage *msg, estream_t *fp)
|
|||
}
|
||||
|
||||
/* Always print the DN - note that by using only unbkown attributes
|
||||
* it is pissible to list just the DNs with out addiional
|
||||
* it is possible to list just the DNs with out additional
|
||||
* linefeeds. */
|
||||
es_fprintf (*fp, "Dn: %s\n", mydn? mydn : "[oops DN missing]");
|
||||
|
||||
|
@ -1305,7 +1307,7 @@ return_all_attributes (LDAP *ld, LDAPMessage *msg, estream_t *fp)
|
|||
len = values[idx]->bv_len;
|
||||
while (len && (s = memchr (val, '\n', len)))
|
||||
{
|
||||
s++; /* We als want to print the LF. */
|
||||
s++; /* We also want to print the LF. */
|
||||
if (es_fwrite (val, s - val, 1, *fp) != 1)
|
||||
goto fwrite_failed;
|
||||
len -= (s-val);
|
||||
|
@ -2359,7 +2361,7 @@ modlist_free (LDAPMod **modlist)
|
|||
LDAPMod *mod = *ml;
|
||||
char **ptr;
|
||||
|
||||
/* The list of values is a NULL termianted array of pointers.
|
||||
/* The list of values is a NULL terminated array of pointers.
|
||||
If the list is NULL, there are no values. */
|
||||
|
||||
if (mod->mod_values)
|
||||
|
@ -2458,7 +2460,7 @@ uncescape (char *str)
|
|||
/* Given one line from an info block (`gpg --list-{keys,sigs}
|
||||
--with-colons KEYID'), pull it apart and fill in the modlist with
|
||||
the relevant (for the LDAP schema) attributes. EXTRACT_STATE
|
||||
should initally be set to 0 by the caller. SCHEMAV2 is set if the
|
||||
should initially be set to 0 by the caller. SCHEMAV2 is set if the
|
||||
server supports the version 2 schema. */
|
||||
static void
|
||||
extract_attributes (LDAPMod ***modlist, int *extract_state,
|
||||
|
@ -2618,7 +2620,7 @@ extract_attributes (LDAPMod ***modlist, int *extract_state,
|
|||
|
||||
memset (&tm, 0, sizeof (tm));
|
||||
|
||||
/* parse_timestamp handles both seconds fromt he epoch and
|
||||
/* parse_timestamp handles both seconds from the epoch and
|
||||
ISO 8601 format. We also need to handle YYYY-MM-DD
|
||||
format (as generated by gpg1 --with-colons --list-key).
|
||||
Check that first and then if it fails, then try
|
||||
|
@ -2666,7 +2668,7 @@ extract_attributes (LDAPMod ***modlist, int *extract_state,
|
|||
|
||||
memset (&tm, 0, sizeof (tm));
|
||||
|
||||
/* parse_timestamp handles both seconds fromt he epoch and
|
||||
/* parse_timestamp handles both seconds from the epoch and
|
||||
ISO 8601 format. We also need to handle YYYY-MM-DD
|
||||
format (as generated by gpg1 --with-colons --list-key).
|
||||
Check that first and then if it fails, then try
|
||||
|
|
|
@ -220,7 +220,7 @@ ldap_to_gpg_err (LDAP *ld)
|
|||
* ^&SCOPE&(objectClasses=*)
|
||||
*
|
||||
* Give a scope and a filter. Note that R_SCOPE is only changed if a
|
||||
* STRING has scope parameter. Setting this initally to -1 allows to
|
||||
* STRING has scope parameter. Setting this initially to -1 allows to
|
||||
* detect this case.
|
||||
*/
|
||||
gpg_error_t
|
||||
|
|
|
@ -162,7 +162,7 @@ ldap_parse_uri (parsed_uri_t *purip, const char *uri)
|
|||
|
||||
if (password)
|
||||
{
|
||||
puri->query = calloc (sizeof (*puri->query), 1);
|
||||
puri->query = calloc (1, sizeof (*puri->query));
|
||||
if (!puri->query)
|
||||
{
|
||||
err = gpg_err_code_from_syserror ();
|
||||
|
|
|
@ -87,7 +87,7 @@ struct wrapper_context_s
|
|||
{
|
||||
struct wrapper_context_s *next;
|
||||
|
||||
pid_t pid; /* The pid of the wrapper process. */
|
||||
gnupg_process_t proc;/* The wrapper process. */
|
||||
int printable_pid; /* Helper to print diagnostics after the process has
|
||||
* been cleaned up. */
|
||||
estream_t fp; /* Connected with stdout of the ldap wrapper. */
|
||||
|
@ -170,10 +170,10 @@ read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
|
|||
static void
|
||||
destroy_wrapper (struct wrapper_context_s *ctx)
|
||||
{
|
||||
if (ctx->pid != (pid_t)(-1))
|
||||
if (ctx->proc)
|
||||
{
|
||||
gnupg_kill_process (ctx->pid);
|
||||
gnupg_release_process (ctx->pid);
|
||||
gnupg_process_terminate (ctx->proc);
|
||||
gnupg_process_release (ctx->proc);
|
||||
}
|
||||
ksba_reader_release (ctx->reader);
|
||||
SAFE_CLOSE (ctx->fp);
|
||||
|
@ -260,7 +260,7 @@ read_log_data (struct wrapper_context_s *ctx)
|
|||
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
|
||||
return 0;
|
||||
log_error (_("error reading log from ldap wrapper %d: %s\n"),
|
||||
(int)ctx->pid, gpg_strerror (err));
|
||||
ctx->printable_pid, gpg_strerror (err));
|
||||
}
|
||||
print_log_line (ctx, NULL); /* Flush. */
|
||||
SAFE_CLOSE (ctx->log_fp);
|
||||
|
@ -438,50 +438,44 @@ ldap_reaper_thread (void *dummy)
|
|||
}
|
||||
|
||||
/* Check whether the process is still running. */
|
||||
if (ctx->pid != (pid_t)(-1))
|
||||
if (ctx->proc)
|
||||
{
|
||||
int status;
|
||||
|
||||
err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
|
||||
&status);
|
||||
err = gnupg_process_wait (ctx->proc, 0);
|
||||
if (!err)
|
||||
{
|
||||
int status;
|
||||
|
||||
gnupg_process_ctl (ctx->proc, GNUPG_PROCESS_GET_EXIT_ID,
|
||||
&status);
|
||||
if (DBG_EXTPROG)
|
||||
log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
|
||||
log_info (_("ldap wrapper %d ready"), ctx->printable_pid);
|
||||
ctx->ready = 1;
|
||||
gnupg_release_process (ctx->pid);
|
||||
ctx->pid = (pid_t)(-1);
|
||||
gnupg_process_release (ctx->proc);
|
||||
ctx->proc = NULL;
|
||||
any_action = 1;
|
||||
}
|
||||
else if (gpg_err_code (err) == GPG_ERR_GENERAL)
|
||||
{
|
||||
|
||||
if (status == 10)
|
||||
log_info (_("ldap wrapper %d ready: timeout\n"),
|
||||
(int)ctx->pid);
|
||||
ctx->printable_pid);
|
||||
else
|
||||
log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
|
||||
(int)ctx->pid, status);
|
||||
ctx->ready = 1;
|
||||
gnupg_release_process (ctx->pid);
|
||||
ctx->pid = (pid_t)(-1);
|
||||
any_action = 1;
|
||||
ctx->printable_pid, status);
|
||||
}
|
||||
else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
|
||||
{
|
||||
log_error (_("waiting for ldap wrapper %d failed: %s\n"),
|
||||
(int)ctx->pid, gpg_strerror (err));
|
||||
ctx->printable_pid, gpg_strerror (err));
|
||||
any_action = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether we should terminate the process. */
|
||||
if (ctx->pid != (pid_t)(-1)
|
||||
&& ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
|
||||
if (ctx->proc && ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
|
||||
{
|
||||
gnupg_kill_process (ctx->pid);
|
||||
gnupg_process_terminate (ctx->proc);
|
||||
ctx->stamp = (time_t)(-1);
|
||||
log_info (_("ldap wrapper %d stalled - killing\n"),
|
||||
(int)ctx->pid);
|
||||
ctx->printable_pid);
|
||||
/* We need to close the log stream because the cleanup
|
||||
* loop waits for it. */
|
||||
SAFE_CLOSE (ctx->log_fp);
|
||||
|
@ -496,10 +490,10 @@ ldap_reaper_thread (void *dummy)
|
|||
{
|
||||
log_debug ("ldap worker states:\n");
|
||||
for (ctx = reaper_list; ctx; ctx = ctx->next)
|
||||
log_debug (" c=%p pid=%d/%d rdr=%p logfp=%p"
|
||||
log_debug (" c=%p pid=%d rdr=%p logfp=%p"
|
||||
" ctrl=%p/%d la=%lu rdy=%d\n",
|
||||
ctx,
|
||||
(int)ctx->pid, (int)ctx->printable_pid,
|
||||
ctx->printable_pid,
|
||||
ctx->reader, ctx->log_fp,
|
||||
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
|
||||
(unsigned long)ctx->stamp, ctx->ready);
|
||||
|
@ -602,9 +596,9 @@ ldap_wrapper_release_context (ksba_reader_t reader)
|
|||
if (ctx->reader == reader)
|
||||
{
|
||||
if (DBG_EXTPROG)
|
||||
log_debug ("releasing ldap worker c=%p pid=%d/%d rdr=%p"
|
||||
log_debug ("releasing ldap worker c=%p pid=%d rdr=%p"
|
||||
" ctrl=%p/%d\n", ctx,
|
||||
(int)ctx->pid, (int)ctx->printable_pid,
|
||||
ctx->printable_pid,
|
||||
ctx->reader,
|
||||
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
|
||||
|
||||
|
@ -639,8 +633,8 @@ ldap_wrapper_connection_cleanup (ctrl_t ctrl)
|
|||
{
|
||||
ctx->ctrl->refcount--;
|
||||
ctx->ctrl = NULL;
|
||||
if (ctx->pid != (pid_t)(-1))
|
||||
gnupg_kill_process (ctx->pid);
|
||||
if (ctx->proc)
|
||||
gnupg_process_terminate (ctx->proc);
|
||||
if (ctx->fp_err)
|
||||
log_info ("%s: reading from ldap wrapper %d failed: %s\n",
|
||||
__func__, ctx->printable_pid, gpg_strerror (ctx->fp_err));
|
||||
|
@ -798,7 +792,7 @@ gpg_error_t
|
|||
ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
|
||||
{
|
||||
gpg_error_t err;
|
||||
pid_t pid;
|
||||
gnupg_process_t process;
|
||||
struct wrapper_context_s *ctx;
|
||||
int i;
|
||||
int j;
|
||||
|
@ -854,19 +848,22 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
|
|||
return err;
|
||||
}
|
||||
|
||||
err = gnupg_spawn_process (pgmname, arg_list,
|
||||
NULL, GNUPG_SPAWN_NONBLOCK,
|
||||
NULL, &outfp, &errfp, &pid);
|
||||
err = gnupg_process_spawn (pgmname, arg_list,
|
||||
(GNUPG_PROCESS_STDOUT_PIPE
|
||||
| GNUPG_PROCESS_STDERR_PIPE),
|
||||
NULL, &process);
|
||||
if (err)
|
||||
{
|
||||
xfree (arg_list);
|
||||
xfree (arg_list);
|
||||
xfree (ctx);
|
||||
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
gnupg_process_get_streams (process, GNUPG_PROCESS_STREAM_NONBLOCK,
|
||||
NULL, &outfp, &errfp);
|
||||
gnupg_process_ctl (process, GNUPG_PROCESS_GET_PROC_ID, &ctx->printable_pid);
|
||||
|
||||
ctx->pid = pid;
|
||||
ctx->printable_pid = (int) pid;
|
||||
ctx->proc = process;
|
||||
ctx->fp = outfp;
|
||||
ctx->log_fp = errfp;
|
||||
ctx->ctrl = ctrl;
|
||||
|
@ -902,7 +899,7 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
|
|||
if (DBG_EXTPROG)
|
||||
{
|
||||
log_debug ("ldap wrapper %d started (%p, %s)",
|
||||
(int)ctx->pid, ctx->reader, pgmname);
|
||||
ctx->printable_pid, ctx->reader, pgmname);
|
||||
for (i=0; arg_list[i]; i++)
|
||||
log_printf (" [%s]", arg_list[i]);
|
||||
log_printf ("\n");
|
||||
|
|
|
@ -256,7 +256,7 @@ url_fetch_ldap (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
|
|||
}
|
||||
|
||||
if (ludp->lud_scheme && !strcmp (ludp->lud_scheme, "ldaps"))
|
||||
tls_mode = 2; /* LDAP-over-TLS here becuase we get it from certs. */
|
||||
tls_mode = 2; /* LDAP-over-TLS here because we get it from certs. */
|
||||
else
|
||||
tls_mode = 0;
|
||||
|
||||
|
@ -524,7 +524,7 @@ make_one_filter (const char *pattern, char **r_result)
|
|||
if (*pattern)
|
||||
{
|
||||
/* We need just the BaseDN. This assumes that the Subject
|
||||
* is correcly stored in the DT. This is however not always
|
||||
* is correctly stored in the DT. This is however not always
|
||||
* the case and the actual DN is different from the
|
||||
* subject. In this case we won't find anything. */
|
||||
if (extfilt_need_escape (pattern)
|
||||
|
@ -606,7 +606,7 @@ make_one_filter (const char *pattern, char **r_result)
|
|||
/* Prepare an LDAP query to return the cACertificate attribute for DN.
|
||||
* All configured default servers are queried until one responds.
|
||||
* This function returns an error code or 0 and stored a newly
|
||||
* allocated contect object at CONTEXT on success. */
|
||||
* allocated context object at CONTEXT on success. */
|
||||
gpg_error_t
|
||||
start_cacert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *r_context,
|
||||
const char *dn)
|
||||
|
@ -778,7 +778,7 @@ start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *r_context,
|
|||
if (argc >= DIM (argv) - 1)
|
||||
{
|
||||
/* Too many patterns. It does not make sense to allow an
|
||||
arbitrary number of patters because the length of the
|
||||
arbitrary number of patterns because the length of the
|
||||
command line is limited anyway. */
|
||||
err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
|
||||
goto leave;
|
||||
|
|
|
@ -60,7 +60,7 @@ ldapserver_list_free (ldap_server_t servers)
|
|||
* Flags are:
|
||||
*
|
||||
* starttls := Use STARTTLS with a default port of 389
|
||||
* ldaptls := Tunnel LDAP trough a TLS tunnel with default port 636
|
||||
* ldaptls := Tunnel LDAP through a TLS tunnel with default port 636
|
||||
* plain := Switch to plain unsecured LDAP.
|
||||
* (The last of these 3 flags is the effective one)
|
||||
* ntds := Use Active Directory authentication
|
||||
|
|
|
@ -583,7 +583,7 @@ gpg_error_t
|
|||
armor_data (char **r_string, const void *data, size_t datalen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct b64state b64state;
|
||||
gpgrt_b64state_t b64state;
|
||||
estream_t fp;
|
||||
long length;
|
||||
char *buffer;
|
||||
|
@ -595,9 +595,15 @@ armor_data (char **r_string, const void *data, size_t datalen)
|
|||
if (!fp)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK"))
|
||||
|| (err=b64enc_write (&b64state, data, datalen))
|
||||
|| (err = b64enc_finish (&b64state)))
|
||||
b64state = gpgrt_b64enc_start (fp, "PGP PUBLIC KEY BLOCK");
|
||||
if (!b64state)
|
||||
{
|
||||
es_fclose (fp);
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
if ((err = gpgrt_b64enc_write (b64state, data, datalen))
|
||||
|| (err = gpgrt_b64enc_finish (b64state)))
|
||||
{
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "certcache.h"
|
||||
#include "ocsp.h"
|
||||
|
||||
/* The maximum size we allow as a response from an OCSP reponder. */
|
||||
/* The maximum size we allow as a response from an OCSP responder. */
|
||||
#define MAX_RESPONSE_SIZE 65536
|
||||
|
||||
|
||||
|
@ -526,7 +526,7 @@ check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig,
|
|||
/* Check the signature of an OCSP response. OCSP is the context,
|
||||
S_SIG the signature value and MD the handle of the hash we used for
|
||||
the response. This function automagically finds the correct public
|
||||
key. If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been
|
||||
key. If SIGNER_FPR_LIST is not NULL, the default OCSP responder has been
|
||||
used and thus the certificate is one of those identified by
|
||||
the fingerprints. */
|
||||
static gpg_error_t
|
||||
|
@ -651,7 +651,7 @@ check_signature (ctrl_t ctrl,
|
|||
or directly through the CERT object is valid by running an OCSP
|
||||
transaction. With FORCE_DEFAULT_RESPONDER set only the configured
|
||||
default responder is used. If R_REVOKED_AT or R_REASON are not
|
||||
NULL and the certificat has been revoked the revocation time and
|
||||
NULL and the certificate has been revoked the revocation time and
|
||||
the reasons are stored there. */
|
||||
gpg_error_t
|
||||
ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
||||
|
@ -723,7 +723,7 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
|
|||
}
|
||||
|
||||
/* Figure out the OCSP responder to use.
|
||||
1. Try to get the reponder from the certificate.
|
||||
1. Try to get the responder from the certificate.
|
||||
We do only take http and https style URIs into account.
|
||||
2. If this fails use the default responder, if any.
|
||||
*/
|
||||
|
|
|
@ -932,7 +932,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
|
|||
err = get_dns_srv (ctrl, domain, "openpgpkey", NULL, &srvs, &srvscount);
|
||||
if (err)
|
||||
{
|
||||
/* Ignore server failed becuase there are too many resolvers
|
||||
/* Ignore server failed because there are too many resolvers
|
||||
* which do not work as expected. */
|
||||
if (gpg_err_code (err) == GPG_ERR_SERVER_FAILED)
|
||||
err = 0; /*(srvcount is guaranteed to be 0)*/
|
||||
|
|
|
@ -291,7 +291,7 @@ main (int argc, char **argv)
|
|||
}
|
||||
if (argc)
|
||||
{
|
||||
fprintf (stderr, PGM ": no argumenst are expected\n");
|
||||
fprintf (stderr, PGM ": no arguments are expected\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ enum cert_usage_modes
|
|||
CERT_USAGE_MODE_VRFY, /* Usable for verification. */
|
||||
CERT_USAGE_MODE_DECR, /* Usable for decryption. */
|
||||
CERT_USAGE_MODE_CERT, /* Usable for cert signing. */
|
||||
CERT_USAGE_MODE_OCSP, /* Usable for OCSP respone signing. */
|
||||
CERT_USAGE_MODE_OCSP, /* Usable for OCSP response signing. */
|
||||
CERT_USAGE_MODE_CRL /* Usable for CRL signing. */
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ struct chain_item_s
|
|||
ksba_cert_t cert; /* The certificate. */
|
||||
unsigned char fpr[20]; /* Fingerprint of the certificate. */
|
||||
int is_self_signed; /* This certificate is self-signed. */
|
||||
int is_valid; /* The certifiate is valid except for revocations. */
|
||||
int is_valid; /* The certificate is valid except for revocations. */
|
||||
};
|
||||
typedef struct chain_item_s *chain_item_t;
|
||||
|
||||
|
@ -173,7 +173,7 @@ check_cert_policy (ksba_cert_t cert)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* STRING is a line delimited list of certifiate policies as stored
|
||||
/* STRING is a line delimited list of certificate policies as stored
|
||||
in the certificate. The line itself is colon delimited where the
|
||||
first field is the OID of the policy and the second field either
|
||||
N or C for normal or critical extension */
|
||||
|
|
27
doc/DETAILS
27
doc/DETAILS
|
@ -132,7 +132,7 @@ described here.
|
|||
*** Field 5 - KeyID
|
||||
|
||||
This is the 64 bit keyid as specified by OpenPGP and the last 64
|
||||
bit of the SHA-1 fingerprint of an X.509 certifciate.
|
||||
bit of the SHA-1 fingerprint of an X.509 certificate.
|
||||
|
||||
*** Field 6 - Creation date
|
||||
|
||||
|
@ -167,11 +167,13 @@ described here.
|
|||
|
||||
The value is quoted like a C string to avoid control characters
|
||||
(the colon is quoted =\x3a=). For a "pub" record this field is
|
||||
not used on --fixed-list-mode. A UAT record puts the attribute
|
||||
not used on --fixed-list-mode. A "uat" record puts the attribute
|
||||
subpacket count here, a space, and then the total attribute
|
||||
subpacket size. In gpgsm the issuer name comes here. The FPR and FP2
|
||||
records store the fingerprints here. The fingerprint of a
|
||||
revocation key is stored here.
|
||||
subpacket size. In gpgsm the issuer name comes here. The FPR and
|
||||
FP2 records store the fingerprints here. The fingerprint of a
|
||||
revocation key is also stored here. A "grp" records puts the
|
||||
keygrip here; for combined algorithms the keygrips are delimited
|
||||
by comma.
|
||||
|
||||
*** Field 11 - Signature class
|
||||
|
||||
|
@ -243,7 +245,8 @@ described here.
|
|||
*** Field 17 - Curve name
|
||||
|
||||
For pub, sub, sec, ssb, crt, and crs records this field is used
|
||||
for the ECC curve name.
|
||||
for the ECC curve name. For combined algorithms the first and the
|
||||
second algorithm name, delimited by an underscore are put here.
|
||||
|
||||
*** Field 18 - Compliance flags
|
||||
|
||||
|
@ -1098,7 +1101,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
gpg-agent.
|
||||
- keyedit.passwd :: Changing the password failed.
|
||||
- nomdc_with_legacy_cipher :: The message was not MDC protected.
|
||||
Use the command line to lern about a workaround.
|
||||
Use the command line to learn about a workaround.
|
||||
- random-compliance :: The random number generator or the used
|
||||
version of Libgcrypt do not fulfill the requirements of the
|
||||
current compliance setting. The error code is often
|
||||
|
@ -1176,7 +1179,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
<total>. For example "B", "KiB", or "MiB".
|
||||
|
||||
*** BACKUP_KEY_CREATED <fingerprint> <fname>
|
||||
A backup of a key identified by <fingerprint> has been writte to
|
||||
A backup of a key identified by <fingerprint> has been written to
|
||||
the file <fname>; <fname> is percent-escaped.
|
||||
|
||||
*** MOUNTPOINT <name>
|
||||
|
@ -1260,7 +1263,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
|
||||
*** CERTINFO <certtype> <certref> [<label>]
|
||||
|
||||
This status is emitted for X.509 certifcates.
|
||||
This status is emitted for X.509 certificates.
|
||||
CERTTYPE is a number indicating the type of the certificate:
|
||||
0 := Unknown
|
||||
100 := Regular X.509 cert
|
||||
|
@ -1271,7 +1274,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
|
||||
CERTREF identifies the certificate uniquely on the card and may be
|
||||
used to match it with a key's KEYREF. LABEL is an optional human
|
||||
readable decription of the certificate; it won't have any space in
|
||||
readable description of the certificate; it won't have any space in
|
||||
it and is percent encoded.
|
||||
|
||||
*** MANUFACTURER <n> [<string>]
|
||||
|
@ -1294,7 +1297,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
*** KEY-ATTR-INFO <keyref> <string>
|
||||
This is the response from scdaemon on GETATTR KEY-ATTR-INFO for
|
||||
OpenPGP cards. <keyref> is the usual keyref (e.g. OPENPGP.1 or
|
||||
OPENPGP.129) and <string> is the algoritm or curve name, which
|
||||
OPENPGP.129) and <string> is the algorithm or curve name, which
|
||||
is available for the key.
|
||||
|
||||
*** KEY-TIME <n> <timestamp>
|
||||
|
@ -1307,7 +1310,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
*** KEY-LABEL <keyref> <label>
|
||||
This returns the human readbable label for the keys given by
|
||||
KEYREF. LABEL won't have any space in it and is percent encoded.
|
||||
This info shall only be used for dispaly purposes.
|
||||
This info shall only be used for display purposes.
|
||||
|
||||
* Format of the --attribute-fd output
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ Note that such a comment will be removed if the git commit option
|
|||
if ( 42 == foo )
|
||||
#+end_src
|
||||
this is harder to read and modern compilers are pretty good in
|
||||
detecing accidental assignments. It is also suggested not to
|
||||
detecting accidental assignments. It is also suggested not to
|
||||
compare to 0 or NULL but to test the value direct or with a '!';
|
||||
this makes it easier to see that a boolean test is done.
|
||||
- We use our own printf style functions like =es_printf=, and
|
||||
|
@ -244,7 +244,7 @@ subject line; the list is used for several different projects.
|
|||
|
||||
In general you should send patches only for the master branch; we may
|
||||
later decide to backport to another branch. Please ask first before
|
||||
sending pacthes for another branch.
|
||||
sending patches for another branch.
|
||||
|
||||
If you're working from the Git repo, here's a suggested workflow:
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ EXTRA_DIST = samplekeys.asc mksamplekeys com-certs.pem \
|
|||
FAQ gnupg7.texi mkdefsinc.c defsincdate \
|
||||
opt-homedir.texi see-also-note.texi specify-user-id.texi \
|
||||
gpgv.texi yat2m.c ChangeLog-2011 whats-new-in-2.1.txt \
|
||||
trust-values.texi
|
||||
trust-values.texi keyformat.txt
|
||||
|
||||
BUILT_SOURCES = gnupg-module-overview.png gnupg-module-overview.pdf \
|
||||
gnupg-card-architecture.png gnupg-card-architecture.pdf \
|
||||
|
|
|
@ -91,7 +91,7 @@ should not occur but sometimes things go wrong), run it using
|
|||
@item How to find the IP address of a keyserver
|
||||
|
||||
If a round robin URL of is used for a keyserver
|
||||
(e.g. subkeys.gnupg.org); it is not easy to see what server is actually
|
||||
(e.g., subkeys.gnupg.org); it is not easy to see what server is actually
|
||||
used. Using the keyserver debug option as in
|
||||
|
||||
@smallexample
|
||||
|
@ -130,7 +130,7 @@ but Dirmngr's OCSP feature has not been enabled using
|
|||
The far most common reason for this is that the environment variable
|
||||
@code{GPG_TTY} has not been set correctly. Make sure that it has been
|
||||
set to a real tty device and not just to @samp{/dev/tty};
|
||||
i.e. @samp{GPG_TTY=tty} is plainly wrong; what you want is
|
||||
i.e., @samp{GPG_TTY=tty} is plainly wrong; what you want is
|
||||
@samp{GPG_TTY=`tty`} --- note the back ticks. Also make sure that
|
||||
this environment variable gets exported, that is you should follow up
|
||||
the setting with an @samp{export GPG_TTY} (assuming a Bourne style
|
||||
|
|
|
@ -213,7 +213,7 @@ however carefully selected to best aid in debugging.
|
|||
@item --debug @var{flags}
|
||||
@opindex debug
|
||||
Set debug flags. All flags are or-ed and @var{flags} may be given in
|
||||
C syntax (e.g. 0x0042) or as a comma separated list of flag names. To
|
||||
C syntax (e.g., 0x0042) or as a comma separated list of flag names. To
|
||||
get a list of all supported flags the single word "help" can be used.
|
||||
This option is only useful for debugging and the behavior may change
|
||||
at any time without notice.
|
||||
|
@ -295,7 +295,7 @@ seconds.
|
|||
@opindex connect-quick-timeout
|
||||
Set the timeout for HTTP and generic TCP connection attempts to N
|
||||
seconds. The value set with the quick variant is used when the
|
||||
--quick option has been given to certain Assuan commands. The quick
|
||||
@option{--quick} option has been given to certain Assuan commands. The quick
|
||||
value is capped at the value of the regular connect timeout. The
|
||||
default values are 15 and 2 seconds. Note that the timeout values are
|
||||
for each connection attempt; the connection code will attempt to
|
||||
|
@ -375,7 +375,7 @@ there for details; here is an example:
|
|||
as given. Replace USERNAME, PASSWORD, and the 'dc' parts
|
||||
according to the instructions received from your LDAP
|
||||
administrator. Note that only simple authentication
|
||||
(i.e. cleartext passwords) is supported and thus using ldaps is
|
||||
(i.e., cleartext passwords) is supported and thus using ldaps is
|
||||
strongly suggested (since 2.2.28 "ldaps" defaults to port 389
|
||||
and uses STARTTLS). On Windows authentication via AD can be
|
||||
requested by adding @code{gpgNtds=1} after the fourth question
|
||||
|
@ -468,7 +468,7 @@ Lines starting with a @samp{#} are comments.
|
|||
Note that as usual all strings entered are expected to be UTF-8 encoded.
|
||||
Obviously this will lead to problems if the password has originally been
|
||||
encoded as Latin-1. There is no other solution here than to put such a
|
||||
password in the binary encoding into the file (i.e. non-ascii characters
|
||||
password in the binary encoding into the file (i.e., non-ascii characters
|
||||
won't show up readable).@footnote{The @command{gpgconf} tool might be
|
||||
helpful for frontends as it enables editing this configuration file using
|
||||
percent-escaped strings.}
|
||||
|
@ -684,7 +684,7 @@ those certificates on startup and when given a SIGHUP. Certificates
|
|||
which are not readable or do not make up a proper X.509 certificate
|
||||
are ignored; see the log file for details.
|
||||
|
||||
Applications using dirmngr (e.g. gpgsm) can request these
|
||||
Applications using dirmngr (e.g., gpgsm) can request these
|
||||
certificates to complete a trust chain in the same way as with the
|
||||
extra-certs directory (see below).
|
||||
|
||||
|
@ -693,7 +693,7 @@ Note that for OCSP responses the certificate specified using the option
|
|||
|
||||
@item /etc/gnupg/extra-certs
|
||||
This directory may contain extra certificates which are preloaded
|
||||
into the internal cache on startup. Applications using dirmngr (e.g. gpgsm)
|
||||
into the internal cache on startup. Applications using dirmngr (e.g., gpgsm)
|
||||
can request cached certificates to complete a trust chain.
|
||||
This is convenient in cases you have a couple intermediate CA certificates
|
||||
or certificates usually used to sign OCSP responses.
|
||||
|
@ -752,7 +752,7 @@ certificate exists it is used to access the special keyservers
|
|||
|
||||
Please note that @command{gpgsm} accepts Root CA certificates for its
|
||||
own purposes only if they are listed in its file @file{trustlist.txt}.
|
||||
@command{dirmngr} does not make use of this list - except FIXME.
|
||||
@command{dirmngr} does not make use of this list --- except FIXME.
|
||||
|
||||
|
||||
@mansect notes
|
||||
|
@ -802,7 +802,7 @@ Enter @code{HELP} at the prompt to see a list of commands and enter
|
|||
@node Dirmngr Signals
|
||||
@section Use of signals
|
||||
|
||||
A running @command{dirmngr} may be controlled by signals, i.e. using
|
||||
A running @command{dirmngr} may be controlled by signals, i.e., using
|
||||
the @command{kill} command to send a signal to the process.
|
||||
|
||||
Here is a list of supported signals:
|
||||
|
@ -1034,7 +1034,7 @@ includes a local certificate store as well as a list of trusted root
|
|||
certificates.
|
||||
|
||||
@noindent
|
||||
The return code is 0 for success; i.e. the certificate has not been
|
||||
The return code is 0 for success; i.e., the certificate has not been
|
||||
revoked or one of the usual error codes from libgpg-error.
|
||||
|
||||
@node Dirmngr CHECKOCSP
|
||||
|
@ -1069,7 +1069,7 @@ of the global option @option{--ignore-ocsp-service-url}.
|
|||
|
||||
|
||||
@noindent
|
||||
The return code is 0 for success; i.e. the certificate has not been
|
||||
The return code is 0 for success; i.e., the certificate has not been
|
||||
revoked or one of the usual error codes from libgpg-error.
|
||||
|
||||
@node Dirmngr CACHECERT
|
||||
|
@ -1091,7 +1091,7 @@ Thus the caller is expected to return the certificate for the request
|
|||
as a binary blob.
|
||||
|
||||
@noindent
|
||||
The return code is 0 for success; i.e. the certificate has not been
|
||||
The return code is 0 for success; i.e., the certificate has not been
|
||||
successfully cached or one of the usual error codes from libgpg-error.
|
||||
|
||||
@node Dirmngr VALIDATE
|
||||
|
@ -1191,7 +1191,7 @@ as a binary blob.
|
|||
@c does not yet end up in memory.
|
||||
@c * @code{crl_cache_insert} is called with that descriptor to
|
||||
@c actually read the CRL into the cache. See below for a
|
||||
@c description of this function. If there is any error (e.g. read
|
||||
@c description of this function. If there is any error (e.g., read
|
||||
@c problem, CRL not correctly signed or verification of signature
|
||||
@c not possible), this descriptor is rejected and we continue
|
||||
@c with the next name. If the CRL has been successfully loaded,
|
||||
|
@ -1217,7 +1217,7 @@ as a binary blob.
|
|||
@c a) An authorityKeyIdentifier with an issuer and serialno exits: The
|
||||
@c certificate is retrieved using @code{find_cert_bysn}. If
|
||||
@c the certificate is in the certificate cache, it is directly
|
||||
@c returned. Then the requester (i.e. the client who requested the
|
||||
@c returned. Then the requester (i.e., the client who requested the
|
||||
@c CRL check) is asked via the Assuan inquiry ``SENDCERT'' whether
|
||||
@c he can provide this certificate. If this succeed the returned
|
||||
@c certificate gets cached and returned. Note, that dirmngr does not
|
||||
|
@ -1278,7 +1278,7 @@ as a binary blob.
|
|||
@c
|
||||
@c For historical reasons the Assuan command ISVALID is a bit different
|
||||
@c to CHECKCRL but this is mainly due to different calling conventions.
|
||||
@c In the end the same fucntionality is used, albeit hidden by a couple
|
||||
@c In the end the same functionality is used, albeit hidden by a couple
|
||||
@c of indirection and argument and result code mangling. It furthere
|
||||
@c ingetrages OCSP checking depending on options are the way it is
|
||||
@c called. GPGSM still uses this command but might eventually switch over
|
||||
|
@ -1296,7 +1296,7 @@ as a binary blob.
|
|||
@c expiration time of all certificates in the chain.
|
||||
@c
|
||||
@c We first check that the certificate may be used for the requested
|
||||
@c purpose (i.e. OCSP or CRL signing). If this is not the case
|
||||
@c purpose (i.e., OCSP or CRL signing). If this is not the case
|
||||
@c GPG_ERR_WRONG_KEY_USAGE is returned.
|
||||
@c
|
||||
@c The next step is to find the trust anchor (root certificate) and to
|
||||
|
@ -1320,7 +1320,7 @@ as a binary blob.
|
|||
@c Now the issuer's certificate is looked up: If an
|
||||
@c authorityKeyIdentifier is available, this one is used to locate the
|
||||
@c certificate either using issuer and serialnumber or subject DN
|
||||
@c (i.e. the issuer's DN) and the keyID. The functions
|
||||
@c (i.e., the issuer's DN) and the keyID. The functions
|
||||
@c @code{find_cert_bysn) and @code{find_cert_bysubject} are used
|
||||
@c respectively. The have already been described above under the
|
||||
@c description of @code{crl_cache_insert}. If no certificate was found
|
||||
|
@ -1334,13 +1334,13 @@ as a binary blob.
|
|||
@c actual certificate is checked and in case this fails the error
|
||||
@c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the
|
||||
@c maximum chain length of the issuing certificate is checked as well as
|
||||
@c the capability of the certificate (i.e. whether he may be used for
|
||||
@c the capability of the certificate (i.e., whether he may be used for
|
||||
@c certificate signing). Then the certificate is prepended to our list
|
||||
@c representing the certificate chain. Finally the loop is continued now
|
||||
@c with the issuer's certificate as the current certificate.
|
||||
@c
|
||||
@c After the end of the loop and if no error as been encountered
|
||||
@c (i.e. the certificate chain has been assempled correctly), a check is
|
||||
@c (i.e., the certificate chain has been assempled correctly), a check is
|
||||
@c done whether any certificate expired or a critical policy has not been
|
||||
@c met. In any of these cases the validation terminates with an
|
||||
@c appropriate error.
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
# and gpgsm.
|
||||
#use-keyboxd
|
||||
|
||||
# For testing ist is somethimes useful to use a different binary
|
||||
# of keybox. This option can be used to speicify this.
|
||||
# For testing it is sometimes useful to use a different binary
|
||||
# of keybox. This option can be used to specify this.
|
||||
#keyboxd-program /foo/bar/keyboxd
|
||||
|
||||
# For the daemons (gpg-agent, scdaemon, dirmngr, keyboxd) it is often
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# one, as well as empty lines are ignored. Lines have a length limit
|
||||
# but this is not serious limitation as the format of the entries is
|
||||
# fixed and checked by gpg-agent. A non-comment line starts with
|
||||
# optional white space, followed by the SHA-1 fingerpint in hex,
|
||||
# optional white space, followed by the SHA-1 fingerprint in hex,
|
||||
# optionally followed by a flag character which my either be 'P', 'S'
|
||||
# or '*'. This file will be read by gpg-agent if no local trustlist
|
||||
# is available or if the statement "include-default" is used in the
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
@c Create a separate index for command line options.
|
||||
@defcodeindex op
|
||||
@c Create an index vor environment variables and files.
|
||||
@c Create an index for environment variables and files.
|
||||
@defcodeindex ef
|
||||
|
||||
@c Merge the function index into the concept index.
|
||||
|
|
|
@ -72,7 +72,7 @@ the included Secure Shell Agent you may start the agent using:
|
|||
@c One way of enforcing this split is a per-key or per-session
|
||||
@c passphrase, known only by the owner, which must be supplied to the
|
||||
@c agent to permit the use of the secret key material. Another way is
|
||||
@c with an out-of-band permission mechanism (e.g. a button or GUI
|
||||
@c with an out-of-band permission mechanism (e.g@:. a button or GUI
|
||||
@c interface that the owner has access to, but the supplicant does not).
|
||||
@c
|
||||
@c The rationale for this separation is that it allows access to the
|
||||
|
@ -111,8 +111,8 @@ Please make sure that a proper pinentry program has been installed
|
|||
under the default filename (which is system dependent) or use the
|
||||
option @option{pinentry-program} to specify the full name of that program.
|
||||
It is often useful to install a symbolic link from the actual used
|
||||
pinentry (e.g. @file{@value{BINDIR}/pinentry-gtk}) to the expected
|
||||
one (e.g. @file{@value{BINDIR}/pinentry}).
|
||||
pinentry (e.g., @file{@value{BINDIR}/pinentry-gtk}) to the expected
|
||||
one (e.g., @file{@value{BINDIR}/pinentry}).
|
||||
|
||||
@manpause
|
||||
@noindent
|
||||
|
@ -177,8 +177,8 @@ Windows.
|
|||
If in @file{common.conf} the option @option{no-autostart} is set, any
|
||||
start attempts will be ignored.
|
||||
|
||||
In --supervised mode, different file descriptors can be provided for
|
||||
use as different socket types (e.g. ssh, extra) as long as they are
|
||||
In @option{--supervised} mode, different file descriptors can be provided for
|
||||
use as different socket types (e.g., ssh, extra) as long as they are
|
||||
identified in the environment variable @code{LISTEN_FDNAMES} (see
|
||||
sd_listen_fds(3) on some Linux distributions for more information on
|
||||
this convention).
|
||||
|
@ -259,7 +259,7 @@ however carefully selected to best aid in debugging.
|
|||
@item --debug @var{flags}
|
||||
@opindex debug
|
||||
Set debug flags. All flags are or-ed and @var{flags} may be given
|
||||
in C syntax (e.g. 0x0042) or as a comma separated list of flag names.
|
||||
in C syntax (e.g., 0x0042) or as a comma separated list of flag names.
|
||||
To get a list of all supported flags the single word "help" can be
|
||||
used. This option is only useful for debugging and the behavior may
|
||||
change at any time without notice.
|
||||
|
@ -345,7 +345,7 @@ specify the logging output.
|
|||
@anchor{option --no-allow-mark-trusted}
|
||||
@item --no-allow-mark-trusted
|
||||
@opindex no-allow-mark-trusted
|
||||
Do not allow clients to mark keys as trusted, i.e. put them into the
|
||||
Do not allow clients to mark keys as trusted, i.e., put them into the
|
||||
@file{trustlist.txt} file. This makes it harder for users to inadvertently
|
||||
accept Root-CA keys.
|
||||
|
||||
|
@ -716,7 +716,7 @@ The order in which keys are presented to ssh are:
|
|||
|
||||
Editing the "Use-for-ssh" values can be done with an editor or using
|
||||
@command{gpg-connect-agent} and "KEYATTR" (Remember to append a colon
|
||||
to the key; i.e. use "Use-for-ssh:").
|
||||
to the key; i.e., use "Use-for-ssh:").
|
||||
|
||||
|
||||
@anchor{option --ssh-fingerprint-digest}
|
||||
|
@ -724,7 +724,7 @@ to the key; i.e. use "Use-for-ssh:").
|
|||
@opindex ssh-fingerprint-digest
|
||||
|
||||
Select the digest algorithm used to compute ssh fingerprints that are
|
||||
communicated to the user, e.g. in pinentry dialogs. OpenSSH has
|
||||
communicated to the user, e.g., in pinentry dialogs. OpenSSH has
|
||||
transitioned from using MD5 to the more secure SHA256.
|
||||
|
||||
|
||||
|
@ -830,7 +830,7 @@ It might even be advisable to change the permissions to read-only so
|
|||
that this file can't be changed inadvertently.
|
||||
|
||||
As a special feature a line @code{include-default} will include a global
|
||||
list of trusted certificates (e.g. @file{@value{SYSCONFDIR}/trustlist.txt}).
|
||||
list of trusted certificates (e.g., @file{@value{SYSCONFDIR}/trustlist.txt}).
|
||||
This global list is also used if the local list is not available;
|
||||
the @ref{option --no-user-trustlist} enforces the use of only
|
||||
this global list.
|
||||
|
@ -892,7 +892,7 @@ The keygrip may be prefixed with a @code{!} to disable an entry.
|
|||
|
||||
The following example lists exactly one key. Note that keys available
|
||||
through a OpenPGP smartcard in the active smartcard reader are
|
||||
implicitly added to this list; i.e. there is no need to list them.
|
||||
implicitly added to this list; i.e., there is no need to list them.
|
||||
|
||||
@cartouche
|
||||
@smallexample
|
||||
|
@ -925,7 +925,7 @@ a small helper script is provided to create these files (@pxref{addgnupghome}).
|
|||
@mansect signals
|
||||
@node Agent Signals
|
||||
@section Use of some signals
|
||||
A running @command{gpg-agent} may be controlled by signals, i.e. using
|
||||
A running @command{gpg-agent} may be controlled by signals, i.e., using
|
||||
the @command{kill} command to send a signal to the process.
|
||||
|
||||
Here is a list of supported signals:
|
||||
|
@ -1407,7 +1407,7 @@ convention either the hexified fingerprint of the key shall be used for
|
|||
calling application and a colon: Like @code{gpg:somestring}.
|
||||
|
||||
@var{error_message} is either a single @code{X} for no error message or
|
||||
a string to be shown as an error message like (e.g. "invalid
|
||||
a string to be shown as an error message like (e.g., "invalid
|
||||
passphrase"). Blanks must be percent escaped or replaced by @code{+}'.
|
||||
|
||||
@var{prompt} is either a single @code{X} for a default prompt or the
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user