diff options
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 70 |
1 files changed, 45 insertions, 25 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.179 2018/02/05 05:37:46 tb 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 | { |
@@ -297,6 +298,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
297 | 298 | ||
298 | authctxt = _authctxt; | 299 | authctxt = _authctxt; |
299 | memset(authctxt, 0, sizeof(*authctxt)); | 300 | memset(authctxt, 0, sizeof(*authctxt)); |
301 | ssh->authctxt = authctxt; | ||
300 | 302 | ||
301 | authctxt->loginmsg = &loginmsg; | 303 | authctxt->loginmsg = &loginmsg; |
302 | 304 | ||
@@ -331,7 +333,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
331 | fatal("%s: unexpected authentication from %d", | 333 | fatal("%s: unexpected authentication from %d", |
332 | __func__, ent->type); | 334 | __func__, ent->type); |
333 | if (authctxt->pw->pw_uid == 0 && | 335 | if (authctxt->pw->pw_uid == 0 && |
334 | !auth_root_allowed(auth_method)) | 336 | !auth_root_allowed(ssh, auth_method)) |
335 | authenticated = 0; | 337 | authenticated = 0; |
336 | #ifdef USE_PAM | 338 | #ifdef USE_PAM |
337 | /* PAM needs to perform account checks after auth */ | 339 | /* PAM needs to perform account checks after auth */ |
@@ -365,6 +367,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) | |||
365 | 367 | ||
366 | debug("%s: %s has been authenticated by privileged process", | 368 | debug("%s: %s has been authenticated by privileged process", |
367 | __func__, authctxt->user); | 369 | __func__, authctxt->user); |
370 | ssh->authctxt = NULL; | ||
368 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); | 371 | ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); |
369 | 372 | ||
370 | mm_get_keystate(pmonitor); | 373 | mm_get_keystate(pmonitor); |
@@ -413,7 +416,7 @@ monitor_child_postauth(struct monitor *pmonitor) | |||
413 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); | 416 | monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); |
414 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); | 417 | monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); |
415 | 418 | ||
416 | if (!no_pty_flag) { | 419 | if (auth_opts->permit_pty_flag) { |
417 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); | 420 | monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); |
418 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); | 421 | monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); |
419 | } | 422 | } |
@@ -558,9 +561,11 @@ monitor_reset_key_state(void) | |||
558 | free(key_blob); | 561 | free(key_blob); |
559 | free(hostbased_cuser); | 562 | free(hostbased_cuser); |
560 | free(hostbased_chost); | 563 | free(hostbased_chost); |
564 | sshauthopt_free(key_opts); | ||
561 | key_blob = NULL; | 565 | key_blob = NULL; |
562 | key_bloblen = 0; | 566 | key_bloblen = 0; |
563 | key_blobtype = MM_NOKEY; | 567 | key_blobtype = MM_NOKEY; |
568 | key_opts = NULL; | ||
564 | hostbased_cuser = NULL; | 569 | hostbased_cuser = NULL; |
565 | hostbased_chost = NULL; | 570 | hostbased_chost = NULL; |
566 | } | 571 | } |
@@ -828,6 +833,7 @@ mm_answer_authserv(int sock, Buffer *m) | |||
828 | int | 833 | int |
829 | mm_answer_authpassword(int sock, Buffer *m) | 834 | mm_answer_authpassword(int sock, Buffer *m) |
830 | { | 835 | { |
836 | struct ssh *ssh = active_state; /* XXX */ | ||
831 | static int call_count; | 837 | static int call_count; |
832 | char *passwd; | 838 | char *passwd; |
833 | int authenticated; | 839 | int authenticated; |
@@ -838,7 +844,7 @@ mm_answer_authpassword(int sock, Buffer *m) | |||
838 | passwd = buffer_get_string(m, &plen); | 844 | passwd = buffer_get_string(m, &plen); |
839 | /* Only authenticate if the context is valid */ | 845 | /* Only authenticate if the context is valid */ |
840 | authenticated = options.password_authentication && | 846 | authenticated = options.password_authentication && |
841 | auth_password(authctxt, passwd); | 847 | auth_password(ssh, passwd); |
842 | explicit_bzero(passwd, strlen(passwd)); | 848 | explicit_bzero(passwd, strlen(passwd)); |
843 | free(passwd); | 849 | free(passwd); |
844 | 850 | ||
@@ -1129,15 +1135,16 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) | |||
1129 | int | 1135 | int |
1130 | mm_answer_keyallowed(int sock, Buffer *m) | 1136 | mm_answer_keyallowed(int sock, Buffer *m) |
1131 | { | 1137 | { |
1138 | struct ssh *ssh = active_state; /* XXX */ | ||
1132 | struct sshkey *key; | 1139 | struct sshkey *key; |
1133 | char *cuser, *chost; | 1140 | char *cuser, *chost; |
1134 | u_char *blob; | 1141 | u_char *blob; |
1135 | u_int bloblen, pubkey_auth_attempt; | 1142 | u_int bloblen, pubkey_auth_attempt; |
1136 | enum mm_keytype type = 0; | 1143 | enum mm_keytype type = 0; |
1137 | int allowed = 0; | 1144 | int r, allowed = 0; |
1145 | struct sshauthopt *opts = NULL; | ||
1138 | 1146 | ||
1139 | debug3("%s entering", __func__); | 1147 | debug3("%s entering", __func__); |
1140 | |||
1141 | type = buffer_get_int(m); | 1148 | type = buffer_get_int(m); |
1142 | cuser = buffer_get_string(m, NULL); | 1149 | cuser = buffer_get_string(m, NULL); |
1143 | chost = buffer_get_string(m, NULL); | 1150 | chost = buffer_get_string(m, NULL); |
@@ -1156,28 +1163,31 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1156 | 1163 | ||
1157 | switch (type) { | 1164 | switch (type) { |
1158 | case MM_USERKEY: | 1165 | case MM_USERKEY: |
1159 | allowed = options.pubkey_authentication && | ||
1160 | !auth2_key_already_used(authctxt, key) && | ||
1161 | match_pattern_list(sshkey_ssh_name(key), | ||
1162 | options.pubkey_key_types, 0) == 1 && | ||
1163 | user_key_allowed(authctxt->pw, key, | ||
1164 | pubkey_auth_attempt); | ||
1165 | auth_method = "publickey"; | 1166 | auth_method = "publickey"; |
1166 | if (options.pubkey_authentication && | 1167 | if (!options.pubkey_authentication) |
1167 | (!pubkey_auth_attempt || allowed != 1)) | 1168 | break; |
1168 | 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); | ||
1169 | break; | 1176 | break; |
1170 | case MM_HOSTKEY: | 1177 | case MM_HOSTKEY: |
1171 | allowed = options.hostbased_authentication && | 1178 | auth_method = "hostbased"; |
1172 | !auth2_key_already_used(authctxt, key) && | 1179 | if (!options.hostbased_authentication) |
1173 | match_pattern_list(sshkey_ssh_name(key), | 1180 | break; |
1174 | options.hostbased_key_types, 0) == 1 && | 1181 | if (auth2_key_already_used(authctxt, key)) |
1175 | 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, | ||
1176 | cuser, chost, key); | 1187 | cuser, chost, key); |
1177 | auth2_record_info(authctxt, | 1188 | auth2_record_info(authctxt, |
1178 | "client user \"%.100s\", client host \"%.100s\"", | 1189 | "client user \"%.100s\", client host \"%.100s\"", |
1179 | cuser, chost); | 1190 | cuser, chost); |
1180 | auth_method = "hostbased"; | ||
1181 | break; | 1191 | break; |
1182 | default: | 1192 | default: |
1183 | fatal("%s: unknown key type %d", __func__, type); | 1193 | fatal("%s: unknown key type %d", __func__, type); |
@@ -1185,7 +1195,10 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1185 | } | 1195 | } |
1186 | } | 1196 | } |
1187 | 1197 | ||
1188 | 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"); | ||
1189 | 1202 | ||
1190 | auth2_record_key(authctxt, 0, key); | 1203 | auth2_record_key(authctxt, 0, key); |
1191 | sshkey_free(key); | 1204 | sshkey_free(key); |
@@ -1198,6 +1211,7 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1198 | key_blob = blob; | 1211 | key_blob = blob; |
1199 | key_bloblen = bloblen; | 1212 | key_bloblen = bloblen; |
1200 | key_blobtype = type; | 1213 | key_blobtype = type; |
1214 | key_opts = opts; | ||
1201 | hostbased_cuser = cuser; | 1215 | hostbased_cuser = cuser; |
1202 | hostbased_chost = chost; | 1216 | hostbased_chost = chost; |
1203 | } else { | 1217 | } else { |
@@ -1210,10 +1224,13 @@ mm_answer_keyallowed(int sock, Buffer *m) | |||
1210 | 1224 | ||
1211 | buffer_clear(m); | 1225 | buffer_clear(m); |
1212 | buffer_put_int(m, allowed); | 1226 | buffer_put_int(m, allowed); |
1213 | buffer_put_int(m, forced_command != NULL); | 1227 | if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) |
1214 | 1228 | fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r)); | |
1215 | mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); | 1229 | mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); |
1216 | 1230 | ||
1231 | if (!allowed) | ||
1232 | sshauthopt_free(opts); | ||
1233 | |||
1217 | return (0); | 1234 | return (0); |
1218 | } | 1235 | } |
1219 | 1236 | ||
@@ -1336,6 +1353,7 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, | |||
1336 | int | 1353 | int |
1337 | mm_answer_keyverify(int sock, struct sshbuf *m) | 1354 | mm_answer_keyverify(int sock, struct sshbuf *m) |
1338 | { | 1355 | { |
1356 | struct ssh *ssh = active_state; /* XXX */ | ||
1339 | struct sshkey *key; | 1357 | struct sshkey *key; |
1340 | u_char *signature, *data, *blob; | 1358 | u_char *signature, *data, *blob; |
1341 | char *sigalg; | 1359 | char *sigalg; |
@@ -1390,6 +1408,8 @@ mm_answer_keyverify(int sock, struct sshbuf *m) | |||
1390 | free(data); | 1408 | free(data); |
1391 | free(sigalg); | 1409 | free(sigalg); |
1392 | 1410 | ||
1411 | if (key_blobtype == MM_USERKEY) | ||
1412 | auth_activate_options(ssh, key_opts); | ||
1393 | monitor_reset_key_state(); | 1413 | monitor_reset_key_state(); |
1394 | 1414 | ||
1395 | sshkey_free(key); | 1415 | sshkey_free(key); |