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