When parsing a KDC or admin server string, allow the name or address
authorGreg Hudson <ghudson@mit.edu>
Tue, 18 May 2010 17:19:15 +0000 (17:19 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 18 May 2010 17:19:15 +0000 (17:19 +0000)
to be enclosed in brackets so that IPv6 addresses can be represented.
(IPv6 addresses contain colons, which look like port separators.)

ticket: 6562

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24055 dc483132-0cff-0310-8789-dd5450dbe970

doc/admin.texinfo
src/lib/kadm5/alt_prof.c
src/lib/krb5/os/locate_kdc.c

index 7d2e79718784ab03f33889d6aaa724760bf3f00d..ad122a7eba3ae04271ad340de03f341488d0880e 100644 (file)
@@ -680,12 +680,14 @@ tags may be specified in the realm's subsection:
 
 @table @b
 @itemx kdc
-The name of a host running a KDC for that realm.  An optional port
-number (separated from the hostname by a colon) may be included.  For
-your computer to be able to communicate with the KDC for each realm,
-this tag must be given a value in each realm subsection in the
-configuration file, or there must be DNS SRV records specifying the
-KDCs (see @ref{Using DNS}).
+The name or address of a host running a KDC for that realm.  An optional
+port number, separated from the hostname by a colon, may be included.
+If the name or address contains colons (for example, if it is an IPv6
+address), enclose it in square brackets to distinguish the colon from a
+port separator.  For your computer to be able to communicate with the
+KDC for each realm, this tag must be given a value in each realm
+subsection in the configuration file, or there must be DNS SRV records
+specifying the KDCs (see @ref{Using DNS}).
 
 @itemx master_kdc
 Identifies the master KDC(s).  Currently, this tag is used in only one
index c8dc307c1953219b64ee4c0e15c4b16f0eb6007d..bc5eb2314e70bfd05c3dc0546f2e6f0c2426bbd6 100644 (file)
@@ -481,6 +481,36 @@ get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in,
     }
 }
 
+/*
+ * Parse out the port number from an admin_server setting.  Modify server to
+ * contain just the hostname or address.  If a port is given, set *port, and
+ * set the appropriate bit in *mask.
+ */
+static void
+parse_admin_server_port(char *server, int *port, long *mask)
+{
+    char *end, *portstr;
+
+    /* Allow the name or addr to be enclosed in brackets, for IPv6 addrs. */
+    if (*server == '[' && (end = strchr(server + 1, ']')) != NULL) {
+        portstr = (*(end + 1) == ':') ? end + 2 : NULL;
+        /* Shift the bracketed name or address back into server. */
+        memmove(server, server + 1, end - (server + 1));
+        *(end - 1) = '\0';
+    } else {
+        /* Terminate the name at the colon, if any. */
+        end = server + strcspn(server, ":");
+        portstr = (*end == ':') ? end + 1 : NULL;
+        *end = '\0';
+    }
+
+    /* If we found a port string, parse it and set the appropriate bit. */
+    if (portstr) {
+        *port = atoi(portstr);
+        *mask |= KADM5_CONFIG_KADMIND_PORT;
+    }
+}
+
 /*
  * Function: kadm5_get_config_params
  *
@@ -581,13 +611,8 @@ krb5_error_code kadm5_get_config_params(context, use_kdc_config,
                      NULL);
 
     if (params.mask & KADM5_CONFIG_ADMIN_SERVER) {
-        char *p;
-        p = strchr(params.admin_server, ':');
-        if (p) {
-            params.kadmind_port = atoi(p+1);
-            params.mask |= KADM5_CONFIG_KADMIND_PORT;
-            *p = '\0';
-        }
+        parse_admin_server_port(params.admin_server, &params.kadmind_port,
+                                &params.mask);
     }
 
     /* Get the value for the database */
index 27004a9d04a1ceb9dd15effa3b8825fbd944db1c..09842360035697ead46531dfe5d94bc25aae8434 100644 (file)
@@ -374,19 +374,11 @@ locate_srv_conf_1(krb5_context context, const krb5_data *realm,
         if (code == 0) {
             for (i=0; masterlist[i]; i++) {
                 host = masterlist[i];
-
-                /*
-                 * Strip off excess whitespace
-                 */
-                cp = strchr(host, ' ');
-                if (cp)
-                    *cp = 0;
-                cp = strchr(host, '\t');
-                if (cp)
-                    *cp = 0;
-                cp = strchr(host, ':');
-                if (cp)
-                    *cp = 0;
+                /* Strip off excess characters. */
+                if (*host == '[' && (cp = strchr(host, ']')))
+                    *(cp + 1) = '\0';
+                else
+                    *(host + strcspn(host, " \t:")) = '\0';
             }
         }
     } else {
@@ -407,20 +399,13 @@ locate_srv_conf_1(krb5_context context, const krb5_data *realm,
 
         host = hostlist[i];
         Tprintf ("entry %d is '%s'\n", i, host);
-        /*
-         * Strip off excess whitespace
-         */
-        cp = strchr(host, ' ');
-        if (cp)
-            *cp = 0;
-        cp = strchr(host, '\t');
-        if (cp)
-            *cp = 0;
-        port = strchr(host, ':');
-        if (port) {
-            *port = 0;
-            port++;
-        }
+        /* Find port number, and strip off any excess characters. */
+        if (*host == '[' && (cp = strchr(host, ']')))
+            cp = cp + 1;
+        else
+            cp = host + strcspn(host, " \t:");
+        port = (*cp == ':') ? cp + 1 : NULL;
+        *cp = '\0';
 
         ismaster = 0;
         if (masterlist) {
@@ -454,15 +439,20 @@ locate_srv_conf_1(krb5_context context, const krb5_data *realm,
             p2 = sec_udpport;
         }
 
+        /* If the hostname was in brackets, strip those off now. */
+        if (*host == '[' && (cp = strchr(host, ']'))) {
+            host++;
+            *cp = '\0';
+        }
+
         if (socktype != 0)
-            code = add_host_to_list (addrlist, hostlist[i], p1, p2,
-                                     socktype, family);
+            code = add_host_to_list(addrlist, host, p1, p2, socktype, family);
         else {
-            code = add_host_to_list (addrlist, hostlist[i], p1, p2,
-                                     SOCK_DGRAM, family);
+            code = add_host_to_list(addrlist, host, p1, p2, SOCK_DGRAM,
+                                    family);
             if (code == 0)
-                code = add_host_to_list (addrlist, hostlist[i], p1, p2,
-                                         SOCK_STREAM, family);
+                code = add_host_to_list(addrlist, host, p1, p2, SOCK_STREAM,
+                                        family);
         }
         if (code) {
             Tprintf ("error %d (%s) returned from add_host_to_list\n", code,