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);
+       }
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to