diff options
author | mav <mav@FreeBSD.org> | 2015-08-08 19:04:37 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-08-08 19:04:37 +0000 |
commit | 35adb2b287f6a212162e322f6369ad381a2b91c6 (patch) | |
tree | 236578eb987056ce25ddab177f89ec5ad12225a1 /usr.sbin/ctld/login.c | |
parent | e6fc39bbd338f1a527813cdda66721a2149f83a7 (diff) | |
download | FreeBSD-src-35adb2b287f6a212162e322f6369ad381a2b91c6.zip FreeBSD-src-35adb2b287f6a212162e322f6369ad381a2b91c6.tar.gz |
Refactor early stages of security negotiation.
MFC after: 2 weeks
Diffstat (limited to 'usr.sbin/ctld/login.c')
-rw-r--r-- | usr.sbin/ctld/login.c | 150 |
1 files changed, 77 insertions, 73 deletions
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c index fcd2b7f..3e52a6a 100644 --- a/usr.sbin/ctld/login.c +++ b/usr.sbin/ctld/login.c @@ -748,6 +748,30 @@ login_negotiate(struct connection *conn, struct pdu *request) keys_delete(request_keys); } +static void +login_wait_transition(struct connection *conn) +{ + struct pdu *request, *response; + struct iscsi_bhs_login_request *bhslr; + + log_debugx("waiting for state transition request"); + request = login_receive(conn, false); + bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs; + if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0) { + login_send_error(request, 0x02, 0x00); + log_errx(1, "got no \"T\" flag after answering AuthMethod"); + } + pdu_delete(request); + + log_debugx("got state transition request"); + response = login_new_response(request); + login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION); + pdu_send(response); + pdu_delete(response); + + login_negotiate(conn, NULL); +} + void login(struct connection *conn) { @@ -758,7 +782,7 @@ login(struct connection *conn) struct portal_group *pg; const char *initiator_name, *initiator_alias, *session_type, *target_name, *auth_method; - bool redirected; + bool redirected, fail, trans; /* * Handle the initial Login Request - figure out required authentication @@ -867,6 +891,19 @@ login(struct connection *conn) } } + if (ag->ag_type == AG_TYPE_DENY) { + login_send_error(request, 0x02, 0x01); + log_errx(1, "auth-type is \"deny\""); + } + + if (ag->ag_type == AG_TYPE_UNKNOWN) { + /* + * This can happen with empty auth-group. + */ + login_send_error(request, 0x02, 0x01); + log_errx(1, "auth-type not set, denying access"); + } + /* * Enforce initiator-name and initiator-portal. */ @@ -900,80 +937,37 @@ login(struct connection *conn) return; } + fail = false; + response = login_new_response(request); + response_keys = keys_new(); + trans = (bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) != 0; + auth_method = keys_find(request_keys, "AuthMethod"); if (ag->ag_type == AG_TYPE_NO_AUTHENTICATION) { - /* - * Initiator might want to to authenticate, - * but we don't need it. - */ - log_debugx("authentication not required; " - "transitioning to operational parameter negotiation"); - - if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0) - log_warnx("initiator did not set the \"T\" flag; " - "transitioning anyway"); - - response = login_new_response(request); - login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION); - response_keys = keys_new(); - /* - * Required by Linux initiator. - */ - auth_method = keys_find(request_keys, "AuthMethod"); - if (auth_method != NULL && - login_list_contains(auth_method, "None")) + log_debugx("authentication not required"); + if (auth_method == NULL || + login_list_contains(auth_method, "None")) { keys_add(response_keys, "AuthMethod", "None"); - - if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { - if (conn->conn_target->t_alias != NULL) - keys_add(response_keys, - "TargetAlias", conn->conn_target->t_alias); - keys_add_int(response_keys, - "TargetPortalGroupTag", pg->pg_tag); + } else { + log_warnx("initiator requests " + "AuthMethod \"%s\" instead of \"None\"", + auth_method); + keys_add(response_keys, "AuthMethod", "Reject"); + } + if (trans) + login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION); + } else { + log_debugx("CHAP authentication required"); + if (auth_method == NULL || + login_list_contains(auth_method, "CHAP")) { + keys_add(response_keys, "AuthMethod", "CHAP"); + } else { + log_warnx("initiator requests unsupported " + "AuthMethod \"%s\" instead of \"CHAP\"", + auth_method); + keys_add(response_keys, "AuthMethod", "Reject"); + fail = true; } - keys_save(response_keys, response); - pdu_send(response); - pdu_delete(response); - keys_delete(response_keys); - pdu_delete(request); - keys_delete(request_keys); - - login_negotiate(conn, NULL); - return; - } - - if (ag->ag_type == AG_TYPE_DENY) { - login_send_error(request, 0x02, 0x01); - log_errx(1, "auth-type is \"deny\""); - } - - if (ag->ag_type == AG_TYPE_UNKNOWN) { - /* - * This can happen with empty auth-group. - */ - login_send_error(request, 0x02, 0x01); - log_errx(1, "auth-type not set, denying access"); - } - - log_debugx("CHAP authentication required"); - - auth_method = keys_find(request_keys, "AuthMethod"); - if (auth_method == NULL) { - login_send_error(request, 0x02, 0x07); - log_errx(1, "received Login PDU without AuthMethod"); - } - /* - * XXX: This should be Reject, not just a login failure (5.3.2). - */ - if (login_list_contains(auth_method, "CHAP") == 0) { - login_send_error(request, 0x02, 0x01); - log_errx(1, "initiator requests unsupported AuthMethod \"%s\" " - "instead of \"CHAP\"", auth_method); } - - response = login_new_response(request); - - response_keys = keys_new(); - keys_add(response_keys, "AuthMethod", "CHAP"); if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { if (conn->conn_target->t_alias != NULL) keys_add(response_keys, @@ -989,7 +983,17 @@ login(struct connection *conn) pdu_delete(request); keys_delete(request_keys); - login_chap(conn, ag); + if (fail) { + log_debugx("sent reject for AuthMethod; exiting"); + exit(1); + } - login_negotiate(conn, NULL); + if (ag->ag_type != AG_TYPE_NO_AUTHENTICATION) { + login_chap(conn, ag); + login_negotiate(conn, NULL); + } else if (trans) { + login_negotiate(conn, NULL); + } else { + login_wait_transition(conn); + } } |