pageant.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812
  1. /*
  2. * pageant.c: cross-platform code to implement Pageant.
  3. */
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include "putty.h"
  8. #include "ssh.h"
  9. #include "pageant.h"
  10. /*
  11. * We need this to link with the RSA code, because rsaencrypt()
  12. * pads its data with random bytes. Since we only use rsadecrypt()
  13. * and the signing functions, which are deterministic, this should
  14. * never be called.
  15. *
  16. * If it _is_ called, there is a _serious_ problem, because it
  17. * won't generate true random numbers. So we must scream, panic,
  18. * and exit immediately if that should happen.
  19. */
  20. int random_byte(void)
  21. {
  22. modalfatalbox("Internal error: attempt to use random numbers in Pageant");
  23. exit(0);
  24. return 0; /* unreachable, but placate optimiser */
  25. }
  26. static int pageant_local = FALSE;
  27. /*
  28. * rsakeys stores SSH-1 RSA keys. ssh2keys stores all SSH-2 keys.
  29. */
  30. static tree234 *rsakeys, *ssh2keys;
  31. /*
  32. * Blob structure for passing to the asymmetric SSH-2 key compare
  33. * function, prototyped here.
  34. */
  35. struct blob {
  36. const unsigned char *blob;
  37. int len;
  38. };
  39. static int cmpkeys_ssh2_asymm(void *av, void *bv);
  40. /*
  41. * Key comparison function for the 2-3-4 tree of RSA keys.
  42. */
  43. static int cmpkeys_rsa(void *av, void *bv)
  44. {
  45. struct RSAKey *a = (struct RSAKey *) av;
  46. struct RSAKey *b = (struct RSAKey *) bv;
  47. Bignum am, bm;
  48. int alen, blen;
  49. am = a->modulus;
  50. bm = b->modulus;
  51. /*
  52. * Compare by length of moduli.
  53. */
  54. alen = bignum_bitcount(am);
  55. blen = bignum_bitcount(bm);
  56. if (alen > blen)
  57. return +1;
  58. else if (alen < blen)
  59. return -1;
  60. /*
  61. * Now compare by moduli themselves.
  62. */
  63. alen = (alen + 7) / 8; /* byte count */
  64. while (alen-- > 0) {
  65. int abyte, bbyte;
  66. abyte = bignum_byte(am, alen);
  67. bbyte = bignum_byte(bm, alen);
  68. if (abyte > bbyte)
  69. return +1;
  70. else if (abyte < bbyte)
  71. return -1;
  72. }
  73. /*
  74. * Give up.
  75. */
  76. return 0;
  77. }
  78. /*
  79. * Key comparison function for the 2-3-4 tree of SSH-2 keys.
  80. */
  81. static int cmpkeys_ssh2(void *av, void *bv)
  82. {
  83. struct ssh2_userkey *a = (struct ssh2_userkey *) av;
  84. struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
  85. int i;
  86. int alen, blen;
  87. unsigned char *ablob, *bblob;
  88. int c;
  89. /*
  90. * Compare purely by public blob.
  91. */
  92. ablob = a->alg->public_blob(a->data, &alen);
  93. bblob = b->alg->public_blob(b->data, &blen);
  94. c = 0;
  95. for (i = 0; i < alen && i < blen; i++) {
  96. if (ablob[i] < bblob[i]) {
  97. c = -1;
  98. break;
  99. } else if (ablob[i] > bblob[i]) {
  100. c = +1;
  101. break;
  102. }
  103. }
  104. if (c == 0 && i < alen)
  105. c = +1; /* a is longer */
  106. if (c == 0 && i < blen)
  107. c = -1; /* a is longer */
  108. sfree(ablob);
  109. sfree(bblob);
  110. return c;
  111. }
  112. /*
  113. * Key comparison function for looking up a blob in the 2-3-4 tree
  114. * of SSH-2 keys.
  115. */
  116. static int cmpkeys_ssh2_asymm(void *av, void *bv)
  117. {
  118. struct blob *a = (struct blob *) av;
  119. struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
  120. int i;
  121. int alen, blen;
  122. const unsigned char *ablob;
  123. unsigned char *bblob;
  124. int c;
  125. /*
  126. * Compare purely by public blob.
  127. */
  128. ablob = a->blob;
  129. alen = a->len;
  130. bblob = b->alg->public_blob(b->data, &blen);
  131. c = 0;
  132. for (i = 0; i < alen && i < blen; i++) {
  133. if (ablob[i] < bblob[i]) {
  134. c = -1;
  135. break;
  136. } else if (ablob[i] > bblob[i]) {
  137. c = +1;
  138. break;
  139. }
  140. }
  141. if (c == 0 && i < alen)
  142. c = +1; /* a is longer */
  143. if (c == 0 && i < blen)
  144. c = -1; /* a is longer */
  145. sfree(bblob);
  146. return c;
  147. }
  148. /*
  149. * Create an SSH-1 key list in a malloc'ed buffer; return its
  150. * length.
  151. */
  152. void *pageant_make_keylist1(int *length)
  153. {
  154. int i, nkeys, len;
  155. struct RSAKey *key;
  156. unsigned char *blob, *p, *ret;
  157. int bloblen;
  158. /*
  159. * Count up the number and length of keys we hold.
  160. */
  161. len = 4;
  162. nkeys = 0;
  163. for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
  164. nkeys++;
  165. blob = rsa_public_blob(key, &bloblen);
  166. len += bloblen;
  167. sfree(blob);
  168. len += 4 + strlen(key->comment);
  169. }
  170. /* Allocate the buffer. */
  171. p = ret = snewn(len, unsigned char);
  172. if (length) *length = len;
  173. PUT_32BIT(p, nkeys);
  174. p += 4;
  175. for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
  176. blob = rsa_public_blob(key, &bloblen);
  177. memcpy(p, blob, bloblen);
  178. p += bloblen;
  179. sfree(blob);
  180. PUT_32BIT(p, strlen(key->comment));
  181. memcpy(p + 4, key->comment, strlen(key->comment));
  182. p += 4 + strlen(key->comment);
  183. }
  184. assert(p - ret == len);
  185. return ret;
  186. }
  187. /*
  188. * Create an SSH-2 key list in a malloc'ed buffer; return its
  189. * length.
  190. */
  191. void *pageant_make_keylist2(int *length)
  192. {
  193. struct ssh2_userkey *key;
  194. int i, len, nkeys;
  195. unsigned char *blob, *p, *ret;
  196. int bloblen;
  197. /*
  198. * Count up the number and length of keys we hold.
  199. */
  200. len = 4;
  201. nkeys = 0;
  202. for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
  203. nkeys++;
  204. len += 4; /* length field */
  205. blob = key->alg->public_blob(key->data, &bloblen);
  206. len += bloblen;
  207. sfree(blob);
  208. len += 4 + strlen(key->comment);
  209. }
  210. /* Allocate the buffer. */
  211. p = ret = snewn(len, unsigned char);
  212. if (length) *length = len;
  213. /*
  214. * Packet header is the obvious five bytes, plus four
  215. * bytes for the key count.
  216. */
  217. PUT_32BIT(p, nkeys);
  218. p += 4;
  219. for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) {
  220. blob = key->alg->public_blob(key->data, &bloblen);
  221. PUT_32BIT(p, bloblen);
  222. p += 4;
  223. memcpy(p, blob, bloblen);
  224. p += bloblen;
  225. sfree(blob);
  226. PUT_32BIT(p, strlen(key->comment));
  227. memcpy(p + 4, key->comment, strlen(key->comment));
  228. p += 4 + strlen(key->comment);
  229. }
  230. assert(p - ret == len);
  231. return ret;
  232. }
  233. static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
  234. #ifdef __GNUC__
  235. __attribute__ ((format (printf, 3, 4)))
  236. #endif
  237. ;
  238. static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
  239. {
  240. /*
  241. * This is the wrapper that takes a variadic argument list and
  242. * turns it into the va_list that the log function really expects.
  243. * It's safe to call this with logfn==NULL, because we
  244. * double-check that below; but if you're going to do lots of work
  245. * before getting here (such as looping, or hashing things) then
  246. * you should probably check logfn manually before doing that.
  247. */
  248. if (logfn) {
  249. va_list ap;
  250. va_start(ap, fmt);
  251. logfn(logctx, fmt, ap);
  252. va_end(ap);
  253. }
  254. }
  255. void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
  256. void *logctx, pageant_logfn_t logfn)
  257. {
  258. const unsigned char *p = msg;
  259. const unsigned char *msgend;
  260. unsigned char *ret = snewn(AGENT_MAX_MSGLEN, unsigned char);
  261. int type;
  262. const char *fail_reason;
  263. msgend = p + msglen;
  264. /*
  265. * Get the message type.
  266. */
  267. if (msgend < p+1) {
  268. fail_reason = "message contained no type code";
  269. goto failure;
  270. }
  271. type = *p++;
  272. switch (type) {
  273. case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:
  274. /*
  275. * Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
  276. */
  277. {
  278. int len;
  279. void *keylist;
  280. plog(logctx, logfn, "request: SSH1_AGENTC_REQUEST_RSA_IDENTITIES");
  281. ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;
  282. keylist = pageant_make_keylist1(&len);
  283. if (len + 5 > AGENT_MAX_MSGLEN) {
  284. sfree(keylist);
  285. fail_reason = "output would exceed max msglen";
  286. goto failure;
  287. }
  288. PUT_32BIT(ret, len + 1);
  289. memcpy(ret + 5, keylist, len);
  290. plog(logctx, logfn, "reply: SSH1_AGENT_RSA_IDENTITIES_ANSWER");
  291. if (logfn) { /* skip this loop if not logging */
  292. int i;
  293. struct RSAKey *rkey;
  294. for (i = 0; NULL != (rkey = pageant_nth_ssh1_key(i)); i++) {
  295. char fingerprint[128];
  296. rsa_fingerprint(fingerprint, sizeof(fingerprint), rkey);
  297. plog(logctx, logfn, "returned key: %s", fingerprint);
  298. }
  299. }
  300. sfree(keylist);
  301. }
  302. break;
  303. case SSH2_AGENTC_REQUEST_IDENTITIES:
  304. /*
  305. * Reply with SSH2_AGENT_IDENTITIES_ANSWER.
  306. */
  307. {
  308. int len;
  309. void *keylist;
  310. plog(logctx, logfn, "request: SSH2_AGENTC_REQUEST_IDENTITIES");
  311. ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;
  312. keylist = pageant_make_keylist2(&len);
  313. if (len + 5 > AGENT_MAX_MSGLEN) {
  314. sfree(keylist);
  315. fail_reason = "output would exceed max msglen";
  316. goto failure;
  317. }
  318. PUT_32BIT(ret, len + 1);
  319. memcpy(ret + 5, keylist, len);
  320. plog(logctx, logfn, "reply: SSH2_AGENT_IDENTITIES_ANSWER");
  321. if (logfn) { /* skip this loop if not logging */
  322. int i;
  323. struct ssh2_userkey *skey;
  324. for (i = 0; NULL != (skey = pageant_nth_ssh2_key(i)); i++) {
  325. char *fingerprint = ssh2_fingerprint(skey->alg,
  326. skey->data);
  327. plog(logctx, logfn, "returned key: %s %s",
  328. fingerprint, skey->comment);
  329. sfree(fingerprint);
  330. }
  331. }
  332. sfree(keylist);
  333. }
  334. break;
  335. case SSH1_AGENTC_RSA_CHALLENGE:
  336. /*
  337. * Reply with either SSH1_AGENT_RSA_RESPONSE or
  338. * SSH_AGENT_FAILURE, depending on whether we have that key
  339. * or not.
  340. */
  341. {
  342. struct RSAKey reqkey, *key;
  343. Bignum challenge, response;
  344. unsigned char response_source[48], response_md5[16];
  345. struct MD5Context md5c;
  346. int i, len;
  347. plog(logctx, logfn, "request: SSH1_AGENTC_RSA_CHALLENGE");
  348. p += 4;
  349. i = ssh1_read_bignum(p, msgend - p, &reqkey.exponent);
  350. if (i < 0) {
  351. fail_reason = "request truncated before key exponent";
  352. goto failure;
  353. }
  354. p += i;
  355. i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
  356. if (i < 0) {
  357. freebn(reqkey.exponent);
  358. fail_reason = "request truncated before key modulus";
  359. goto failure;
  360. }
  361. p += i;
  362. i = ssh1_read_bignum(p, msgend - p, &challenge);
  363. if (i < 0) {
  364. freebn(reqkey.exponent);
  365. freebn(reqkey.modulus);
  366. fail_reason = "request truncated before challenge";
  367. goto failure;
  368. }
  369. p += i;
  370. if (msgend < p+16) {
  371. freebn(reqkey.exponent);
  372. freebn(reqkey.modulus);
  373. freebn(challenge);
  374. fail_reason = "request truncated before session id";
  375. goto failure;
  376. }
  377. memcpy(response_source + 32, p, 16);
  378. p += 16;
  379. if (msgend < p+4) {
  380. freebn(reqkey.exponent);
  381. freebn(reqkey.modulus);
  382. freebn(challenge);
  383. fail_reason = "request truncated before response type";
  384. goto failure;
  385. }
  386. if (GET_32BIT(p) != 1) {
  387. freebn(reqkey.exponent);
  388. freebn(reqkey.modulus);
  389. freebn(challenge);
  390. fail_reason = "response type other than 1 not supported";
  391. goto failure;
  392. }
  393. if (logfn) {
  394. char fingerprint[128];
  395. reqkey.comment = NULL;
  396. rsa_fingerprint(fingerprint, sizeof(fingerprint), &reqkey);
  397. plog(logctx, logfn, "requested key: %s", fingerprint);
  398. }
  399. if ((key = find234(rsakeys, &reqkey, NULL)) == NULL) {
  400. freebn(reqkey.exponent);
  401. freebn(reqkey.modulus);
  402. freebn(challenge);
  403. fail_reason = "key not found";
  404. goto failure;
  405. }
  406. response = rsadecrypt(challenge, key);
  407. for (i = 0; i < 32; i++)
  408. response_source[i] = bignum_byte(response, 31 - i);
  409. MD5Init(&md5c);
  410. MD5Update(&md5c, response_source, 48);
  411. MD5Final(response_md5, &md5c);
  412. smemclr(response_source, 48); /* burn the evidence */
  413. freebn(response); /* and that evidence */
  414. freebn(challenge); /* yes, and that evidence */
  415. freebn(reqkey.exponent); /* and free some memory ... */
  416. freebn(reqkey.modulus); /* ... while we're at it. */
  417. /*
  418. * Packet is the obvious five byte header, plus sixteen
  419. * bytes of MD5.
  420. */
  421. len = 5 + 16;
  422. PUT_32BIT(ret, len - 4);
  423. ret[4] = SSH1_AGENT_RSA_RESPONSE;
  424. memcpy(ret + 5, response_md5, 16);
  425. plog(logctx, logfn, "reply: SSH1_AGENT_RSA_RESPONSE");
  426. }
  427. break;
  428. case SSH2_AGENTC_SIGN_REQUEST:
  429. /*
  430. * Reply with either SSH2_AGENT_SIGN_RESPONSE or
  431. * SSH_AGENT_FAILURE, depending on whether we have that key
  432. * or not.
  433. */
  434. {
  435. struct ssh2_userkey *key;
  436. struct blob b;
  437. const unsigned char *data;
  438. unsigned char *signature;
  439. int datalen, siglen, len;
  440. plog(logctx, logfn, "request: SSH2_AGENTC_SIGN_REQUEST");
  441. if (msgend < p+4) {
  442. fail_reason = "request truncated before public key";
  443. goto failure;
  444. }
  445. b.len = toint(GET_32BIT(p));
  446. if (b.len < 0 || b.len > msgend - (p+4)) {
  447. fail_reason = "request truncated before public key";
  448. goto failure;
  449. }
  450. p += 4;
  451. b.blob = p;
  452. p += b.len;
  453. if (msgend < p+4) {
  454. fail_reason = "request truncated before string to sign";
  455. goto failure;
  456. }
  457. datalen = toint(GET_32BIT(p));
  458. p += 4;
  459. if (datalen < 0 || datalen > msgend - p) {
  460. fail_reason = "request truncated before string to sign";
  461. goto failure;
  462. }
  463. data = p;
  464. if (logfn) {
  465. char *fingerprint = ssh2_fingerprint_blob(b.blob, b.len);
  466. plog(logctx, logfn, "requested key: %s", fingerprint);
  467. sfree(fingerprint);
  468. }
  469. key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
  470. if (!key) {
  471. fail_reason = "key not found";
  472. goto failure;
  473. }
  474. signature = key->alg->sign(key->data, (const char *)data,
  475. datalen, &siglen);
  476. len = 5 + 4 + siglen;
  477. PUT_32BIT(ret, len - 4);
  478. ret[4] = SSH2_AGENT_SIGN_RESPONSE;
  479. PUT_32BIT(ret + 5, siglen);
  480. memcpy(ret + 5 + 4, signature, siglen);
  481. sfree(signature);
  482. plog(logctx, logfn, "reply: SSH2_AGENT_SIGN_RESPONSE");
  483. }
  484. break;
  485. case SSH1_AGENTC_ADD_RSA_IDENTITY:
  486. /*
  487. * Add to the list and return SSH_AGENT_SUCCESS, or
  488. * SSH_AGENT_FAILURE if the key was malformed.
  489. */
  490. {
  491. struct RSAKey *key;
  492. char *comment;
  493. int n, commentlen;
  494. plog(logctx, logfn, "request: SSH1_AGENTC_ADD_RSA_IDENTITY");
  495. key = snew(struct RSAKey);
  496. memset(key, 0, sizeof(struct RSAKey));
  497. n = makekey(p, msgend - p, key, NULL, 1);
  498. if (n < 0) {
  499. freersakey(key);
  500. sfree(key);
  501. fail_reason = "request truncated before public key";
  502. goto failure;
  503. }
  504. p += n;
  505. n = makeprivate(p, msgend - p, key);
  506. if (n < 0) {
  507. freersakey(key);
  508. sfree(key);
  509. fail_reason = "request truncated before private key";
  510. goto failure;
  511. }
  512. p += n;
  513. /* SSH-1 names p and q the other way round, i.e. we have
  514. * the inverse of p mod q and not of q mod p. We swap the
  515. * names, because our internal RSA wants iqmp. */
  516. n = ssh1_read_bignum(p, msgend - p, &key->iqmp); /* p^-1 mod q */
  517. if (n < 0) {
  518. freersakey(key);
  519. sfree(key);
  520. fail_reason = "request truncated before iqmp";
  521. goto failure;
  522. }
  523. p += n;
  524. n = ssh1_read_bignum(p, msgend - p, &key->q); /* p */
  525. if (n < 0) {
  526. freersakey(key);
  527. sfree(key);
  528. fail_reason = "request truncated before p";
  529. goto failure;
  530. }
  531. p += n;
  532. n = ssh1_read_bignum(p, msgend - p, &key->p); /* q */
  533. if (n < 0) {
  534. freersakey(key);
  535. sfree(key);
  536. fail_reason = "request truncated before q";
  537. goto failure;
  538. }
  539. p += n;
  540. if (msgend < p+4) {
  541. freersakey(key);
  542. sfree(key);
  543. fail_reason = "request truncated before key comment";
  544. goto failure;
  545. }
  546. commentlen = toint(GET_32BIT(p));
  547. if (commentlen < 0 || commentlen > msgend - p) {
  548. freersakey(key);
  549. sfree(key);
  550. fail_reason = "request truncated before key comment";
  551. goto failure;
  552. }
  553. comment = snewn(commentlen+1, char);
  554. if (comment) {
  555. memcpy(comment, p + 4, commentlen);
  556. comment[commentlen] = '\0';
  557. key->comment = comment;
  558. }
  559. if (logfn) {
  560. char fingerprint[128];
  561. rsa_fingerprint(fingerprint, sizeof(fingerprint), key);
  562. plog(logctx, logfn, "submitted key: %s", fingerprint);
  563. }
  564. if (add234(rsakeys, key) == key) {
  565. keylist_update();
  566. PUT_32BIT(ret, 1);
  567. ret[4] = SSH_AGENT_SUCCESS;
  568. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  569. } else {
  570. freersakey(key);
  571. sfree(key);
  572. fail_reason = "key already present";
  573. goto failure;
  574. }
  575. }
  576. break;
  577. case SSH2_AGENTC_ADD_IDENTITY:
  578. /*
  579. * Add to the list and return SSH_AGENT_SUCCESS, or
  580. * SSH_AGENT_FAILURE if the key was malformed.
  581. */
  582. {
  583. struct ssh2_userkey *key;
  584. char *comment;
  585. const char *alg;
  586. int alglen, commlen;
  587. int bloblen;
  588. plog(logctx, logfn, "request: SSH2_AGENTC_ADD_IDENTITY");
  589. if (msgend < p+4) {
  590. fail_reason = "request truncated before key algorithm";
  591. goto failure;
  592. }
  593. alglen = toint(GET_32BIT(p));
  594. p += 4;
  595. if (alglen < 0 || alglen > msgend - p) {
  596. fail_reason = "request truncated before key algorithm";
  597. goto failure;
  598. }
  599. alg = (const char *)p;
  600. p += alglen;
  601. key = snew(struct ssh2_userkey);
  602. key->alg = find_pubkey_alg_len(alglen, alg);
  603. if (!key->alg) {
  604. sfree(key);
  605. fail_reason = "algorithm unknown";
  606. goto failure;
  607. }
  608. bloblen = msgend - p;
  609. key->data = key->alg->openssh_createkey(key->alg, &p, &bloblen);
  610. if (!key->data) {
  611. sfree(key);
  612. fail_reason = "key setup failed";
  613. goto failure;
  614. }
  615. /*
  616. * p has been advanced by openssh_createkey, but
  617. * certainly not _beyond_ the end of the buffer.
  618. */
  619. assert(p <= msgend);
  620. if (msgend < p+4) {
  621. key->alg->freekey(key->data);
  622. sfree(key);
  623. fail_reason = "request truncated before key comment";
  624. goto failure;
  625. }
  626. commlen = toint(GET_32BIT(p));
  627. p += 4;
  628. if (commlen < 0 || commlen > msgend - p) {
  629. key->alg->freekey(key->data);
  630. sfree(key);
  631. fail_reason = "request truncated before key comment";
  632. goto failure;
  633. }
  634. comment = snewn(commlen + 1, char);
  635. if (comment) {
  636. memcpy(comment, p, commlen);
  637. comment[commlen] = '\0';
  638. }
  639. key->comment = comment;
  640. if (logfn) {
  641. char *fingerprint = ssh2_fingerprint(key->alg, key->data);
  642. plog(logctx, logfn, "submitted key: %s %s",
  643. fingerprint, key->comment);
  644. sfree(fingerprint);
  645. }
  646. if (add234(ssh2keys, key) == key) {
  647. keylist_update();
  648. PUT_32BIT(ret, 1);
  649. ret[4] = SSH_AGENT_SUCCESS;
  650. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  651. } else {
  652. key->alg->freekey(key->data);
  653. sfree(key->comment);
  654. sfree(key);
  655. fail_reason = "key already present";
  656. goto failure;
  657. }
  658. }
  659. break;
  660. case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
  661. /*
  662. * Remove from the list and return SSH_AGENT_SUCCESS, or
  663. * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
  664. * start with.
  665. */
  666. {
  667. struct RSAKey reqkey, *key;
  668. int n;
  669. plog(logctx, logfn, "request: SSH1_AGENTC_REMOVE_RSA_IDENTITY");
  670. n = makekey(p, msgend - p, &reqkey, NULL, 0);
  671. if (n < 0) {
  672. fail_reason = "request truncated before public key";
  673. goto failure;
  674. }
  675. if (logfn) {
  676. char fingerprint[128];
  677. reqkey.comment = NULL;
  678. rsa_fingerprint(fingerprint, sizeof(fingerprint), &reqkey);
  679. plog(logctx, logfn, "unwanted key: %s", fingerprint);
  680. }
  681. key = find234(rsakeys, &reqkey, NULL);
  682. freebn(reqkey.exponent);
  683. freebn(reqkey.modulus);
  684. PUT_32BIT(ret, 1);
  685. if (key) {
  686. plog(logctx, logfn, "found with comment: %s", key->comment);
  687. del234(rsakeys, key);
  688. keylist_update();
  689. freersakey(key);
  690. sfree(key);
  691. ret[4] = SSH_AGENT_SUCCESS;
  692. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  693. } else {
  694. fail_reason = "key not found";
  695. goto failure;
  696. }
  697. }
  698. break;
  699. case SSH2_AGENTC_REMOVE_IDENTITY:
  700. /*
  701. * Remove from the list and return SSH_AGENT_SUCCESS, or
  702. * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
  703. * start with.
  704. */
  705. {
  706. struct ssh2_userkey *key;
  707. struct blob b;
  708. plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY");
  709. if (msgend < p+4) {
  710. fail_reason = "request truncated before public key";
  711. goto failure;
  712. }
  713. b.len = toint(GET_32BIT(p));
  714. p += 4;
  715. if (b.len < 0 || b.len > msgend - p) {
  716. fail_reason = "request truncated before public key";
  717. goto failure;
  718. }
  719. b.blob = p;
  720. p += b.len;
  721. if (logfn) {
  722. char *fingerprint = ssh2_fingerprint_blob(b.blob, b.len);
  723. plog(logctx, logfn, "unwanted key: %s", fingerprint);
  724. sfree(fingerprint);
  725. }
  726. key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
  727. if (!key) {
  728. fail_reason = "key not found";
  729. goto failure;
  730. }
  731. plog(logctx, logfn, "found with comment: %s", key->comment);
  732. del234(ssh2keys, key);
  733. keylist_update();
  734. key->alg->freekey(key->data);
  735. sfree(key);
  736. PUT_32BIT(ret, 1);
  737. ret[4] = SSH_AGENT_SUCCESS;
  738. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  739. }
  740. break;
  741. case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
  742. /*
  743. * Remove all SSH-1 keys. Always returns success.
  744. */
  745. {
  746. struct RSAKey *rkey;
  747. plog(logctx, logfn, "request:"
  748. " SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES");
  749. while ((rkey = index234(rsakeys, 0)) != NULL) {
  750. del234(rsakeys, rkey);
  751. freersakey(rkey);
  752. sfree(rkey);
  753. }
  754. keylist_update();
  755. PUT_32BIT(ret, 1);
  756. ret[4] = SSH_AGENT_SUCCESS;
  757. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  758. }
  759. break;
  760. case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
  761. /*
  762. * Remove all SSH-2 keys. Always returns success.
  763. */
  764. {
  765. struct ssh2_userkey *skey;
  766. plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_ALL_IDENTITIES");
  767. while ((skey = index234(ssh2keys, 0)) != NULL) {
  768. del234(ssh2keys, skey);
  769. skey->alg->freekey(skey->data);
  770. sfree(skey);
  771. }
  772. keylist_update();
  773. PUT_32BIT(ret, 1);
  774. ret[4] = SSH_AGENT_SUCCESS;
  775. plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
  776. }
  777. break;
  778. default:
  779. plog(logctx, logfn, "request: unknown message type %d", type);
  780. fail_reason = "unrecognised message";
  781. /* fall through */
  782. failure:
  783. /*
  784. * Unrecognised message. Return SSH_AGENT_FAILURE.
  785. */
  786. PUT_32BIT(ret, 1);
  787. ret[4] = SSH_AGENT_FAILURE;
  788. plog(logctx, logfn, "reply: SSH_AGENT_FAILURE (%s)", fail_reason);
  789. break;
  790. }
  791. *outlen = 4 + GET_32BIT(ret);
  792. return ret;
  793. }
  794. void *pageant_failure_msg(int *outlen)
  795. {
  796. unsigned char *ret = snewn(5, unsigned char);
  797. PUT_32BIT(ret, 1);
  798. ret[4] = SSH_AGENT_FAILURE;
  799. *outlen = 5;
  800. return ret;
  801. }
  802. void pageant_init(void)
  803. {
  804. pageant_local = TRUE;
  805. rsakeys = newtree234(cmpkeys_rsa);
  806. ssh2keys = newtree234(cmpkeys_ssh2);
  807. }
  808. struct RSAKey *pageant_nth_ssh1_key(int i)
  809. {
  810. return index234(rsakeys, i);
  811. }
  812. struct ssh2_userkey *pageant_nth_ssh2_key(int i)
  813. {
  814. return index234(ssh2keys, i);
  815. }
  816. int pageant_count_ssh1_keys(void)
  817. {
  818. return count234(rsakeys);
  819. }
  820. int pageant_count_ssh2_keys(void)
  821. {
  822. return count234(ssh2keys);
  823. }
  824. int pageant_add_ssh1_key(struct RSAKey *rkey)
  825. {
  826. return add234(rsakeys, rkey) == rkey;
  827. }
  828. int pageant_add_ssh2_key(struct ssh2_userkey *skey)
  829. {
  830. return add234(ssh2keys, skey) == skey;
  831. }
  832. int pageant_delete_ssh1_key(struct RSAKey *rkey)
  833. {
  834. struct RSAKey *deleted = del234(rsakeys, rkey);
  835. if (!deleted)
  836. return FALSE;
  837. assert(deleted == rkey);
  838. return TRUE;
  839. }
  840. int pageant_delete_ssh2_key(struct ssh2_userkey *skey)
  841. {
  842. struct ssh2_userkey *deleted = del234(ssh2keys, skey);
  843. if (!deleted)
  844. return FALSE;
  845. assert(deleted == skey);
  846. return TRUE;
  847. }
  848. /* ----------------------------------------------------------------------
  849. * The agent plug.
  850. */
  851. /*
  852. * Coroutine macros similar to, but simplified from, those in ssh.c.
  853. */
  854. #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
  855. #define crFinish(z) } *crLine = 0; return (z); }
  856. #define crGetChar(c) do \
  857. { \
  858. while (len == 0) { \
  859. *crLine =__LINE__; return 1; case __LINE__:; \
  860. } \
  861. len--; \
  862. (c) = (unsigned char)*data++; \
  863. } while (0)
  864. struct pageant_conn_state {
  865. const struct plug_function_table *fn;
  866. /* the above variable absolutely *must* be the first in this structure */
  867. Socket connsock;
  868. void *logctx;
  869. pageant_logfn_t logfn;
  870. unsigned char lenbuf[4], pktbuf[AGENT_MAX_MSGLEN];
  871. unsigned len, got;
  872. int real_packet;
  873. int crLine; /* for coroutine in pageant_conn_receive */
  874. };
  875. static int pageant_conn_closing(Plug plug, const char *error_msg,
  876. int error_code, int calling_back)
  877. {
  878. struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
  879. if (error_msg)
  880. plog(pc->logctx, pc->logfn, "%p: error: %s", pc, error_msg);
  881. else
  882. plog(pc->logctx, pc->logfn, "%p: connection closed", pc);
  883. sk_close(pc->connsock);
  884. sfree(pc);
  885. return 1;
  886. }
  887. static void pageant_conn_sent(Plug plug, int bufsize)
  888. {
  889. /* struct pageant_conn_state *pc = (struct pageant_conn_state *)plug; */
  890. /*
  891. * We do nothing here, because we expect that there won't be a
  892. * need to throttle and unthrottle the connection to an agent -
  893. * clients will typically not send many requests, and will wait
  894. * until they receive each reply before sending a new request.
  895. */
  896. }
  897. static void pageant_conn_log(void *logctx, const char *fmt, va_list ap)
  898. {
  899. /* Wrapper on pc->logfn that prefixes the connection identifier */
  900. struct pageant_conn_state *pc = (struct pageant_conn_state *)logctx;
  901. char *formatted = dupvprintf(fmt, ap);
  902. plog(pc->logctx, pc->logfn, "%p: %s", pc, formatted);
  903. sfree(formatted);
  904. }
  905. static int pageant_conn_receive(Plug plug, int urgent, char *data, int len)
  906. {
  907. struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
  908. char c;
  909. crBegin(pc->crLine);
  910. while (len > 0) {
  911. pc->got = 0;
  912. while (pc->got < 4) {
  913. crGetChar(c);
  914. pc->lenbuf[pc->got++] = c;
  915. }
  916. pc->len = GET_32BIT(pc->lenbuf);
  917. pc->got = 0;
  918. pc->real_packet = (pc->len < AGENT_MAX_MSGLEN-4);
  919. while (pc->got < pc->len) {
  920. crGetChar(c);
  921. if (pc->real_packet)
  922. pc->pktbuf[pc->got] = c;
  923. pc->got++;
  924. }
  925. {
  926. void *reply;
  927. int replylen;
  928. if (pc->real_packet) {
  929. reply = pageant_handle_msg(pc->pktbuf, pc->len, &replylen, pc,
  930. pc->logfn?pageant_conn_log:NULL);
  931. } else {
  932. plog(pc->logctx, pc->logfn, "%p: overlong message (%u)",
  933. pc, pc->len);
  934. plog(pc->logctx, pc->logfn, "%p: reply: SSH_AGENT_FAILURE "
  935. "(message too long)", pc);
  936. reply = pageant_failure_msg(&replylen);
  937. }
  938. sk_write(pc->connsock, reply, replylen);
  939. smemclr(reply, replylen);
  940. }
  941. }
  942. crFinish(1);
  943. }
  944. struct pageant_listen_state {
  945. const struct plug_function_table *fn;
  946. /* the above variable absolutely *must* be the first in this structure */
  947. Socket listensock;
  948. void *logctx;
  949. pageant_logfn_t logfn;
  950. };
  951. static int pageant_listen_closing(Plug plug, const char *error_msg,
  952. int error_code, int calling_back)
  953. {
  954. struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
  955. if (error_msg)
  956. plog(pl->logctx, pl->logfn, "listening socket: error: %s", error_msg);
  957. sk_close(pl->listensock);
  958. pl->listensock = NULL;
  959. return 1;
  960. }
  961. static int pageant_listen_accepting(Plug plug,
  962. accept_fn_t constructor, accept_ctx_t ctx)
  963. {
  964. static const struct plug_function_table connection_fn_table = {
  965. NULL, /* no log function, because that's for outgoing connections */
  966. pageant_conn_closing,
  967. pageant_conn_receive,
  968. pageant_conn_sent,
  969. NULL /* no accepting function, because we've already done it */
  970. };
  971. struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
  972. struct pageant_conn_state *pc;
  973. const char *err;
  974. char *peerinfo;
  975. pc = snew(struct pageant_conn_state);
  976. pc->fn = &connection_fn_table;
  977. pc->logfn = pl->logfn;
  978. pc->logctx = pl->logctx;
  979. pc->crLine = 0;
  980. pc->connsock = constructor(ctx, (Plug) pc);
  981. if ((err = sk_socket_error(pc->connsock)) != NULL) {
  982. sk_close(pc->connsock);
  983. sfree(pc);
  984. return TRUE;
  985. }
  986. sk_set_frozen(pc->connsock, 0);
  987. peerinfo = sk_peer_info(pc->connsock);
  988. if (peerinfo) {
  989. plog(pl->logctx, pl->logfn, "%p: new connection from %s",
  990. pc, peerinfo);
  991. } else {
  992. plog(pl->logctx, pl->logfn, "%p: new connection", pc);
  993. }
  994. return 0;
  995. }
  996. struct pageant_listen_state *pageant_listener_new(void)
  997. {
  998. static const struct plug_function_table listener_fn_table = {
  999. NULL, /* no log function, because that's for outgoing connections */
  1000. pageant_listen_closing,
  1001. NULL, /* no receive function on a listening socket */
  1002. NULL, /* no sent function on a listening socket */
  1003. pageant_listen_accepting
  1004. };
  1005. struct pageant_listen_state *pl = snew(struct pageant_listen_state);
  1006. pl->fn = &listener_fn_table;
  1007. pl->logctx = NULL;
  1008. pl->logfn = NULL;
  1009. pl->listensock = NULL;
  1010. return pl;
  1011. }
  1012. void pageant_listener_got_socket(struct pageant_listen_state *pl, Socket sock)
  1013. {
  1014. pl->listensock = sock;
  1015. }
  1016. void pageant_listener_set_logfn(struct pageant_listen_state *pl,
  1017. void *logctx, pageant_logfn_t logfn)
  1018. {
  1019. pl->logctx = logctx;
  1020. pl->logfn = logfn;
  1021. }
  1022. void pageant_listener_free(struct pageant_listen_state *pl)
  1023. {
  1024. if (pl->listensock)
  1025. sk_close(pl->listensock);
  1026. sfree(pl);
  1027. }
  1028. /* ----------------------------------------------------------------------
  1029. * Code to perform agent operations either as a client, or within the
  1030. * same process as the running agent.
  1031. */
  1032. static tree234 *passphrases = NULL;
  1033. /*
  1034. * After processing a list of filenames, we want to forget the
  1035. * passphrases.
  1036. */
  1037. void pageant_forget_passphrases(void)
  1038. {
  1039. if (!passphrases) /* in case we never set it up at all */
  1040. return;
  1041. while (count234(passphrases) > 0) {
  1042. char *pp = index234(passphrases, 0);
  1043. smemclr(pp, strlen(pp));
  1044. delpos234(passphrases, 0);
  1045. free(pp);
  1046. }
  1047. }
  1048. void *pageant_get_keylist1(int *length)
  1049. {
  1050. void *ret;
  1051. if (!pageant_local) {
  1052. unsigned char request[5], *response;
  1053. void *vresponse;
  1054. int resplen, retval;
  1055. request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
  1056. PUT_32BIT(request, 1);
  1057. retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
  1058. assert(retval == 1);
  1059. response = vresponse;
  1060. if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
  1061. sfree(response);
  1062. return NULL;
  1063. }
  1064. ret = snewn(resplen-5, unsigned char);
  1065. memcpy(ret, response+5, resplen-5);
  1066. sfree(response);
  1067. if (length)
  1068. *length = resplen-5;
  1069. } else {
  1070. ret = pageant_make_keylist1(length);
  1071. }
  1072. return ret;
  1073. }
  1074. void *pageant_get_keylist2(int *length)
  1075. {
  1076. void *ret;
  1077. if (!pageant_local) {
  1078. unsigned char request[5], *response;
  1079. void *vresponse;
  1080. int resplen, retval;
  1081. request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
  1082. PUT_32BIT(request, 1);
  1083. retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
  1084. assert(retval == 1);
  1085. response = vresponse;
  1086. if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
  1087. sfree(response);
  1088. return NULL;
  1089. }
  1090. ret = snewn(resplen-5, unsigned char);
  1091. memcpy(ret, response+5, resplen-5);
  1092. sfree(response);
  1093. if (length)
  1094. *length = resplen-5;
  1095. } else {
  1096. ret = pageant_make_keylist2(length);
  1097. }
  1098. return ret;
  1099. }
  1100. int pageant_add_keyfile(Filename *filename, const char *passphrase,
  1101. char **retstr)
  1102. {
  1103. struct RSAKey *rkey = NULL;
  1104. struct ssh2_userkey *skey = NULL;
  1105. int needs_pass;
  1106. int ret;
  1107. int attempts;
  1108. char *comment;
  1109. const char *this_passphrase;
  1110. const char *error = NULL;
  1111. int type;
  1112. if (!passphrases) {
  1113. passphrases = newtree234(NULL);
  1114. }
  1115. *retstr = NULL;
  1116. type = key_type(filename);
  1117. if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
  1118. *retstr = dupprintf("Couldn't load this key (%s)",
  1119. key_type_to_str(type));
  1120. return PAGEANT_ACTION_FAILURE;
  1121. }
  1122. /*
  1123. * See if the key is already loaded (in the primary Pageant,
  1124. * which may or may not be us).
  1125. */
  1126. {
  1127. void *blob;
  1128. unsigned char *keylist, *p;
  1129. int i, nkeys, bloblen, keylistlen;
  1130. if (type == SSH_KEYTYPE_SSH1) {
  1131. if (!rsakey_pubblob(filename, &blob, &bloblen, NULL, &error)) {
  1132. *retstr = dupprintf("Couldn't load private key (%s)", error);
  1133. return PAGEANT_ACTION_FAILURE;
  1134. }
  1135. keylist = pageant_get_keylist1(&keylistlen);
  1136. } else {
  1137. unsigned char *blob2;
  1138. blob = ssh2_userkey_loadpub(filename, NULL, &bloblen,
  1139. NULL, &error);
  1140. if (!blob) {
  1141. *retstr = dupprintf("Couldn't load private key (%s)", error);
  1142. return PAGEANT_ACTION_FAILURE;
  1143. }
  1144. /* For our purposes we want the blob prefixed with its length */
  1145. blob2 = snewn(bloblen+4, unsigned char);
  1146. PUT_32BIT(blob2, bloblen);
  1147. memcpy(blob2 + 4, blob, bloblen);
  1148. sfree(blob);
  1149. blob = blob2;
  1150. keylist = pageant_get_keylist2(&keylistlen);
  1151. }
  1152. if (keylist) {
  1153. if (keylistlen < 4) {
  1154. *retstr = dupstr("Received broken key list from agent");
  1155. return PAGEANT_ACTION_FAILURE;
  1156. }
  1157. nkeys = toint(GET_32BIT(keylist));
  1158. if (nkeys < 0) {
  1159. *retstr = dupstr("Received broken key list from agent");
  1160. return PAGEANT_ACTION_FAILURE;
  1161. }
  1162. p = keylist + 4;
  1163. keylistlen -= 4;
  1164. for (i = 0; i < nkeys; i++) {
  1165. if (!memcmp(blob, p, bloblen)) {
  1166. /* Key is already present; we can now leave. */
  1167. sfree(keylist);
  1168. sfree(blob);
  1169. return PAGEANT_ACTION_OK;
  1170. }
  1171. /* Now skip over public blob */
  1172. if (type == SSH_KEYTYPE_SSH1) {
  1173. int n = rsa_public_blob_len(p, keylistlen);
  1174. if (n < 0) {
  1175. *retstr = dupstr("Received broken key list from agent");
  1176. return PAGEANT_ACTION_FAILURE;
  1177. }
  1178. p += n;
  1179. keylistlen -= n;
  1180. } else {
  1181. int n;
  1182. if (keylistlen < 4) {
  1183. *retstr = dupstr("Received broken key list from agent");
  1184. return PAGEANT_ACTION_FAILURE;
  1185. }
  1186. n = toint(4 + GET_32BIT(p));
  1187. if (n < 0 || keylistlen < n) {
  1188. *retstr = dupstr("Received broken key list from agent");
  1189. return PAGEANT_ACTION_FAILURE;
  1190. }
  1191. p += n;
  1192. keylistlen -= n;
  1193. }
  1194. /* Now skip over comment field */
  1195. {
  1196. int n;
  1197. if (keylistlen < 4) {
  1198. *retstr = dupstr("Received broken key list from agent");
  1199. return PAGEANT_ACTION_FAILURE;
  1200. }
  1201. n = toint(4 + GET_32BIT(p));
  1202. if (n < 0 || keylistlen < n) {
  1203. *retstr = dupstr("Received broken key list from agent");
  1204. return PAGEANT_ACTION_FAILURE;
  1205. }
  1206. p += n;
  1207. keylistlen -= n;
  1208. }
  1209. }
  1210. sfree(keylist);
  1211. }
  1212. sfree(blob);
  1213. }
  1214. error = NULL;
  1215. if (type == SSH_KEYTYPE_SSH1)
  1216. needs_pass = rsakey_encrypted(filename, &comment);
  1217. else
  1218. needs_pass = ssh2_userkey_encrypted(filename, &comment);
  1219. attempts = 0;
  1220. if (type == SSH_KEYTYPE_SSH1)
  1221. rkey = snew(struct RSAKey);
  1222. /*
  1223. * Loop round repeatedly trying to load the key, until we either
  1224. * succeed, fail for some serious reason, or run out of
  1225. * passphrases to try.
  1226. */
  1227. while (1) {
  1228. if (needs_pass) {
  1229. /*
  1230. * If we've been given a passphrase on input, try using
  1231. * it. Otherwise, try one from our tree234 of previously
  1232. * useful passphrases.
  1233. */
  1234. if (passphrase) {
  1235. this_passphrase = (attempts == 0 ? passphrase : NULL);
  1236. } else {
  1237. this_passphrase = (const char *)index234(passphrases, attempts);
  1238. }
  1239. if (!this_passphrase) {
  1240. /*
  1241. * Run out of passphrases to try.
  1242. */
  1243. *retstr = comment;
  1244. return PAGEANT_ACTION_NEED_PP;
  1245. }
  1246. } else
  1247. this_passphrase = "";
  1248. if (type == SSH_KEYTYPE_SSH1)
  1249. ret = loadrsakey(filename, rkey, this_passphrase, &error);
  1250. else {
  1251. skey = ssh2_load_userkey(filename, this_passphrase, &error);
  1252. if (skey == SSH2_WRONG_PASSPHRASE)
  1253. ret = -1;
  1254. else if (!skey)
  1255. ret = 0;
  1256. else
  1257. ret = 1;
  1258. }
  1259. if (ret == 0) {
  1260. /*
  1261. * Failed to load the key file, for some reason other than
  1262. * a bad passphrase.
  1263. */
  1264. *retstr = dupstr(error);
  1265. return PAGEANT_ACTION_FAILURE;
  1266. } else if (ret == 1) {
  1267. /*
  1268. * Successfully loaded the key file.
  1269. */
  1270. break;
  1271. } else {
  1272. /*
  1273. * Passphrase wasn't right; go round again.
  1274. */
  1275. attempts++;
  1276. }
  1277. }
  1278. /*
  1279. * If we get here, we've succesfully loaded the key into
  1280. * rkey/skey, but not yet added it to the agent.
  1281. */
  1282. /*
  1283. * If the key was successfully decrypted, save the passphrase for
  1284. * use with other keys we try to load.
  1285. */
  1286. {
  1287. char *pp_copy = dupstr(this_passphrase);
  1288. if (addpos234(passphrases, pp_copy, 0) != pp_copy) {
  1289. /* No need; it was already there. */
  1290. smemclr(pp_copy, strlen(pp_copy));
  1291. sfree(pp_copy);
  1292. }
  1293. }
  1294. if (comment)
  1295. sfree(comment);
  1296. if (type == SSH_KEYTYPE_SSH1) {
  1297. if (!pageant_local) {
  1298. unsigned char *request, *response;
  1299. void *vresponse;
  1300. int reqlen, clen, resplen, ret;
  1301. clen = strlen(rkey->comment);
  1302. reqlen = 4 + 1 + /* length, message type */
  1303. 4 + /* bit count */
  1304. ssh1_bignum_length(rkey->modulus) +
  1305. ssh1_bignum_length(rkey->exponent) +
  1306. ssh1_bignum_length(rkey->private_exponent) +
  1307. ssh1_bignum_length(rkey->iqmp) +
  1308. ssh1_bignum_length(rkey->p) +
  1309. ssh1_bignum_length(rkey->q) + 4 + clen /* comment */
  1310. ;
  1311. request = snewn(reqlen, unsigned char);
  1312. request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
  1313. reqlen = 5;
  1314. PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
  1315. reqlen += 4;
  1316. reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
  1317. reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);
  1318. reqlen +=
  1319. ssh1_write_bignum(request + reqlen,
  1320. rkey->private_exponent);
  1321. reqlen += ssh1_write_bignum(request + reqlen, rkey->iqmp);
  1322. reqlen += ssh1_write_bignum(request + reqlen, rkey->p);
  1323. reqlen += ssh1_write_bignum(request + reqlen, rkey->q);
  1324. PUT_32BIT(request + reqlen, clen);
  1325. memcpy(request + reqlen + 4, rkey->comment, clen);
  1326. reqlen += 4 + clen;
  1327. PUT_32BIT(request, reqlen - 4);
  1328. ret = agent_query(request, reqlen, &vresponse, &resplen,
  1329. NULL, NULL);
  1330. assert(ret == 1);
  1331. response = vresponse;
  1332. if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
  1333. *retstr = dupstr("The already running Pageant "
  1334. "refused to add the key.");
  1335. return PAGEANT_ACTION_FAILURE;
  1336. }
  1337. sfree(request);
  1338. sfree(response);
  1339. } else {
  1340. if (!pageant_add_ssh1_key(rkey)) {
  1341. sfree(rkey); /* already present, don't waste RAM */
  1342. }
  1343. }
  1344. } else {
  1345. if (!pageant_local) {
  1346. unsigned char *request, *response;
  1347. void *vresponse;
  1348. int reqlen, alglen, clen, keybloblen, resplen, ret;
  1349. alglen = strlen(skey->alg->name);
  1350. clen = strlen(skey->comment);
  1351. keybloblen = skey->alg->openssh_fmtkey(skey->data, NULL, 0);
  1352. reqlen = 4 + 1 + /* length, message type */
  1353. 4 + alglen + /* algorithm name */
  1354. keybloblen + /* key data */
  1355. 4 + clen /* comment */
  1356. ;
  1357. request = snewn(reqlen, unsigned char);
  1358. request[4] = SSH2_AGENTC_ADD_IDENTITY;
  1359. reqlen = 5;
  1360. PUT_32BIT(request + reqlen, alglen);
  1361. reqlen += 4;
  1362. memcpy(request + reqlen, skey->alg->name, alglen);
  1363. reqlen += alglen;
  1364. reqlen += skey->alg->openssh_fmtkey(skey->data,
  1365. request + reqlen,
  1366. keybloblen);
  1367. PUT_32BIT(request + reqlen, clen);
  1368. memcpy(request + reqlen + 4, skey->comment, clen);
  1369. reqlen += clen + 4;
  1370. PUT_32BIT(request, reqlen - 4);
  1371. ret = agent_query(request, reqlen, &vresponse, &resplen,
  1372. NULL, NULL);
  1373. assert(ret == 1);
  1374. response = vresponse;
  1375. if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
  1376. *retstr = dupstr("The already running Pageant "
  1377. "refused to add the key.");
  1378. return PAGEANT_ACTION_FAILURE;
  1379. }
  1380. sfree(request);
  1381. sfree(response);
  1382. } else {
  1383. if (!pageant_add_ssh2_key(skey)) {
  1384. skey->alg->freekey(skey->data);
  1385. sfree(skey); /* already present, don't waste RAM */
  1386. }
  1387. }
  1388. }
  1389. return PAGEANT_ACTION_OK;
  1390. }
  1391. int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx,
  1392. char **retstr)
  1393. {
  1394. unsigned char *keylist, *p;
  1395. int i, nkeys, keylistlen;
  1396. char *comment;
  1397. struct pageant_pubkey cbkey;
  1398. keylist = pageant_get_keylist1(&keylistlen);
  1399. if (keylistlen < 4) {
  1400. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1401. sfree(keylist);
  1402. return PAGEANT_ACTION_FAILURE;
  1403. }
  1404. nkeys = toint(GET_32BIT(keylist));
  1405. if (nkeys < 0) {
  1406. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1407. sfree(keylist);
  1408. return PAGEANT_ACTION_FAILURE;
  1409. }
  1410. p = keylist + 4;
  1411. keylistlen -= 4;
  1412. for (i = 0; i < nkeys; i++) {
  1413. struct RSAKey rkey;
  1414. char fingerprint[128];
  1415. int n;
  1416. /* public blob and fingerprint */
  1417. memset(&rkey, 0, sizeof(rkey));
  1418. n = makekey(p, keylistlen, &rkey, NULL, 0);
  1419. if (n < 0 || n > keylistlen) {
  1420. freersakey(&rkey);
  1421. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1422. sfree(keylist);
  1423. return PAGEANT_ACTION_FAILURE;
  1424. }
  1425. p += n, keylistlen -= n;
  1426. rsa_fingerprint(fingerprint, sizeof(fingerprint), &rkey);
  1427. /* comment */
  1428. if (keylistlen < 4) {
  1429. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1430. freersakey(&rkey);
  1431. sfree(keylist);
  1432. return PAGEANT_ACTION_FAILURE;
  1433. }
  1434. n = toint(GET_32BIT(p));
  1435. p += 4, keylistlen -= 4;
  1436. if (n < 0 || keylistlen < n) {
  1437. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1438. freersakey(&rkey);
  1439. sfree(keylist);
  1440. return PAGEANT_ACTION_FAILURE;
  1441. }
  1442. comment = dupprintf("%.*s", (int)n, (const char *)p);
  1443. p += n, keylistlen -= n;
  1444. cbkey.blob = rsa_public_blob(&rkey, &cbkey.bloblen);
  1445. cbkey.comment = comment;
  1446. cbkey.ssh_version = 1;
  1447. callback(callback_ctx, fingerprint, comment, &cbkey);
  1448. sfree(cbkey.blob);
  1449. freersakey(&rkey);
  1450. sfree(comment);
  1451. }
  1452. sfree(keylist);
  1453. if (keylistlen != 0) {
  1454. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1455. return PAGEANT_ACTION_FAILURE;
  1456. }
  1457. keylist = pageant_get_keylist2(&keylistlen);
  1458. if (keylistlen < 4) {
  1459. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1460. sfree(keylist);
  1461. return PAGEANT_ACTION_FAILURE;
  1462. }
  1463. nkeys = toint(GET_32BIT(keylist));
  1464. if (nkeys < 0) {
  1465. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1466. sfree(keylist);
  1467. return PAGEANT_ACTION_FAILURE;
  1468. }
  1469. p = keylist + 4;
  1470. keylistlen -= 4;
  1471. for (i = 0; i < nkeys; i++) {
  1472. char *fingerprint;
  1473. int n;
  1474. /* public blob */
  1475. if (keylistlen < 4) {
  1476. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1477. sfree(keylist);
  1478. return PAGEANT_ACTION_FAILURE;
  1479. }
  1480. n = toint(GET_32BIT(p));
  1481. p += 4, keylistlen -= 4;
  1482. if (n < 0 || keylistlen < n) {
  1483. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1484. sfree(keylist);
  1485. return PAGEANT_ACTION_FAILURE;
  1486. }
  1487. fingerprint = ssh2_fingerprint_blob(p, n);
  1488. cbkey.blob = p;
  1489. cbkey.bloblen = n;
  1490. p += n, keylistlen -= n;
  1491. /* comment */
  1492. if (keylistlen < 4) {
  1493. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1494. sfree(fingerprint);
  1495. sfree(keylist);
  1496. return PAGEANT_ACTION_FAILURE;
  1497. }
  1498. n = toint(GET_32BIT(p));
  1499. p += 4, keylistlen -= 4;
  1500. if (n < 0 || keylistlen < n) {
  1501. *retstr = dupstr("Received broken SSH-2 key list from agent");
  1502. sfree(fingerprint);
  1503. sfree(keylist);
  1504. return PAGEANT_ACTION_FAILURE;
  1505. }
  1506. comment = dupprintf("%.*s", (int)n, (const char *)p);
  1507. p += n, keylistlen -= n;
  1508. cbkey.ssh_version = 2;
  1509. cbkey.comment = comment;
  1510. callback(callback_ctx, fingerprint, comment, &cbkey);
  1511. sfree(fingerprint);
  1512. sfree(comment);
  1513. }
  1514. sfree(keylist);
  1515. if (keylistlen != 0) {
  1516. *retstr = dupstr("Received broken SSH-1 key list from agent");
  1517. return PAGEANT_ACTION_FAILURE;
  1518. }
  1519. return PAGEANT_ACTION_OK;
  1520. }
  1521. int pageant_delete_key(struct pageant_pubkey *key, char **retstr)
  1522. {
  1523. unsigned char *request, *response;
  1524. int reqlen, resplen, ret;
  1525. void *vresponse;
  1526. if (key->ssh_version == 1) {
  1527. reqlen = 5 + key->bloblen;
  1528. request = snewn(reqlen, unsigned char);
  1529. PUT_32BIT(request, reqlen - 4);
  1530. request[4] = SSH1_AGENTC_REMOVE_RSA_IDENTITY;
  1531. memcpy(request + 5, key->blob, key->bloblen);
  1532. } else {
  1533. reqlen = 9 + key->bloblen;
  1534. request = snewn(reqlen, unsigned char);
  1535. PUT_32BIT(request, reqlen - 4);
  1536. request[4] = SSH2_AGENTC_REMOVE_IDENTITY;
  1537. PUT_32BIT(request + 5, key->bloblen);
  1538. memcpy(request + 9, key->blob, key->bloblen);
  1539. }
  1540. ret = agent_query(request, reqlen, &vresponse, &resplen, NULL, NULL);
  1541. assert(ret == 1);
  1542. response = vresponse;
  1543. if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
  1544. *retstr = dupstr("Agent failed to delete key");
  1545. ret = PAGEANT_ACTION_FAILURE;
  1546. } else {
  1547. *retstr = NULL;
  1548. ret = PAGEANT_ACTION_OK;
  1549. }
  1550. sfree(request);
  1551. sfree(response);
  1552. return ret;
  1553. }
  1554. int pageant_delete_all_keys(char **retstr)
  1555. {
  1556. unsigned char request[5], *response;
  1557. int reqlen, resplen, success, ret;
  1558. void *vresponse;
  1559. PUT_32BIT(request, 1);
  1560. request[4] = SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
  1561. reqlen = 5;
  1562. ret = agent_query(request, reqlen, &vresponse, &resplen, NULL, NULL);
  1563. assert(ret == 1);
  1564. response = vresponse;
  1565. success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
  1566. sfree(response);
  1567. if (!success) {
  1568. *retstr = dupstr("Agent failed to delete SSH-2 keys");
  1569. return PAGEANT_ACTION_FAILURE;
  1570. }
  1571. PUT_32BIT(request, 1);
  1572. request[4] = SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
  1573. reqlen = 5;
  1574. ret = agent_query(request, reqlen, &vresponse, &resplen, NULL, NULL);
  1575. assert(ret == 1);
  1576. response = vresponse;
  1577. success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
  1578. sfree(response);
  1579. if (!success) {
  1580. *retstr = dupstr("Agent failed to delete SSH-1 keys");
  1581. return PAGEANT_ACTION_FAILURE;
  1582. }
  1583. *retstr = NULL;
  1584. return PAGEANT_ACTION_OK;
  1585. }
  1586. struct pageant_pubkey *pageant_pubkey_copy(struct pageant_pubkey *key)
  1587. {
  1588. struct pageant_pubkey *ret = snew(struct pageant_pubkey);
  1589. ret->blob = snewn(key->bloblen, unsigned char);
  1590. memcpy(ret->blob, key->blob, key->bloblen);
  1591. ret->bloblen = key->bloblen;
  1592. ret->comment = key->comment ? dupstr(key->comment) : NULL;
  1593. ret->ssh_version = key->ssh_version;
  1594. return ret;
  1595. }
  1596. void pageant_pubkey_free(struct pageant_pubkey *key)
  1597. {
  1598. sfree(key->comment);
  1599. sfree(key->blob);
  1600. sfree(key);
  1601. }