summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2015-01-30 11:43:14 +0000
committerDamien Miller <djm@mindrot.org>2015-01-30 22:47:01 +1100
commit46347ed5968f582661e8a70a45f448e0179ca0ab (patch)
tree73d7bdde30c7833671bec134d737efb09075bd55 /sshconnect2.c
parent802660cb70453fa4d230cb0233bc1bbdf8328de1 (diff)
upstream commit
Add a ssh_config HostbasedKeyType option to control which host public key types are tried during hostbased authentication. This may be used to prevent too many keys being sent to the server, and blowing past its MaxAuthTries limit. bz#2211 based on patch by Iain Morgan; ok markus@
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c306
1 files changed, 198 insertions, 108 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 48882e3a5..804194aab 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.222 2015/01/28 22:36:00 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.223 2015/01/30 11:43:14 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -273,6 +273,8 @@ struct cauthctxt {
273 int agent_fd; 273 int agent_fd;
274 /* hostbased */ 274 /* hostbased */
275 Sensitive *sensitive; 275 Sensitive *sensitive;
276 char *oktypes, *ktypes;
277 const char *active_ktype;
276 /* kbd-interactive */ 278 /* kbd-interactive */
277 int info_req_seen; 279 int info_req_seen;
278 /* generic */ 280 /* generic */
@@ -401,6 +403,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
401 authctxt.authlist = NULL; 403 authctxt.authlist = NULL;
402 authctxt.methoddata = NULL; 404 authctxt.methoddata = NULL;
403 authctxt.sensitive = sensitive; 405 authctxt.sensitive = sensitive;
406 authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL;
404 authctxt.info_req_seen = 0; 407 authctxt.info_req_seen = 0;
405 authctxt.agent_fd = -1; 408 authctxt.agent_fd = -1;
406 if (authctxt.method == NULL) 409 if (authctxt.method == NULL)
@@ -1452,78 +1455,116 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
1452} 1455}
1453 1456
1454static int 1457static int
1455ssh_keysign(Key *key, u_char **sigp, u_int *lenp, 1458ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
1456 u_char *data, u_int datalen) 1459 const u_char *data, size_t datalen)
1457{ 1460{
1458 Buffer b; 1461 struct sshbuf *b;
1459 struct stat st; 1462 struct stat st;
1460 pid_t pid; 1463 pid_t pid;
1461 int to[2], from[2], status, version = 2; 1464 int i, r, to[2], from[2], status, sock = packet_get_connection_in();
1465 u_char rversion = 0, version = 2;
1466 void (*osigchld)(int);
1462 1467
1463 debug2("ssh_keysign called"); 1468 *sigp = NULL;
1469 *lenp = 0;
1464 1470
1465 if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { 1471 if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
1466 error("ssh_keysign: not installed: %s", strerror(errno)); 1472 error("%s: not installed: %s", __func__, strerror(errno));
1473 return -1;
1474 }
1475 if (fflush(stdout) != 0) {
1476 error("%s: fflush: %s", __func__, strerror(errno));
1467 return -1; 1477 return -1;
1468 } 1478 }
1469 if (fflush(stdout) != 0)
1470 error("ssh_keysign: fflush: %s", strerror(errno));
1471 if (pipe(to) < 0) { 1479 if (pipe(to) < 0) {
1472 error("ssh_keysign: pipe: %s", strerror(errno)); 1480 error("%s: pipe: %s", __func__, strerror(errno));
1473 return -1; 1481 return -1;
1474 } 1482 }
1475 if (pipe(from) < 0) { 1483 if (pipe(from) < 0) {
1476 error("ssh_keysign: pipe: %s", strerror(errno)); 1484 error("%s: pipe: %s", __func__, strerror(errno));
1477 return -1; 1485 return -1;
1478 } 1486 }
1479 if ((pid = fork()) < 0) { 1487 if ((pid = fork()) < 0) {
1480 error("ssh_keysign: fork: %s", strerror(errno)); 1488 error("%s: fork: %s", __func__, strerror(errno));
1481 return -1; 1489 return -1;
1482 } 1490 }
1491 osigchld = signal(SIGCHLD, SIG_DFL);
1483 if (pid == 0) { 1492 if (pid == 0) {
1484 /* keep the socket on exec */ 1493 /* keep the socket on exec */
1485 fcntl(packet_get_connection_in(), F_SETFD, 0); 1494 fcntl(sock, F_SETFD, 0);
1486 permanently_drop_suid(getuid()); 1495 permanently_drop_suid(getuid());
1487 close(from[0]); 1496 close(from[0]);
1488 if (dup2(from[1], STDOUT_FILENO) < 0) 1497 if (dup2(from[1], STDOUT_FILENO) < 0)
1489 fatal("ssh_keysign: dup2: %s", strerror(errno)); 1498 fatal("%s: dup2: %s", __func__, strerror(errno));
1490 close(to[1]); 1499 close(to[1]);
1491 if (dup2(to[0], STDIN_FILENO) < 0) 1500 if (dup2(to[0], STDIN_FILENO) < 0)
1492 fatal("ssh_keysign: dup2: %s", strerror(errno)); 1501 fatal("%s: dup2: %s", __func__, strerror(errno));
1493 close(from[1]); 1502 close(from[1]);
1494 close(to[0]); 1503 close(to[0]);
1504 /* Close everything but stdio and the socket */
1505 for (i = STDERR_FILENO + 1; i < sock; i++)
1506 close(i);
1507 closefrom(sock + 1);
1508 debug3("%s: [child] pid=%ld, exec %s",
1509 __func__, (long)getpid(), _PATH_SSH_KEY_SIGN);
1495 execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); 1510 execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
1496 fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, 1511 fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN,
1497 strerror(errno)); 1512 strerror(errno));
1498 } 1513 }
1499 close(from[1]); 1514 close(from[1]);
1500 close(to[0]); 1515 close(to[0]);
1501 1516
1502 buffer_init(&b); 1517 if ((b = sshbuf_new()) == NULL)
1503 buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ 1518 fatal("%s: sshbuf_new failed", __func__);
1504 buffer_put_string(&b, data, datalen); 1519 /* send # of sock, data to be signed */
1505 if (ssh_msg_send(to[1], version, &b) == -1) 1520 if ((r = sshbuf_put_u32(b, sock) != 0) ||
1506 fatal("ssh_keysign: couldn't send request"); 1521 (r = sshbuf_put_string(b, data, datalen)) != 0)
1507 1522 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1508 if (ssh_msg_recv(from[0], &b) < 0) { 1523 if (ssh_msg_send(to[1], version, b) == -1)
1509 error("ssh_keysign: no reply"); 1524 fatal("%s: couldn't send request", __func__);
1510 buffer_free(&b); 1525 sshbuf_reset(b);
1511 return -1; 1526 r = ssh_msg_recv(from[0], b);
1512 }
1513 close(from[0]); 1527 close(from[0]);
1514 close(to[1]); 1528 close(to[1]);
1529 if (r < 0) {
1530 error("%s: no reply", __func__);
1531 goto fail;
1532 }
1515 1533
1516 while (waitpid(pid, &status, 0) < 0) 1534 errno = 0;
1517 if (errno != EINTR) 1535 while (waitpid(pid, &status, 0) < 0) {
1518 break; 1536 if (errno != EINTR) {
1519 1537 error("%s: waitpid %ld: %s",
1520 if (buffer_get_char(&b) != version) { 1538 __func__, (long)pid, strerror(errno));
1521 error("ssh_keysign: bad version"); 1539 goto fail;
1522 buffer_free(&b); 1540 }
1541 }
1542 if (!WIFEXITED(status)) {
1543 error("%s: exited abnormally", __func__);
1544 goto fail;
1545 }
1546 if (WEXITSTATUS(status) != 0) {
1547 error("%s: exited with status %d",
1548 __func__, WEXITSTATUS(status));
1549 goto fail;
1550 }
1551 if ((r = sshbuf_get_u8(b, &rversion)) != 0) {
1552 error("%s: buffer error: %s", __func__, ssh_err(r));
1553 goto fail;
1554 }
1555 if (rversion != version) {
1556 error("%s: bad version", __func__);
1557 goto fail;
1558 }
1559 if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
1560 error("%s: buffer error: %s", __func__, ssh_err(r));
1561 fail:
1562 signal(SIGCHLD, osigchld);
1563 sshbuf_free(b);
1523 return -1; 1564 return -1;
1524 } 1565 }
1525 *sigp = buffer_get_string(&b, lenp); 1566 signal(SIGCHLD, osigchld);
1526 buffer_free(&b); 1567 sshbuf_free(b);
1527 1568
1528 return 0; 1569 return 0;
1529} 1570}
@@ -1531,100 +1572,149 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
1531int 1572int
1532userauth_hostbased(Authctxt *authctxt) 1573userauth_hostbased(Authctxt *authctxt)
1533{ 1574{
1534 Key *private = NULL; 1575 struct ssh *ssh = active_state;
1535 Sensitive *sensitive = authctxt->sensitive; 1576 struct sshkey *private = NULL;
1536 Buffer b; 1577 struct sshbuf *b = NULL;
1537 u_char *signature, *blob;
1538 char *chost, *pkalg, *p;
1539 const char *service; 1578 const char *service;
1540 u_int blen, slen; 1579 u_char *sig = NULL, *keyblob = NULL;
1541 int ok, i, found = 0; 1580 char *fp = NULL, *chost = NULL, *lname = NULL;
1542 1581 size_t siglen = 0, keylen = 0;
1543 /* XXX provide some way to allow user to specify key types attempted */ 1582 int i, r, success = 0;
1583
1584 if (authctxt->ktypes == NULL) {
1585 authctxt->oktypes = xstrdup(options.hostbased_key_types);
1586 authctxt->ktypes = authctxt->oktypes;
1587 }
1544 1588
1545 /* check for a useful key */ 1589 /*
1546 for (i = 0; i < sensitive->nkeys; i++) { 1590 * Work through each listed type pattern in HostbasedKeyTypes,
1547 private = sensitive->keys[i]; 1591 * trying each hostkey that matches the type in turn.
1548 if (private && private->type != KEY_RSA1) { 1592 */
1549 found = 1; 1593 for (;;) {
1594 if (authctxt->active_ktype == NULL)
1595 authctxt->active_ktype = strsep(&authctxt->ktypes, ",");
1596 if (authctxt->active_ktype == NULL ||
1597 *authctxt->active_ktype == '\0')
1598 break;
1599 debug3("%s: trying key type %s", __func__,
1600 authctxt->active_ktype);
1601
1602 /* check for a useful key */
1603 private = NULL;
1604 for (i = 0; i < authctxt->sensitive->nkeys; i++) {
1605 if (authctxt->sensitive->keys[i] == NULL ||
1606 authctxt->sensitive->keys[i]->type == KEY_RSA1 ||
1607 authctxt->sensitive->keys[i]->type == KEY_UNSPEC)
1608 continue;
1609 if (match_pattern_list(
1610 sshkey_ssh_name(authctxt->sensitive->keys[i]),
1611 authctxt->active_ktype,
1612 strlen(authctxt->active_ktype), 0) != 1)
1613 continue;
1550 /* we take and free the key */ 1614 /* we take and free the key */
1551 sensitive->keys[i] = NULL; 1615 private = authctxt->sensitive->keys[i];
1616 authctxt->sensitive->keys[i] = NULL;
1552 break; 1617 break;
1553 } 1618 }
1619 /* Found one */
1620 if (private != NULL)
1621 break;
1622 /* No more keys of this type; advance */
1623 authctxt->active_ktype = NULL;
1554 } 1624 }
1555 if (!found) { 1625 if (private == NULL) {
1626 free(authctxt->oktypes);
1627 authctxt->oktypes = authctxt->ktypes = NULL;
1628 authctxt->active_ktype = NULL;
1556 debug("No more client hostkeys for hostbased authentication."); 1629 debug("No more client hostkeys for hostbased authentication.");
1557 return 0; 1630 goto out;
1558 } 1631 }
1559 1632
1560 debug("%s: trying hostkey type %s", __func__, key_type(private)); 1633 if ((fp = sshkey_fingerprint(private, options.fingerprint_hash,
1561 1634 SSH_FP_DEFAULT)) == NULL) {
1562 if (key_to_blob(private, &blob, &blen) == 0) { 1635 error("%s: sshkey_fingerprint failed", __func__);
1563 key_free(private); 1636 goto out;
1564 return 0;
1565 } 1637 }
1638 debug("%s: trying hostkey %s %s",
1639 __func__, sshkey_ssh_name(private), fp);
1566 1640
1567 /* figure out a name for the client host */ 1641 /* figure out a name for the client host */
1568 p = get_local_name(packet_get_connection_in()); 1642 if ((lname = get_local_name(packet_get_connection_in())) == NULL) {
1569 if (p == NULL) { 1643 error("%s: cannot get local ipaddr/name", __func__);
1570 error("userauth_hostbased: cannot get local ipaddr/name"); 1644 goto out;
1571 key_free(private);
1572 free(blob);
1573 return 0;
1574 } 1645 }
1575 xasprintf(&chost, "%s.", p); 1646
1576 debug2("userauth_hostbased: chost %s", chost); 1647 /* XXX sshbuf_put_stringf? */
1577 free(p); 1648 xasprintf(&chost, "%s.", lname);
1649 debug2("%s: chost %s", __func__, chost);
1578 1650
1579 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : 1651 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
1580 authctxt->service; 1652 authctxt->service;
1581 pkalg = xstrdup(key_ssh_name(private)); 1653
1582 buffer_init(&b);
1583 /* construct data */ 1654 /* construct data */
1584 buffer_put_string(&b, session_id2, session_id2_len); 1655 if ((b = sshbuf_new()) == NULL) {
1585 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 1656 error("%s: sshbuf_new failed", __func__);
1586 buffer_put_cstring(&b, authctxt->server_user); 1657 goto out;
1587 buffer_put_cstring(&b, service); 1658 }
1588 buffer_put_cstring(&b, authctxt->method->name); 1659 if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) {
1589 buffer_put_cstring(&b, pkalg); 1660 error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
1590 buffer_put_string(&b, blob, blen); 1661 goto out;
1591 buffer_put_cstring(&b, chost); 1662 }
1592 buffer_put_cstring(&b, authctxt->local_user); 1663 if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
1664 (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1665 (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
1666 (r = sshbuf_put_cstring(b, service)) != 0 ||
1667 (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
1668 (r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 ||
1669 (r = sshbuf_put_string(b, keyblob, keylen)) != 0 ||
1670 (r = sshbuf_put_cstring(b, chost)) != 0 ||
1671 (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) {
1672 error("%s: buffer error: %s", __func__, ssh_err(r));
1673 goto out;
1674 }
1675
1593#ifdef DEBUG_PK 1676#ifdef DEBUG_PK
1594 buffer_dump(&b); 1677 sshbuf_dump(b, stderr);
1595#endif 1678#endif
1596 if (sensitive->external_keysign) 1679 if (authctxt->sensitive->external_keysign)
1597 ok = ssh_keysign(private, &signature, &slen, 1680 r = ssh_keysign(private, &sig, &siglen,
1598 buffer_ptr(&b), buffer_len(&b)); 1681 sshbuf_ptr(b), sshbuf_len(b));
1599 else 1682 else if ((r = sshkey_sign(private, &sig, &siglen,
1600 ok = key_sign(private, &signature, &slen, 1683 sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0)
1601 buffer_ptr(&b), buffer_len(&b)); 1684 debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
1602 key_free(private); 1685 if (r != 0) {
1603 buffer_free(&b); 1686 error("sign using hostkey %s %s failed",
1604 if (ok != 0) { 1687 sshkey_ssh_name(private), fp);
1605 error("key_sign failed"); 1688 goto out;
1606 free(chost);
1607 free(pkalg);
1608 free(blob);
1609 return 0;
1610 } 1689 }
1611 packet_start(SSH2_MSG_USERAUTH_REQUEST); 1690 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1612 packet_put_cstring(authctxt->server_user); 1691 (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
1613 packet_put_cstring(authctxt->service); 1692 (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
1614 packet_put_cstring(authctxt->method->name); 1693 (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
1615 packet_put_cstring(pkalg); 1694 (r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 ||
1616 packet_put_string(blob, blen); 1695 (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 ||
1617 packet_put_cstring(chost); 1696 (r = sshpkt_put_cstring(ssh, chost)) != 0 ||
1618 packet_put_cstring(authctxt->local_user); 1697 (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 ||
1619 packet_put_string(signature, slen); 1698 (r = sshpkt_put_string(ssh, sig, siglen)) != 0 ||
1620 explicit_bzero(signature, slen); 1699 (r = sshpkt_send(ssh)) != 0) {
1621 free(signature); 1700 error("%s: packet error: %s", __func__, ssh_err(r));
1701 goto out;
1702 }
1703 success = 1;
1704
1705 out:
1706 if (sig != NULL) {
1707 explicit_bzero(sig, siglen);
1708 free(sig);
1709 }
1710 free(keyblob);
1711 free(lname);
1712 free(fp);
1622 free(chost); 1713 free(chost);
1623 free(pkalg); 1714 sshkey_free(private);
1624 free(blob); 1715 sshbuf_free(b);
1625 1716
1626 packet_send(); 1717 return success;
1627 return 1;
1628} 1718}
1629 1719
1630/* find auth method */ 1720/* find auth method */