diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 116 |
1 files changed, 71 insertions, 45 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.180 2018/03/03 03:15:51 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> |
@@ -116,6 +116,7 @@ extern u_char session_id[]; | |||
116 | extern Buffer auth_debug; | 116 | extern Buffer auth_debug; |
117 | extern int auth_debug_init; | 117 | extern int auth_debug_init; |
118 | extern Buffer loginmsg; | 118 | extern Buffer loginmsg; |
119 | extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ | ||
119 | 120 | ||
120 | /* State exported from the child */ | 121 | /* State exported from the child */ |
121 | static struct sshbuf *child_state; | 122 | static struct sshbuf *child_state; |
@@ -172,6 +173,7 @@ static Authctxt *authctxt; | |||
172 | static u_char *key_blob = NULL; | 173 | static u_char *key_blob = NULL; |
173 | static u_int key_bloblen = 0; | 174 | static u_int key_bloblen = 0; |
174 | static int key_blobtype = MM_NOKEY; | 175 | static int key_blobtype = MM_NOKEY; |
176 | static struct sshauthopt *key_opts = NULL; | ||
175 | static char *hostbased_cuser = NULL; | 177 | static char *hostbased_cuser = NULL; |
176 | static char *hostbased_chost = NULL; | 178 | static char *hostbased_chost = NULL; |
177 | static char *auth_method = "unknown"; | 179 | static char *auth_method = "unknown"; |
@@ -252,7 +254,6 @@ struct mon_table mon_dispatch_postauth20[] = { | |||
252 | struct mon_table *mon_dispatch; | 254 | struct mon_table *mon_dispatch; |
253 | 255 | ||
254 | /* Specifies if a certain message is allowed at the moment */ | 256 | /* Specifies if a certain message is allowed at the moment */ |
255 | |||
256 | static void | 257 | static void |
257 | monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) | 258 | monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) |
258 | { | 259 | { |
@@ -289,12 +290,15 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
289 | 290 | ||
290 | debug3("preauth child monitor started"); | 291 | debug3("preauth child monitor started"); |
291 | 292 | ||
292 | close(pmonitor->m_recvfd); | 293 | if (pmonitor->m_recvfd >= 0) |
293 | close(pmonitor->m_log_sendfd); | 294 | close(pmonitor->m_recvfd); |
295 | if (pmonitor->m_log_sendfd >= 0) | ||
296 | close(pmonitor->m_log_sendfd); | ||
294 | pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; | 297 | pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; |
295 | 298 | ||
296 | authctxt = _authctxt; | 299 | authctxt = _authctxt; |
297 | memset(authctxt, 0, sizeof(*authctxt)); | 300 | memset(authctxt, 0, sizeof(*authctxt)); |
301 | ssh->authctxt = authctxt; | ||
298 | 302 | ||
299 | authctxt->loginmsg = &loginmsg; | 303 | authctxt->loginmsg = &loginmsg; |
300 | 304 | ||
@@ -329,7 +333,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
329 | fatal("%s: unexpected authentication from %d", | 333 | fatal("%s: unexpected authentication from %d", |
330 | __func__, ent->type); | 334 | __func__, ent->type); |
331 | if (authctxt->pw->pw_uid == 0 && | 335 | if (authctxt->pw->pw_uid == 0 && |
332 | !auth_root_allowed(auth_method)) | 336 | !auth_root_allowed(ssh, auth_method)) |
333 | authenticated = 0; | 337 | authenticated = 0; |
334 | #ifdef USE_PAM | 338 | #ifdef USE_PAM |
335 | /* PAM needs to perform account checks after auth */ | 339 | /* PAM needs to perform account checks after auth */ |
@@ -363,6 +367,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
363 | 367 | ||
364 | debug("%s: %s has been authenticated by privileged process", | 368 | debug("%s: %s has been authenticated by privileged process", |
365 | __func__, authctxt->user); | 369 | __func__, authctxt->user); |
370 | ssh->authctxt = NULL; | ||
366 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); | 371 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); |
367 | 372 | ||
368 | mm_get_keystate(pmonitor); | 373 | mm_get_keystate(pmonitor); |
@@ -371,8 +376,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
371 | while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) | 376 | while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) |
372 | ; | 377 | ; |
373 | 378 | ||
374 | close(pmonitor->m_sendfd); | 379 | if (pmonitor->m_recvfd >= 0) |
375 | close(pmonitor->m_log_recvfd); | 380 | close(pmonitor->m_recvfd); |
381 | if (pmonitor->m_log_sendfd >= 0) | ||
382 | close(pmonitor->m_log_sendfd); | ||
376 | pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; | 383 | pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; |
377 | } | 384 | } |
378 | 385 | ||
@@ -409,7 +416,7 @@ monitor_child_postauth(struct monitor *pmonitor) | |||
409 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 416 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
410 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); | 417 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
411 | 418 | ||
412 | if (!no_pty_flag) { | 419 | if (auth_opts->permit_pty_flag) { |
413 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); | 420 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); |
414 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); | 421 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); |
415 | } | 422 | } |
@@ -554,9 +561,11 @@ monitor_reset_key_state(void) | |||
554 | free(key_blob); | 561 | free(key_blob); |
555 | free(hostbased_cuser); | 562 | free(hostbased_cuser); |
556 | free(hostbased_chost); | 563 | free(hostbased_chost); |
564 | sshauthopt_free(key_opts); | ||
557 | key_blob = NULL; | 565 | key_blob = NULL; |
558 | key_bloblen = 0; | 566 | key_bloblen = 0; |
559 | key_blobtype = MM_NOKEY; | 567 | key_blobtype = MM_NOKEY; |
568 | key_opts = NULL; | ||
560 | hostbased_cuser = NULL; | 569 | hostbased_cuser = NULL; |
561 | hostbased_chost = NULL; | 570 | hostbased_chost = NULL; |
562 | } | 571 | } |
@@ -760,12 +769,10 @@ mm_answer_pwnamallow(int sock, Buffer *m) | |||
760 | for (i = 0; i < options.nx; i++) \ | 769 | for (i = 0; i < options.nx; i++) \ |
761 | buffer_put_cstring(m, options.x[i]); \ | 770 | buffer_put_cstring(m, options.x[i]); \ |
762 | } while (0) | 771 | } while (0) |
763 | #define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx) | ||
764 | /* See comment in servconf.h */ | 772 | /* See comment in servconf.h */ |
765 | COPY_MATCH_STRING_OPTS(); | 773 | COPY_MATCH_STRING_OPTS(); |
766 | #undef M_CP_STROPT | 774 | #undef M_CP_STROPT |
767 | #undef M_CP_STRARRAYOPT | 775 | #undef M_CP_STRARRAYOPT |
768 | #undef M_CP_STRARRAYOPT_ALLOC | ||
769 | 776 | ||
770 | /* Create valid auth method lists */ | 777 | /* Create valid auth method lists */ |
771 | if (auth2_setup_methods_lists(authctxt) != 0) { | 778 | if (auth2_setup_methods_lists(authctxt) != 0) { |
@@ -826,6 +833,7 @@ mm_answer_authserv(int sock, Buffer *m) | |||
826 | int | 833 | int |
827 | mm_answer_authpassword(int sock, Buffer *m) | 834 | mm_answer_authpassword(int sock, Buffer *m) |
828 | { | 835 | { |
836 | struct ssh *ssh = active_state; /* XXX */ | ||
829 | static int call_count; | 837 | static int call_count; |
830 | char *passwd; | 838 | char *passwd; |
831 | int authenticated; | 839 | int authenticated; |
@@ -836,7 +844,7 @@ mm_answer_authpassword(int sock, Buffer *m) | |||
836 | passwd = buffer_get_string(m, &plen); | 844 | passwd = buffer_get_string(m, &plen); |
837 | /* Only authenticate if the context is valid */ | 845 | /* Only authenticate if the context is valid */ |
838 | authenticated = options.password_authentication && | 846 | authenticated = options.password_authentication && |
839 | auth_password(authctxt, passwd); | 847 | auth_password(ssh, passwd); |
840 | explicit_bzero(passwd, strlen(passwd)); | 848 | explicit_bzero(passwd, strlen(passwd)); |
841 | free(passwd); | 849 | free(passwd); |
842 | 850 | ||
@@ -1127,15 +1135,16 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) | |||
1127 | int | 1135 | int |
1128 | mm_answer_keyallowed(int sock, Buffer *m) | 1136 | mm_answer_keyallowed(int sock, Buffer *m) |
1129 | { | 1137 | { |
1138 | struct ssh *ssh = active_state; /* XXX */ | ||
1130 | struct sshkey *key; | 1139 | struct sshkey *key; |
1131 | char *cuser, *chost; | 1140 | char *cuser, *chost; |
1132 | u_char *blob; | 1141 | u_char *blob; |
1133 | u_int bloblen, pubkey_auth_attempt; | 1142 | u_int bloblen, pubkey_auth_attempt; |
1134 | enum mm_keytype type = 0; | 1143 | enum mm_keytype type = 0; |
1135 | int allowed = 0; | 1144 | int r, allowed = 0; |
1145 | struct sshauthopt *opts = NULL; | ||
1136 | 1146 | ||
1137 | debug3("%s entering", __func__); | 1147 | debug3("%s entering", __func__); |
1138 | |||
1139 | type = buffer_get_int(m); | 1148 | type = buffer_get_int(m); |
1140 | cuser = buffer_get_string(m, NULL); | 1149 | cuser = buffer_get_string(m, NULL); |
1141 | chost = buffer_get_string(m, NULL); | 1150 | chost = buffer_get_string(m, NULL); |
@@ -1154,28 +1163,31 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1154 | 1163 | ||
1155 | switch (type) { | 1164 | switch (type) { |
1156 | case MM_USERKEY: | 1165 | case MM_USERKEY: |
1157 | allowed = options.pubkey_authentication && | ||
1158 | !auth2_key_already_used(authctxt, key) && | ||
1159 | match_pattern_list(sshkey_ssh_name(key), | ||
1160 | options.pubkey_key_types, 0) == 1 && | ||
1161 | user_key_allowed(authctxt->pw, key, | ||
1162 | pubkey_auth_attempt); | ||
1163 | auth_method = "publickey"; | 1166 | auth_method = "publickey"; |
1164 | if (options.pubkey_authentication && | 1167 | if (!options.pubkey_authentication) |
1165 | (!pubkey_auth_attempt || allowed != 1)) | 1168 | break; |
1166 | auth_clear_options(); | 1169 | if (auth2_key_already_used(authctxt, key)) |
1170 | break; | ||
1171 | if (match_pattern_list(sshkey_ssh_name(key), | ||
1172 | options.pubkey_key_types, 0) != 1) | ||
1173 | break; | ||
1174 | allowed = user_key_allowed(ssh, authctxt->pw, key, | ||
1175 | pubkey_auth_attempt, &opts); | ||
1167 | break; | 1176 | break; |
1168 | case MM_HOSTKEY: | 1177 | case MM_HOSTKEY: |
1169 | allowed = options.hostbased_authentication && | 1178 | auth_method = "hostbased"; |
1170 | !auth2_key_already_used(authctxt, key) && | 1179 | if (!options.hostbased_authentication) |
1171 | match_pattern_list(sshkey_ssh_name(key), | 1180 | break; |
1172 | options.hostbased_key_types, 0) == 1 && | 1181 | if (auth2_key_already_used(authctxt, key)) |
1173 | hostbased_key_allowed(authctxt->pw, | 1182 | break; |
1183 | if (match_pattern_list(sshkey_ssh_name(key), | ||
1184 | options.hostbased_key_types, 0) != 1) | ||
1185 | break; | ||
1186 | allowed = hostbased_key_allowed(authctxt->pw, | ||
1174 | cuser, chost, key); | 1187 | cuser, chost, key); |
1175 | auth2_record_info(authctxt, | 1188 | auth2_record_info(authctxt, |
1176 | "client user \"%.100s\", client host \"%.100s\"", | 1189 | "client user \"%.100s\", client host \"%.100s\"", |
1177 | cuser, chost); | 1190 | cuser, chost); |
1178 | auth_method = "hostbased"; | ||
1179 | break; | 1191 | break; |
1180 | default: | 1192 | default: |
1181 | fatal("%s: unknown key type %d", __func__, type); | 1193 | fatal("%s: unknown key type %d", __func__, type); |
@@ -1183,7 +1195,10 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1183 | } | 1195 | } |
1184 | } | 1196 | } |
1185 | 1197 | ||
1186 | debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); | 1198 | debug3("%s: %s authentication%s: %s key is %s", __func__, |
1199 | auth_method, pubkey_auth_attempt ? "" : " test", | ||
1200 | (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), | ||
1201 | allowed ? "allowed" : "not allowed"); | ||
1187 | 1202 | ||
1188 | auth2_record_key(authctxt, 0, key); | 1203 | auth2_record_key(authctxt, 0, key); |
1189 | sshkey_free(key); | 1204 | sshkey_free(key); |
@@ -1196,6 +1211,7 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1196 | key_blob = blob; | 1211 | key_blob = blob; |
1197 | key_bloblen = bloblen; | 1212 | key_bloblen = bloblen; |
1198 | key_blobtype = type; | 1213 | key_blobtype = type; |
1214 | key_opts = opts; | ||
1199 | hostbased_cuser = cuser; | 1215 | hostbased_cuser = cuser; |
1200 | hostbased_chost = chost; | 1216 | hostbased_chost = chost; |
1201 | } else { | 1217 | } else { |
@@ -1208,10 +1224,13 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1208 | 1224 | ||
1209 | buffer_clear(m); | 1225 | buffer_clear(m); |
1210 | buffer_put_int(m, allowed); | 1226 | buffer_put_int(m, allowed); |
1211 | buffer_put_int(m, forced_command != NULL); | 1227 | if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) |
1212 | 1228 | fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r)); | |
1213 | mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); | 1229 | mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); |
1214 | 1230 | ||
1231 | if (!allowed) | ||
1232 | sshauthopt_free(opts); | ||
1233 | |||
1215 | return (0); | 1234 | return (0); |
1216 | } | 1235 | } |
1217 | 1236 | ||
@@ -1257,18 +1276,13 @@ monitor_valid_userblob(u_char *data, u_int datalen) | |||
1257 | free(userstyle); | 1276 | free(userstyle); |
1258 | free(cp); | 1277 | free(cp); |
1259 | buffer_skip_string(&b); | 1278 | buffer_skip_string(&b); |
1260 | if (datafellows & SSH_BUG_PKAUTH) { | 1279 | cp = buffer_get_cstring(&b, NULL); |
1261 | if (!buffer_get_char(&b)) | 1280 | if (strcmp("publickey", cp) != 0) |
1262 | fail++; | 1281 | fail++; |
1263 | } else { | 1282 | free(cp); |
1264 | cp = buffer_get_cstring(&b, NULL); | 1283 | if (!buffer_get_char(&b)) |
1265 | if (strcmp("publickey", cp) != 0) | 1284 | fail++; |
1266 | fail++; | 1285 | buffer_skip_string(&b); |
1267 | free(cp); | ||
1268 | if (!buffer_get_char(&b)) | ||
1269 | fail++; | ||
1270 | buffer_skip_string(&b); | ||
1271 | } | ||
1272 | buffer_skip_string(&b); | 1286 | buffer_skip_string(&b); |
1273 | if (buffer_len(&b) != 0) | 1287 | if (buffer_len(&b) != 0) |
1274 | fail++; | 1288 | fail++; |
@@ -1339,20 +1353,29 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, | |||
1339 | int | 1353 | int |
1340 | mm_answer_keyverify(int sock, struct sshbuf *m) | 1354 | mm_answer_keyverify(int sock, struct sshbuf *m) |
1341 | { | 1355 | { |
1356 | struct ssh *ssh = active_state; /* XXX */ | ||
1342 | struct sshkey *key; | 1357 | struct sshkey *key; |
1343 | u_char *signature, *data, *blob; | 1358 | u_char *signature, *data, *blob; |
1359 | char *sigalg; | ||
1344 | size_t signaturelen, datalen, bloblen; | 1360 | size_t signaturelen, datalen, bloblen; |
1345 | int r, ret, valid_data = 0, encoded_ret; | 1361 | int r, ret, valid_data = 0, encoded_ret; |
1346 | 1362 | ||
1347 | if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || | 1363 | if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || |
1348 | (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || | 1364 | (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || |
1349 | (r = sshbuf_get_string(m, &data, &datalen)) != 0) | 1365 | (r = sshbuf_get_string(m, &data, &datalen)) != 0 || |
1366 | (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) | ||
1350 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 1367 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1351 | 1368 | ||
1352 | if (hostbased_cuser == NULL || hostbased_chost == NULL || | 1369 | if (hostbased_cuser == NULL || hostbased_chost == NULL || |
1353 | !monitor_allowed_key(blob, bloblen)) | 1370 | !monitor_allowed_key(blob, bloblen)) |
1354 | fatal("%s: bad key, not previously allowed", __func__); | 1371 | fatal("%s: bad key, not previously allowed", __func__); |
1355 | 1372 | ||
1373 | /* Empty signature algorithm means NULL. */ | ||
1374 | if (*sigalg == '\0') { | ||
1375 | free(sigalg); | ||
1376 | sigalg = NULL; | ||
1377 | } | ||
1378 | |||
1356 | /* XXX use sshkey_froms here; need to change key_blob, etc. */ | 1379 | /* XXX use sshkey_froms here; need to change key_blob, etc. */ |
1357 | if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) | 1380 | if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) |
1358 | fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); | 1381 | fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); |
@@ -1375,7 +1398,7 @@ mm_answer_keyverify(int sock, struct sshbuf *m) | |||
1375 | fatal("%s: bad signature data blob", __func__); | 1398 | fatal("%s: bad signature data blob", __func__); |
1376 | 1399 | ||
1377 | ret = sshkey_verify(key, signature, signaturelen, data, datalen, | 1400 | ret = sshkey_verify(key, signature, signaturelen, data, datalen, |
1378 | active_state->compat); | 1401 | sigalg, active_state->compat); |
1379 | debug3("%s: %s %p signature %s", __func__, auth_method, key, | 1402 | debug3("%s: %s %p signature %s", __func__, auth_method, key, |
1380 | (ret == 0) ? "verified" : "unverified"); | 1403 | (ret == 0) ? "verified" : "unverified"); |
1381 | auth2_record_key(authctxt, ret == 0, key); | 1404 | auth2_record_key(authctxt, ret == 0, key); |
@@ -1383,7 +1406,10 @@ mm_answer_keyverify(int sock, struct sshbuf *m) | |||
1383 | free(blob); | 1406 | free(blob); |
1384 | free(signature); | 1407 | free(signature); |
1385 | free(data); | 1408 | free(data); |
1409 | free(sigalg); | ||
1386 | 1410 | ||
1411 | if (key_blobtype == MM_USERKEY) | ||
1412 | auth_activate_options(ssh, key_opts); | ||
1387 | monitor_reset_key_state(); | 1413 | monitor_reset_key_state(); |
1388 | 1414 | ||
1389 | sshkey_free(key); | 1415 | sshkey_free(key); |