Author: trasz
Date: Tue Mar 25 12:01:55 2014
New Revision: 263720
URL: http://svnweb.freebsd.org/changeset/base/263720

Log:
  MFC r261754:
  
  Implement initiator-name and initiator-portal restrictions.
  
  Sponsored by: The FreeBSD Foundation

Modified:
  stable/10/usr.sbin/ctld/ctl.conf.5
  stable/10/usr.sbin/ctld/ctld.c
  stable/10/usr.sbin/ctld/ctld.h
  stable/10/usr.sbin/ctld/login.c
  stable/10/usr.sbin/ctld/parse.y
  stable/10/usr.sbin/ctld/token.l
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.sbin/ctld/ctl.conf.5
==============================================================================
--- stable/10/usr.sbin/ctld/ctl.conf.5  Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/ctl.conf.5  Tue Mar 25 12:01:55 2014        
(r263720)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 2, 2013
+.Dd February 11, 2014
 .Dt CTL.CONF 5
 .Os
 .Sh NAME
@@ -107,6 +107,18 @@ Specifies CHAP authentication credential
 Specifies mutual CHAP authentication credentials.
 Note that for any auth-group, configuration may contain either chap,
 or chap-mutual entries; it's an error to mix them.
+.It Ic initiator-name Ao Ar initiator-name Ac
+Specifies iSCSI initiator name.
+If not defined, there will be no restrictions based on initiator
+name.
+Otherwise, only initiators with names matching one of defined
+ones will be allowed to connect.
+.It Ic initiator-portal Ao Ar address Ac
+Specifies iSCSI initiator portal - IPv4 or IPv6 address.
+If not defined, there will be no restrictions based on initiator
+address.
+Otherwise, only initiators with addresses matching one of defined
+ones will be allowed to connect.
 .El
 .Ss portal-group level
 The following statements are available at the portal-group level:
@@ -143,6 +155,22 @@ or chap-mutual clauses; it's a configura
 Specifies mutual CHAP authentication credentials.
 Note that targets must use either auth-group, chap, or
 chap-mutual clauses; it's a configuration error to mix them in one target.
+.It Ic initiator-name Ao Ar initiator-name Ac
+Specifies iSCSI initiator name.
+If not defined, there will be no restrictions based on initiator
+name.
+Otherwise, only initiators with names matching one of defined
+ones will be allowed to connect.
+This clause is mutually exclusive with auth-group; one cannot use
+both in a single target.
+.It Ic initiator-portal Ao Ar address Ac
+Specifies iSCSI initiator portal - IPv4 or IPv6 address.
+If not defined, there will be no restrictions based on initiator
+address.
+Otherwise, only initiators with addresses matching one of defined
+ones will be allowed to connect.
+This clause is mutually exclusive with auth-group; one cannot use
+both in a single target.
 .It Ic portal-group Aq Ar name
 Assigns previously defined portal group to that target.
 Default portal group is "default", which makes the target available

Modified: stable/10/usr.sbin/ctld/ctld.c
==============================================================================
--- stable/10/usr.sbin/ctld/ctld.c      Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/ctld.c      Tue Mar 25 12:01:55 2014        
(r263720)
@@ -149,6 +149,94 @@ auth_find(struct auth_group *ag, const c
        return (NULL);
 }
 
+const struct auth_name *
+auth_name_new(struct auth_group *ag, const char *name)
+{
+       struct auth_name *an;
+
+       an = calloc(1, sizeof(*an));
+       if (an == NULL)
+               log_err(1, "calloc");
+       an->an_auth_group = ag;
+       an->an_initator_name = checked_strdup(name);
+       TAILQ_INSERT_TAIL(&ag->ag_names, an, an_next);
+       return (an);
+}
+
+static void
+auth_name_delete(struct auth_name *an)
+{
+       TAILQ_REMOVE(&an->an_auth_group->ag_names, an, an_next);
+
+       free(an->an_initator_name);
+       free(an);
+}
+
+bool
+auth_name_defined(const struct auth_group *ag)
+{
+       if (TAILQ_EMPTY(&ag->ag_names))
+               return (false);
+       return (true);
+}
+
+const struct auth_name *
+auth_name_find(const struct auth_group *ag, const char *name)
+{
+       const struct auth_name *auth_name;
+
+       TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) {
+               if (strcmp(auth_name->an_initator_name, name) == 0)
+                       return (auth_name);
+       }
+
+       return (NULL);
+}
+
+const struct auth_portal *
+auth_portal_new(struct auth_group *ag, const char *portal)
+{
+       struct auth_portal *ap;
+
+       ap = calloc(1, sizeof(*ap));
+       if (ap == NULL)
+               log_err(1, "calloc");
+       ap->ap_auth_group = ag;
+       ap->ap_initator_portal = checked_strdup(portal);
+       TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
+       return (ap);
+}
+
+static void
+auth_portal_delete(struct auth_portal *ap)
+{
+       TAILQ_REMOVE(&ap->ap_auth_group->ag_portals, ap, ap_next);
+
+       free(ap->ap_initator_portal);
+       free(ap);
+}
+
+bool
+auth_portal_defined(const struct auth_group *ag)
+{
+       if (TAILQ_EMPTY(&ag->ag_portals))
+               return (false);
+       return (true);
+}
+
+const struct auth_portal *
+auth_portal_find(const struct auth_group *ag, const char *portal)
+{
+       const struct auth_portal *auth_portal;
+
+       TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next) {
+               if (strcmp(auth_portal->ap_initator_portal, portal) == 0)
+                       return (auth_portal);
+       }
+
+       return (NULL);
+}
+
 struct auth_group *
 auth_group_new(struct conf *conf, const char *name)
 {
@@ -168,6 +256,8 @@ auth_group_new(struct conf *conf, const 
        if (name != NULL)
                ag->ag_name = checked_strdup(name);
        TAILQ_INIT(&ag->ag_auths);
+       TAILQ_INIT(&ag->ag_names);
+       TAILQ_INIT(&ag->ag_portals);
        ag->ag_conf = conf;
        TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
 
@@ -177,12 +267,19 @@ auth_group_new(struct conf *conf, const 
 void
 auth_group_delete(struct auth_group *ag)
 {
-       struct auth *auth, *tmp;
+       struct auth *auth, *auth_tmp;
+       struct auth_name *auth_name, *auth_name_tmp;
+       struct auth_portal *auth_portal, *auth_portal_tmp;
 
        TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
 
-       TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, tmp)
+       TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, auth_tmp)
                auth_delete(auth);
+       TAILQ_FOREACH_SAFE(auth_name, &ag->ag_names, an_next, auth_name_tmp)
+               auth_name_delete(auth_name);
+       TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_portals, ap_next,
+           auth_portal_tmp)
+               auth_portal_delete(auth_portal);
        free(ag->ag_name);
        free(ag);
 }
@@ -832,6 +929,8 @@ conf_print(struct conf *conf)
 {
        struct auth_group *ag;
        struct auth *auth;
+       struct auth_name *auth_name;
+       struct auth_portal *auth_portal;
        struct portal_group *pg;
        struct portal *portal;
        struct target *targ;
@@ -844,6 +943,12 @@ conf_print(struct conf *conf)
                        fprintf(stderr, "\t chap-mutual %s %s %s %s\n",
                            auth->a_user, auth->a_secret,
                            auth->a_mutual_user, auth->a_mutual_secret);
+               TAILQ_FOREACH(auth_name, &ag->ag_names, an_next)
+                       fprintf(stderr, "\t initiator-name %s\n",
+                           auth_name->an_initator_name);
+               TAILQ_FOREACH(auth_portal, &ag->ag_portals, an_next)
+                       fprintf(stderr, "\t initiator-portal %s\n",
+                           auth_portal->an_initator_portal);
                fprintf(stderr, "}\n");
        }
        TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {

Modified: stable/10/usr.sbin/ctld/ctld.h
==============================================================================
--- stable/10/usr.sbin/ctld/ctld.h      Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/ctld.h      Tue Mar 25 12:01:55 2014        
(r263720)
@@ -53,6 +53,18 @@ struct auth {
        char                            *a_mutual_secret;
 };
 
+struct auth_name {
+       TAILQ_ENTRY(auth_name)          an_next;
+       struct auth_group               *an_auth_group;
+       char                            *an_initator_name;
+};
+
+struct auth_portal {
+       TAILQ_ENTRY(auth_portal)        ap_next;
+       struct auth_group               *ap_auth_group;
+       char                            *ap_initator_portal;
+};
+
 #define        AG_TYPE_UNKNOWN                 0
 #define        AG_TYPE_NO_AUTHENTICATION       1
 #define        AG_TYPE_CHAP                    2
@@ -65,6 +77,8 @@ struct auth_group {
        struct target                   *ag_target;
        int                             ag_type;
        TAILQ_HEAD(, auth)              ag_auths;
+       TAILQ_HEAD(, auth_name)         ag_names;
+       TAILQ_HEAD(, auth_portal)       ag_portals;
 };
 
 struct portal {
@@ -192,6 +206,18 @@ const struct auth  *auth_new_chap_mutual(
 const struct auth      *auth_find(struct auth_group *ag,
                            const char *user);
 
+const struct auth_name *auth_name_new(struct auth_group *ag,
+                           const char *initiator_name);
+bool                   auth_name_defined(const struct auth_group *ag);
+const struct auth_name *auth_name_find(const struct auth_group *ag,
+                           const char *initiator_name);
+
+const struct auth_portal       *auth_portal_new(struct auth_group *ag,
+                                   const char *initiator_portal);
+bool                   auth_portal_defined(const struct auth_group *ag);
+const struct auth_portal       *auth_portal_find(const struct auth_group *ag,
+                                   const char *initiator_portal);
+
 struct portal_group    *portal_group_new(struct conf *conf, const char *name);
 void                   portal_group_delete(struct portal_group *pg);
 struct portal_group    *portal_group_find(struct conf *conf, const char *name);

Modified: stable/10/usr.sbin/ctld/login.c
==============================================================================
--- stable/10/usr.sbin/ctld/login.c     Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/login.c     Tue Mar 25 12:01:55 2014        
(r263720)
@@ -940,6 +940,33 @@ login(struct connection *conn)
        }
 
        /*
+        * Enforce initiator-name and initiator-portal.
+        */
+       if (auth_name_defined(ag)) {
+               if (auth_name_find(ag, initiator_name) == NULL) {
+                       login_send_error(request, 0x02, 0x02);
+                       log_errx(1, "initiator does not match allowed "
+                           "initiator names");
+               }
+               log_debugx("initiator matches allowed initiator names");
+       } else {
+               log_debugx("auth-group does not define initiator name "
+                   "restrictions");
+       }
+
+       if (auth_portal_defined(ag)) {
+               if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
+                       login_send_error(request, 0x02, 0x02);
+                       log_errx(1, "initiator does not match allowed "
+                           "initiator portals");
+               }
+               log_debugx("initiator matches allowed initiator portals");
+       } else {
+               log_debugx("auth-group does not define initiator portal "
+                   "restrictions");
+       }
+
+       /*
         * Let's see if the initiator intends to do any kind of authentication
         * at all.
         */

Modified: stable/10/usr.sbin/ctld/parse.y
==============================================================================
--- stable/10/usr.sbin/ctld/parse.y     Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/parse.y     Tue Mar 25 12:01:55 2014        
(r263720)
@@ -58,9 +58,9 @@ extern void   yyrestart(FILE *);
 %}
 
 %token ALIAS AUTH_GROUP BACKEND BLOCKSIZE CHAP CHAP_MUTUAL CLOSING_BRACKET
-%token DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP LISTEN LISTEN_ISER LUN MAXPROC NUM
-%token OPENING_BRACKET OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR TARGET 
-%token TIMEOUT
+%token DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP INITIATOR_NAME INITIATOR_PORTAL
+%token LISTEN LISTEN_ISER LUN MAXPROC NUM OPENING_BRACKET OPTION PATH PIDFILE
+%token PORTAL_GROUP SERIAL SIZE STR TARGET TIMEOUT
 
 %union
 {
@@ -148,6 +148,10 @@ auth_group_entry:
        auth_group_chap
        |
        auth_group_chap_mutual
+       |
+       auth_group_initiator_name
+       |
+       auth_group_initiator_portal
        ;
 
 auth_group_chap:       CHAP STR STR
@@ -176,6 +180,28 @@ auth_group_chap_mutual:    CHAP_MUTUAL STR 
        }
        ;
 
+auth_group_initiator_name:     INITIATOR_NAME STR
+       {
+               const struct auth_name *an;
+
+               an = auth_name_new(auth_group, $2);
+               free($2);
+               if (an == NULL)
+                       return (1);
+       }
+       ;
+
+auth_group_initiator_portal:   INITIATOR_PORTAL STR
+       {
+               const struct auth_portal *ap;
+
+               ap = auth_portal_new(auth_group, $2);
+               free($2);
+               if (ap == NULL)
+                       return (1);
+       }
+       ;
+
 portal_group_definition:       PORTAL_GROUP portal_group_name
     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
        {
@@ -277,6 +303,10 @@ target_entry:
        |
        chap_mutual_statement
        |
+       initiator_name_statement
+       |
+       initiator_portal_statement
+       |
        portal_group_statement
        |
        lun_statement
@@ -382,6 +412,60 @@ chap_mutual_statement:     CHAP_MUTUAL STR S
        }
        ;
 
+initiator_name_statement:      INITIATOR_NAME STR
+       {
+               const struct auth_name *an;
+
+               if (target->t_auth_group != NULL) {
+                       if (target->t_auth_group->ag_name != NULL) {
+                               log_warnx("cannot mix auth-group with "
+                                   "initiator-name for target \"%s\"",
+                                   target->t_iqn);
+                               free($2);
+                               return (1);
+                       }
+               } else {
+                       target->t_auth_group = auth_group_new(conf, NULL);
+                       if (target->t_auth_group == NULL) {
+                               free($2);
+                               return (1);
+                       }
+                       target->t_auth_group->ag_target = target;
+               }
+               an = auth_name_new(target->t_auth_group, $2);
+               free($2);
+               if (an == NULL)
+                       return (1);
+       }
+       ;
+
+initiator_portal_statement:    INITIATOR_PORTAL STR
+       {
+               const struct auth_portal *ap;
+
+               if (target->t_auth_group != NULL) {
+                       if (target->t_auth_group->ag_name != NULL) {
+                               log_warnx("cannot mix auth-group with "
+                                   "initiator-portal for target \"%s\"",
+                                   target->t_iqn);
+                               free($2);
+                               return (1);
+                       }
+               } else {
+                       target->t_auth_group = auth_group_new(conf, NULL);
+                       if (target->t_auth_group == NULL) {
+                               free($2);
+                               return (1);
+                       }
+                       target->t_auth_group->ag_target = target;
+               }
+               ap = auth_portal_new(target->t_auth_group, $2);
+               free($2);
+               if (ap == NULL)
+                       return (1);
+       }
+       ;
+
 portal_group_statement:        PORTAL_GROUP STR
        {
                if (target->t_portal_group != NULL) {

Modified: stable/10/usr.sbin/ctld/token.l
==============================================================================
--- stable/10/usr.sbin/ctld/token.l     Tue Mar 25 12:00:05 2014        
(r263719)
+++ stable/10/usr.sbin/ctld/token.l     Tue Mar 25 12:01:55 2014        
(r263720)
@@ -57,6 +57,8 @@ chap-mutual           { return CHAP_MUTUAL; }
 debug                  { return DEBUG; }
 device-id              { return DEVICE_ID; }
 discovery-auth-group   { return DISCOVERY_AUTH_GROUP; }
+initiator-name         { return INITIATOR_NAME; }
+initiator-portal       { return INITIATOR_PORTAL; }
 listen                 { return LISTEN; }
 listen-iser            { return LISTEN_ISER; }
 lun                    { return LUN; }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to