]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Allow ":port" suffixes in sn2princ hostnames
authorGreg Hudson <ghudson@mit.edu>
Sun, 8 Dec 2013 23:05:26 +0000 (18:05 -0500)
committerGreg Hudson <ghudson@mit.edu>
Thu, 12 Dec 2013 04:56:35 +0000 (23:56 -0500)
MSSQLSvc principal names can contain a ":port" or ":instance" trailer
on the hostname part.  If we see that in the hostname argument of
krb5_sname_to_principal(), remove it before canonicalizing the
hostname and put it back on afterwards.

ticket: 7795 (new)

src/lib/krb5/os/sn2princ.c

index c9b3c8276b2d8c89a74d78c627a449c57f800894..92969cd413fc3bf3882f0dd9a6e237f4eda403c3 100644 (file)
@@ -116,6 +116,20 @@ cleanup:
     return (*canonhost_out == NULL) ? ENOMEM : 0;
 }
 
+/* If hostname appears to have a :port or :instance trailer (used in MSSQLSvc
+ * principals), return a pointer to the separator.  Otherwise return NULL. */
+static const char *
+find_trailer(const char *hostname)
+{
+    const char *p = strchr(hostname, ':');
+
+    /* Look for a single colon followed by one or more characters.  An IPv6
+     * address will have more than one colon, so don't accept that. */
+    if (p == NULL || p[1] == '\0' || strchr(p + 1, ':') != NULL)
+        return NULL;
+    return p;
+}
+
 krb5_error_code KRB5_CALLCONV
 krb5_sname_to_principal(krb5_context context, const char *hostname,
                         const char *sname, krb5_int32 type,
@@ -123,8 +137,9 @@ krb5_sname_to_principal(krb5_context context, const char *hostname,
 {
     krb5_error_code ret;
     krb5_principal princ;
-    const char *realm;
-    char **hrealms = NULL, *canonhost = NULL, localname[MAXHOSTNAMELEN];
+    const char *realm, *trailer;
+    char **hrealms = NULL, *canonhost = NULL, *hostonly = NULL, *concat = NULL;
+    char localname[MAXHOSTNAMELEN];
 
     *princ_out = NULL;
 
@@ -142,6 +157,15 @@ krb5_sname_to_principal(krb5_context context, const char *hostname,
     if (sname == NULL)
         sname = "host";
 
+    /* If there is a trailer, remove it for now. */
+    trailer = find_trailer(hostname);
+    if (trailer != NULL) {
+        hostonly = k5memdup0(hostname, trailer - hostname, &ret);
+        if (hostonly == NULL)
+            goto cleanup;
+        hostname = hostonly;
+    }
+
     /* Canonicalize the hostname if appropriate. */
     ret = canon_hostname(context, type, hostname, &canonhost);
     if (ret)
@@ -158,6 +182,15 @@ krb5_sname_to_principal(krb5_context context, const char *hostname,
     }
     realm = hrealms[0];
 
+    /* If there was a trailer, put it back on the end. */
+    if (trailer != NULL) {
+        if (asprintf(&concat, "%s%s", hostname, trailer) < 0) {
+            ret = ENOMEM;
+            goto cleanup;
+        }
+        hostname = concat;
+    }
+
     ret = krb5_build_principal(context, &princ, strlen(realm), realm, sname,
                                hostname, (char *)NULL);
     if (ret)
@@ -167,7 +200,9 @@ krb5_sname_to_principal(krb5_context context, const char *hostname,
     *princ_out = princ;
 
 cleanup:
+    free(hostonly);
     free(canonhost);
+    free(concat);
     krb5_free_host_realm(context, hrealms);
     return ret;
 }