ssh-add.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. /* $OpenBSD: ssh-add.c,v 1.157 2020/08/31 04:33:17 djm Exp $ */
  2. /*
  3. * Author: Tatu Ylonen <ylo@cs.hut.fi>
  4. * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  5. * All rights reserved
  6. * Adds an identity to the authentication server, or removes an identity.
  7. *
  8. * As far as I am concerned, the code I have written for this software
  9. * can be used freely for any purpose. Any derived versions of this
  10. * software must be clearly marked as such, and if the derived work is
  11. * incompatible with the protocol description in the RFC file, it must be
  12. * called by a name other than "ssh" or "Secure Shell".
  13. *
  14. * SSH2 implementation,
  15. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or without
  18. * modification, are permitted provided that the following conditions
  19. * are met:
  20. * 1. Redistributions of source code must retain the above copyright
  21. * notice, this list of conditions and the following disclaimer.
  22. * 2. Redistributions in binary form must reproduce the above copyright
  23. * notice, this list of conditions and the following disclaimer in the
  24. * documentation and/or other materials provided with the distribution.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  27. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  28. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  29. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  30. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  31. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  35. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include "includes.h"
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #ifdef WITH_OPENSSL
  41. # include <openssl/evp.h>
  42. # include "openbsd-compat/openssl-compat.h"
  43. #endif
  44. #include <errno.h>
  45. #include <fcntl.h>
  46. #include <pwd.h>
  47. #include <stdarg.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <unistd.h>
  52. #include <limits.h>
  53. #include "xmalloc.h"
  54. #include "ssh.h"
  55. #include "log.h"
  56. #include "sshkey.h"
  57. #include "sshbuf.h"
  58. #include "authfd.h"
  59. #include "authfile.h"
  60. #include "pathnames.h"
  61. #include "misc.h"
  62. #include "ssherr.h"
  63. #include "digest.h"
  64. #include "ssh-sk.h"
  65. #include "sk-api.h"
  66. #include "ssh-pkcs11-uri.h"
  67. /* argv0 */
  68. extern char *__progname;
  69. /* Default files to add */
  70. static char *default_files[] = {
  71. #ifdef WITH_OPENSSL
  72. _PATH_SSH_CLIENT_ID_RSA,
  73. _PATH_SSH_CLIENT_ID_DSA,
  74. #ifdef OPENSSL_HAS_ECC
  75. _PATH_SSH_CLIENT_ID_ECDSA,
  76. _PATH_SSH_CLIENT_ID_ECDSA_SK,
  77. #endif
  78. #endif /* WITH_OPENSSL */
  79. _PATH_SSH_CLIENT_ID_ED25519,
  80. _PATH_SSH_CLIENT_ID_ED25519_SK,
  81. _PATH_SSH_CLIENT_ID_XMSS,
  82. NULL
  83. };
  84. static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
  85. /* Default lifetime (0 == forever) */
  86. static int lifetime = 0;
  87. /* User has to confirm key use */
  88. static int confirm = 0;
  89. /* Maximum number of signatures (XMSS) */
  90. static u_int maxsign = 0;
  91. static u_int minleft = 0;
  92. /* we keep a cache of one passphrase */
  93. static char *pass = NULL;
  94. static void
  95. clear_pass(void)
  96. {
  97. if (pass) {
  98. freezero(pass, strlen(pass));
  99. pass = NULL;
  100. }
  101. }
  102. static int
  103. delete_one(int agent_fd, const struct sshkey *key, const char *comment,
  104. const char *path, int qflag)
  105. {
  106. int r;
  107. if ((r = ssh_remove_identity(agent_fd, key)) != 0) {
  108. fprintf(stderr, "Could not remove identity \"%s\": %s\n",
  109. path, ssh_err(r));
  110. return r;
  111. }
  112. if (!qflag) {
  113. fprintf(stderr, "Identity removed: %s %s (%s)\n", path,
  114. sshkey_type(key), comment);
  115. }
  116. return 0;
  117. }
  118. static int
  119. delete_stdin(int agent_fd, int qflag)
  120. {
  121. char *line = NULL, *cp;
  122. size_t linesize = 0;
  123. struct sshkey *key = NULL;
  124. int lnum = 0, r, ret = -1;
  125. while (getline(&line, &linesize, stdin) != -1) {
  126. lnum++;
  127. sshkey_free(key);
  128. key = NULL;
  129. line[strcspn(line, "\n")] = '\0';
  130. cp = line + strspn(line, " \t");
  131. if (*cp == '#' || *cp == '\0')
  132. continue;
  133. if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
  134. fatal("%s: sshkey_new", __func__);
  135. if ((r = sshkey_read(key, &cp)) != 0) {
  136. error("(stdin):%d: invalid key: %s", lnum, ssh_err(r));
  137. continue;
  138. }
  139. if (delete_one(agent_fd, key, cp, "(stdin)", qflag) == 0)
  140. ret = 0;
  141. }
  142. sshkey_free(key);
  143. free(line);
  144. return ret;
  145. }
  146. static int
  147. delete_file(int agent_fd, const char *filename, int key_only, int qflag)
  148. {
  149. struct sshkey *public, *cert = NULL;
  150. char *certpath = NULL, *comment = NULL;
  151. int r, ret = -1;
  152. if (strcmp(filename, "-") == 0)
  153. return delete_stdin(agent_fd, qflag);
  154. if ((r = sshkey_load_public(filename, &public, &comment)) != 0) {
  155. printf("Bad key file %s: %s\n", filename, ssh_err(r));
  156. return -1;
  157. }
  158. if (delete_one(agent_fd, public, comment, filename, qflag) == 0)
  159. ret = 0;
  160. if (key_only)
  161. goto out;
  162. /* Now try to delete the corresponding certificate too */
  163. free(comment);
  164. comment = NULL;
  165. xasprintf(&certpath, "%s-cert.pub", filename);
  166. if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) {
  167. if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
  168. error("Failed to load certificate \"%s\": %s",
  169. certpath, ssh_err(r));
  170. goto out;
  171. }
  172. if (!sshkey_equal_public(cert, public))
  173. fatal("Certificate %s does not match private key %s",
  174. certpath, filename);
  175. if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0)
  176. ret = 0;
  177. out:
  178. sshkey_free(cert);
  179. sshkey_free(public);
  180. free(certpath);
  181. free(comment);
  182. return ret;
  183. }
  184. /* Send a request to remove all identities. */
  185. static int
  186. delete_all(int agent_fd, int qflag)
  187. {
  188. int ret = -1;
  189. /*
  190. * Since the agent might be forwarded, old or non-OpenSSH, when asked
  191. * to remove all keys, attempt to remove both protocol v.1 and v.2
  192. * keys.
  193. */
  194. if (ssh_remove_all_identities(agent_fd, 2) == 0)
  195. ret = 0;
  196. /* ignore error-code for ssh1 */
  197. ssh_remove_all_identities(agent_fd, 1);
  198. if (ret != 0)
  199. fprintf(stderr, "Failed to remove all identities.\n");
  200. else if (!qflag)
  201. fprintf(stderr, "All identities removed.\n");
  202. return ret;
  203. }
  204. #ifdef ENABLE_PKCS11
  205. static int update_card(int, int, const char *, int, char *);
  206. int
  207. update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag)
  208. {
  209. char *pin = NULL;
  210. struct pkcs11_uri *uri;
  211. /* dry-run parse to make sure the URI is valid and to report errors */
  212. uri = pkcs11_uri_init();
  213. if (pkcs11_uri_parse((char *) pkcs11_uri, uri) != 0)
  214. fatal("Failed to parse PKCS#11 URI");
  215. if (uri->pin != NULL) {
  216. pin = strdup(uri->pin);
  217. if (pin == NULL) {
  218. fatal("Failed to dupplicate string");
  219. }
  220. /* pin is freed in the update_card() */
  221. }
  222. pkcs11_uri_cleanup(uri);
  223. return update_card(agent_fd, adding, pkcs11_uri, qflag, pin);
  224. }
  225. #endif
  226. static int
  227. add_file(int agent_fd, const char *filename, int key_only, int qflag,
  228. const char *skprovider)
  229. {
  230. struct sshkey *private, *cert;
  231. char *comment = NULL;
  232. char msg[1024], *certpath = NULL;
  233. int r, fd, ret = -1;
  234. size_t i;
  235. u_int32_t left;
  236. struct sshbuf *keyblob;
  237. struct ssh_identitylist *idlist;
  238. if (strcmp(filename, "-") == 0) {
  239. fd = STDIN_FILENO;
  240. filename = "(stdin)";
  241. } else if ((fd = open(filename, O_RDONLY)) == -1) {
  242. perror(filename);
  243. return -1;
  244. }
  245. /*
  246. * Since we'll try to load a keyfile multiple times, permission errors
  247. * will occur multiple times, so check perms first and bail if wrong.
  248. */
  249. if (fd != STDIN_FILENO) {
  250. if (sshkey_perm_ok(fd, filename) != 0) {
  251. close(fd);
  252. return -1;
  253. }
  254. }
  255. if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) {
  256. fprintf(stderr, "Error loading key \"%s\": %s\n",
  257. filename, ssh_err(r));
  258. sshbuf_free(keyblob);
  259. close(fd);
  260. return -1;
  261. }
  262. close(fd);
  263. /* At first, try empty passphrase */
  264. if ((r = sshkey_parse_private_fileblob(keyblob, "", &private,
  265. &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
  266. fprintf(stderr, "Error loading key \"%s\": %s\n",
  267. filename, ssh_err(r));
  268. goto fail_load;
  269. }
  270. /* try last */
  271. if (private == NULL && pass != NULL) {
  272. if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private,
  273. &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
  274. fprintf(stderr, "Error loading key \"%s\": %s\n",
  275. filename, ssh_err(r));
  276. goto fail_load;
  277. }
  278. }
  279. if (private == NULL) {
  280. /* clear passphrase since it did not work */
  281. clear_pass();
  282. snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ",
  283. filename, confirm ? " (will confirm each use)" : "");
  284. for (;;) {
  285. pass = read_passphrase(msg, RP_ALLOW_STDIN);
  286. if (strcmp(pass, "") == 0)
  287. goto fail_load;
  288. if ((r = sshkey_parse_private_fileblob(keyblob, pass,
  289. &private, &comment)) == 0)
  290. break;
  291. else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
  292. fprintf(stderr,
  293. "Error loading key \"%s\": %s\n",
  294. filename, ssh_err(r));
  295. fail_load:
  296. clear_pass();
  297. sshbuf_free(keyblob);
  298. return -1;
  299. }
  300. clear_pass();
  301. snprintf(msg, sizeof msg,
  302. "Bad passphrase, try again for %s%s: ", filename,
  303. confirm ? " (will confirm each use)" : "");
  304. }
  305. }
  306. if (comment == NULL || *comment == '\0')
  307. comment = xstrdup(filename);
  308. sshbuf_free(keyblob);
  309. /* For XMSS */
  310. if ((r = sshkey_set_filename(private, filename)) != 0) {
  311. fprintf(stderr, "Could not add filename to private key: %s (%s)\n",
  312. filename, comment);
  313. goto out;
  314. }
  315. if (maxsign && minleft &&
  316. (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) {
  317. for (i = 0; i < idlist->nkeys; i++) {
  318. if (!sshkey_equal_public(idlist->keys[i], private))
  319. continue;
  320. left = sshkey_signatures_left(idlist->keys[i]);
  321. if (left < minleft) {
  322. fprintf(stderr,
  323. "Only %d signatures left.\n", left);
  324. break;
  325. }
  326. fprintf(stderr, "Skipping update: ");
  327. if (left == minleft) {
  328. fprintf(stderr,
  329. "required signatures left (%d).\n", left);
  330. } else {
  331. fprintf(stderr,
  332. "more signatures left (%d) than"
  333. " required (%d).\n", left, minleft);
  334. }
  335. ssh_free_identitylist(idlist);
  336. goto out;
  337. }
  338. ssh_free_identitylist(idlist);
  339. }
  340. if (sshkey_is_sk(private)) {
  341. if (skprovider == NULL) {
  342. fprintf(stderr, "Cannot load FIDO key %s "
  343. "without provider\n", filename);
  344. goto out;
  345. }
  346. if ((private->sk_flags & SSH_SK_USER_VERIFICATION_REQD) != 0) {
  347. fprintf(stderr, "FIDO verify-required key %s is not "
  348. "currently supported by ssh-agent\n", filename);
  349. goto out;
  350. }
  351. } else {
  352. /* Don't send provider constraint for other keys */
  353. skprovider = NULL;
  354. }
  355. if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
  356. lifetime, confirm, maxsign, skprovider)) == 0) {
  357. ret = 0;
  358. if (!qflag) {
  359. fprintf(stderr, "Identity added: %s (%s)\n",
  360. filename, comment);
  361. if (lifetime != 0) {
  362. fprintf(stderr,
  363. "Lifetime set to %d seconds\n", lifetime);
  364. }
  365. if (confirm != 0) {
  366. fprintf(stderr, "The user must confirm "
  367. "each use of the key\n");
  368. }
  369. }
  370. } else {
  371. fprintf(stderr, "Could not add identity \"%s\": %s\n",
  372. filename, ssh_err(r));
  373. }
  374. /* Skip trying to load the cert if requested */
  375. if (key_only)
  376. goto out;
  377. /* Now try to add the certificate flavour too */
  378. xasprintf(&certpath, "%s-cert.pub", filename);
  379. if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
  380. if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
  381. error("Failed to load certificate \"%s\": %s",
  382. certpath, ssh_err(r));
  383. goto out;
  384. }
  385. if (!sshkey_equal_public(cert, private)) {
  386. error("Certificate %s does not match private key %s",
  387. certpath, filename);
  388. sshkey_free(cert);
  389. goto out;
  390. }
  391. /* Graft with private bits */
  392. if ((r = sshkey_to_certified(private)) != 0) {
  393. error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
  394. sshkey_free(cert);
  395. goto out;
  396. }
  397. if ((r = sshkey_cert_copy(cert, private)) != 0) {
  398. error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
  399. sshkey_free(cert);
  400. goto out;
  401. }
  402. sshkey_free(cert);
  403. if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
  404. lifetime, confirm, maxsign, skprovider)) != 0) {
  405. error("Certificate %s (%s) add failed: %s", certpath,
  406. private->cert->key_id, ssh_err(r));
  407. goto out;
  408. }
  409. /* success */
  410. if (!qflag) {
  411. fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
  412. private->cert->key_id);
  413. if (lifetime != 0) {
  414. fprintf(stderr, "Lifetime set to %d seconds\n",
  415. lifetime);
  416. }
  417. if (confirm != 0) {
  418. fprintf(stderr, "The user must confirm each use "
  419. "of the key\n");
  420. }
  421. }
  422. out:
  423. free(certpath);
  424. free(comment);
  425. sshkey_free(private);
  426. return ret;
  427. }
  428. static int
  429. update_card(int agent_fd, int add, const char *id, int qflag, char *pin)
  430. {
  431. int r, ret = -1;
  432. if (add && pin == NULL) {
  433. if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
  434. RP_ALLOW_STDIN)) == NULL)
  435. return -1;
  436. }
  437. if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,
  438. lifetime, confirm)) == 0) {
  439. ret = 0;
  440. if (!qflag) {
  441. fprintf(stderr, "Card %s: %s\n",
  442. add ? "added" : "removed", id);
  443. }
  444. } else {
  445. fprintf(stderr, "Could not %s card \"%s\": %s\n",
  446. add ? "add" : "remove", id, ssh_err(r));
  447. ret = -1;
  448. }
  449. free(pin);
  450. return ret;
  451. }
  452. static int
  453. test_key(int agent_fd, const char *filename)
  454. {
  455. struct sshkey *key = NULL;
  456. u_char *sig = NULL;
  457. size_t slen = 0;
  458. int r, ret = -1;
  459. char data[1024];
  460. if ((r = sshkey_load_public(filename, &key, NULL)) != 0) {
  461. error("Couldn't read public key %s: %s", filename, ssh_err(r));
  462. return -1;
  463. }
  464. arc4random_buf(data, sizeof(data));
  465. if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data),
  466. NULL, 0)) != 0) {
  467. error("Agent signature failed for %s: %s",
  468. filename, ssh_err(r));
  469. goto done;
  470. }
  471. if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
  472. NULL, 0, NULL)) != 0) {
  473. error("Signature verification failed for %s: %s",
  474. filename, ssh_err(r));
  475. goto done;
  476. }
  477. /* success */
  478. ret = 0;
  479. done:
  480. free(sig);
  481. sshkey_free(key);
  482. return ret;
  483. }
  484. static int
  485. list_identities(int agent_fd, int do_fp)
  486. {
  487. char *fp;
  488. int r;
  489. struct ssh_identitylist *idlist;
  490. u_int32_t left;
  491. size_t i;
  492. if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
  493. if (r != SSH_ERR_AGENT_NO_IDENTITIES)
  494. fprintf(stderr, "error fetching identities: %s\n",
  495. ssh_err(r));
  496. else
  497. printf("The agent has no identities.\n");
  498. return -1;
  499. }
  500. for (i = 0; i < idlist->nkeys; i++) {
  501. if (do_fp) {
  502. fp = sshkey_fingerprint(idlist->keys[i],
  503. fingerprint_hash, SSH_FP_DEFAULT);
  504. printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]),
  505. fp == NULL ? "(null)" : fp, idlist->comments[i],
  506. sshkey_type(idlist->keys[i]));
  507. free(fp);
  508. } else {
  509. if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) {
  510. fprintf(stderr, "sshkey_write: %s\n",
  511. ssh_err(r));
  512. continue;
  513. }
  514. fprintf(stdout, " %s", idlist->comments[i]);
  515. left = sshkey_signatures_left(idlist->keys[i]);
  516. if (left > 0)
  517. fprintf(stdout,
  518. " [signatures left %d]", left);
  519. fprintf(stdout, "\n");
  520. }
  521. }
  522. ssh_free_identitylist(idlist);
  523. return 0;
  524. }
  525. static int
  526. lock_agent(int agent_fd, int lock)
  527. {
  528. char prompt[100], *p1, *p2;
  529. int r, passok = 1, ret = -1;
  530. strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
  531. p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
  532. if (lock) {
  533. strlcpy(prompt, "Again: ", sizeof prompt);
  534. p2 = read_passphrase(prompt, RP_ALLOW_STDIN);
  535. if (strcmp(p1, p2) != 0) {
  536. fprintf(stderr, "Passwords do not match.\n");
  537. passok = 0;
  538. }
  539. freezero(p2, strlen(p2));
  540. }
  541. if (passok) {
  542. if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) {
  543. fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
  544. ret = 0;
  545. } else {
  546. fprintf(stderr, "Failed to %slock agent: %s\n",
  547. lock ? "" : "un", ssh_err(r));
  548. }
  549. }
  550. freezero(p1, strlen(p1));
  551. return (ret);
  552. }
  553. static int
  554. load_resident_keys(int agent_fd, const char *skprovider, int qflag)
  555. {
  556. struct sshkey **keys;
  557. size_t nkeys, i;
  558. int r, ok = 0;
  559. char *fp;
  560. pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
  561. if ((r = sshsk_load_resident(skprovider, NULL, pass,
  562. &keys, &nkeys)) != 0) {
  563. error("Unable to load resident keys: %s", ssh_err(r));
  564. return r;
  565. }
  566. for (i = 0; i < nkeys; i++) {
  567. if ((fp = sshkey_fingerprint(keys[i],
  568. fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
  569. fatal("%s: sshkey_fingerprint failed", __func__);
  570. if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "",
  571. lifetime, confirm, maxsign, skprovider)) != 0) {
  572. error("Unable to add key %s %s",
  573. sshkey_type(keys[i]), fp);
  574. free(fp);
  575. ok = r;
  576. continue;
  577. }
  578. if (ok == 0)
  579. ok = 1;
  580. if (!qflag) {
  581. fprintf(stderr, "Resident identity added: %s %s\n",
  582. sshkey_type(keys[i]), fp);
  583. if (lifetime != 0) {
  584. fprintf(stderr,
  585. "Lifetime set to %d seconds\n", lifetime);
  586. }
  587. if (confirm != 0) {
  588. fprintf(stderr, "The user must confirm "
  589. "each use of the key\n");
  590. }
  591. }
  592. free(fp);
  593. sshkey_free(keys[i]);
  594. }
  595. free(keys);
  596. if (nkeys == 0)
  597. return SSH_ERR_KEY_NOT_FOUND;
  598. return ok == 1 ? 0 : ok;
  599. }
  600. static int
  601. do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
  602. const char *skprovider)
  603. {
  604. #ifdef ENABLE_PKCS11
  605. if (strlen(file) >= strlen(PKCS11_URI_SCHEME) &&
  606. strncmp(file, PKCS11_URI_SCHEME,
  607. strlen(PKCS11_URI_SCHEME)) == 0) {
  608. return update_pkcs11_uri(agent_fd, !deleting, file, qflag);
  609. }
  610. #endif
  611. if (deleting) {
  612. if (delete_file(agent_fd, file, key_only, qflag) == -1)
  613. return -1;
  614. } else {
  615. if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)
  616. return -1;
  617. }
  618. return 0;
  619. }
  620. static void
  621. usage(void)
  622. {
  623. fprintf(stderr,
  624. "usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-S provider] [-t life]\n"
  625. #ifdef WITH_XMSS
  626. " [-M maxsign] [-m minleft]\n"
  627. #endif
  628. " [file ...]\n"
  629. " ssh-add -s pkcs11\n"
  630. " ssh-add -e pkcs11\n"
  631. " ssh-add -T pubkey ...\n"
  632. );
  633. }
  634. int
  635. main(int argc, char **argv)
  636. {
  637. extern char *optarg;
  638. extern int optind;
  639. int agent_fd;
  640. char *pkcs11provider = NULL, *skprovider = NULL;
  641. int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0;
  642. int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
  643. SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
  644. LogLevel log_level = SYSLOG_LEVEL_INFO;
  645. /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  646. sanitise_stdfd();
  647. __progname = ssh_get_progname(argv[0]);
  648. seed_rng();
  649. log_init(__progname, log_level, log_facility, 1);
  650. setvbuf(stdout, NULL, _IOLBF, 0);
  651. /* First, get a connection to the authentication agent. */
  652. switch (r = ssh_get_authentication_socket(&agent_fd)) {
  653. case 0:
  654. break;
  655. case SSH_ERR_AGENT_NOT_PRESENT:
  656. fprintf(stderr, "Could not open a connection to your "
  657. "authentication agent.\n");
  658. exit(2);
  659. default:
  660. fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r));
  661. exit(2);
  662. }
  663. skprovider = getenv("SSH_SK_PROVIDER");
  664. while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:M:m:qs:S:t:")) != -1) {
  665. switch (ch) {
  666. case 'v':
  667. if (log_level == SYSLOG_LEVEL_INFO)
  668. log_level = SYSLOG_LEVEL_DEBUG1;
  669. else if (log_level < SYSLOG_LEVEL_DEBUG3)
  670. log_level++;
  671. break;
  672. case 'E':
  673. fingerprint_hash = ssh_digest_alg_by_name(optarg);
  674. if (fingerprint_hash == -1)
  675. fatal("Invalid hash algorithm \"%s\"", optarg);
  676. break;
  677. case 'k':
  678. key_only = 1;
  679. break;
  680. case 'K':
  681. do_download = 1;
  682. break;
  683. case 'l':
  684. case 'L':
  685. if (lflag != 0)
  686. fatal("-%c flag already specified", lflag);
  687. lflag = ch;
  688. break;
  689. case 'x':
  690. case 'X':
  691. if (xflag != 0)
  692. fatal("-%c flag already specified", xflag);
  693. xflag = ch;
  694. break;
  695. case 'c':
  696. confirm = 1;
  697. break;
  698. case 'm':
  699. minleft = (int)strtonum(optarg, 1, UINT_MAX, NULL);
  700. if (minleft == 0) {
  701. usage();
  702. ret = 1;
  703. goto done;
  704. }
  705. break;
  706. case 'M':
  707. maxsign = (int)strtonum(optarg, 1, UINT_MAX, NULL);
  708. if (maxsign == 0) {
  709. usage();
  710. ret = 1;
  711. goto done;
  712. }
  713. break;
  714. case 'd':
  715. deleting = 1;
  716. break;
  717. case 'D':
  718. Dflag = 1;
  719. break;
  720. case 's':
  721. pkcs11provider = optarg;
  722. break;
  723. case 'S':
  724. skprovider = optarg;
  725. break;
  726. case 'e':
  727. deleting = 1;
  728. pkcs11provider = optarg;
  729. break;
  730. case 't':
  731. if ((lifetime = convtime(optarg)) == -1 ||
  732. lifetime < 0 || (u_long)lifetime > UINT32_MAX) {
  733. fprintf(stderr, "Invalid lifetime\n");
  734. ret = 1;
  735. goto done;
  736. }
  737. break;
  738. case 'q':
  739. qflag = 1;
  740. break;
  741. case 'T':
  742. Tflag = 1;
  743. break;
  744. default:
  745. usage();
  746. ret = 1;
  747. goto done;
  748. }
  749. }
  750. log_init(__progname, log_level, log_facility, 1);
  751. if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
  752. fatal("Invalid combination of actions");
  753. else if (xflag) {
  754. if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1)
  755. ret = 1;
  756. goto done;
  757. } else if (lflag) {
  758. if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1)
  759. ret = 1;
  760. goto done;
  761. } else if (Dflag) {
  762. if (delete_all(agent_fd, qflag) == -1)
  763. ret = 1;
  764. goto done;
  765. }
  766. #ifdef ENABLE_SK_INTERNAL
  767. if (skprovider == NULL)
  768. skprovider = "internal";
  769. #endif
  770. argc -= optind;
  771. argv += optind;
  772. if (Tflag) {
  773. if (argc <= 0)
  774. fatal("no keys to test");
  775. for (r = i = 0; i < argc; i++)
  776. r |= test_key(agent_fd, argv[i]);
  777. ret = r == 0 ? 0 : 1;
  778. goto done;
  779. }
  780. if (pkcs11provider != NULL) {
  781. if (update_card(agent_fd, !deleting, pkcs11provider,
  782. qflag, NULL) == -1)
  783. ret = 1;
  784. goto done;
  785. }
  786. if (do_download) {
  787. if (skprovider == NULL)
  788. fatal("Cannot download keys without provider");
  789. if (load_resident_keys(agent_fd, skprovider, qflag) != 0)
  790. ret = 1;
  791. goto done;
  792. }
  793. if (argc == 0) {
  794. char buf[PATH_MAX];
  795. struct passwd *pw;
  796. struct stat st;
  797. int count = 0;
  798. if ((pw = getpwuid(getuid())) == NULL) {
  799. fprintf(stderr, "No user found with uid %u\n",
  800. (u_int)getuid());
  801. ret = 1;
  802. goto done;
  803. }
  804. for (i = 0; default_files[i]; i++) {
  805. snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
  806. default_files[i]);
  807. if (stat(buf, &st) == -1)
  808. continue;
  809. if (do_file(agent_fd, deleting, key_only, buf,
  810. qflag, skprovider) == -1)
  811. ret = 1;
  812. else
  813. count++;
  814. }
  815. if (count == 0)
  816. ret = 1;
  817. } else {
  818. for (i = 0; i < argc; i++) {
  819. if (do_file(agent_fd, deleting, key_only,
  820. argv[i], qflag, skprovider) == -1)
  821. ret = 1;
  822. }
  823. }
  824. done:
  825. clear_pass();
  826. ssh_close_authentication_socket(agent_fd);
  827. return ret;
  828. }