authfile.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. /* $OpenBSD: authfile.c,v 1.141 2020/06/18 23:33:38 djm Exp $ */
  2. /*
  3. * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "includes.h"
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/uio.h>
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #include <grp.h>
  32. #include <stdio.h>
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include <limits.h>
  38. #include "cipher.h"
  39. #include "ssh.h"
  40. #include "log.h"
  41. #include "authfile.h"
  42. #include "misc.h"
  43. #include "atomicio.h"
  44. #include "sshkey.h"
  45. #include "sshbuf.h"
  46. #include "ssherr.h"
  47. #include "krl.h"
  48. #define MAX_KEY_FILE_SIZE (1024 * 1024)
  49. /* Save a key blob to a file */
  50. static int
  51. sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
  52. {
  53. int r;
  54. mode_t omask;
  55. omask = umask(077);
  56. r = sshbuf_write_file(filename, keybuf);
  57. umask(omask);
  58. return r;
  59. }
  60. int
  61. sshkey_save_private(struct sshkey *key, const char *filename,
  62. const char *passphrase, const char *comment,
  63. int format, const char *openssh_format_cipher, int openssh_format_rounds)
  64. {
  65. struct sshbuf *keyblob = NULL;
  66. int r;
  67. if ((keyblob = sshbuf_new()) == NULL)
  68. return SSH_ERR_ALLOC_FAIL;
  69. if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
  70. format, openssh_format_cipher, openssh_format_rounds)) != 0)
  71. goto out;
  72. if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
  73. goto out;
  74. r = 0;
  75. out:
  76. sshbuf_free(keyblob);
  77. return r;
  78. }
  79. /* XXX remove error() calls from here? */
  80. int
  81. sshkey_perm_ok(int fd, const char *filename)
  82. {
  83. struct stat st;
  84. if (fstat(fd, &st) == -1)
  85. return SSH_ERR_SYSTEM_ERROR;
  86. /*
  87. * if a key owned by the user is accessed, then we check the
  88. * permissions of the file. if the key owned by a different user,
  89. * then we don't care.
  90. */
  91. #ifdef HAVE_CYGWIN
  92. if (check_ntsec(filename))
  93. #endif
  94. if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
  95. if (st.st_mode & 040) {
  96. struct group *gr;
  97. if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) {
  98. /* The only additional bit is read
  99. * for ssh_keys group, which is fine */
  100. if ((st.st_mode & 077) == 040 ) {
  101. return 0;
  102. }
  103. }
  104. }
  105. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  106. error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
  107. error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  108. error("Permissions 0%3.3o for '%s' are too open.",
  109. (u_int)st.st_mode & 0777, filename);
  110. error("It is required that your private key files are NOT accessible by others.");
  111. error("This private key will be ignored.");
  112. return SSH_ERR_KEY_BAD_PERMISSIONS;
  113. }
  114. return 0;
  115. }
  116. int
  117. sshkey_load_private_type(int type, const char *filename, const char *passphrase,
  118. struct sshkey **keyp, char **commentp)
  119. {
  120. int fd, r;
  121. if (keyp != NULL)
  122. *keyp = NULL;
  123. if (commentp != NULL)
  124. *commentp = NULL;
  125. if ((fd = open(filename, O_RDONLY)) == -1)
  126. return SSH_ERR_SYSTEM_ERROR;
  127. r = sshkey_perm_ok(fd, filename);
  128. if (r != 0)
  129. goto out;
  130. r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
  131. if (r == 0 && keyp && *keyp)
  132. r = sshkey_set_filename(*keyp, filename);
  133. out:
  134. close(fd);
  135. return r;
  136. }
  137. int
  138. sshkey_load_private(const char *filename, const char *passphrase,
  139. struct sshkey **keyp, char **commentp)
  140. {
  141. return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase,
  142. keyp, commentp);
  143. }
  144. int
  145. sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
  146. struct sshkey **keyp, char **commentp)
  147. {
  148. struct sshbuf *buffer = NULL;
  149. int r;
  150. if (keyp != NULL)
  151. *keyp = NULL;
  152. if ((r = sshbuf_load_fd(fd, &buffer)) != 0 ||
  153. (r = sshkey_parse_private_fileblob_type(buffer, type,
  154. passphrase, keyp, commentp)) != 0)
  155. goto out;
  156. /* success */
  157. r = 0;
  158. out:
  159. sshbuf_free(buffer);
  160. return r;
  161. }
  162. /* Load a pubkey from the unencrypted envelope of a new-format private key */
  163. static int
  164. sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp)
  165. {
  166. struct sshbuf *buffer = NULL;
  167. struct sshkey *pubkey = NULL;
  168. int r, fd;
  169. if (pubkeyp != NULL)
  170. *pubkeyp = NULL;
  171. if ((fd = open(filename, O_RDONLY)) == -1)
  172. return SSH_ERR_SYSTEM_ERROR;
  173. if ((r = sshbuf_load_fd(fd, &buffer)) != 0 ||
  174. (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer,
  175. KEY_UNSPEC, &pubkey)) != 0)
  176. goto out;
  177. if ((r = sshkey_set_filename(pubkey, filename)) != 0)
  178. goto out;
  179. /* success */
  180. if (pubkeyp != NULL) {
  181. *pubkeyp = pubkey;
  182. pubkey = NULL;
  183. }
  184. r = 0;
  185. out:
  186. close(fd);
  187. sshbuf_free(buffer);
  188. sshkey_free(pubkey);
  189. return r;
  190. }
  191. static int
  192. sshkey_try_load_public(struct sshkey **kp, const char *filename,
  193. char **commentp)
  194. {
  195. FILE *f;
  196. char *line = NULL, *cp;
  197. size_t linesize = 0;
  198. int r;
  199. struct sshkey *k = NULL;
  200. *kp = NULL;
  201. if (commentp != NULL)
  202. *commentp = NULL;
  203. if ((f = fopen(filename, "r")) == NULL)
  204. return SSH_ERR_SYSTEM_ERROR;
  205. if ((k = sshkey_new(KEY_UNSPEC)) == NULL) {
  206. fclose(f);
  207. return SSH_ERR_ALLOC_FAIL;
  208. }
  209. while (getline(&line, &linesize, f) != -1) {
  210. cp = line;
  211. switch (*cp) {
  212. case '#':
  213. case '\n':
  214. case '\0':
  215. continue;
  216. }
  217. /* Abort loading if this looks like a private key */
  218. if (strncmp(cp, "-----BEGIN", 10) == 0 ||
  219. strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
  220. break;
  221. /* Skip leading whitespace. */
  222. for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
  223. ;
  224. if (*cp) {
  225. if ((r = sshkey_read(k, &cp)) == 0) {
  226. cp[strcspn(cp, "\r\n")] = '\0';
  227. if (commentp) {
  228. *commentp = strdup(*cp ?
  229. cp : filename);
  230. if (*commentp == NULL)
  231. r = SSH_ERR_ALLOC_FAIL;
  232. }
  233. /* success */
  234. *kp = k;
  235. free(line);
  236. fclose(f);
  237. return r;
  238. }
  239. }
  240. }
  241. free(k);
  242. free(line);
  243. fclose(f);
  244. return SSH_ERR_INVALID_FORMAT;
  245. }
  246. /* load public key from any pubkey file */
  247. int
  248. sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
  249. {
  250. char *pubfile = NULL;
  251. int r, oerrno;
  252. if (keyp != NULL)
  253. *keyp = NULL;
  254. if (commentp != NULL)
  255. *commentp = NULL;
  256. if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0)
  257. goto out;
  258. /* try .pub suffix */
  259. if (asprintf(&pubfile, "%s.pub", filename) == -1)
  260. return SSH_ERR_ALLOC_FAIL;
  261. if ((r = sshkey_try_load_public(keyp, pubfile, commentp)) == 0)
  262. goto out;
  263. /* finally, try to extract public key from private key file */
  264. if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0)
  265. goto out;
  266. /* Pretend we couldn't find the key */
  267. r = SSH_ERR_SYSTEM_ERROR;
  268. errno = ENOENT;
  269. out:
  270. oerrno = errno;
  271. free(pubfile);
  272. errno = oerrno;
  273. return r;
  274. }
  275. /* Load the certificate associated with the named private key */
  276. int
  277. sshkey_load_cert(const char *filename, struct sshkey **keyp)
  278. {
  279. struct sshkey *pub = NULL;
  280. char *file = NULL;
  281. int r = SSH_ERR_INTERNAL_ERROR;
  282. if (keyp != NULL)
  283. *keyp = NULL;
  284. if (asprintf(&file, "%s-cert.pub", filename) == -1)
  285. return SSH_ERR_ALLOC_FAIL;
  286. r = sshkey_try_load_public(keyp, file, NULL);
  287. free(file);
  288. sshkey_free(pub);
  289. return r;
  290. }
  291. /* Load private key and certificate */
  292. int
  293. sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
  294. struct sshkey **keyp)
  295. {
  296. struct sshkey *key = NULL, *cert = NULL;
  297. int r;
  298. if (keyp != NULL)
  299. *keyp = NULL;
  300. switch (type) {
  301. #ifdef WITH_OPENSSL
  302. case KEY_RSA:
  303. case KEY_DSA:
  304. case KEY_ECDSA:
  305. #endif /* WITH_OPENSSL */
  306. case KEY_ED25519:
  307. case KEY_XMSS:
  308. case KEY_UNSPEC:
  309. break;
  310. default:
  311. return SSH_ERR_KEY_TYPE_UNKNOWN;
  312. }
  313. if ((r = sshkey_load_private_type(type, filename,
  314. passphrase, &key, NULL)) != 0 ||
  315. (r = sshkey_load_cert(filename, &cert)) != 0)
  316. goto out;
  317. /* Make sure the private key matches the certificate */
  318. if (sshkey_equal_public(key, cert) == 0) {
  319. r = SSH_ERR_KEY_CERT_MISMATCH;
  320. goto out;
  321. }
  322. if ((r = sshkey_to_certified(key)) != 0 ||
  323. (r = sshkey_cert_copy(cert, key)) != 0)
  324. goto out;
  325. r = 0;
  326. if (keyp != NULL) {
  327. *keyp = key;
  328. key = NULL;
  329. }
  330. out:
  331. sshkey_free(key);
  332. sshkey_free(cert);
  333. return r;
  334. }
  335. /*
  336. * Returns success if the specified "key" is listed in the file "filename",
  337. * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
  338. * If "strict_type" is set then the key type must match exactly,
  339. * otherwise a comparison that ignores certficiate data is performed.
  340. * If "check_ca" is set and "key" is a certificate, then its CA key is
  341. * also checked and sshkey_in_file() will return success if either is found.
  342. */
  343. int
  344. sshkey_in_file(struct sshkey *key, const char *filename, int strict_type,
  345. int check_ca)
  346. {
  347. FILE *f;
  348. char *line = NULL, *cp;
  349. size_t linesize = 0;
  350. int r = 0;
  351. struct sshkey *pub = NULL;
  352. int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
  353. strict_type ? sshkey_equal : sshkey_equal_public;
  354. if ((f = fopen(filename, "r")) == NULL)
  355. return SSH_ERR_SYSTEM_ERROR;
  356. while (getline(&line, &linesize, f) != -1) {
  357. sshkey_free(pub);
  358. pub = NULL;
  359. cp = line;
  360. /* Skip leading whitespace. */
  361. for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
  362. ;
  363. /* Skip comments and empty lines */
  364. switch (*cp) {
  365. case '#':
  366. case '\n':
  367. case '\0':
  368. continue;
  369. }
  370. if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
  371. r = SSH_ERR_ALLOC_FAIL;
  372. goto out;
  373. }
  374. switch (r = sshkey_read(pub, &cp)) {
  375. case 0:
  376. break;
  377. case SSH_ERR_KEY_LENGTH:
  378. continue;
  379. default:
  380. goto out;
  381. }
  382. if (sshkey_compare(key, pub) ||
  383. (check_ca && sshkey_is_cert(key) &&
  384. sshkey_compare(key->cert->signature_key, pub))) {
  385. r = 0;
  386. goto out;
  387. }
  388. }
  389. r = SSH_ERR_KEY_NOT_FOUND;
  390. out:
  391. free(line);
  392. sshkey_free(pub);
  393. fclose(f);
  394. return r;
  395. }
  396. /*
  397. * Checks whether the specified key is revoked, returning 0 if not,
  398. * SSH_ERR_KEY_REVOKED if it is or another error code if something
  399. * unexpected happened.
  400. * This will check both the key and, if it is a certificate, its CA key too.
  401. * "revoked_keys_file" may be a KRL or a one-per-line list of public keys.
  402. */
  403. int
  404. sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file)
  405. {
  406. int r;
  407. r = ssh_krl_file_contains_key(revoked_keys_file, key);
  408. /* If this was not a KRL to begin with then continue below */
  409. if (r != SSH_ERR_KRL_BAD_MAGIC)
  410. return r;
  411. /*
  412. * If the file is not a KRL or we can't handle KRLs then attempt to
  413. * parse the file as a flat list of keys.
  414. */
  415. switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) {
  416. case 0:
  417. /* Key found => revoked */
  418. return SSH_ERR_KEY_REVOKED;
  419. case SSH_ERR_KEY_NOT_FOUND:
  420. /* Key not found => not revoked */
  421. return 0;
  422. default:
  423. /* Some other error occurred */
  424. return r;
  425. }
  426. }
  427. /*
  428. * Advanced *cpp past the end of key options, defined as the first unquoted
  429. * whitespace character. Returns 0 on success or -1 on failure (e.g.
  430. * unterminated quotes).
  431. */
  432. int
  433. sshkey_advance_past_options(char **cpp)
  434. {
  435. char *cp = *cpp;
  436. int quoted = 0;
  437. for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
  438. if (*cp == '\\' && cp[1] == '"')
  439. cp++; /* Skip both */
  440. else if (*cp == '"')
  441. quoted = !quoted;
  442. }
  443. *cpp = cp;
  444. /* return failure for unterminated quotes */
  445. return (*cp == '\0' && quoted) ? -1 : 0;
  446. }
  447. /* Save a public key */
  448. int
  449. sshkey_save_public(const struct sshkey *key, const char *path,
  450. const char *comment)
  451. {
  452. int fd, oerrno;
  453. FILE *f = NULL;
  454. int r = SSH_ERR_INTERNAL_ERROR;
  455. if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
  456. return SSH_ERR_SYSTEM_ERROR;
  457. if ((f = fdopen(fd, "w")) == NULL) {
  458. r = SSH_ERR_SYSTEM_ERROR;
  459. goto fail;
  460. }
  461. if ((r = sshkey_write(key, f)) != 0)
  462. goto fail;
  463. fprintf(f, " %s\n", comment);
  464. if (ferror(f) || fclose(f) != 0) {
  465. r = SSH_ERR_SYSTEM_ERROR;
  466. fail:
  467. oerrno = errno;
  468. if (f != NULL)
  469. fclose(f);
  470. else
  471. close(fd);
  472. errno = oerrno;
  473. return r;
  474. }
  475. return 0;
  476. }