diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 103 |
1 files changed, 68 insertions, 35 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -323,6 +323,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
323 | partial = 0; | 323 | partial = 0; |
324 | auth_method = "unknown"; | 324 | auth_method = "unknown"; |
325 | auth_submethod = NULL; | 325 | auth_submethod = NULL; |
326 | auth2_authctxt_reset_info(authctxt); | ||
327 | |||
326 | authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); | 328 | authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); |
327 | 329 | ||
328 | /* Special handling for multiple required authentications */ | 330 | /* Special handling for multiple required authentications */ |
@@ -362,6 +364,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
362 | auth_method, auth_submethod); | 364 | auth_method, auth_submethod); |
363 | if (!partial && !authenticated) | 365 | if (!partial && !authenticated) |
364 | authctxt->failures++; | 366 | authctxt->failures++; |
367 | if (authenticated || partial) { | ||
368 | auth2_update_session_info(authctxt, | ||
369 | auth_method, auth_submethod); | ||
370 | } | ||
365 | } | 371 | } |
366 | } | 372 | } |
367 | 373 | ||
@@ -773,10 +779,12 @@ mm_answer_pwnamallow(int sock, Buffer *m) | |||
773 | for (i = 0; i < options.nx; i++) \ | 779 | for (i = 0; i < options.nx; i++) \ |
774 | buffer_put_cstring(m, options.x[i]); \ | 780 | buffer_put_cstring(m, options.x[i]); \ |
775 | } while (0) | 781 | } while (0) |
782 | #define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx) | ||
776 | /* See comment in servconf.h */ | 783 | /* See comment in servconf.h */ |
777 | COPY_MATCH_STRING_OPTS(); | 784 | COPY_MATCH_STRING_OPTS(); |
778 | #undef M_CP_STROPT | 785 | #undef M_CP_STROPT |
779 | #undef M_CP_STRARRAYOPT | 786 | #undef M_CP_STRARRAYOPT |
787 | #undef M_CP_STRARRAYOPT_ALLOC | ||
780 | 788 | ||
781 | /* Create valid auth method lists */ | 789 | /* Create valid auth method lists */ |
782 | if (auth2_setup_methods_lists(authctxt) != 0) { | 790 | if (auth2_setup_methods_lists(authctxt) != 0) { |
@@ -1162,7 +1170,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) | |||
1162 | int | 1170 | int |
1163 | mm_answer_keyallowed(int sock, Buffer *m) | 1171 | mm_answer_keyallowed(int sock, Buffer *m) |
1164 | { | 1172 | { |
1165 | Key *key; | 1173 | struct sshkey *key; |
1166 | char *cuser, *chost; | 1174 | char *cuser, *chost; |
1167 | u_char *blob; | 1175 | u_char *blob; |
1168 | u_int bloblen, pubkey_auth_attempt; | 1176 | u_int bloblen, pubkey_auth_attempt; |
@@ -1190,12 +1198,11 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1190 | switch (type) { | 1198 | switch (type) { |
1191 | case MM_USERKEY: | 1199 | case MM_USERKEY: |
1192 | allowed = options.pubkey_authentication && | 1200 | allowed = options.pubkey_authentication && |
1193 | !auth2_userkey_already_used(authctxt, key) && | 1201 | !auth2_key_already_used(authctxt, key) && |
1194 | match_pattern_list(sshkey_ssh_name(key), | 1202 | match_pattern_list(sshkey_ssh_name(key), |
1195 | options.pubkey_key_types, 0) == 1 && | 1203 | options.pubkey_key_types, 0) == 1 && |
1196 | user_key_allowed(authctxt->pw, key, | 1204 | user_key_allowed(authctxt->pw, key, |
1197 | pubkey_auth_attempt); | 1205 | pubkey_auth_attempt); |
1198 | pubkey_auth_info(authctxt, key, NULL); | ||
1199 | auth_method = "publickey"; | 1206 | auth_method = "publickey"; |
1200 | if (options.pubkey_authentication && | 1207 | if (options.pubkey_authentication && |
1201 | (!pubkey_auth_attempt || allowed != 1)) | 1208 | (!pubkey_auth_attempt || allowed != 1)) |
@@ -1203,11 +1210,12 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1203 | break; | 1210 | break; |
1204 | case MM_HOSTKEY: | 1211 | case MM_HOSTKEY: |
1205 | allowed = options.hostbased_authentication && | 1212 | allowed = options.hostbased_authentication && |
1213 | !auth2_key_already_used(authctxt, key) && | ||
1206 | match_pattern_list(sshkey_ssh_name(key), | 1214 | match_pattern_list(sshkey_ssh_name(key), |
1207 | options.hostbased_key_types, 0) == 1 && | 1215 | options.hostbased_key_types, 0) == 1 && |
1208 | hostbased_key_allowed(authctxt->pw, | 1216 | hostbased_key_allowed(authctxt->pw, |
1209 | cuser, chost, key); | 1217 | cuser, chost, key); |
1210 | pubkey_auth_info(authctxt, key, | 1218 | auth2_record_info(authctxt, |
1211 | "client user \"%.100s\", client host \"%.100s\"", | 1219 | "client user \"%.100s\", client host \"%.100s\"", |
1212 | cuser, chost); | 1220 | cuser, chost); |
1213 | auth_method = "hostbased"; | 1221 | auth_method = "hostbased"; |
@@ -1218,11 +1226,10 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1218 | } | 1226 | } |
1219 | } | 1227 | } |
1220 | 1228 | ||
1221 | debug3("%s: key %p is %s", | 1229 | debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); |
1222 | __func__, key, allowed ? "allowed" : "not allowed"); | ||
1223 | 1230 | ||
1224 | if (key != NULL) | 1231 | auth2_record_key(authctxt, 0, key); |
1225 | key_free(key); | 1232 | sshkey_free(key); |
1226 | 1233 | ||
1227 | /* clear temporarily storage (used by verify) */ | 1234 | /* clear temporarily storage (used by verify) */ |
1228 | monitor_reset_key_state(); | 1235 | monitor_reset_key_state(); |
@@ -1373,33 +1380,35 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, | |||
1373 | } | 1380 | } |
1374 | 1381 | ||
1375 | int | 1382 | int |
1376 | mm_answer_keyverify(int sock, Buffer *m) | 1383 | mm_answer_keyverify(int sock, struct sshbuf *m) |
1377 | { | 1384 | { |
1378 | Key *key; | 1385 | struct sshkey *key; |
1379 | u_char *signature, *data, *blob; | 1386 | u_char *signature, *data, *blob; |
1380 | u_int signaturelen, datalen, bloblen; | 1387 | size_t signaturelen, datalen, bloblen; |
1381 | int verified = 0; | 1388 | int r, ret, valid_data = 0, encoded_ret; |
1382 | int valid_data = 0; | ||
1383 | 1389 | ||
1384 | blob = buffer_get_string(m, &bloblen); | 1390 | if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || |
1385 | signature = buffer_get_string(m, &signaturelen); | 1391 | (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || |
1386 | data = buffer_get_string(m, &datalen); | 1392 | (r = sshbuf_get_string(m, &data, &datalen)) != 0) |
1393 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1387 | 1394 | ||
1388 | if (hostbased_cuser == NULL || hostbased_chost == NULL || | 1395 | if (hostbased_cuser == NULL || hostbased_chost == NULL || |
1389 | !monitor_allowed_key(blob, bloblen)) | 1396 | !monitor_allowed_key(blob, bloblen)) |
1390 | fatal("%s: bad key, not previously allowed", __func__); | 1397 | fatal("%s: bad key, not previously allowed", __func__); |
1391 | 1398 | ||
1392 | key = key_from_blob(blob, bloblen); | 1399 | /* XXX use sshkey_froms here; need to change key_blob, etc. */ |
1393 | if (key == NULL) | 1400 | if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) |
1394 | fatal("%s: bad public key blob", __func__); | 1401 | fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); |
1395 | 1402 | ||
1396 | switch (key_blobtype) { | 1403 | switch (key_blobtype) { |
1397 | case MM_USERKEY: | 1404 | case MM_USERKEY: |
1398 | valid_data = monitor_valid_userblob(data, datalen); | 1405 | valid_data = monitor_valid_userblob(data, datalen); |
1406 | auth_method = "publickey"; | ||
1399 | break; | 1407 | break; |
1400 | case MM_HOSTKEY: | 1408 | case MM_HOSTKEY: |
1401 | valid_data = monitor_valid_hostbasedblob(data, datalen, | 1409 | valid_data = monitor_valid_hostbasedblob(data, datalen, |
1402 | hostbased_cuser, hostbased_chost); | 1410 | hostbased_cuser, hostbased_chost); |
1411 | auth_method = "hostbased"; | ||
1403 | break; | 1412 | break; |
1404 | default: | 1413 | default: |
1405 | valid_data = 0; | 1414 | valid_data = 0; |
@@ -1408,29 +1417,28 @@ mm_answer_keyverify(int sock, Buffer *m) | |||
1408 | if (!valid_data) | 1417 | if (!valid_data) |
1409 | fatal("%s: bad signature data blob", __func__); | 1418 | fatal("%s: bad signature data blob", __func__); |
1410 | 1419 | ||
1411 | verified = key_verify(key, signature, signaturelen, data, datalen); | 1420 | ret = sshkey_verify(key, signature, signaturelen, data, datalen, |
1412 | debug3("%s: key %p signature %s", | 1421 | active_state->compat); |
1413 | __func__, key, (verified == 1) ? "verified" : "unverified"); | 1422 | debug3("%s: %s %p signature %s", __func__, auth_method, key, |
1414 | 1423 | (ret == 0) ? "verified" : "unverified"); | |
1415 | /* If auth was successful then record key to ensure it isn't reused */ | 1424 | auth2_record_key(authctxt, ret == 0, key); |
1416 | if (verified == 1 && key_blobtype == MM_USERKEY) | ||
1417 | auth2_record_userkey(authctxt, key); | ||
1418 | else | ||
1419 | key_free(key); | ||
1420 | 1425 | ||
1421 | free(blob); | 1426 | free(blob); |
1422 | free(signature); | 1427 | free(signature); |
1423 | free(data); | 1428 | free(data); |
1424 | 1429 | ||
1425 | auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; | ||
1426 | |||
1427 | monitor_reset_key_state(); | 1430 | monitor_reset_key_state(); |
1428 | 1431 | ||
1429 | buffer_clear(m); | 1432 | sshkey_free(key); |
1430 | buffer_put_int(m, verified); | 1433 | sshbuf_reset(m); |
1434 | |||
1435 | /* encode ret != 0 as positive integer, since we're sending u32 */ | ||
1436 | encoded_ret = (ret != 0); | ||
1437 | if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) | ||
1438 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1431 | mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); | 1439 | mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
1432 | 1440 | ||
1433 | return (verified == 1); | 1441 | return ret == 0; |
1434 | } | 1442 | } |
1435 | 1443 | ||
1436 | static void | 1444 | static void |
@@ -1556,13 +1564,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m) | |||
1556 | int | 1564 | int |
1557 | mm_answer_term(int sock, Buffer *req) | 1565 | mm_answer_term(int sock, Buffer *req) |
1558 | { | 1566 | { |
1567 | struct ssh *ssh = active_state; /* XXX */ | ||
1559 | extern struct monitor *pmonitor; | 1568 | extern struct monitor *pmonitor; |
1560 | int res, status; | 1569 | int res, status; |
1561 | 1570 | ||
1562 | debug3("%s: tearing down sessions", __func__); | 1571 | debug3("%s: tearing down sessions", __func__); |
1563 | 1572 | ||
1564 | /* The child is terminating */ | 1573 | /* The child is terminating */ |
1565 | session_destroy_all(&mm_session_close); | 1574 | session_destroy_all(ssh, &mm_session_close); |
1566 | 1575 | ||
1567 | #ifdef USE_PAM | 1576 | #ifdef USE_PAM |
1568 | if (options.use_pam) | 1577 | if (options.use_pam) |
@@ -1622,6 +1631,17 @@ mm_answer_audit_command(int socket, Buffer *m) | |||
1622 | #endif /* SSH_AUDIT_EVENTS */ | 1631 | #endif /* SSH_AUDIT_EVENTS */ |
1623 | 1632 | ||
1624 | void | 1633 | void |
1634 | monitor_clear_keystate(struct monitor *pmonitor) | ||
1635 | { | ||
1636 | struct ssh *ssh = active_state; /* XXX */ | ||
1637 | |||
1638 | ssh_clear_newkeys(ssh, MODE_IN); | ||
1639 | ssh_clear_newkeys(ssh, MODE_OUT); | ||
1640 | sshbuf_free(child_state); | ||
1641 | child_state = NULL; | ||
1642 | } | ||
1643 | |||
1644 | void | ||
1625 | monitor_apply_keystate(struct monitor *pmonitor) | 1645 | monitor_apply_keystate(struct monitor *pmonitor) |
1626 | { | 1646 | { |
1627 | struct ssh *ssh = active_state; /* XXX */ | 1647 | struct ssh *ssh = active_state; /* XXX */ |
@@ -1689,9 +1709,18 @@ static void | |||
1689 | monitor_openfds(struct monitor *mon, int do_logfds) | 1709 | monitor_openfds(struct monitor *mon, int do_logfds) |
1690 | { | 1710 | { |
1691 | int pair[2]; | 1711 | int pair[2]; |
1712 | #ifdef SO_ZEROIZE | ||
1713 | int on = 1; | ||
1714 | #endif | ||
1692 | 1715 | ||
1693 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) | 1716 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) |
1694 | fatal("%s: socketpair: %s", __func__, strerror(errno)); | 1717 | fatal("%s: socketpair: %s", __func__, strerror(errno)); |
1718 | #ifdef SO_ZEROIZE | ||
1719 | if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) | ||
1720 | error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); | ||
1721 | if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) | ||
1722 | error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); | ||
1723 | #endif | ||
1695 | FD_CLOSEONEXEC(pair[0]); | 1724 | FD_CLOSEONEXEC(pair[0]); |
1696 | FD_CLOSEONEXEC(pair[1]); | 1725 | FD_CLOSEONEXEC(pair[1]); |
1697 | mon->m_recvfd = pair[0]; | 1726 | mon->m_recvfd = pair[0]; |
@@ -1825,6 +1854,7 @@ int | |||
1825 | mm_answer_gss_userok(int sock, Buffer *m) | 1854 | mm_answer_gss_userok(int sock, Buffer *m) |
1826 | { | 1855 | { |
1827 | int authenticated; | 1856 | int authenticated; |
1857 | const char *displayname; | ||
1828 | 1858 | ||
1829 | if (!options.gss_authentication && !options.gss_keyex) | 1859 | if (!options.gss_authentication && !options.gss_keyex) |
1830 | fatal("%s: GSSAPI not enabled", __func__); | 1860 | fatal("%s: GSSAPI not enabled", __func__); |
@@ -1840,6 +1870,9 @@ mm_answer_gss_userok(int sock, Buffer *m) | |||
1840 | 1870 | ||
1841 | auth_method = "gssapi-with-mic"; | 1871 | auth_method = "gssapi-with-mic"; |
1842 | 1872 | ||
1873 | if ((displayname = ssh_gssapi_displayname()) != NULL) | ||
1874 | auth2_record_info(authctxt, "%s", displayname); | ||
1875 | |||
1843 | /* Monitor loop will terminate if authenticated */ | 1876 | /* Monitor loop will terminate if authenticated */ |
1844 | return (authenticated); | 1877 | return (authenticated); |
1845 | } | 1878 | } |