From owner-svn-src-head@freebsd.org Sat Aug 8 19:04:38 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 62D579B64EC; Sat, 8 Aug 2015 19:04:38 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4664D1DD3; Sat, 8 Aug 2015 19:04:38 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t78J4cZr001848; Sat, 8 Aug 2015 19:04:38 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t78J4c0R001847; Sat, 8 Aug 2015 19:04:38 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201508081904.t78J4c0R001847@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Sat, 8 Aug 2015 19:04:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r286462 - head/usr.sbin/ctld X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Aug 2015 19:04:38 -0000 Author: mav Date: Sat Aug 8 19:04:37 2015 New Revision: 286462 URL: https://svnweb.freebsd.org/changeset/base/286462 Log: Refactor early stages of security negotiation. MFC after: 2 weeks Modified: head/usr.sbin/ctld/login.c Modified: head/usr.sbin/ctld/login.c ============================================================================== --- head/usr.sbin/ctld/login.c Sat Aug 8 18:37:20 2015 (r286461) +++ head/usr.sbin/ctld/login.c Sat Aug 8 19:04:37 2015 (r286462) @@ -748,6 +748,30 @@ login_negotiate(struct connection *conn, 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); - } - 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); + } 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; + } } - - 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); + } }