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> |
@@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
308 | partial = 0; | 308 | partial = 0; |
309 | auth_method = "unknown"; | 309 | auth_method = "unknown"; |
310 | auth_submethod = NULL; | 310 | auth_submethod = NULL; |
311 | auth2_authctxt_reset_info(authctxt); | ||
312 | |||
311 | authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); | 313 | authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); |
312 | 314 | ||
313 | /* Special handling for multiple required authentications */ | 315 | /* Special handling for multiple required authentications */ |
@@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
347 | auth_method, auth_submethod); | 349 | auth_method, auth_submethod); |
348 | if (!partial && !authenticated) | 350 | if (!partial && !authenticated) |
349 | authctxt->failures++; | 351 | authctxt->failures++; |
352 | if (authenticated || partial) { | ||
353 | auth2_update_session_info(authctxt, | ||
354 | auth_method, auth_submethod); | ||
355 | } | ||
350 | } | 356 | } |
351 | } | 357 | } |
352 | 358 | ||
@@ -754,10 +760,12 @@ mm_answer_pwnamallow(int sock, Buffer *m) | |||
754 | for (i = 0; i < options.nx; i++) \ | 760 | for (i = 0; i < options.nx; i++) \ |
755 | buffer_put_cstring(m, options.x[i]); \ | 761 | buffer_put_cstring(m, options.x[i]); \ |
756 | } while (0) | 762 | } while (0) |
763 | #define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx) | ||
757 | /* See comment in servconf.h */ | 764 | /* See comment in servconf.h */ |
758 | COPY_MATCH_STRING_OPTS(); | 765 | COPY_MATCH_STRING_OPTS(); |
759 | #undef M_CP_STROPT | 766 | #undef M_CP_STROPT |
760 | #undef M_CP_STRARRAYOPT | 767 | #undef M_CP_STRARRAYOPT |
768 | #undef M_CP_STRARRAYOPT_ALLOC | ||
761 | 769 | ||
762 | /* Create valid auth method lists */ | 770 | /* Create valid auth method lists */ |
763 | if (auth2_setup_methods_lists(authctxt) != 0) { | 771 | if (auth2_setup_methods_lists(authctxt) != 0) { |
@@ -1119,7 +1127,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) | |||
1119 | int | 1127 | int |
1120 | mm_answer_keyallowed(int sock, Buffer *m) | 1128 | mm_answer_keyallowed(int sock, Buffer *m) |
1121 | { | 1129 | { |
1122 | Key *key; | 1130 | struct sshkey *key; |
1123 | char *cuser, *chost; | 1131 | char *cuser, *chost; |
1124 | u_char *blob; | 1132 | u_char *blob; |
1125 | u_int bloblen, pubkey_auth_attempt; | 1133 | u_int bloblen, pubkey_auth_attempt; |
@@ -1147,12 +1155,11 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1147 | switch (type) { | 1155 | switch (type) { |
1148 | case MM_USERKEY: | 1156 | case MM_USERKEY: |
1149 | allowed = options.pubkey_authentication && | 1157 | allowed = options.pubkey_authentication && |
1150 | !auth2_userkey_already_used(authctxt, key) && | 1158 | !auth2_key_already_used(authctxt, key) && |
1151 | match_pattern_list(sshkey_ssh_name(key), | 1159 | match_pattern_list(sshkey_ssh_name(key), |
1152 | options.pubkey_key_types, 0) == 1 && | 1160 | options.pubkey_key_types, 0) == 1 && |
1153 | user_key_allowed(authctxt->pw, key, | 1161 | user_key_allowed(authctxt->pw, key, |
1154 | pubkey_auth_attempt); | 1162 | pubkey_auth_attempt); |
1155 | pubkey_auth_info(authctxt, key, NULL); | ||
1156 | auth_method = "publickey"; | 1163 | auth_method = "publickey"; |
1157 | if (options.pubkey_authentication && | 1164 | if (options.pubkey_authentication && |
1158 | (!pubkey_auth_attempt || allowed != 1)) | 1165 | (!pubkey_auth_attempt || allowed != 1)) |
@@ -1160,11 +1167,12 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1160 | break; | 1167 | break; |
1161 | case MM_HOSTKEY: | 1168 | case MM_HOSTKEY: |
1162 | allowed = options.hostbased_authentication && | 1169 | allowed = options.hostbased_authentication && |
1170 | !auth2_key_already_used(authctxt, key) && | ||
1163 | match_pattern_list(sshkey_ssh_name(key), | 1171 | match_pattern_list(sshkey_ssh_name(key), |
1164 | options.hostbased_key_types, 0) == 1 && | 1172 | options.hostbased_key_types, 0) == 1 && |
1165 | hostbased_key_allowed(authctxt->pw, | 1173 | hostbased_key_allowed(authctxt->pw, |
1166 | cuser, chost, key); | 1174 | cuser, chost, key); |
1167 | pubkey_auth_info(authctxt, key, | 1175 | auth2_record_info(authctxt, |
1168 | "client user \"%.100s\", client host \"%.100s\"", | 1176 | "client user \"%.100s\", client host \"%.100s\"", |
1169 | cuser, chost); | 1177 | cuser, chost); |
1170 | auth_method = "hostbased"; | 1178 | auth_method = "hostbased"; |
@@ -1175,11 +1183,10 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1175 | } | 1183 | } |
1176 | } | 1184 | } |
1177 | 1185 | ||
1178 | debug3("%s: key %p is %s", | 1186 | debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); |
1179 | __func__, key, allowed ? "allowed" : "not allowed"); | ||
1180 | 1187 | ||
1181 | if (key != NULL) | 1188 | auth2_record_key(authctxt, 0, key); |
1182 | key_free(key); | 1189 | sshkey_free(key); |
1183 | 1190 | ||
1184 | /* clear temporarily storage (used by verify) */ | 1191 | /* clear temporarily storage (used by verify) */ |
1185 | monitor_reset_key_state(); | 1192 | monitor_reset_key_state(); |
@@ -1330,33 +1337,35 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, | |||
1330 | } | 1337 | } |
1331 | 1338 | ||
1332 | int | 1339 | int |
1333 | mm_answer_keyverify(int sock, Buffer *m) | 1340 | mm_answer_keyverify(int sock, struct sshbuf *m) |
1334 | { | 1341 | { |
1335 | Key *key; | 1342 | struct sshkey *key; |
1336 | u_char *signature, *data, *blob; | 1343 | u_char *signature, *data, *blob; |
1337 | u_int signaturelen, datalen, bloblen; | 1344 | size_t signaturelen, datalen, bloblen; |
1338 | int verified = 0; | 1345 | int r, ret, valid_data = 0, encoded_ret; |
1339 | int valid_data = 0; | ||
1340 | 1346 | ||
1341 | blob = buffer_get_string(m, &bloblen); | 1347 | if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || |
1342 | signature = buffer_get_string(m, &signaturelen); | 1348 | (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || |
1343 | data = buffer_get_string(m, &datalen); | 1349 | (r = sshbuf_get_string(m, &data, &datalen)) != 0) |
1350 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1344 | 1351 | ||
1345 | if (hostbased_cuser == NULL || hostbased_chost == NULL || | 1352 | if (hostbased_cuser == NULL || hostbased_chost == NULL || |
1346 | !monitor_allowed_key(blob, bloblen)) | 1353 | !monitor_allowed_key(blob, bloblen)) |
1347 | fatal("%s: bad key, not previously allowed", __func__); | 1354 | fatal("%s: bad key, not previously allowed", __func__); |
1348 | 1355 | ||
1349 | key = key_from_blob(blob, bloblen); | 1356 | /* XXX use sshkey_froms here; need to change key_blob, etc. */ |
1350 | if (key == NULL) | 1357 | if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) |
1351 | fatal("%s: bad public key blob", __func__); | 1358 | fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); |
1352 | 1359 | ||
1353 | switch (key_blobtype) { | 1360 | switch (key_blobtype) { |
1354 | case MM_USERKEY: | 1361 | case MM_USERKEY: |
1355 | valid_data = monitor_valid_userblob(data, datalen); | 1362 | valid_data = monitor_valid_userblob(data, datalen); |
1363 | auth_method = "publickey"; | ||
1356 | break; | 1364 | break; |
1357 | case MM_HOSTKEY: | 1365 | case MM_HOSTKEY: |
1358 | valid_data = monitor_valid_hostbasedblob(data, datalen, | 1366 | valid_data = monitor_valid_hostbasedblob(data, datalen, |
1359 | hostbased_cuser, hostbased_chost); | 1367 | hostbased_cuser, hostbased_chost); |
1368 | auth_method = "hostbased"; | ||
1360 | break; | 1369 | break; |
1361 | default: | 1370 | default: |
1362 | valid_data = 0; | 1371 | valid_data = 0; |
@@ -1365,29 +1374,28 @@ mm_answer_keyverify(int sock, Buffer *m) | |||
1365 | if (!valid_data) | 1374 | if (!valid_data) |
1366 | fatal("%s: bad signature data blob", __func__); | 1375 | fatal("%s: bad signature data blob", __func__); |
1367 | 1376 | ||
1368 | verified = key_verify(key, signature, signaturelen, data, datalen); | 1377 | ret = sshkey_verify(key, signature, signaturelen, data, datalen, |
1369 | debug3("%s: key %p signature %s", | 1378 | active_state->compat); |
1370 | __func__, key, (verified == 1) ? "verified" : "unverified"); | 1379 | debug3("%s: %s %p signature %s", __func__, auth_method, key, |
1371 | 1380 | (ret == 0) ? "verified" : "unverified"); | |
1372 | /* If auth was successful then record key to ensure it isn't reused */ | 1381 | auth2_record_key(authctxt, ret == 0, key); |
1373 | if (verified == 1 && key_blobtype == MM_USERKEY) | ||
1374 | auth2_record_userkey(authctxt, key); | ||
1375 | else | ||
1376 | key_free(key); | ||
1377 | 1382 | ||
1378 | free(blob); | 1383 | free(blob); |
1379 | free(signature); | 1384 | free(signature); |
1380 | free(data); | 1385 | free(data); |
1381 | 1386 | ||
1382 | auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; | ||
1383 | |||
1384 | monitor_reset_key_state(); | 1387 | monitor_reset_key_state(); |
1385 | 1388 | ||
1386 | buffer_clear(m); | 1389 | sshkey_free(key); |
1387 | buffer_put_int(m, verified); | 1390 | sshbuf_reset(m); |
1391 | |||
1392 | /* encode ret != 0 as positive integer, since we're sending u32 */ | ||
1393 | encoded_ret = (ret != 0); | ||
1394 | if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) | ||
1395 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1388 | mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); | 1396 | mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); |
1389 | 1397 | ||
1390 | return (verified == 1); | 1398 | return ret == 0; |
1391 | } | 1399 | } |
1392 | 1400 | ||
1393 | static void | 1401 | static void |
@@ -1513,13 +1521,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m) | |||
1513 | int | 1521 | int |
1514 | mm_answer_term(int sock, Buffer *req) | 1522 | mm_answer_term(int sock, Buffer *req) |
1515 | { | 1523 | { |
1524 | struct ssh *ssh = active_state; /* XXX */ | ||
1516 | extern struct monitor *pmonitor; | 1525 | extern struct monitor *pmonitor; |
1517 | int res, status; | 1526 | int res, status; |
1518 | 1527 | ||
1519 | debug3("%s: tearing down sessions", __func__); | 1528 | debug3("%s: tearing down sessions", __func__); |
1520 | 1529 | ||
1521 | /* The child is terminating */ | 1530 | /* The child is terminating */ |
1522 | session_destroy_all(&mm_session_close); | 1531 | session_destroy_all(ssh, &mm_session_close); |
1523 | 1532 | ||
1524 | #ifdef USE_PAM | 1533 | #ifdef USE_PAM |
1525 | if (options.use_pam) | 1534 | if (options.use_pam) |
@@ -1579,6 +1588,17 @@ mm_answer_audit_command(int socket, Buffer *m) | |||
1579 | #endif /* SSH_AUDIT_EVENTS */ | 1588 | #endif /* SSH_AUDIT_EVENTS */ |
1580 | 1589 | ||
1581 | void | 1590 | void |
1591 | monitor_clear_keystate(struct monitor *pmonitor) | ||
1592 | { | ||
1593 | struct ssh *ssh = active_state; /* XXX */ | ||
1594 | |||
1595 | ssh_clear_newkeys(ssh, MODE_IN); | ||
1596 | ssh_clear_newkeys(ssh, MODE_OUT); | ||
1597 | sshbuf_free(child_state); | ||
1598 | child_state = NULL; | ||
1599 | } | ||
1600 | |||
1601 | void | ||
1582 | monitor_apply_keystate(struct monitor *pmonitor) | 1602 | monitor_apply_keystate(struct monitor *pmonitor) |
1583 | { | 1603 | { |
1584 | struct ssh *ssh = active_state; /* XXX */ | 1604 | struct ssh *ssh = active_state; /* XXX */ |
@@ -1639,9 +1659,18 @@ static void | |||
1639 | monitor_openfds(struct monitor *mon, int do_logfds) | 1659 | monitor_openfds(struct monitor *mon, int do_logfds) |
1640 | { | 1660 | { |
1641 | int pair[2]; | 1661 | int pair[2]; |
1662 | #ifdef SO_ZEROIZE | ||
1663 | int on = 1; | ||
1664 | #endif | ||
1642 | 1665 | ||
1643 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) | 1666 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) |
1644 | fatal("%s: socketpair: %s", __func__, strerror(errno)); | 1667 | fatal("%s: socketpair: %s", __func__, strerror(errno)); |
1668 | #ifdef SO_ZEROIZE | ||
1669 | if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) | ||
1670 | error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); | ||
1671 | if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) | ||
1672 | error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); | ||
1673 | #endif | ||
1645 | FD_CLOSEONEXEC(pair[0]); | 1674 | FD_CLOSEONEXEC(pair[0]); |
1646 | FD_CLOSEONEXEC(pair[1]); | 1675 | FD_CLOSEONEXEC(pair[1]); |
1647 | mon->m_recvfd = pair[0]; | 1676 | mon->m_recvfd = pair[0]; |
@@ -1774,6 +1803,7 @@ int | |||
1774 | mm_answer_gss_userok(int sock, Buffer *m) | 1803 | mm_answer_gss_userok(int sock, Buffer *m) |
1775 | { | 1804 | { |
1776 | int authenticated; | 1805 | int authenticated; |
1806 | const char *displayname; | ||
1777 | 1807 | ||
1778 | if (!options.gss_authentication) | 1808 | if (!options.gss_authentication) |
1779 | fatal("%s: GSSAPI authentication not enabled", __func__); | 1809 | fatal("%s: GSSAPI authentication not enabled", __func__); |
@@ -1788,6 +1818,9 @@ mm_answer_gss_userok(int sock, Buffer *m) | |||
1788 | 1818 | ||
1789 | auth_method = "gssapi-with-mic"; | 1819 | auth_method = "gssapi-with-mic"; |
1790 | 1820 | ||
1821 | if ((displayname = ssh_gssapi_displayname()) != NULL) | ||
1822 | auth2_record_info(authctxt, "%s", displayname); | ||
1823 | |||
1791 | /* Monitor loop will terminate if authenticated */ | 1824 | /* Monitor loop will terminate if authenticated */ |
1792 | return (authenticated); | 1825 | return (authenticated); |
1793 | } | 1826 | } |