|
Lines 267-272
struct cauthctxt {
Link Here
|
| 267 |
int agent_fd; |
267 |
int agent_fd; |
| 268 |
/* hostbased */ |
268 |
/* hostbased */ |
| 269 |
Sensitive *sensitive; |
269 |
Sensitive *sensitive; |
|
|
270 |
char *oktypes, *ktypes; |
| 271 |
const char *active_ktype; |
| 270 |
/* kbd-interactive */ |
272 |
/* kbd-interactive */ |
| 271 |
int info_req_seen; |
273 |
int info_req_seen; |
| 272 |
/* generic */ |
274 |
/* generic */ |
|
Lines 395-400
ssh_userauth2(const char *local_user, const char *server_user, char *host,
Link Here
|
| 395 |
authctxt.authlist = NULL; |
397 |
authctxt.authlist = NULL; |
| 396 |
authctxt.methoddata = NULL; |
398 |
authctxt.methoddata = NULL; |
| 397 |
authctxt.sensitive = sensitive; |
399 |
authctxt.sensitive = sensitive; |
|
|
400 |
authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; |
| 398 |
authctxt.info_req_seen = 0; |
401 |
authctxt.info_req_seen = 0; |
| 399 |
authctxt.agent_fd = -1; |
402 |
authctxt.agent_fd = -1; |
| 400 |
if (authctxt.method == NULL) |
403 |
if (authctxt.method == NULL) |
|
Lines 1446-1523
input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
Link Here
|
| 1446 |
} |
1449 |
} |
| 1447 |
|
1450 |
|
| 1448 |
static int |
1451 |
static int |
| 1449 |
ssh_keysign(Key *key, u_char **sigp, u_int *lenp, |
1452 |
ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, |
| 1450 |
u_char *data, u_int datalen) |
1453 |
const u_char *data, size_t datalen) |
| 1451 |
{ |
1454 |
{ |
| 1452 |
Buffer b; |
1455 |
struct sshbuf *b; |
| 1453 |
struct stat st; |
1456 |
struct stat st; |
| 1454 |
pid_t pid; |
1457 |
pid_t pid; |
| 1455 |
int to[2], from[2], status, version = 2; |
1458 |
int i, r, to[2], from[2], status, sock = packet_get_connection_in(); |
|
|
1459 |
u_char rversion = 0, version = 2; |
| 1460 |
void (*osigchld)(int); |
| 1456 |
|
1461 |
|
| 1457 |
debug2("ssh_keysign called"); |
1462 |
*sigp = NULL; |
|
|
1463 |
*lenp = 0; |
| 1458 |
|
1464 |
|
| 1459 |
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { |
1465 |
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { |
| 1460 |
error("ssh_keysign: not installed: %s", strerror(errno)); |
1466 |
error("%s: not installed: %s", __func__, strerror(errno)); |
|
|
1467 |
return -1; |
| 1468 |
} |
| 1469 |
if (fflush(stdout) != 0) { |
| 1470 |
error("%s: fflush: %s", __func__, strerror(errno)); |
| 1461 |
return -1; |
1471 |
return -1; |
| 1462 |
} |
1472 |
} |
| 1463 |
if (fflush(stdout) != 0) |
|
|
| 1464 |
error("ssh_keysign: fflush: %s", strerror(errno)); |
| 1465 |
if (pipe(to) < 0) { |
1473 |
if (pipe(to) < 0) { |
| 1466 |
error("ssh_keysign: pipe: %s", strerror(errno)); |
1474 |
error("%s: pipe: %s", __func__, strerror(errno)); |
| 1467 |
return -1; |
1475 |
return -1; |
| 1468 |
} |
1476 |
} |
| 1469 |
if (pipe(from) < 0) { |
1477 |
if (pipe(from) < 0) { |
| 1470 |
error("ssh_keysign: pipe: %s", strerror(errno)); |
1478 |
error("%s: pipe: %s", __func__, strerror(errno)); |
| 1471 |
return -1; |
1479 |
return -1; |
| 1472 |
} |
1480 |
} |
| 1473 |
if ((pid = fork()) < 0) { |
1481 |
if ((pid = fork()) < 0) { |
| 1474 |
error("ssh_keysign: fork: %s", strerror(errno)); |
1482 |
error("%s: fork: %s", __func__, strerror(errno)); |
| 1475 |
return -1; |
1483 |
return -1; |
| 1476 |
} |
1484 |
} |
|
|
1485 |
osigchld = signal(SIGCHLD, SIG_DFL); |
| 1477 |
if (pid == 0) { |
1486 |
if (pid == 0) { |
| 1478 |
/* keep the socket on exec */ |
1487 |
/* keep the socket on exec */ |
| 1479 |
fcntl(packet_get_connection_in(), F_SETFD, 0); |
1488 |
fcntl(sock, F_SETFD, 0); |
| 1480 |
permanently_drop_suid(getuid()); |
1489 |
permanently_drop_suid(getuid()); |
| 1481 |
close(from[0]); |
1490 |
close(from[0]); |
| 1482 |
if (dup2(from[1], STDOUT_FILENO) < 0) |
1491 |
if (dup2(from[1], STDOUT_FILENO) < 0) |
| 1483 |
fatal("ssh_keysign: dup2: %s", strerror(errno)); |
1492 |
fatal("%s: dup2: %s", __func__, strerror(errno)); |
| 1484 |
close(to[1]); |
1493 |
close(to[1]); |
| 1485 |
if (dup2(to[0], STDIN_FILENO) < 0) |
1494 |
if (dup2(to[0], STDIN_FILENO) < 0) |
| 1486 |
fatal("ssh_keysign: dup2: %s", strerror(errno)); |
1495 |
fatal("%s: dup2: %s", __func__, strerror(errno)); |
| 1487 |
close(from[1]); |
1496 |
close(from[1]); |
| 1488 |
close(to[0]); |
1497 |
close(to[0]); |
|
|
1498 |
/* Close everything but stdio and the socket */ |
| 1499 |
for (i = STDERR_FILENO + 1; i < sock; i++) |
| 1500 |
close(i); |
| 1501 |
closefrom(sock + 1); |
| 1502 |
debug3("%s: [child] pid=%ld, exec %s", |
| 1503 |
__func__, (long)getpid(), _PATH_SSH_KEY_SIGN); |
| 1489 |
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); |
1504 |
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); |
| 1490 |
fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, |
1505 |
fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN, |
| 1491 |
strerror(errno)); |
1506 |
strerror(errno)); |
| 1492 |
} |
1507 |
} |
| 1493 |
close(from[1]); |
1508 |
close(from[1]); |
| 1494 |
close(to[0]); |
1509 |
close(to[0]); |
| 1495 |
|
1510 |
|
| 1496 |
buffer_init(&b); |
1511 |
if ((b = sshbuf_new()) == NULL) |
| 1497 |
buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ |
1512 |
fatal("%s: sshbuf_new failed", __func__); |
| 1498 |
buffer_put_string(&b, data, datalen); |
1513 |
/* send # of sock, data to be signed */ |
| 1499 |
if (ssh_msg_send(to[1], version, &b) == -1) |
1514 |
if ((r = sshbuf_put_u32(b, sock) != 0) || |
| 1500 |
fatal("ssh_keysign: couldn't send request"); |
1515 |
(r = sshbuf_put_string(b, data, datalen)) != 0) |
| 1501 |
|
1516 |
fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
| 1502 |
if (ssh_msg_recv(from[0], &b) < 0) { |
1517 |
if (ssh_msg_send(to[1], version, b) == -1) |
| 1503 |
error("ssh_keysign: no reply"); |
1518 |
fatal("%s: couldn't send request", __func__); |
| 1504 |
buffer_free(&b); |
1519 |
sshbuf_reset(b); |
| 1505 |
return -1; |
1520 |
r = ssh_msg_recv(from[0], b); |
| 1506 |
} |
|
|
| 1507 |
close(from[0]); |
1521 |
close(from[0]); |
| 1508 |
close(to[1]); |
1522 |
close(to[1]); |
|
|
1523 |
if (r < 0) { |
| 1524 |
error("%s: no reply", __func__); |
| 1525 |
goto fail; |
| 1526 |
} |
| 1509 |
|
1527 |
|
| 1510 |
while (waitpid(pid, &status, 0) < 0) |
1528 |
errno = 0; |
| 1511 |
if (errno != EINTR) |
1529 |
while (waitpid(pid, &status, 0) < 0) { |
| 1512 |
break; |
1530 |
if (errno != EINTR) { |
| 1513 |
|
1531 |
error("%s: waitpid %ld: %s", |
| 1514 |
if (buffer_get_char(&b) != version) { |
1532 |
__func__, (long)pid, strerror(errno)); |
| 1515 |
error("ssh_keysign: bad version"); |
1533 |
goto fail; |
| 1516 |
buffer_free(&b); |
1534 |
} |
|
|
1535 |
} |
| 1536 |
if (!WIFEXITED(status)) { |
| 1537 |
error("%s: exited abnormally", __func__); |
| 1538 |
goto fail; |
| 1539 |
} |
| 1540 |
if (WEXITSTATUS(status) != 0) { |
| 1541 |
error("%s: exited with status %d", |
| 1542 |
__func__, WEXITSTATUS(status)); |
| 1543 |
goto fail; |
| 1544 |
} |
| 1545 |
if ((r = sshbuf_get_u8(b, &rversion)) != 0) { |
| 1546 |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
| 1547 |
goto fail; |
| 1548 |
} |
| 1549 |
if (rversion != version) { |
| 1550 |
error("%s: bad version", __func__); |
| 1551 |
goto fail; |
| 1552 |
} |
| 1553 |
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { |
| 1554 |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
| 1555 |
fail: |
| 1556 |
signal(SIGCHLD, osigchld); |
| 1557 |
sshbuf_free(b); |
| 1517 |
return -1; |
1558 |
return -1; |
| 1518 |
} |
1559 |
} |
| 1519 |
*sigp = buffer_get_string(&b, lenp); |
1560 |
signal(SIGCHLD, osigchld); |
| 1520 |
buffer_free(&b); |
1561 |
sshbuf_free(b); |
| 1521 |
|
1562 |
|
| 1522 |
return 0; |
1563 |
return 0; |
| 1523 |
} |
1564 |
} |
|
Lines 1525-1624
ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
Link Here
|
| 1525 |
int |
1566 |
int |
| 1526 |
userauth_hostbased(Authctxt *authctxt) |
1567 |
userauth_hostbased(Authctxt *authctxt) |
| 1527 |
{ |
1568 |
{ |
| 1528 |
Key *private = NULL; |
1569 |
struct ssh *ssh = active_state; |
| 1529 |
Sensitive *sensitive = authctxt->sensitive; |
1570 |
struct sshkey *private = NULL; |
| 1530 |
Buffer b; |
1571 |
struct sshbuf *b = NULL; |
| 1531 |
u_char *signature, *blob; |
|
|
| 1532 |
char *chost, *pkalg, *p; |
| 1533 |
const char *service; |
1572 |
const char *service; |
| 1534 |
u_int blen, slen; |
1573 |
u_char *sig = NULL, *keyblob = NULL; |
| 1535 |
int ok, i, found = 0; |
1574 |
char *fp = NULL, *chost = NULL, *lname = NULL; |
|
|
1575 |
size_t siglen = 0, keylen = 0; |
| 1576 |
int i, r, success = 0; |
| 1536 |
|
1577 |
|
| 1537 |
/* XXX provide some way to allow user to specify key types attempted */ |
1578 |
if (authctxt->ktypes == NULL) { |
|
|
1579 |
authctxt->oktypes = xstrdup(options.hostbased_key_types); |
| 1580 |
authctxt->ktypes = authctxt->oktypes; |
| 1581 |
} |
| 1538 |
|
1582 |
|
| 1539 |
/* check for a useful key */ |
1583 |
/* |
| 1540 |
for (i = 0; i < sensitive->nkeys; i++) { |
1584 |
* Work through each listed type pattern in HostbasedKeyTypes, |
| 1541 |
private = sensitive->keys[i]; |
1585 |
* trying each hostkey that matches the type in turn. |
| 1542 |
if (private && private->type != KEY_RSA1) { |
1586 |
*/ |
| 1543 |
found = 1; |
1587 |
for (;;) { |
|
|
1588 |
if (authctxt->active_ktype == NULL) |
| 1589 |
authctxt->active_ktype = strsep(&authctxt->ktypes, ","); |
| 1590 |
if (authctxt->active_ktype == NULL || |
| 1591 |
*authctxt->active_ktype == '\0') |
| 1592 |
break; |
| 1593 |
debug3("%s: trying key type %s", __func__, |
| 1594 |
authctxt->active_ktype); |
| 1595 |
|
| 1596 |
/* check for a useful key */ |
| 1597 |
private = NULL; |
| 1598 |
for (i = 0; i < authctxt->sensitive->nkeys; i++) { |
| 1599 |
if (authctxt->sensitive->keys[i] == NULL || |
| 1600 |
authctxt->sensitive->keys[i]->type == KEY_RSA1 || |
| 1601 |
authctxt->sensitive->keys[i]->type == KEY_UNSPEC) |
| 1602 |
continue; |
| 1603 |
if (match_pattern_list( |
| 1604 |
sshkey_ssh_name(authctxt->sensitive->keys[i]), |
| 1605 |
authctxt->active_ktype, |
| 1606 |
strlen(authctxt->active_ktype), 0) != 1) |
| 1607 |
continue; |
| 1544 |
/* we take and free the key */ |
1608 |
/* we take and free the key */ |
| 1545 |
sensitive->keys[i] = NULL; |
1609 |
private = authctxt->sensitive->keys[i]; |
|
|
1610 |
authctxt->sensitive->keys[i] = NULL; |
| 1546 |
break; |
1611 |
break; |
| 1547 |
} |
1612 |
} |
|
|
1613 |
/* Found one */ |
| 1614 |
if (private != NULL) |
| 1615 |
break; |
| 1616 |
/* No more keys of this type; advance */ |
| 1617 |
authctxt->active_ktype = NULL; |
| 1548 |
} |
1618 |
} |
| 1549 |
if (!found) { |
1619 |
if (private == NULL) { |
|
|
1620 |
free(authctxt->oktypes); |
| 1621 |
authctxt->oktypes = authctxt->ktypes = NULL; |
| 1622 |
authctxt->active_ktype = NULL; |
| 1550 |
debug("No more client hostkeys for hostbased authentication."); |
1623 |
debug("No more client hostkeys for hostbased authentication."); |
| 1551 |
return 0; |
1624 |
goto out; |
| 1552 |
} |
1625 |
} |
| 1553 |
|
1626 |
|
| 1554 |
debug("%s: trying hostkey type %s", __func__, key_type(private)); |
1627 |
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, |
| 1555 |
|
1628 |
SSH_FP_DEFAULT)) == NULL) { |
| 1556 |
if (key_to_blob(private, &blob, &blen) == 0) { |
1629 |
error("%s: sshkey_fingerprint failed", __func__); |
| 1557 |
key_free(private); |
1630 |
goto out; |
| 1558 |
return 0; |
|
|
| 1559 |
} |
1631 |
} |
|
|
1632 |
debug("%s: trying hostkey %s %s", |
| 1633 |
__func__, sshkey_ssh_name(private), fp); |
| 1560 |
|
1634 |
|
| 1561 |
/* figure out a name for the client host */ |
1635 |
/* figure out a name for the client host */ |
| 1562 |
p = get_local_name(packet_get_connection_in()); |
1636 |
if ((lname = get_local_name(packet_get_connection_in())) == NULL) { |
| 1563 |
if (p == NULL) { |
1637 |
error("%s: cannot get local ipaddr/name", __func__); |
| 1564 |
error("userauth_hostbased: cannot get local ipaddr/name"); |
1638 |
goto out; |
| 1565 |
key_free(private); |
|
|
| 1566 |
free(blob); |
| 1567 |
return 0; |
| 1568 |
} |
1639 |
} |
| 1569 |
xasprintf(&chost, "%s.", p); |
1640 |
|
| 1570 |
debug2("userauth_hostbased: chost %s", chost); |
1641 |
/* XXX sshbuf_put_stringf? */ |
| 1571 |
free(p); |
1642 |
xasprintf(&chost, "%s.", lname); |
|
|
1643 |
debug2("%s: chost %s", __func__, chost); |
| 1572 |
|
1644 |
|
| 1573 |
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : |
1645 |
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : |
| 1574 |
authctxt->service; |
1646 |
authctxt->service; |
| 1575 |
pkalg = xstrdup(key_ssh_name(private)); |
1647 |
|
| 1576 |
buffer_init(&b); |
|
|
| 1577 |
/* construct data */ |
1648 |
/* construct data */ |
| 1578 |
buffer_put_string(&b, session_id2, session_id2_len); |
1649 |
if ((b = sshbuf_new()) == NULL) { |
| 1579 |
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); |
1650 |
error("%s: sshbuf_new failed", __func__); |
| 1580 |
buffer_put_cstring(&b, authctxt->server_user); |
1651 |
goto out; |
| 1581 |
buffer_put_cstring(&b, service); |
1652 |
} |
| 1582 |
buffer_put_cstring(&b, authctxt->method->name); |
1653 |
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { |
| 1583 |
buffer_put_cstring(&b, pkalg); |
1654 |
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); |
| 1584 |
buffer_put_string(&b, blob, blen); |
1655 |
goto out; |
| 1585 |
buffer_put_cstring(&b, chost); |
1656 |
} |
| 1586 |
buffer_put_cstring(&b, authctxt->local_user); |
1657 |
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || |
|
|
1658 |
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
| 1659 |
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || |
| 1660 |
(r = sshbuf_put_cstring(b, service)) != 0 || |
| 1661 |
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || |
| 1662 |
(r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 || |
| 1663 |
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 || |
| 1664 |
(r = sshbuf_put_cstring(b, chost)) != 0 || |
| 1665 |
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { |
| 1666 |
error("%s: buffer error: %s", __func__, ssh_err(r)); |
| 1667 |
goto out; |
| 1668 |
} |
| 1669 |
|
| 1587 |
#ifdef DEBUG_PK |
1670 |
#ifdef DEBUG_PK |
| 1588 |
buffer_dump(&b); |
1671 |
sshbuf_dump(b, stderr); |
| 1589 |
#endif |
1672 |
#endif |
| 1590 |
if (sensitive->external_keysign) |
1673 |
if (authctxt->sensitive->external_keysign) |
| 1591 |
ok = ssh_keysign(private, &signature, &slen, |
1674 |
r = ssh_keysign(private, &sig, &siglen, |
| 1592 |
buffer_ptr(&b), buffer_len(&b)); |
1675 |
sshbuf_ptr(b), sshbuf_len(b)); |
| 1593 |
else |
1676 |
else if ((r = sshkey_sign(private, &sig, &siglen, |
| 1594 |
ok = key_sign(private, &signature, &slen, |
1677 |
sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0) |
| 1595 |
buffer_ptr(&b), buffer_len(&b)); |
1678 |
debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
| 1596 |
key_free(private); |
1679 |
if (r != 0) { |
| 1597 |
buffer_free(&b); |
1680 |
error("sign using hostkey %s %s failed", |
| 1598 |
if (ok != 0) { |
1681 |
sshkey_ssh_name(private), fp); |
| 1599 |
error("key_sign failed"); |
1682 |
goto out; |
| 1600 |
free(chost); |
|
|
| 1601 |
free(pkalg); |
| 1602 |
free(blob); |
| 1603 |
return 0; |
| 1604 |
} |
1683 |
} |
| 1605 |
packet_start(SSH2_MSG_USERAUTH_REQUEST); |
1684 |
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
| 1606 |
packet_put_cstring(authctxt->server_user); |
1685 |
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
| 1607 |
packet_put_cstring(authctxt->service); |
1686 |
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
| 1608 |
packet_put_cstring(authctxt->method->name); |
1687 |
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
| 1609 |
packet_put_cstring(pkalg); |
1688 |
(r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 || |
| 1610 |
packet_put_string(blob, blen); |
1689 |
(r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || |
| 1611 |
packet_put_cstring(chost); |
1690 |
(r = sshpkt_put_cstring(ssh, chost)) != 0 || |
| 1612 |
packet_put_cstring(authctxt->local_user); |
1691 |
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || |
| 1613 |
packet_put_string(signature, slen); |
1692 |
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 || |
| 1614 |
explicit_bzero(signature, slen); |
1693 |
(r = sshpkt_send(ssh)) != 0) { |
| 1615 |
free(signature); |
1694 |
error("%s: packet error: %s", __func__, ssh_err(r)); |
|
|
1695 |
goto out; |
| 1696 |
} |
| 1697 |
success = 1; |
| 1698 |
|
| 1699 |
out: |
| 1700 |
if (sig != NULL) { |
| 1701 |
explicit_bzero(sig, siglen); |
| 1702 |
free(sig); |
| 1703 |
} |
| 1704 |
free(keyblob); |
| 1705 |
free(lname); |
| 1706 |
free(fp); |
| 1616 |
free(chost); |
1707 |
free(chost); |
| 1617 |
free(pkalg); |
1708 |
sshkey_free(private); |
| 1618 |
free(blob); |
1709 |
sshbuf_free(b); |
| 1619 |
|
1710 |
|
| 1620 |
packet_send(); |
1711 |
return success; |
| 1621 |
return 1; |
|
|
| 1622 |
} |
1712 |
} |
| 1623 |
|
1713 |
|
| 1624 |
/* find auth method */ |
1714 |
/* find auth method */ |