1 /*
2  * pageant.c: cross-platform code to implement Pageant.
3  */
4 
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <assert.h>
8 
9 #include "putty.h"
10 #include "mpint.h"
11 #include "ssh.h"
12 #include "sshcr.h"
13 #include "pageant.h"
14 
15 /*
16  * We need this to link with the RSA code, because rsa_ssh1_encrypt()
17  * pads its data with random bytes. Since we only use rsa_ssh1_decrypt()
18  * and the signing functions, which are deterministic, this should
19  * never be called.
20  *
21  * If it _is_ called, there is a _serious_ problem, because it
22  * won't generate true random numbers. So we must scream, panic,
23  * and exit immediately if that should happen.
24  */
random_read(void * buf,size_t size)25 void random_read(void *buf, size_t size)
26 {
27     modalfatalbox("Internal error: attempt to use random numbers in Pageant");
28 }
29 
30 static bool pageant_local = false;
31 
32 struct PageantClientDialogId {
33     int dummy;
34 };
35 
36 typedef struct PageantKeySort PageantKeySort;
37 typedef struct PageantKey PageantKey;
38 typedef struct PageantAsyncOp PageantAsyncOp;
39 typedef struct PageantAsyncOpVtable PageantAsyncOpVtable;
40 typedef struct PageantClientRequestNode PageantClientRequestNode;
41 typedef struct PageantKeyRequestNode PageantKeyRequestNode;
42 
43 struct PageantClientRequestNode {
44     PageantClientRequestNode *prev, *next;
45 };
46 struct PageantKeyRequestNode {
47     PageantKeyRequestNode *prev, *next;
48 };
49 
50 struct PageantClientInfo {
51     PageantClient *pc; /* goes to NULL when client is unregistered */
52     PageantClientRequestNode head;
53 };
54 
55 struct PageantAsyncOp {
56     const PageantAsyncOpVtable *vt;
57     PageantClientInfo *info;
58     PageantClientRequestNode cr;
59     PageantClientRequestId *reqid;
60 };
61 struct PageantAsyncOpVtable {
62     void (*coroutine)(PageantAsyncOp *pao);
63     void (*free)(PageantAsyncOp *pao);
64 };
pageant_async_op_coroutine(PageantAsyncOp * pao)65 static inline void pageant_async_op_coroutine(PageantAsyncOp *pao)
66 { pao->vt->coroutine(pao); }
pageant_async_op_free(PageantAsyncOp * pao)67 static inline void pageant_async_op_free(PageantAsyncOp *pao)
68 {
69     delete_callbacks_for_context(pao);
70     pao->vt->free(pao);
71 }
pageant_async_op_unlink(PageantAsyncOp * pao)72 static inline void pageant_async_op_unlink(PageantAsyncOp *pao)
73 {
74     pao->cr.prev->next = pao->cr.next;
75     pao->cr.next->prev = pao->cr.prev;
76 }
pageant_async_op_unlink_and_free(PageantAsyncOp * pao)77 static inline void pageant_async_op_unlink_and_free(PageantAsyncOp *pao)
78 {
79     pageant_async_op_unlink(pao);
80     pageant_async_op_free(pao);
81 }
pageant_async_op_callback(void * vctx)82 static void pageant_async_op_callback(void *vctx)
83 {
84     pageant_async_op_coroutine((PageantAsyncOp *)vctx);
85 }
86 
87 /*
88  * Master list of all the keys we have stored, in any form at all.
89  */
90 static tree234 *keytree;
91 struct PageantKeySort {
92     /* Prefix of the main PageantKey structure which contains all the
93      * data that the sorting order depends on. Also simple enough that
94      * you can construct one for lookup purposes. */
95     int ssh_version; /* 1 or 2; primary sort key */
96     ptrlen public_blob; /* secondary sort key */
97 };
98 struct PageantKey {
99     PageantKeySort sort;
100     strbuf *public_blob; /* the true owner of sort.public_blob */
101     char *comment;       /* stored separately, whether or not in rkey/skey */
102     union {
103         RSAKey *rkey;       /* if ssh_version == 1 */
104         ssh2_userkey *skey; /* if ssh_version == 2 */
105     };
106     strbuf *encrypted_key_file;
107     bool decryption_prompt_active;
108     PageantKeyRequestNode blocked_requests;
109     PageantClientDialogId dlgid;
110 };
111 
112 typedef struct PageantSignOp PageantSignOp;
113 struct PageantSignOp {
114     PageantKey *pk;
115     strbuf *data_to_sign;
116     unsigned flags;
117     int crLine;
118     unsigned char failure_type;
119 
120     PageantKeyRequestNode pkr;
121     PageantAsyncOp pao;
122 };
123 
124 /* Master lock that indicates whether a GUI request is currently in
125  * progress */
126 static bool gui_request_in_progress = false;
127 
128 static void failure(PageantClient *pc, PageantClientRequestId *reqid,
129                     strbuf *sb, unsigned char type, const char *fmt, ...);
130 static void fail_requests_for_key(PageantKey *pk, const char *reason);
131 static PageantKey *pageant_nth_key(int ssh_version, int i);
132 
pk_free(PageantKey * pk)133 static void pk_free(PageantKey *pk)
134 {
135     if (pk->public_blob) strbuf_free(pk->public_blob);
136     sfree(pk->comment);
137     if (pk->sort.ssh_version == 1 && pk->rkey) {
138         freersakey(pk->rkey);
139         sfree(pk->rkey);
140     }
141     if (pk->sort.ssh_version == 2 && pk->skey) {
142         sfree(pk->skey->comment);
143         ssh_key_free(pk->skey->key);
144         sfree(pk->skey);
145     }
146     if (pk->encrypted_key_file) strbuf_free(pk->encrypted_key_file);
147     fail_requests_for_key(pk, "key deleted from Pageant while signing "
148                           "request was pending");
149     sfree(pk);
150 }
151 
cmpkeys(void * av,void * bv)152 static int cmpkeys(void *av, void *bv)
153 {
154     PageantKeySort *a = (PageantKeySort *)av, *b = (PageantKeySort *)bv;
155 
156     if (a->ssh_version != b->ssh_version)
157         return a->ssh_version < b->ssh_version ? -1 : +1;
158     else
159         return ptrlen_strcmp(a->public_blob, b->public_blob);
160 }
161 
keysort(int version,ptrlen blob)162 static inline PageantKeySort keysort(int version, ptrlen blob)
163 {
164     PageantKeySort sort;
165     sort.ssh_version = version;
166     sort.public_blob = blob;
167     return sort;
168 }
169 
makeblob1(RSAKey * rkey)170 static strbuf *makeblob1(RSAKey *rkey)
171 {
172     strbuf *blob = strbuf_new();
173     rsa_ssh1_public_blob(BinarySink_UPCAST(blob), rkey,
174                          RSA_SSH1_EXPONENT_FIRST);
175     return blob;
176 }
177 
makeblob2(ssh2_userkey * skey)178 static strbuf *makeblob2(ssh2_userkey *skey)
179 {
180     strbuf *blob = strbuf_new();
181     ssh_key_public_blob(skey->key, BinarySink_UPCAST(blob));
182     return blob;
183 }
184 
findkey1(RSAKey * reqkey)185 static PageantKey *findkey1(RSAKey *reqkey)
186 {
187     strbuf *blob = makeblob1(reqkey);
188     PageantKeySort sort = keysort(1, ptrlen_from_strbuf(blob));
189     PageantKey *toret = find234(keytree, &sort, NULL);
190     strbuf_free(blob);
191     return toret;
192 }
193 
findkey2(ptrlen blob)194 static PageantKey *findkey2(ptrlen blob)
195 {
196     PageantKeySort sort = keysort(2, blob);
197     return find234(keytree, &sort, NULL);
198 }
199 
find_first_key_for_version(int ssh_version)200 static int find_first_key_for_version(int ssh_version)
201 {
202     PageantKeySort sort = keysort(ssh_version, PTRLEN_LITERAL(""));
203     int pos;
204     if (findrelpos234(keytree, &sort, NULL, REL234_GE, &pos))
205         return pos;
206     return count234(keytree);
207 }
208 
count_keys(int ssh_version)209 static int count_keys(int ssh_version)
210 {
211     return (find_first_key_for_version(ssh_version + 1) -
212             find_first_key_for_version(ssh_version));
213 }
pageant_count_ssh1_keys(void)214 int pageant_count_ssh1_keys(void) { return count_keys(1); }
pageant_count_ssh2_keys(void)215 int pageant_count_ssh2_keys(void) { return count_keys(2); }
216 
pageant_add_ssh1_key(RSAKey * rkey)217 static bool pageant_add_ssh1_key(RSAKey *rkey)
218 {
219     PageantKey *pk = snew(PageantKey);
220     memset(pk, 0, sizeof(PageantKey));
221     pk->sort.ssh_version = 1;
222     pk->public_blob = makeblob1(rkey);
223     pk->sort.public_blob = ptrlen_from_strbuf(pk->public_blob);
224     pk->blocked_requests.next = pk->blocked_requests.prev =
225         &pk->blocked_requests;
226 
227     if (add234(keytree, pk) == pk) {
228         pk->rkey = rkey;
229         if (rkey->comment)
230             pk->comment = dupstr(rkey->comment);
231         return true;
232     } else {
233         pk_free(pk);
234         return false;
235     }
236 }
237 
pageant_add_ssh2_key(ssh2_userkey * skey)238 static bool pageant_add_ssh2_key(ssh2_userkey *skey)
239 {
240     PageantKey *pk = snew(PageantKey);
241     memset(pk, 0, sizeof(PageantKey));
242     pk->sort.ssh_version = 2;
243     pk->public_blob = makeblob2(skey);
244     pk->sort.public_blob = ptrlen_from_strbuf(pk->public_blob);
245     pk->blocked_requests.next = pk->blocked_requests.prev =
246         &pk->blocked_requests;
247 
248     PageantKey *pk_in_tree = add234(keytree, pk);
249     if (pk_in_tree == pk) {
250         /* The key wasn't in the tree at all, and we've just added it. */
251         pk->skey = skey;
252         if (skey->comment)
253             pk->comment = dupstr(skey->comment);
254         return true;
255     } else if (!pk_in_tree->skey) {
256         /* The key was only stored encrypted, and now we have an
257          * unencrypted version to add to the existing record. */
258         pk_in_tree->skey = skey;
259         pk_free(pk);
260         return true;
261     } else {
262         /* The key was already in the tree in full. */
263         pk_free(pk);
264         return false;
265     }
266 }
267 
remove_all_keys(int ssh_version)268 static void remove_all_keys(int ssh_version)
269 {
270     int start = find_first_key_for_version(ssh_version);
271     int end = find_first_key_for_version(ssh_version + 1);
272     while (end > start) {
273         PageantKey *pk = delpos234(keytree, --end);
274         assert(pk->sort.ssh_version == ssh_version);
275         pk_free(pk);
276     }
277 }
278 
list_keys(BinarySink * bs,int ssh_version,bool extended)279 static void list_keys(BinarySink *bs, int ssh_version, bool extended)
280 {
281     int i;
282     PageantKey *pk;
283 
284     put_uint32(bs, count_keys(ssh_version));
285     for (i = find_first_key_for_version(ssh_version);
286          NULL != (pk = index234(keytree, i)); i++) {
287         if (pk->sort.ssh_version != ssh_version)
288             break;
289 
290         if (ssh_version > 1)
291             put_stringpl(bs, pk->sort.public_blob);
292         else
293             put_datapl(bs, pk->sort.public_blob); /* no header */
294 
295         put_stringpl(bs, ptrlen_from_asciz(pk->comment));
296 
297         if (extended) {
298             /*
299              * Append to each key entry a string containing extension
300              * data. This string begins with a flags word, and may in
301              * future contain further data if flag bits are set saying
302              * that it does. Hence, it's wrapped in a containing
303              * string, so that clients that only partially understand
304              * it can still find the parts they do understand.
305              */
306             strbuf *sb = strbuf_new();
307 
308             uint32_t flags = 0;
309             if (!pk->skey)
310                 flags |= LIST_EXTENDED_FLAG_HAS_NO_CLEARTEXT_KEY;
311             if (pk->encrypted_key_file)
312                 flags |= LIST_EXTENDED_FLAG_HAS_ENCRYPTED_KEY_FILE;
313             put_uint32(sb, flags);
314 
315             put_stringsb(bs, sb);
316         }
317     }
318 }
319 
pageant_make_keylist1(BinarySink * bs)320 void pageant_make_keylist1(BinarySink *bs) { list_keys(bs, 1, false); }
pageant_make_keylist2(BinarySink * bs)321 void pageant_make_keylist2(BinarySink *bs) { list_keys(bs, 2, false); }
pageant_make_keylist_extended(BinarySink * bs)322 void pageant_make_keylist_extended(BinarySink *bs) { list_keys(bs, 2, true); }
323 
pageant_register_client(PageantClient * pc)324 void pageant_register_client(PageantClient *pc)
325 {
326     pc->info = snew(PageantClientInfo);
327     pc->info->pc = pc;
328     pc->info->head.prev = pc->info->head.next = &pc->info->head;
329 }
330 
pageant_unregister_client(PageantClient * pc)331 void pageant_unregister_client(PageantClient *pc)
332 {
333     PageantClientInfo *info = pc->info;
334     assert(info);
335     assert(info->pc == pc);
336 
337     while (pc->info->head.next != &pc->info->head) {
338         PageantAsyncOp *pao = container_of(pc->info->head.next,
339                                            PageantAsyncOp, cr);
340         pageant_async_op_unlink_and_free(pao);
341     }
342 
343     sfree(pc->info);
344 }
345 
failure(PageantClient * pc,PageantClientRequestId * reqid,strbuf * sb,unsigned char type,const char * fmt,...)346 static PRINTF_LIKE(5, 6) void failure(
347     PageantClient *pc, PageantClientRequestId *reqid, strbuf *sb,
348     unsigned char type, const char *fmt, ...)
349 {
350     strbuf_clear(sb);
351     put_byte(sb, type);
352     if (!pc->suppress_logging) {
353         va_list ap;
354         va_start(ap, fmt);
355         char *msg = dupvprintf(fmt, ap);
356         va_end(ap);
357         pageant_client_log(pc, reqid, "reply: SSH_AGENT_FAILURE (%s)", msg);
358         sfree(msg);
359     }
360 }
361 
signop_link(PageantSignOp * so)362 static void signop_link(PageantSignOp *so)
363 {
364     assert(!so->pkr.prev);
365     assert(!so->pkr.next);
366 
367     so->pkr.prev = so->pk->blocked_requests.prev;
368     so->pkr.next = &so->pk->blocked_requests;
369     so->pkr.prev->next = &so->pkr;
370     so->pkr.next->prev = &so->pkr;
371 }
372 
signop_unlink(PageantSignOp * so)373 static void signop_unlink(PageantSignOp *so)
374 {
375     if (so->pkr.next) {
376         assert(so->pkr.prev);
377         so->pkr.next->prev = so->pkr.prev;
378         so->pkr.prev->next = so->pkr.next;
379     } else {
380         assert(!so->pkr.prev);
381     }
382 }
383 
signop_free(PageantAsyncOp * pao)384 static void signop_free(PageantAsyncOp *pao)
385 {
386     PageantSignOp *so = container_of(pao, PageantSignOp, pao);
387     strbuf_free(so->data_to_sign);
388     sfree(so);
389 }
390 
request_passphrase(PageantClient * pc,PageantKey * pk)391 static bool request_passphrase(PageantClient *pc, PageantKey *pk)
392 {
393     if (!pk->decryption_prompt_active) {
394         assert(!gui_request_in_progress);
395 
396         bool created_dlg = pageant_client_ask_passphrase(
397             pc, &pk->dlgid, pk->comment);
398 
399         if (!created_dlg)
400             return false;
401 
402         gui_request_in_progress = true;
403         pk->decryption_prompt_active = true;
404     }
405 
406     return true;
407 }
408 
signop_coroutine(PageantAsyncOp * pao)409 static void signop_coroutine(PageantAsyncOp *pao)
410 {
411     PageantSignOp *so = container_of(pao, PageantSignOp, pao);
412     strbuf *response;
413 
414     crBegin(so->crLine);
415 
416     while (!so->pk->skey && gui_request_in_progress)
417         crReturnV;
418 
419     if (!so->pk->skey) {
420         assert(so->pk->encrypted_key_file);
421 
422         if (!request_passphrase(so->pao.info->pc, so->pk)) {
423             response = strbuf_new();
424             failure(so->pao.info->pc, so->pao.reqid, response,
425                     so->failure_type, "on-demand decryption could not "
426                     "prompt for a passphrase");
427             goto respond;
428         }
429 
430         signop_link(so);
431         crReturnV;
432         signop_unlink(so);
433     }
434 
435     uint32_t supported_flags = ssh_key_alg(so->pk->skey->key)->supported_flags;
436     if (so->flags & ~supported_flags) {
437         /*
438          * We MUST reject any message containing flags we don't
439          * understand.
440          */
441         response = strbuf_new();
442         failure(so->pao.info->pc, so->pao.reqid, response, so->failure_type,
443                 "unsupported flag bits 0x%08"PRIx32,
444                 so->flags & ~supported_flags);
445         goto respond;
446     }
447 
448     char *invalid = ssh_key_invalid(so->pk->skey->key, so->flags);
449     if (invalid) {
450         response = strbuf_new();
451         failure(so->pao.info->pc, so->pao.reqid, response, so->failure_type,
452                 "key invalid: %s", invalid);
453         sfree(invalid);
454         goto respond;
455     }
456 
457     strbuf *signature = strbuf_new();
458     ssh_key_sign(so->pk->skey->key, ptrlen_from_strbuf(so->data_to_sign),
459                  so->flags, BinarySink_UPCAST(signature));
460 
461     response = strbuf_new();
462     put_byte(response, SSH2_AGENT_SIGN_RESPONSE);
463     put_stringsb(response, signature);
464 
465   respond:
466     pageant_client_got_response(so->pao.info->pc, so->pao.reqid,
467                                 ptrlen_from_strbuf(response));
468     strbuf_free(response);
469 
470     pageant_async_op_unlink_and_free(&so->pao);
471     crFinishFreedV;
472 }
473 
474 static const PageantAsyncOpVtable signop_vtable = {
475     .coroutine = signop_coroutine,
476     .free = signop_free,
477 };
478 
fail_requests_for_key(PageantKey * pk,const char * reason)479 static void fail_requests_for_key(PageantKey *pk, const char *reason)
480 {
481     while (pk->blocked_requests.next != &pk->blocked_requests) {
482         PageantSignOp *so = container_of(pk->blocked_requests.next,
483                                          PageantSignOp, pkr);
484         signop_unlink(so);
485         strbuf *sb = strbuf_new();
486         failure(so->pao.info->pc, so->pao.reqid, sb, so->failure_type,
487                 "%s", reason);
488         pageant_client_got_response(so->pao.info->pc, so->pao.reqid,
489                                     ptrlen_from_strbuf(sb));
490         strbuf_free(sb);
491         pageant_async_op_unlink_and_free(&so->pao);
492     }
493 }
494 
unblock_requests_for_key(PageantKey * pk)495 static void unblock_requests_for_key(PageantKey *pk)
496 {
497     for (PageantKeyRequestNode *pkr = pk->blocked_requests.next;
498          pkr != &pk->blocked_requests; pkr = pkr->next) {
499         PageantSignOp *so = container_of(pk->blocked_requests.next,
500                                          PageantSignOp, pkr);
501         queue_toplevel_callback(pageant_async_op_callback, &so->pao);
502     }
503 }
504 
pageant_passphrase_request_success(PageantClientDialogId * dlgid,ptrlen passphrase)505 void pageant_passphrase_request_success(PageantClientDialogId *dlgid,
506                                         ptrlen passphrase)
507 {
508     PageantKey *pk = container_of(dlgid, PageantKey, dlgid);
509 
510     assert(gui_request_in_progress);
511     gui_request_in_progress = false;
512     pk->decryption_prompt_active = false;
513 
514     if (!pk->skey) {
515         const char *error;
516 
517         BinarySource src[1];
518         BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(
519                                       pk->encrypted_key_file));
520 
521         strbuf *ppsb = strbuf_new_nm();
522         put_datapl(ppsb, passphrase);
523 
524         pk->skey = ppk_load_s(src, ppsb->s, &error);
525 
526         strbuf_free(ppsb);
527 
528         if (!pk->skey) {
529             fail_requests_for_key(pk, "unable to decrypt key");
530             return;
531         } else if (pk->skey == SSH2_WRONG_PASSPHRASE) {
532             pk->skey = NULL;
533 
534             /*
535              * Find a PageantClient to use for another attempt at
536              * request_passphrase.
537              */
538             PageantKeyRequestNode *pkr = pk->blocked_requests.next;
539             if (pkr == &pk->blocked_requests) {
540                 /*
541                  * Special case: if all the requests have gone away at
542                  * this point, we need not bother putting up a request
543                  * at all any more.
544                  */
545                 return;
546             }
547 
548             PageantSignOp *so = container_of(pk->blocked_requests.next,
549                                              PageantSignOp, pkr);
550 
551             pk->decryption_prompt_active = false;
552             if (!request_passphrase(so->pao.info->pc, pk)) {
553                 fail_requests_for_key(pk, "unable to continue creating "
554                                       "passphrase prompts");
555             }
556             return;
557         } else {
558             keylist_update();
559         }
560     }
561 
562     unblock_requests_for_key(pk);
563 }
564 
pageant_passphrase_request_refused(PageantClientDialogId * dlgid)565 void pageant_passphrase_request_refused(PageantClientDialogId *dlgid)
566 {
567     PageantKey *pk = container_of(dlgid, PageantKey, dlgid);
568 
569     assert(gui_request_in_progress);
570     gui_request_in_progress = false;
571     pk->decryption_prompt_active = false;
572 
573     fail_requests_for_key(pk, "user refused to supply passphrase");
574 }
575 
576 typedef struct PageantImmOp PageantImmOp;
577 struct PageantImmOp {
578     int crLine;
579     strbuf *response;
580 
581     PageantAsyncOp pao;
582 };
583 
immop_free(PageantAsyncOp * pao)584 static void immop_free(PageantAsyncOp *pao)
585 {
586     PageantImmOp *io = container_of(pao, PageantImmOp, pao);
587     if (io->response)
588         strbuf_free(io->response);
589     sfree(io);
590 }
591 
immop_coroutine(PageantAsyncOp * pao)592 static void immop_coroutine(PageantAsyncOp *pao)
593 {
594     PageantImmOp *io = container_of(pao, PageantImmOp, pao);
595 
596     crBegin(io->crLine);
597 
598     if (0) crReturnV;
599 
600     pageant_client_got_response(io->pao.info->pc, io->pao.reqid,
601                                 ptrlen_from_strbuf(io->response));
602     pageant_async_op_unlink_and_free(&io->pao);
603     crFinishFreedV;
604 }
605 
606 static const PageantAsyncOpVtable immop_vtable = {
607     .coroutine = immop_coroutine,
608     .free = immop_free,
609 };
610 
reencrypt_key(PageantKey * pk)611 static bool reencrypt_key(PageantKey *pk)
612 {
613     if (pk->sort.ssh_version != 2) {
614         /*
615          * We don't support storing SSH-1 keys in encrypted form at
616          * all.
617          */
618         return false;
619     }
620 
621     if (!pk->encrypted_key_file) {
622         /*
623          * We can't re-encrypt a key if it doesn't have an encrypted
624          * form. (We could make one up, of course - but with what
625          * passphrase that we could expect the user to know later?)
626          */
627         return false;
628     }
629 
630     /* Only actually free pk->skey if it exists. But we return success
631      * regardless, so that 'please ensure this key isn't stored
632      * decrypted' is idempotent. */
633     if (pk->skey) {
634         sfree(pk->skey->comment);
635         ssh_key_free(pk->skey->key);
636         sfree(pk->skey);
637         pk->skey = NULL;
638     }
639 
640     return true;
641 }
642 
643 #define DECL_EXT_ENUM(id, name) id,
644 enum Extension { KNOWN_EXTENSIONS(DECL_EXT_ENUM) EXT_UNKNOWN };
645 #define DEF_EXT_NAMES(id, name) PTRLEN_DECL_LITERAL(name),
646 static const ptrlen extension_names[] = { KNOWN_EXTENSIONS(DEF_EXT_NAMES) };
647 
pageant_make_op(PageantClient * pc,PageantClientRequestId * reqid,ptrlen msgpl)648 static PageantAsyncOp *pageant_make_op(
649     PageantClient *pc, PageantClientRequestId *reqid, ptrlen msgpl)
650 {
651     BinarySource msg[1];
652     strbuf *sb = strbuf_new_nm();
653     unsigned char failure_type = SSH_AGENT_FAILURE;
654     int type;
655 
656 #define fail(...) failure(pc, reqid, sb, failure_type, __VA_ARGS__)
657 
658     BinarySource_BARE_INIT_PL(msg, msgpl);
659 
660     type = get_byte(msg);
661     if (get_err(msg)) {
662         fail("message contained no type code");
663         goto responded;
664     }
665 
666     switch (type) {
667       case SSH1_AGENTC_REQUEST_RSA_IDENTITIES: {
668         /*
669          * Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
670          */
671         pageant_client_log(pc, reqid,
672                            "request: SSH1_AGENTC_REQUEST_RSA_IDENTITIES");
673 
674         put_byte(sb, SSH1_AGENT_RSA_IDENTITIES_ANSWER);
675         pageant_make_keylist1(BinarySink_UPCAST(sb));
676 
677         pageant_client_log(pc, reqid,
678                            "reply: SSH1_AGENT_RSA_IDENTITIES_ANSWER");
679         if (!pc->suppress_logging) {
680             int i;
681             PageantKey *pk;
682             for (i = 0; NULL != (pk = pageant_nth_key(1, i)); i++) {
683                 char *fingerprint = rsa_ssh1_fingerprint(pk->rkey);
684                 pageant_client_log(pc, reqid, "returned key: %s",
685                                    fingerprint);
686                 sfree(fingerprint);
687             }
688         }
689         break;
690       }
691       case SSH2_AGENTC_REQUEST_IDENTITIES: {
692         /*
693          * Reply with SSH2_AGENT_IDENTITIES_ANSWER.
694          */
695         pageant_client_log(pc, reqid,
696                            "request: SSH2_AGENTC_REQUEST_IDENTITIES");
697 
698         put_byte(sb, SSH2_AGENT_IDENTITIES_ANSWER);
699         pageant_make_keylist2(BinarySink_UPCAST(sb));
700 
701         pageant_client_log(pc, reqid, "reply: SSH2_AGENT_IDENTITIES_ANSWER");
702         if (!pc->suppress_logging) {
703             int i;
704             PageantKey *pk;
705             for (i = 0; NULL != (pk = pageant_nth_key(2, i)); i++) {
706                 char *fingerprint = ssh2_fingerprint_blob(
707                     ptrlen_from_strbuf(pk->public_blob), SSH_FPTYPE_DEFAULT);
708                 pageant_client_log(pc, reqid, "returned key: %s %s",
709                                    fingerprint, pk->comment);
710                 sfree(fingerprint);
711             }
712         }
713         break;
714       }
715       case SSH1_AGENTC_RSA_CHALLENGE: {
716         /*
717          * Reply with either SSH1_AGENT_RSA_RESPONSE or
718          * SSH_AGENT_FAILURE, depending on whether we have that key
719          * or not.
720          */
721         RSAKey reqkey;
722         PageantKey *pk;
723         mp_int *challenge, *response;
724         ptrlen session_id;
725         unsigned response_type;
726         unsigned char response_md5[16];
727         int i;
728 
729         pageant_client_log(pc, reqid, "request: SSH1_AGENTC_RSA_CHALLENGE");
730 
731         response = NULL;
732         memset(&reqkey, 0, sizeof(reqkey));
733 
734         get_rsa_ssh1_pub(msg, &reqkey, RSA_SSH1_EXPONENT_FIRST);
735         challenge = get_mp_ssh1(msg);
736         session_id = get_data(msg, 16);
737         response_type = get_uint32(msg);
738 
739         if (get_err(msg)) {
740             fail("unable to decode request");
741             goto challenge1_cleanup;
742         }
743         if (response_type != 1) {
744             fail("response type other than 1 not supported");
745             goto challenge1_cleanup;
746         }
747 
748         if (!pc->suppress_logging) {
749             char *fingerprint;
750             reqkey.comment = NULL;
751             fingerprint = rsa_ssh1_fingerprint(&reqkey);
752             pageant_client_log(pc, reqid, "requested key: %s", fingerprint);
753             sfree(fingerprint);
754         }
755 
756         if ((pk = findkey1(&reqkey)) == NULL) {
757             fail("key not found");
758             goto challenge1_cleanup;
759         }
760         response = rsa_ssh1_decrypt(challenge, pk->rkey);
761 
762         {
763             ssh_hash *h = ssh_hash_new(&ssh_md5);
764             for (i = 0; i < 32; i++)
765                 put_byte(h, mp_get_byte(response, 31 - i));
766             put_datapl(h, session_id);
767             ssh_hash_final(h, response_md5);
768         }
769 
770         put_byte(sb, SSH1_AGENT_RSA_RESPONSE);
771         put_data(sb, response_md5, 16);
772 
773         pageant_client_log(pc, reqid, "reply: SSH1_AGENT_RSA_RESPONSE");
774 
775           challenge1_cleanup:
776         if (response)
777             mp_free(response);
778         mp_free(challenge);
779         freersakey(&reqkey);
780         break;
781       }
782       case SSH2_AGENTC_SIGN_REQUEST: {
783         /*
784          * Reply with either SSH2_AGENT_SIGN_RESPONSE or
785          * SSH_AGENT_FAILURE, depending on whether we have that key
786          * or not.
787          */
788         PageantKey *pk;
789         ptrlen keyblob, sigdata;
790         uint32_t flags;
791 
792         pageant_client_log(pc, reqid, "request: SSH2_AGENTC_SIGN_REQUEST");
793 
794         keyblob = get_string(msg);
795         sigdata = get_string(msg);
796 
797         if (get_err(msg)) {
798             fail("unable to decode request");
799             goto responded;
800         }
801 
802         /*
803          * Later versions of the agent protocol added a flags word
804          * on the end of the sign request. That hasn't always been
805          * there, so we don't complain if we don't find it.
806          *
807          * get_uint32 will default to returning zero if no data is
808          * available.
809          */
810         bool have_flags = false;
811         flags = get_uint32(msg);
812         if (!get_err(msg))
813             have_flags = true;
814 
815         if (!pc->suppress_logging) {
816             char *fingerprint = ssh2_fingerprint_blob(
817                 keyblob, SSH_FPTYPE_DEFAULT);
818             pageant_client_log(pc, reqid, "requested key: %s", fingerprint);
819             sfree(fingerprint);
820         }
821         if ((pk = findkey2(keyblob)) == NULL) {
822             fail("key not found");
823             goto responded;
824         }
825 
826         if (have_flags)
827             pageant_client_log(pc, reqid, "signature flags = 0x%08"PRIx32,
828                                flags);
829         else
830             pageant_client_log(pc, reqid, "no signature flags");
831 
832         strbuf_free(sb); /* no immediate response */
833 
834         PageantSignOp *so = snew(PageantSignOp);
835         so->pao.vt = &signop_vtable;
836         so->pao.info = pc->info;
837         so->pao.cr.prev = pc->info->head.prev;
838         so->pao.cr.next = &pc->info->head;
839         so->pao.reqid = reqid;
840         so->pk = pk;
841         so->pkr.prev = so->pkr.next = NULL;
842         so->data_to_sign = strbuf_new();
843         put_datapl(so->data_to_sign, sigdata);
844         so->flags = flags;
845         so->failure_type = failure_type;
846         so->crLine = 0;
847         return &so->pao;
848         break;
849       }
850       case SSH1_AGENTC_ADD_RSA_IDENTITY: {
851         /*
852          * Add to the list and return SSH_AGENT_SUCCESS, or
853          * SSH_AGENT_FAILURE if the key was malformed.
854          */
855         RSAKey *key;
856 
857         pageant_client_log(pc, reqid, "request: SSH1_AGENTC_ADD_RSA_IDENTITY");
858 
859         key = get_rsa_ssh1_priv_agent(msg);
860         key->comment = mkstr(get_string(msg));
861 
862         if (get_err(msg)) {
863             fail("unable to decode request");
864             goto add1_cleanup;
865         }
866 
867         if (!rsa_verify(key)) {
868             fail("key is invalid");
869             goto add1_cleanup;
870         }
871 
872         if (!pc->suppress_logging) {
873             char *fingerprint = rsa_ssh1_fingerprint(key);
874             pageant_client_log(pc, reqid,
875                                "submitted key: %s", fingerprint);
876             sfree(fingerprint);
877         }
878 
879         if (pageant_add_ssh1_key(key)) {
880             keylist_update();
881             put_byte(sb, SSH_AGENT_SUCCESS);
882             pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
883             key = NULL;            /* don't free it in cleanup */
884         } else {
885             fail("key already present");
886         }
887 
888           add1_cleanup:
889         if (key) {
890             freersakey(key);
891             sfree(key);
892         }
893         break;
894       }
895       case SSH2_AGENTC_ADD_IDENTITY: {
896         /*
897          * Add to the list and return SSH_AGENT_SUCCESS, or
898          * SSH_AGENT_FAILURE if the key was malformed.
899          */
900         ssh2_userkey *key = NULL;
901         ptrlen algpl;
902         const ssh_keyalg *alg;
903 
904         pageant_client_log(pc, reqid, "request: SSH2_AGENTC_ADD_IDENTITY");
905 
906         algpl = get_string(msg);
907 
908         key = snew(ssh2_userkey);
909         key->key = NULL;
910         key->comment = NULL;
911         alg = find_pubkey_alg_len(algpl);
912         if (!alg) {
913             fail("algorithm unknown");
914             goto add2_cleanup;
915         }
916 
917         key->key = ssh_key_new_priv_openssh(alg, msg);
918 
919         if (!key->key) {
920             fail("key setup failed");
921             goto add2_cleanup;
922         }
923 
924         key->comment = mkstr(get_string(msg));
925 
926         if (get_err(msg)) {
927             fail("unable to decode request");
928             goto add2_cleanup;
929         }
930 
931         if (!pc->suppress_logging) {
932             char *fingerprint = ssh2_fingerprint(key->key, SSH_FPTYPE_DEFAULT);
933             pageant_client_log(pc, reqid, "submitted key: %s %s",
934                                fingerprint, key->comment);
935             sfree(fingerprint);
936         }
937 
938         if (pageant_add_ssh2_key(key)) {
939             keylist_update();
940             put_byte(sb, SSH_AGENT_SUCCESS);
941 
942             pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
943 
944             key = NULL;            /* don't clean it up */
945         } else {
946             fail("key already present");
947         }
948 
949           add2_cleanup:
950         if (key) {
951             if (key->key)
952                 ssh_key_free(key->key);
953             if (key->comment)
954                 sfree(key->comment);
955             sfree(key);
956         }
957         break;
958       }
959       case SSH1_AGENTC_REMOVE_RSA_IDENTITY: {
960         /*
961          * Remove from the list and return SSH_AGENT_SUCCESS, or
962          * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
963          * start with.
964          */
965         RSAKey reqkey;
966         PageantKey *pk;
967 
968         pageant_client_log(pc, reqid,
969                            "request: SSH1_AGENTC_REMOVE_RSA_IDENTITY");
970 
971         memset(&reqkey, 0, sizeof(reqkey));
972         get_rsa_ssh1_pub(msg, &reqkey, RSA_SSH1_EXPONENT_FIRST);
973 
974         if (get_err(msg)) {
975             fail("unable to decode request");
976             freersakey(&reqkey);
977             goto responded;
978         }
979 
980         if (!pc->suppress_logging) {
981             char *fingerprint;
982             reqkey.comment = NULL;
983             fingerprint = rsa_ssh1_fingerprint(&reqkey);
984             pageant_client_log(pc, reqid, "unwanted key: %s", fingerprint);
985             sfree(fingerprint);
986         }
987 
988         pk = findkey1(&reqkey);
989         freersakey(&reqkey);
990         if (pk) {
991             pageant_client_log(pc, reqid, "found with comment: %s",
992                                pk->rkey->comment);
993 
994             del234(keytree, pk);
995             keylist_update();
996             pk_free(pk);
997             put_byte(sb, SSH_AGENT_SUCCESS);
998 
999             pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
1000         } else {
1001             fail("key not found");
1002         }
1003         break;
1004       }
1005       case SSH2_AGENTC_REMOVE_IDENTITY: {
1006         /*
1007          * Remove from the list and return SSH_AGENT_SUCCESS, or
1008          * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
1009          * start with.
1010          */
1011         PageantKey *pk;
1012         ptrlen blob;
1013 
1014         pageant_client_log(pc, reqid, "request: SSH2_AGENTC_REMOVE_IDENTITY");
1015 
1016         blob = get_string(msg);
1017 
1018         if (get_err(msg)) {
1019             fail("unable to decode request");
1020             goto responded;
1021         }
1022 
1023         if (!pc->suppress_logging) {
1024             char *fingerprint = ssh2_fingerprint_blob(
1025                 blob, SSH_FPTYPE_DEFAULT);
1026             pageant_client_log(pc, reqid, "unwanted key: %s", fingerprint);
1027             sfree(fingerprint);
1028         }
1029 
1030         pk = findkey2(blob);
1031         if (!pk) {
1032             fail("key not found");
1033             goto responded;
1034         }
1035 
1036         pageant_client_log(pc, reqid, "found with comment: %s", pk->comment);
1037 
1038         del234(keytree, pk);
1039         keylist_update();
1040         pk_free(pk);
1041         put_byte(sb, SSH_AGENT_SUCCESS);
1042 
1043         pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
1044         break;
1045       }
1046       case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES: {
1047         /*
1048          * Remove all SSH-1 keys. Always returns success.
1049          */
1050         pageant_client_log(pc, reqid,
1051                            "request: SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES");
1052 
1053         remove_all_keys(1);
1054         keylist_update();
1055 
1056         put_byte(sb, SSH_AGENT_SUCCESS);
1057 
1058         pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
1059         break;
1060       }
1061       case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: {
1062         /*
1063          * Remove all SSH-2 keys. Always returns success.
1064          */
1065         pageant_client_log(pc, reqid,
1066                            "request: SSH2_AGENTC_REMOVE_ALL_IDENTITIES");
1067 
1068         remove_all_keys(2);
1069         keylist_update();
1070 
1071         put_byte(sb, SSH_AGENT_SUCCESS);
1072 
1073         pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
1074         break;
1075       }
1076       case SSH2_AGENTC_EXTENSION: {
1077         enum Extension exttype = EXT_UNKNOWN;
1078         ptrlen extname = get_string(msg);
1079         pageant_client_log(pc, reqid,
1080                            "request: SSH2_AGENTC_EXTENSION \"%.*s\"",
1081                            PTRLEN_PRINTF(extname));
1082 
1083         for (size_t i = 0; i < lenof(extension_names); i++)
1084             if (ptrlen_eq_ptrlen(extname, extension_names[i])) {
1085                 exttype = i;
1086 
1087                 /*
1088                  * For SSH_AGENTC_EXTENSION requests, the message
1089                  * code SSH_AGENT_FAILURE is reserved for "I don't
1090                  * recognise this extension name at all". For any
1091                  * other kind of failure while processing an
1092                  * extension we _do_ recognise, we must switch to
1093                  * returning a different failure code, with
1094                  * semantics "I understood the extension name, but
1095                  * something else went wrong".
1096                  */
1097                 failure_type = SSH_AGENT_EXTENSION_FAILURE;
1098                 break;
1099             }
1100 
1101         switch (exttype) {
1102           case EXT_UNKNOWN:
1103             fail("unrecognised extension name '%.*s'",
1104                  PTRLEN_PRINTF(extname));
1105             break;
1106 
1107           case EXT_QUERY:
1108             /* Standard request to list the supported extensions. */
1109             put_byte(sb, SSH_AGENT_SUCCESS);
1110             for (size_t i = 0; i < lenof(extension_names); i++)
1111                 put_stringpl(sb, extension_names[i]);
1112             pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS + names");
1113             break;
1114 
1115           case EXT_ADD_PPK: {
1116             ptrlen keyfile = get_string(msg);
1117 
1118             if (get_err(msg)) {
1119                 fail("unable to decode request");
1120                 goto responded;
1121             }
1122 
1123             BinarySource src[1];
1124             const char *error;
1125 
1126             strbuf *public_blob = strbuf_new();
1127             char *comment;
1128 
1129             BinarySource_BARE_INIT_PL(src, keyfile);
1130             if (!ppk_loadpub_s(src, NULL, BinarySink_UPCAST(public_blob),
1131                                &comment, &error)) {
1132                 fail("failed to extract public key blob: %s", error);
1133                 goto add_ppk_cleanup;
1134             }
1135 
1136             if (!pc->suppress_logging) {
1137                 char *fingerprint = ssh2_fingerprint_blob(
1138                     ptrlen_from_strbuf(public_blob), SSH_FPTYPE_DEFAULT);
1139                 pageant_client_log(pc, reqid, "add-ppk: %s %s",
1140                                    fingerprint, comment);
1141                 sfree(fingerprint);
1142             }
1143 
1144             BinarySource_BARE_INIT_PL(src, keyfile);
1145             bool encrypted = ppk_encrypted_s(src, NULL);
1146 
1147             if (!encrypted) {
1148                 /* If the key isn't encrypted, then we should just
1149                  * load and add it in the obvious way. */
1150                 BinarySource_BARE_INIT_PL(src, keyfile);
1151                 ssh2_userkey *skey = ppk_load_s(src, NULL, &error);
1152                 if (!skey) {
1153                     fail("failed to decode private key: %s", error);
1154                 } else if (pageant_add_ssh2_key(skey)) {
1155                     keylist_update();
1156                     put_byte(sb, SSH_AGENT_SUCCESS);
1157 
1158                     pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS"
1159                                        " (loaded unencrypted PPK)");
1160                 } else {
1161                     fail("key already present");
1162                     if (skey->key)
1163                         ssh_key_free(skey->key);
1164                     if (skey->comment)
1165                         sfree(skey->comment);
1166                     sfree(skey);
1167                 }
1168                 goto add_ppk_cleanup;
1169             }
1170 
1171             PageantKeySort sort =
1172                 keysort(2, ptrlen_from_strbuf(public_blob));
1173 
1174             PageantKey *pk = find234(keytree, &sort, NULL);
1175             if (pk) {
1176                 /*
1177                  * This public key blob already exists in the
1178                  * keytree. Add the encrypted key file to the
1179                  * existing record, if it doesn't have one already.
1180                  */
1181                 if (!pk->encrypted_key_file) {
1182                     pk->encrypted_key_file = strbuf_new_nm();
1183                     put_datapl(pk->encrypted_key_file, keyfile);
1184 
1185                     keylist_update();
1186                     put_byte(sb, SSH_AGENT_SUCCESS);
1187                     pageant_client_log(
1188                         pc, reqid, "reply: SSH_AGENT_SUCCESS (added encrypted"
1189                         " PPK to existing key record)");
1190                 } else {
1191                     fail("key already present");
1192                 }
1193             } else {
1194                 /*
1195                  * We're adding a new key record containing only
1196                  * an encrypted key file.
1197                  */
1198                 PageantKey *pk = snew(PageantKey);
1199                 memset(pk, 0, sizeof(PageantKey));
1200                 pk->blocked_requests.next = pk->blocked_requests.prev =
1201                     &pk->blocked_requests;
1202                 pk->sort.ssh_version = 2;
1203                 pk->public_blob = public_blob;
1204                 public_blob = NULL;
1205                 pk->sort.public_blob = ptrlen_from_strbuf(pk->public_blob);
1206                 pk->comment = dupstr(comment);
1207                 pk->encrypted_key_file = strbuf_new_nm();
1208                 put_datapl(pk->encrypted_key_file, keyfile);
1209 
1210                 PageantKey *added = add234(keytree, pk);
1211                 assert(added == pk); (void)added;
1212 
1213                 keylist_update();
1214                 put_byte(sb, SSH_AGENT_SUCCESS);
1215                 pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS (made"
1216                                    " new encrypted-only key record)");
1217             }
1218 
1219               add_ppk_cleanup:
1220             if (public_blob)
1221                 strbuf_free(public_blob);
1222             sfree(comment);
1223             break;
1224           }
1225 
1226           case EXT_REENCRYPT: {
1227             /*
1228              * Re-encrypt a single key, in the sense of deleting
1229              * its unencrypted copy, returning it to the state of
1230              * only having the encrypted PPK form stored, so that
1231              * the next attempt to use it will have to re-prompt
1232              * for the passphrase.
1233              */
1234             ptrlen blob = get_string(msg);
1235 
1236             if (get_err(msg)) {
1237                 fail("unable to decode request");
1238                 goto responded;
1239             }
1240 
1241             if (!pc->suppress_logging) {
1242                 char *fingerprint = ssh2_fingerprint_blob(
1243                     blob, SSH_FPTYPE_DEFAULT);
1244                 pageant_client_log(pc, reqid, "key to re-encrypt: %s",
1245                                    fingerprint);
1246                 sfree(fingerprint);
1247             }
1248 
1249             PageantKey *pk = findkey2(blob);
1250             if (!pk) {
1251                 fail("key not found");
1252                 goto responded;
1253             }
1254 
1255             pageant_client_log(pc, reqid,
1256                                "found with comment: %s", pk->comment);
1257 
1258             if (!reencrypt_key(pk)) {
1259                 fail("this key couldn't be re-encrypted");
1260                 goto responded;
1261             }
1262 
1263             keylist_update();
1264             put_byte(sb, SSH_AGENT_SUCCESS);
1265             pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS");
1266             break;
1267           }
1268 
1269           case EXT_REENCRYPT_ALL: {
1270             /*
1271              * Re-encrypt all keys that have an encrypted form
1272              * stored. Usually, returns success, but with a uint32
1273              * appended indicating how many keys remain
1274              * unencrypted. The exception is if there is at least
1275              * one key in the agent and _no_ key was successfully
1276              * re-encrypted; in that situation we've done nothing,
1277              * and the client didn't _want_ us to do nothing, so
1278              * we return failure.
1279              *
1280              * (Rationale: the 'failure' message ought to be
1281              * atomic, that is, you shouldn't return failure
1282              * having made a state change.)
1283              */
1284             unsigned nfailures = 0, nsuccesses = 0;
1285             PageantKey *pk;
1286 
1287             for (int i = 0; (pk = index234(keytree, i)) != NULL; i++) {
1288                 if (reencrypt_key(pk))
1289                     nsuccesses++;
1290                 else
1291                     nfailures++;
1292             }
1293 
1294             if (nsuccesses == 0 && nfailures > 0) {
1295                 fail("no key could be re-encrypted");
1296             } else {
1297                 keylist_update();
1298                 put_byte(sb, SSH_AGENT_SUCCESS);
1299                 put_uint32(sb, nfailures);
1300                 pageant_client_log(pc, reqid, "reply: SSH_AGENT_SUCCESS "
1301                                    "(%u keys re-encrypted, %u failures)",
1302                                    nsuccesses, nfailures);
1303             }
1304             break;
1305           }
1306 
1307           case EXT_LIST_EXTENDED: {
1308             /*
1309              * Return a key list like SSH2_AGENTC_REQUEST_IDENTITIES,
1310              * except that each key is annotated with extra
1311              * information such as whether it's currently encrypted.
1312              *
1313              * The return message type is AGENT_SUCCESS with auxiliary
1314              * data, which is more like other extension messages. I
1315              * think it would be confusing to reuse IDENTITIES_ANSWER
1316              * for a reply message with an incompatible format.
1317              */
1318             put_byte(sb, SSH_AGENT_SUCCESS);
1319             pageant_make_keylist_extended(BinarySink_UPCAST(sb));
1320 
1321             pageant_client_log(pc, reqid,
1322                                "reply: SSH2_AGENT_SUCCESS + key list");
1323             if (!pc->suppress_logging) {
1324                 int i;
1325                 PageantKey *pk;
1326                 for (i = 0; NULL != (pk = pageant_nth_key(2, i)); i++) {
1327                     char *fingerprint = ssh2_fingerprint_blob(
1328                         ptrlen_from_strbuf(pk->public_blob),
1329                         SSH_FPTYPE_DEFAULT);
1330                     pageant_client_log(pc, reqid, "returned key: %s %s",
1331                                        fingerprint, pk->comment);
1332                     sfree(fingerprint);
1333                 }
1334             }
1335             break;
1336           }
1337         }
1338         break;
1339       }
1340       default:
1341         pageant_client_log(pc, reqid, "request: unknown message type %d",
1342                            type);
1343         fail("unrecognised message");
1344         break;
1345     }
1346 
1347 #undef fail
1348 
1349   responded:;
1350 
1351     PageantImmOp *io = snew(PageantImmOp);
1352     io->pao.vt = &immop_vtable;
1353     io->pao.info = pc->info;
1354     io->pao.cr.prev = pc->info->head.prev;
1355     io->pao.cr.next = &pc->info->head;
1356     io->pao.reqid = reqid;
1357     io->response = sb;
1358     io->crLine = 0;
1359     return &io->pao;
1360 }
1361 
pageant_handle_msg(PageantClient * pc,PageantClientRequestId * reqid,ptrlen msgpl)1362 void pageant_handle_msg(PageantClient *pc, PageantClientRequestId *reqid,
1363                         ptrlen msgpl)
1364 {
1365     PageantAsyncOp *pao = pageant_make_op(pc, reqid, msgpl);
1366     queue_toplevel_callback(pageant_async_op_callback, pao);
1367 }
1368 
pageant_init(void)1369 void pageant_init(void)
1370 {
1371     pageant_local = true;
1372     keytree = newtree234(cmpkeys);
1373 }
1374 
pageant_nth_key(int ssh_version,int i)1375 static PageantKey *pageant_nth_key(int ssh_version, int i)
1376 {
1377     PageantKey *pk = index234(
1378         keytree, find_first_key_for_version(ssh_version) + i);
1379     if (pk && pk->sort.ssh_version == ssh_version)
1380         return pk;
1381     else
1382         return NULL;
1383 }
1384 
pageant_delete_nth_ssh1_key(int i)1385 bool pageant_delete_nth_ssh1_key(int i)
1386 {
1387     PageantKey *pk = delpos234(keytree, find_first_key_for_version(1) + i);
1388     if (!pk)
1389         return false;
1390     pk_free(pk);
1391     return true;
1392 }
1393 
pageant_delete_nth_ssh2_key(int i)1394 bool pageant_delete_nth_ssh2_key(int i)
1395 {
1396     PageantKey *pk = delpos234(keytree, find_first_key_for_version(2) + i);
1397     if (!pk)
1398         return false;
1399     pk_free(pk);
1400     return true;
1401 }
1402 
pageant_reencrypt_nth_ssh2_key(int i)1403 bool pageant_reencrypt_nth_ssh2_key(int i)
1404 {
1405     PageantKey *pk = index234(keytree, find_first_key_for_version(2) + i);
1406     if (!pk)
1407         return false;
1408     return reencrypt_key(pk);
1409 }
1410 
pageant_delete_all(void)1411 void pageant_delete_all(void)
1412 {
1413     remove_all_keys(1);
1414     remove_all_keys(2);
1415 }
1416 
pageant_reencrypt_all(void)1417 void pageant_reencrypt_all(void)
1418 {
1419     PageantKey *pk;
1420     for (int i = 0; (pk = index234(keytree, i)) != NULL; i++)
1421         reencrypt_key(pk);
1422 }
1423 
1424 /* ----------------------------------------------------------------------
1425  * The agent plug.
1426  */
1427 
1428 /*
1429  * An extra coroutine macro, specific to this code which is consuming
1430  * 'const char *data'.
1431  */
1432 #define crGetChar(c) do                                         \
1433     {                                                           \
1434         while (len == 0) {                                      \
1435             *crLine =__LINE__; return; case __LINE__:;          \
1436         }                                                       \
1437         len--;                                                  \
1438         (c) = (unsigned char)*data++;                           \
1439     } while (0)
1440 
1441 struct pageant_conn_queued_response {
1442     struct pageant_conn_queued_response *next, *prev;
1443     size_t req_index;      /* for indexing requests in log messages */
1444     strbuf *sb;
1445     PageantClientRequestId reqid;
1446 };
1447 
1448 struct pageant_conn_state {
1449     Socket *connsock;
1450     PageantListenerClient *plc;
1451     unsigned char lenbuf[4], pktbuf[AGENT_MAX_MSGLEN];
1452     unsigned len, got;
1453     bool real_packet;
1454     size_t conn_index;     /* for indexing connections in log messages */
1455     size_t req_index;      /* for indexing requests in log messages */
1456     int crLine;            /* for coroutine in pageant_conn_receive */
1457 
1458     struct pageant_conn_queued_response response_queue;
1459 
1460     PageantClient pc;
1461     Plug plug;
1462 };
1463 
pageant_conn_closing(Plug * plug,const char * error_msg,int error_code,bool calling_back)1464 static void pageant_conn_closing(Plug *plug, const char *error_msg,
1465                                  int error_code, bool calling_back)
1466 {
1467     struct pageant_conn_state *pc = container_of(
1468         plug, struct pageant_conn_state, plug);
1469     if (error_msg)
1470         pageant_listener_client_log(pc->plc, "c#%"SIZEu": error: %s",
1471                                     pc->conn_index, error_msg);
1472     else
1473         pageant_listener_client_log(pc->plc, "c#%"SIZEu": connection closed",
1474                                     pc->conn_index);
1475     sk_close(pc->connsock);
1476     pageant_unregister_client(&pc->pc);
1477     sfree(pc);
1478 }
1479 
pageant_conn_sent(Plug * plug,size_t bufsize)1480 static void pageant_conn_sent(Plug *plug, size_t bufsize)
1481 {
1482     /* struct pageant_conn_state *pc = container_of(
1483         plug, struct pageant_conn_state, plug); */
1484 
1485     /*
1486      * We do nothing here, because we expect that there won't be a
1487      * need to throttle and unthrottle the connection to an agent -
1488      * clients will typically not send many requests, and will wait
1489      * until they receive each reply before sending a new request.
1490      */
1491 }
1492 
pageant_conn_log(PageantClient * pc,PageantClientRequestId * reqid,const char * fmt,va_list ap)1493 static void pageant_conn_log(PageantClient *pc, PageantClientRequestId *reqid,
1494                              const char *fmt, va_list ap)
1495 {
1496     struct pageant_conn_state *pcs =
1497         container_of(pc, struct pageant_conn_state, pc);
1498     struct pageant_conn_queued_response *qr =
1499         container_of(reqid, struct pageant_conn_queued_response, reqid);
1500 
1501     char *formatted = dupvprintf(fmt, ap);
1502     pageant_listener_client_log(pcs->plc, "c#%"SIZEu",r#%"SIZEu": %s",
1503                                 pcs->conn_index, qr->req_index, formatted);
1504     sfree(formatted);
1505 }
1506 
pageant_conn_got_response(PageantClient * pc,PageantClientRequestId * reqid,ptrlen response)1507 static void pageant_conn_got_response(
1508     PageantClient *pc, PageantClientRequestId *reqid, ptrlen response)
1509 {
1510     struct pageant_conn_state *pcs =
1511         container_of(pc, struct pageant_conn_state, pc);
1512     struct pageant_conn_queued_response *qr =
1513         container_of(reqid, struct pageant_conn_queued_response, reqid);
1514 
1515     qr->sb = strbuf_new_nm();
1516     put_stringpl(qr->sb, response);
1517 
1518     while (pcs->response_queue.next != &pcs->response_queue &&
1519            pcs->response_queue.next->sb) {
1520         qr = pcs->response_queue.next;
1521         sk_write(pcs->connsock, qr->sb->u, qr->sb->len);
1522         qr->next->prev = qr->prev;
1523         qr->prev->next = qr->next;
1524         strbuf_free(qr->sb);
1525         sfree(qr);
1526     }
1527 }
1528 
pageant_conn_ask_passphrase(PageantClient * pc,PageantClientDialogId * dlgid,const char * comment)1529 static bool pageant_conn_ask_passphrase(
1530     PageantClient *pc, PageantClientDialogId *dlgid, const char *comment)
1531 {
1532     struct pageant_conn_state *pcs =
1533         container_of(pc, struct pageant_conn_state, pc);
1534     return pageant_listener_client_ask_passphrase(pcs->plc, dlgid, comment);
1535 }
1536 
1537 static const PageantClientVtable pageant_connection_clientvt = {
1538     .log = pageant_conn_log,
1539     .got_response = pageant_conn_got_response,
1540     .ask_passphrase = pageant_conn_ask_passphrase,
1541 };
1542 
pageant_conn_receive(Plug * plug,int urgent,const char * data,size_t len)1543 static void pageant_conn_receive(
1544     Plug *plug, int urgent, const char *data, size_t len)
1545 {
1546     struct pageant_conn_state *pc = container_of(
1547         plug, struct pageant_conn_state, plug);
1548     char c;
1549 
1550     crBegin(pc->crLine);
1551 
1552     while (len > 0) {
1553         pc->got = 0;
1554         while (pc->got < 4) {
1555             crGetChar(c);
1556             pc->lenbuf[pc->got++] = c;
1557         }
1558 
1559         pc->len = GET_32BIT_MSB_FIRST(pc->lenbuf);
1560         pc->got = 0;
1561         pc->real_packet = (pc->len < AGENT_MAX_MSGLEN-4);
1562 
1563         {
1564             struct pageant_conn_queued_response *qr =
1565                 snew(struct pageant_conn_queued_response);
1566             qr->prev = pc->response_queue.prev;
1567             qr->next = &pc->response_queue;
1568             qr->prev->next = qr->next->prev = qr;
1569             qr->sb = NULL;
1570             qr->req_index = pc->req_index++;
1571         }
1572 
1573         if (!pc->real_packet) {
1574             /*
1575              * Send failure immediately, before consuming the packet
1576              * data. That way we notify the client reasonably early
1577              * even if the data channel has just started spewing
1578              * nonsense.
1579              */
1580             pageant_client_log(&pc->pc, &pc->response_queue.prev->reqid,
1581                                "early reply: SSH_AGENT_FAILURE "
1582                                "(overlong message, length %u)", pc->len);
1583             static const unsigned char failure[] = { SSH_AGENT_FAILURE };
1584             pageant_conn_got_response(&pc->pc, &pc->response_queue.prev->reqid,
1585                                       make_ptrlen(failure, lenof(failure)));
1586         }
1587 
1588         while (pc->got < pc->len) {
1589             crGetChar(c);
1590             if (pc->real_packet)
1591                 pc->pktbuf[pc->got] = c;
1592             pc->got++;
1593         }
1594 
1595         if (pc->real_packet)
1596             pageant_handle_msg(&pc->pc, &pc->response_queue.prev->reqid,
1597                                make_ptrlen(pc->pktbuf, pc->len));
1598     }
1599 
1600     crFinishV;
1601 }
1602 
1603 struct pageant_listen_state {
1604     Socket *listensock;
1605     PageantListenerClient *plc;
1606     size_t conn_index;     /* for indexing connections in log messages */
1607 
1608     Plug plug;
1609 };
1610 
pageant_listen_closing(Plug * plug,const char * error_msg,int error_code,bool calling_back)1611 static void pageant_listen_closing(Plug *plug, const char *error_msg,
1612                                    int error_code, bool calling_back)
1613 {
1614     struct pageant_listen_state *pl = container_of(
1615         plug, struct pageant_listen_state, plug);
1616     if (error_msg)
1617         pageant_listener_client_log(pl->plc, "listening socket: error: %s",
1618                                     error_msg);
1619     sk_close(pl->listensock);
1620     pl->listensock = NULL;
1621 }
1622 
1623 static const PlugVtable pageant_connection_plugvt = {
1624     .closing = pageant_conn_closing,
1625     .receive = pageant_conn_receive,
1626     .sent = pageant_conn_sent,
1627 };
1628 
pageant_listen_accepting(Plug * plug,accept_fn_t constructor,accept_ctx_t ctx)1629 static int pageant_listen_accepting(Plug *plug,
1630                                     accept_fn_t constructor, accept_ctx_t ctx)
1631 {
1632     struct pageant_listen_state *pl = container_of(
1633         plug, struct pageant_listen_state, plug);
1634     struct pageant_conn_state *pc;
1635     const char *err;
1636     SocketPeerInfo *peerinfo;
1637 
1638     pc = snew(struct pageant_conn_state);
1639     pc->plug.vt = &pageant_connection_plugvt;
1640     pc->pc.vt = &pageant_connection_clientvt;
1641     pc->plc = pl->plc;
1642     pc->response_queue.next = pc->response_queue.prev = &pc->response_queue;
1643     pc->conn_index = pl->conn_index++;
1644     pc->req_index = 0;
1645     pc->crLine = 0;
1646 
1647     pc->connsock = constructor(ctx, &pc->plug);
1648     if ((err = sk_socket_error(pc->connsock)) != NULL) {
1649         sk_close(pc->connsock);
1650         sfree(pc);
1651         return 1;
1652     }
1653 
1654     sk_set_frozen(pc->connsock, false);
1655 
1656     peerinfo = sk_peer_info(pc->connsock);
1657     if (peerinfo && peerinfo->log_text) {
1658         pageant_listener_client_log(pl->plc,
1659                                     "c#%"SIZEu": new connection from %s",
1660                                     pc->conn_index, peerinfo->log_text);
1661     } else {
1662         pageant_listener_client_log(pl->plc, "c#%"SIZEu": new connection",
1663                                     pc->conn_index);
1664     }
1665     sk_free_peer_info(peerinfo);
1666 
1667     pageant_register_client(&pc->pc);
1668 
1669     return 0;
1670 }
1671 
1672 static const PlugVtable pageant_listener_plugvt = {
1673     .closing = pageant_listen_closing,
1674     .accepting = pageant_listen_accepting,
1675 };
1676 
pageant_listener_new(Plug ** plug,PageantListenerClient * plc)1677 struct pageant_listen_state *pageant_listener_new(
1678     Plug **plug, PageantListenerClient *plc)
1679 {
1680     struct pageant_listen_state *pl = snew(struct pageant_listen_state);
1681     pl->plug.vt = &pageant_listener_plugvt;
1682     pl->plc = plc;
1683     pl->listensock = NULL;
1684     pl->conn_index = 0;
1685     *plug = &pl->plug;
1686     return pl;
1687 }
1688 
pageant_listener_got_socket(struct pageant_listen_state * pl,Socket * sock)1689 void pageant_listener_got_socket(struct pageant_listen_state *pl, Socket *sock)
1690 {
1691     pl->listensock = sock;
1692 }
1693 
pageant_listener_free(struct pageant_listen_state * pl)1694 void pageant_listener_free(struct pageant_listen_state *pl)
1695 {
1696     if (pl->listensock)
1697         sk_close(pl->listensock);
1698     sfree(pl);
1699 }
1700 
1701 /* ----------------------------------------------------------------------
1702  * Code to perform agent operations either as a client, or within the
1703  * same process as the running agent.
1704  */
1705 
1706 static tree234 *passphrases = NULL;
1707 
1708 typedef struct PageantInternalClient {
1709     strbuf *response;
1710     bool got_response;
1711     PageantClient pc;
1712 } PageantInternalClient;
1713 
internal_client_got_response(PageantClient * pc,PageantClientRequestId * reqid,ptrlen response)1714 static void internal_client_got_response(
1715     PageantClient *pc, PageantClientRequestId *reqid, ptrlen response)
1716 {
1717     PageantInternalClient *pic = container_of(pc, PageantInternalClient, pc);
1718     strbuf_clear(pic->response);
1719     put_datapl(pic->response, response);
1720     pic->got_response = true;
1721 }
1722 
internal_client_ask_passphrase(PageantClient * pc,PageantClientDialogId * dlgid,const char * comment)1723 static bool internal_client_ask_passphrase(
1724     PageantClient *pc, PageantClientDialogId *dlgid, const char *comment)
1725 {
1726     /* No delaying operations are permitted in this mode */
1727     return false;
1728 }
1729 
1730 static const PageantClientVtable internal_clientvt = {
1731     .log = NULL,
1732     .got_response = internal_client_got_response,
1733     .ask_passphrase = internal_client_ask_passphrase,
1734 };
1735 
1736 typedef struct PageantClientOp {
1737     strbuf *buf;
1738     bool request_made;
1739     BinarySink_DELEGATE_IMPLEMENTATION;
1740     BinarySource_IMPLEMENTATION;
1741 } PageantClientOp;
1742 
pageant_client_op_new(void)1743 static PageantClientOp *pageant_client_op_new(void)
1744 {
1745     PageantClientOp *pco = snew(PageantClientOp);
1746     pco->buf = strbuf_new_for_agent_query();
1747     pco->request_made = false;
1748     BinarySink_DELEGATE_INIT(pco, pco->buf);
1749     BinarySource_INIT(pco, "", 0);
1750     return pco;
1751 }
1752 
pageant_client_op_free(PageantClientOp * pco)1753 static void pageant_client_op_free(PageantClientOp *pco)
1754 {
1755     if (pco->buf)
1756         strbuf_free(pco->buf);
1757     sfree(pco);
1758 }
1759 
pageant_client_op_query(PageantClientOp * pco)1760 static unsigned pageant_client_op_query(PageantClientOp *pco)
1761 {
1762     /* Since we use the same strbuf for the request and the response,
1763      * check by assertion that we aren't embarrassingly sending a
1764      * previous response back to the agent */
1765     assert(!pco->request_made);
1766     pco->request_made = true;
1767 
1768     if (!pageant_local) {
1769         void *response_raw;
1770         int resplen_raw;
1771         agent_query_synchronous(pco->buf, &response_raw, &resplen_raw);
1772         strbuf_clear(pco->buf);
1773         put_data(pco->buf, response_raw, resplen_raw);
1774         sfree(response_raw);
1775 
1776         /* The data coming back from agent_query_synchronous will have
1777          * its length field prepended. So we start by parsing it as an
1778          * SSH-formatted string, and then reinitialise our
1779          * BinarySource with the interior of that string. */
1780         BinarySource_INIT_PL(pco, ptrlen_from_strbuf(pco->buf));
1781         BinarySource_INIT_PL(pco, get_string(pco));
1782     } else {
1783         PageantInternalClient pic;
1784         PageantClientRequestId reqid;
1785 
1786         pic.pc.vt = &internal_clientvt;
1787         pic.pc.suppress_logging = true;
1788         pic.response = pco->buf;
1789         pic.got_response = false;
1790         pageant_register_client(&pic.pc);
1791 
1792         assert(pco->buf->len > 4);
1793         PageantAsyncOp *pao = pageant_make_op(
1794             &pic.pc, &reqid, make_ptrlen(pco->buf->s + 4, pco->buf->len - 4));
1795         while (!pic.got_response)
1796             pageant_async_op_coroutine(pao);
1797 
1798         pageant_unregister_client(&pic.pc);
1799 
1800         BinarySource_INIT_PL(pco, ptrlen_from_strbuf(pco->buf));
1801     }
1802 
1803     /* Strip off and directly return the type byte, which every client
1804      * will need, to save a boilerplate get_byte at each call site */
1805     unsigned reply_type = get_byte(pco);
1806     if (get_err(pco))
1807         reply_type = 256;              /* out-of-range code */
1808     return reply_type;
1809 }
1810 
1811 /*
1812  * After processing a list of filenames, we want to forget the
1813  * passphrases.
1814  */
pageant_forget_passphrases(void)1815 void pageant_forget_passphrases(void)
1816 {
1817     if (!passphrases)                  /* in case we never set it up at all */
1818         return;
1819 
1820     while (count234(passphrases) > 0) {
1821         char *pp = index234(passphrases, 0);
1822         smemclr(pp, strlen(pp));
1823         delpos234(passphrases, 0);
1824         sfree(pp);
1825     }
1826 }
1827 
1828 typedef struct KeyListEntry {
1829     ptrlen blob, comment;
1830     uint32_t flags;
1831 } KeyListEntry;
1832 typedef struct KeyList {
1833     strbuf *raw_data;
1834     KeyListEntry *keys;
1835     size_t nkeys;
1836     bool broken;
1837 } KeyList;
1838 
keylist_free(KeyList * kl)1839 static void keylist_free(KeyList *kl)
1840 {
1841     sfree(kl->keys);
1842     strbuf_free(kl->raw_data);
1843     sfree(kl);
1844 }
1845 
pageant_request_keylist_1(void)1846 static PageantClientOp *pageant_request_keylist_1(void)
1847 {
1848     PageantClientOp *pco = pageant_client_op_new();
1849     put_byte(pco, SSH1_AGENTC_REQUEST_RSA_IDENTITIES);
1850     if (pageant_client_op_query(pco) == SSH1_AGENT_RSA_IDENTITIES_ANSWER)
1851         return pco;
1852     pageant_client_op_free(pco);
1853     return NULL;
1854 }
1855 
pageant_request_keylist_2(void)1856 static PageantClientOp *pageant_request_keylist_2(void)
1857 {
1858     PageantClientOp *pco = pageant_client_op_new();
1859     put_byte(pco, SSH2_AGENTC_REQUEST_IDENTITIES);
1860     if (pageant_client_op_query(pco) == SSH2_AGENT_IDENTITIES_ANSWER)
1861         return pco;
1862     pageant_client_op_free(pco);
1863     return NULL;
1864 }
1865 
pageant_request_keylist_extended(void)1866 static PageantClientOp *pageant_request_keylist_extended(void)
1867 {
1868     PageantClientOp *pco = pageant_client_op_new();
1869     put_byte(pco, SSH2_AGENTC_EXTENSION);
1870     put_stringpl(pco, extension_names[EXT_LIST_EXTENDED]);
1871     if (pageant_client_op_query(pco) == SSH_AGENT_SUCCESS)
1872         return pco;
1873     pageant_client_op_free(pco);
1874     return NULL;
1875 }
1876 
pageant_get_keylist(unsigned ssh_version)1877 static KeyList *pageant_get_keylist(unsigned ssh_version)
1878 {
1879     PageantClientOp *pco;
1880     bool list_is_extended = false;
1881 
1882     if (ssh_version == 1) {
1883         pco = pageant_request_keylist_1();
1884     } else {
1885         if ((pco = pageant_request_keylist_extended()) != NULL)
1886             list_is_extended = true;
1887         else
1888             pco = pageant_request_keylist_2();
1889     }
1890 
1891     if (!pco)
1892         return NULL;
1893 
1894     KeyList *kl = snew(KeyList);
1895     kl->nkeys = get_uint32(pco);
1896     kl->keys = snewn(kl->nkeys, struct KeyListEntry);
1897     kl->broken = false;
1898 
1899     for (size_t i = 0; i < kl->nkeys && !get_err(pco); i++) {
1900         if (ssh_version == 1) {
1901             int bloblen = rsa_ssh1_public_blob_len(
1902                 make_ptrlen(get_ptr(pco), get_avail(pco)));
1903             if (bloblen < 0) {
1904                 kl->broken = true;
1905                 bloblen = 0;
1906             }
1907             kl->keys[i].blob = get_data(pco, bloblen);
1908         } else {
1909             kl->keys[i].blob = get_string(pco);
1910         }
1911         kl->keys[i].comment = get_string(pco);
1912 
1913         if (list_is_extended) {
1914             ptrlen key_ext_info = get_string(pco);
1915             BinarySource src[1];
1916             BinarySource_BARE_INIT_PL(src, key_ext_info);
1917 
1918             kl->keys[i].flags = get_uint32(src);
1919         } else {
1920             kl->keys[i].flags = 0;
1921         }
1922     }
1923 
1924     if (get_err(pco))
1925         kl->broken = true;
1926     kl->raw_data = pco->buf;
1927     pco->buf = NULL;
1928     pageant_client_op_free(pco);
1929     return kl;
1930 }
1931 
pageant_add_keyfile(Filename * filename,const char * passphrase,char ** retstr,bool add_encrypted)1932 int pageant_add_keyfile(Filename *filename, const char *passphrase,
1933                         char **retstr, bool add_encrypted)
1934 {
1935     RSAKey *rkey = NULL;
1936     ssh2_userkey *skey = NULL;
1937     bool needs_pass;
1938     int ret;
1939     int attempts;
1940     char *comment;
1941     const char *this_passphrase;
1942     const char *error = NULL;
1943     int type;
1944 
1945     if (!passphrases) {
1946         passphrases = newtree234(NULL);
1947     }
1948 
1949     *retstr = NULL;
1950 
1951     type = key_type(filename);
1952     if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
1953         *retstr = dupprintf("Couldn't load this key (%s)",
1954                             key_type_to_str(type));
1955         return PAGEANT_ACTION_FAILURE;
1956     }
1957 
1958     if (add_encrypted && type == SSH_KEYTYPE_SSH1) {
1959         *retstr = dupprintf("Can't add SSH-1 keys in encrypted form");
1960         return PAGEANT_ACTION_FAILURE;
1961     }
1962 
1963     /*
1964      * See if the key is already loaded (in the primary Pageant,
1965      * which may or may not be us).
1966      */
1967     {
1968         strbuf *blob = strbuf_new();
1969         KeyList *kl;
1970 
1971         if (type == SSH_KEYTYPE_SSH1) {
1972             if (!rsa1_loadpub_f(filename, BinarySink_UPCAST(blob),
1973                                 NULL, &error)) {
1974                 *retstr = dupprintf("Couldn't load private key (%s)", error);
1975                 strbuf_free(blob);
1976                 return PAGEANT_ACTION_FAILURE;
1977             }
1978             kl = pageant_get_keylist(1);
1979         } else {
1980             if (!ppk_loadpub_f(filename, NULL, BinarySink_UPCAST(blob),
1981                                NULL, &error)) {
1982                 *retstr = dupprintf("Couldn't load private key (%s)", error);
1983                 strbuf_free(blob);
1984                 return PAGEANT_ACTION_FAILURE;
1985             }
1986             kl = pageant_get_keylist(2);
1987         }
1988 
1989         if (kl) {
1990             if (kl->broken) {
1991                 *retstr = dupstr("Received broken key list from agent");
1992                 keylist_free(kl);
1993                 strbuf_free(blob);
1994                 return PAGEANT_ACTION_FAILURE;
1995             }
1996 
1997             for (size_t i = 0; i < kl->nkeys; i++) {
1998                 /*
1999                  * If the key already exists in the agent, we're done,
2000                  * except in the following special cases:
2001                  *
2002                  * It's encrypted in the agent, and we're being asked
2003                  * to add it unencrypted, in which case we still want
2004                  * to upload the unencrypted version to cause the key
2005                  * to become decrypted.
2006                  * (Rationale: if you know in advance you're going to
2007                  * want it, and don't want to be interrupted at an
2008                  * unpredictable moment to be asked for the
2009                  * passphrase.)
2010                  *
2011                  * The agent only has cleartext, and we're being asked
2012                  * to add it encrypted, in which case we'll add the
2013                  * encrypted form.
2014                  * (Rationale: if you might want to re-encrypt the key
2015                  * at some future point, but it happened to have been
2016                  * initially added in cleartext, perhaps by something
2017                  * other than Pageant.)
2018                  */
2019                 if (ptrlen_eq_ptrlen(ptrlen_from_strbuf(blob),
2020                                      kl->keys[i].blob)) {
2021                     bool have_unencrypted =
2022                         !(kl->keys[i].flags &
2023                           LIST_EXTENDED_FLAG_HAS_NO_CLEARTEXT_KEY);
2024                     bool have_encrypted =
2025                         (kl->keys[i].flags &
2026                          LIST_EXTENDED_FLAG_HAS_ENCRYPTED_KEY_FILE);
2027                     if ((have_unencrypted && !add_encrypted)
2028                         || (have_encrypted && add_encrypted)) {
2029                         /* Key is already present in the desired form;
2030                          * we can now leave. */
2031                         keylist_free(kl);
2032                         strbuf_free(blob);
2033                         return PAGEANT_ACTION_OK;
2034                     }
2035                 }
2036             }
2037 
2038             keylist_free(kl);
2039         }
2040 
2041         strbuf_free(blob);
2042     }
2043 
2044     if (add_encrypted) {
2045         const char *load_error;
2046         LoadedFile *lf = lf_load_keyfile(filename, &load_error);
2047         if (!lf) {
2048             *retstr = dupstr(load_error);
2049             return PAGEANT_ACTION_FAILURE;
2050         }
2051 
2052         PageantClientOp *pco = pageant_client_op_new();
2053         put_byte(pco, SSH2_AGENTC_EXTENSION);
2054         put_stringpl(pco, extension_names[EXT_ADD_PPK]);
2055         put_string(pco, lf->data, lf->len);
2056 
2057         lf_free(lf);
2058 
2059         unsigned reply = pageant_client_op_query(pco);
2060         pageant_client_op_free(pco);
2061 
2062         if (reply != SSH_AGENT_SUCCESS) {
2063             if (reply == SSH_AGENT_FAILURE) {
2064                 /* The agent didn't understand the protocol extension
2065                  * at all. */
2066                 *retstr = dupstr("Agent doesn't support adding "
2067                                  "encrypted keys");
2068             } else {
2069                 *retstr = dupstr("The already running agent "
2070                                  "refused to add the key.");
2071             }
2072             return PAGEANT_ACTION_FAILURE;
2073         }
2074 
2075         return PAGEANT_ACTION_OK;
2076     }
2077 
2078     error = NULL;
2079     if (type == SSH_KEYTYPE_SSH1)
2080         needs_pass = rsa1_encrypted_f(filename, &comment);
2081     else
2082         needs_pass = ppk_encrypted_f(filename, &comment);
2083     attempts = 0;
2084     if (type == SSH_KEYTYPE_SSH1)
2085         rkey = snew(RSAKey);
2086 
2087     /*
2088      * Loop round repeatedly trying to load the key, until we either
2089      * succeed, fail for some serious reason, or run out of
2090      * passphrases to try.
2091      */
2092     while (1) {
2093         if (needs_pass) {
2094 
2095             /*
2096              * If we've been given a passphrase on input, try using
2097              * it. Otherwise, try one from our tree234 of previously
2098              * useful passphrases.
2099              */
2100             if (passphrase) {
2101                 this_passphrase = (attempts == 0 ? passphrase : NULL);
2102             } else {
2103                 this_passphrase = (const char *)index234(passphrases, attempts);
2104             }
2105 
2106             if (!this_passphrase) {
2107                 /*
2108                  * Run out of passphrases to try.
2109                  */
2110                 *retstr = comment;
2111                 sfree(rkey);
2112                 return PAGEANT_ACTION_NEED_PP;
2113             }
2114         } else
2115             this_passphrase = "";
2116 
2117         if (type == SSH_KEYTYPE_SSH1)
2118             ret = rsa1_load_f(filename, rkey, this_passphrase, &error);
2119         else {
2120             skey = ppk_load_f(filename, this_passphrase, &error);
2121             if (skey == SSH2_WRONG_PASSPHRASE)
2122                 ret = -1;
2123             else if (!skey)
2124                 ret = 0;
2125             else
2126                 ret = 1;
2127         }
2128 
2129         if (ret == 0) {
2130             /*
2131              * Failed to load the key file, for some reason other than
2132              * a bad passphrase.
2133              */
2134             *retstr = dupstr(error);
2135             sfree(rkey);
2136             if (comment)
2137                 sfree(comment);
2138             return PAGEANT_ACTION_FAILURE;
2139         } else if (ret == 1) {
2140             /*
2141              * Successfully loaded the key file.
2142              */
2143             break;
2144         } else {
2145             /*
2146              * Passphrase wasn't right; go round again.
2147              */
2148             attempts++;
2149         }
2150     }
2151 
2152     /*
2153      * If we get here, we've successfully loaded the key into
2154      * rkey/skey, but not yet added it to the agent.
2155      */
2156 
2157     /*
2158      * If the key was successfully decrypted, save the passphrase for
2159      * use with other keys we try to load.
2160      */
2161     {
2162         char *pp_copy = dupstr(this_passphrase);
2163         if (addpos234(passphrases, pp_copy, 0) != pp_copy) {
2164             /* No need; it was already there. */
2165             smemclr(pp_copy, strlen(pp_copy));
2166             sfree(pp_copy);
2167         }
2168     }
2169 
2170     if (comment)
2171         sfree(comment);
2172 
2173     if (type == SSH_KEYTYPE_SSH1) {
2174         PageantClientOp *pco = pageant_client_op_new();
2175         put_byte(pco, SSH1_AGENTC_ADD_RSA_IDENTITY);
2176         rsa_ssh1_private_blob_agent(BinarySink_UPCAST(pco), rkey);
2177         put_stringz(pco, rkey->comment);
2178         unsigned reply = pageant_client_op_query(pco);
2179         pageant_client_op_free(pco);
2180 
2181         freersakey(rkey);
2182         sfree(rkey);
2183 
2184         if (reply != SSH_AGENT_SUCCESS) {
2185             *retstr = dupstr("The already running agent "
2186                              "refused to add the key.");
2187             return PAGEANT_ACTION_FAILURE;
2188         }
2189     } else {
2190         PageantClientOp *pco = pageant_client_op_new();
2191         put_byte(pco, SSH2_AGENTC_ADD_IDENTITY);
2192         put_stringz(pco, ssh_key_ssh_id(skey->key));
2193         ssh_key_openssh_blob(skey->key, BinarySink_UPCAST(pco));
2194         put_stringz(pco, skey->comment);
2195         unsigned reply = pageant_client_op_query(pco);
2196         pageant_client_op_free(pco);
2197 
2198         sfree(skey->comment);
2199         ssh_key_free(skey->key);
2200         sfree(skey);
2201 
2202         if (reply != SSH_AGENT_SUCCESS) {
2203             *retstr = dupstr("The already running agent "
2204                              "refused to add the key.");
2205             return PAGEANT_ACTION_FAILURE;
2206         }
2207     }
2208     return PAGEANT_ACTION_OK;
2209 }
2210 
pageant_enum_keys(pageant_key_enum_fn_t callback,void * callback_ctx,char ** retstr)2211 int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx,
2212                       char **retstr)
2213 {
2214     KeyList *kl1 = NULL, *kl2 = NULL;
2215     struct pageant_pubkey cbkey;
2216     int toret = PAGEANT_ACTION_FAILURE;
2217 
2218     kl1 = pageant_get_keylist(1);
2219     if (kl1 && kl1->broken) {
2220         *retstr = dupstr("Received broken SSH-1 key list from agent");
2221         goto out;
2222     }
2223 
2224     kl2 = pageant_get_keylist(2);
2225     if (kl2 && kl2->broken) {
2226         *retstr = dupstr("Received broken SSH-2 key list from agent");
2227         goto out;
2228     }
2229 
2230     if (kl1) {
2231         for (size_t i = 0; i < kl1->nkeys; i++) {
2232             cbkey.blob = strbuf_new();
2233             put_datapl(cbkey.blob, kl1->keys[i].blob);
2234             cbkey.comment = mkstr(kl1->keys[i].comment);
2235             cbkey.ssh_version = 1;
2236 
2237             /* Decode public blob into a key in order to fingerprint it */
2238             RSAKey rkey;
2239             memset(&rkey, 0, sizeof(rkey));
2240             {
2241                 BinarySource src[1];
2242                 BinarySource_BARE_INIT_PL(src, kl1->keys[i].blob);
2243                 get_rsa_ssh1_pub(src, &rkey, RSA_SSH1_EXPONENT_FIRST);
2244                 if (get_err(src)) {
2245                     *retstr = dupstr(
2246                         "Received an invalid SSH-1 key from agent");
2247                     goto out;
2248                 }
2249             }
2250             char **fingerprints = rsa_ssh1_fake_all_fingerprints(&rkey);
2251             freersakey(&rkey);
2252 
2253             callback(callback_ctx, fingerprints, cbkey.comment,
2254                      kl1->keys[i].flags, &cbkey);
2255 
2256             strbuf_free(cbkey.blob);
2257             sfree(cbkey.comment);
2258             ssh2_free_all_fingerprints(fingerprints);
2259         }
2260     }
2261 
2262     if (kl2) {
2263         for (size_t i = 0; i < kl2->nkeys; i++) {
2264             cbkey.blob = strbuf_new();
2265             put_datapl(cbkey.blob, kl2->keys[i].blob);
2266             cbkey.comment = mkstr(kl2->keys[i].comment);
2267             cbkey.ssh_version = 2;
2268 
2269             char **fingerprints =
2270                 ssh2_all_fingerprints_for_blob(kl2->keys[i].blob);
2271 
2272             callback(callback_ctx, fingerprints, cbkey.comment,
2273                      kl2->keys[i].flags, &cbkey);
2274 
2275             ssh2_free_all_fingerprints(fingerprints);
2276             sfree(cbkey.comment);
2277             strbuf_free(cbkey.blob);
2278         }
2279     }
2280 
2281     *retstr = NULL;
2282     toret = PAGEANT_ACTION_OK;
2283   out:
2284     if (kl1)
2285         keylist_free(kl1);
2286     if (kl2)
2287         keylist_free(kl2);
2288     return toret;
2289 }
2290 
pageant_delete_key(struct pageant_pubkey * key,char ** retstr)2291 int pageant_delete_key(struct pageant_pubkey *key, char **retstr)
2292 {
2293     PageantClientOp *pco = pageant_client_op_new();
2294 
2295     if (key->ssh_version == 1) {
2296         put_byte(pco, SSH1_AGENTC_REMOVE_RSA_IDENTITY);
2297         put_data(pco, key->blob->s, key->blob->len);
2298     } else {
2299         put_byte(pco, SSH2_AGENTC_REMOVE_IDENTITY);
2300         put_string(pco, key->blob->s, key->blob->len);
2301     }
2302 
2303     unsigned reply = pageant_client_op_query(pco);
2304     pageant_client_op_free(pco);
2305 
2306     if (reply != SSH_AGENT_SUCCESS) {
2307         *retstr = dupstr("Agent failed to delete key");
2308         return PAGEANT_ACTION_FAILURE;
2309     } else {
2310         *retstr = NULL;
2311         return PAGEANT_ACTION_OK;
2312     }
2313 }
2314 
pageant_delete_all_keys(char ** retstr)2315 int pageant_delete_all_keys(char **retstr)
2316 {
2317     PageantClientOp *pco;
2318     unsigned reply;
2319 
2320     pco = pageant_client_op_new();
2321     put_byte(pco, SSH2_AGENTC_REMOVE_ALL_IDENTITIES);
2322     reply = pageant_client_op_query(pco);
2323     pageant_client_op_free(pco);
2324     if (reply != SSH_AGENT_SUCCESS) {
2325         *retstr = dupstr("Agent failed to delete SSH-2 keys");
2326         return PAGEANT_ACTION_FAILURE;
2327     }
2328 
2329     pco = pageant_client_op_new();
2330     put_byte(pco, SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
2331     reply = pageant_client_op_query(pco);
2332     pageant_client_op_free(pco);
2333     if (reply != SSH_AGENT_SUCCESS) {
2334         *retstr = dupstr("Agent failed to delete SSH-1 keys");
2335         return PAGEANT_ACTION_FAILURE;
2336     }
2337 
2338     *retstr = NULL;
2339     return PAGEANT_ACTION_OK;
2340 }
2341 
pageant_reencrypt_key(struct pageant_pubkey * key,char ** retstr)2342 int pageant_reencrypt_key(struct pageant_pubkey *key, char **retstr)
2343 {
2344     PageantClientOp *pco = pageant_client_op_new();
2345 
2346     if (key->ssh_version == 1) {
2347         *retstr = dupstr("Can't re-encrypt an SSH-1 key");
2348         pageant_client_op_free(pco);
2349         return PAGEANT_ACTION_FAILURE;
2350     } else {
2351         put_byte(pco, SSH2_AGENTC_EXTENSION);
2352         put_stringpl(pco, extension_names[EXT_REENCRYPT]);
2353         put_string(pco, key->blob->s, key->blob->len);
2354     }
2355 
2356     unsigned reply = pageant_client_op_query(pco);
2357     pageant_client_op_free(pco);
2358 
2359     if (reply != SSH_AGENT_SUCCESS) {
2360         if (reply == SSH_AGENT_FAILURE) {
2361             /* The agent didn't understand the protocol extension at all. */
2362             *retstr = dupstr("Agent doesn't support encrypted keys");
2363         } else {
2364             *retstr = dupstr("Agent failed to re-encrypt key");
2365         }
2366         return PAGEANT_ACTION_FAILURE;
2367     } else {
2368         *retstr = NULL;
2369         return PAGEANT_ACTION_OK;
2370     }
2371 }
2372 
pageant_reencrypt_all_keys(char ** retstr)2373 int pageant_reencrypt_all_keys(char **retstr)
2374 {
2375     PageantClientOp *pco = pageant_client_op_new();
2376     put_byte(pco, SSH2_AGENTC_EXTENSION);
2377     put_stringpl(pco, extension_names[EXT_REENCRYPT_ALL]);
2378     unsigned reply = pageant_client_op_query(pco);
2379     uint32_t failures = get_uint32(pco);
2380     pageant_client_op_free(pco);
2381     if (reply != SSH_AGENT_SUCCESS) {
2382         if (reply == SSH_AGENT_FAILURE) {
2383             /* The agent didn't understand the protocol extension at all. */
2384             *retstr = dupstr("Agent doesn't support encrypted keys");
2385         } else {
2386             *retstr = dupstr("Agent failed to re-encrypt any keys");
2387         }
2388         return PAGEANT_ACTION_FAILURE;
2389     } else if (failures == 1) {
2390         /* special case for English grammar */
2391         *retstr = dupstr("1 key remains unencrypted");
2392         return PAGEANT_ACTION_WARNING;
2393     } else if (failures > 0) {
2394         *retstr = dupprintf("%"PRIu32" keys remain unencrypted", failures);
2395         return PAGEANT_ACTION_WARNING;
2396     } else {
2397         *retstr = NULL;
2398         return PAGEANT_ACTION_OK;
2399     }
2400 }
2401 
pageant_sign(struct pageant_pubkey * key,ptrlen message,strbuf * out,uint32_t flags,char ** retstr)2402 int pageant_sign(struct pageant_pubkey *key, ptrlen message, strbuf *out,
2403                  uint32_t flags, char **retstr)
2404 {
2405     PageantClientOp *pco = pageant_client_op_new();
2406     put_byte(pco, SSH2_AGENTC_SIGN_REQUEST);
2407     put_string(pco, key->blob->s, key->blob->len);
2408     put_stringpl(pco, message);
2409     put_uint32(pco, flags);
2410     unsigned reply = pageant_client_op_query(pco);
2411     ptrlen signature = get_string(pco);
2412 
2413     if (reply == SSH2_AGENT_SIGN_RESPONSE && !get_err(pco)) {
2414         *retstr = NULL;
2415         put_datapl(out, signature);
2416         pageant_client_op_free(pco);
2417         return PAGEANT_ACTION_OK;
2418     } else {
2419         *retstr = dupstr("Agent failed to create signature");
2420         pageant_client_op_free(pco);
2421         return PAGEANT_ACTION_FAILURE;
2422     }
2423 }
2424 
pageant_pubkey_copy(struct pageant_pubkey * key)2425 struct pageant_pubkey *pageant_pubkey_copy(struct pageant_pubkey *key)
2426 {
2427     struct pageant_pubkey *ret = snew(struct pageant_pubkey);
2428     ret->blob = strbuf_new();
2429     put_data(ret->blob, key->blob->s, key->blob->len);
2430     ret->comment = key->comment ? dupstr(key->comment) : NULL;
2431     ret->ssh_version = key->ssh_version;
2432     return ret;
2433 }
2434 
pageant_pubkey_free(struct pageant_pubkey * key)2435 void pageant_pubkey_free(struct pageant_pubkey *key)
2436 {
2437     sfree(key->comment);
2438     strbuf_free(key->blob);
2439     sfree(key);
2440 }
2441