components/krb5/patches/027-add_admin_sname_princ.patch
author Neng Xue <neng.xue@oracle.com>
Mon, 26 Sep 2016 15:58:55 -0700
changeset 6978 14cbeb78966a
parent 6599 1d033832c5e7
permissions -rw-r--r--
24669827 Update Userland krb5 to MIT 1.14.4

#
# This patch modifies add_admin_princ() to call krb5_sname_to_princ() instead
# of querying naming and constructing the service principal names directly.
#
# Patch offered upstream:
# https://github.com/krb5/krb5/pull/333
# Patch source: in-house
#
--- a/src/kadmin/dbutil/kadm5_create.c
+++ b/src/kadmin/dbutil/kadm5_create.c
@@ -44,8 +44,14 @@
 #include <kdb.h>
 #include "kdb5_util.h"
 
-static int add_admin_princ(void *handle, krb5_context context,
-                           char *name, char *realm, int attrs, int lifetime);
+static int add_admin_princ_common(void *handle, krb5_context context,
+                                  krb5_principal principal, int attrs,
+                                  int lifetime);
+static int add_admin_princ(void *handle, krb5_context context, char *name,
+                           char *realm, int attrs, int lifetime);
+static int add_admin_sname_princ(void *handle, krb5_context context,
+                                 char *sname, char *realm, int attrs,
+                                 int lifetime);
 static int add_admin_princs(void *handle, krb5_context context, char *realm);
 
 #define ERR 1
@@ -145,64 +151,11 @@ int kadm5_create_magic_princs(kadm5_config_params *params,
 static int add_admin_princs(void *handle, krb5_context context, char *realm)
 {
     krb5_error_code ret = 0;
-    char *service_name = 0, *kiprop_name = 0, *p;
-    char localname[MAXHOSTNAMELEN];
-    struct addrinfo *ai, ai_hints;
-    int gai_error;
-
-    if (gethostname(localname, MAXHOSTNAMELEN)) {
-        ret = errno;
-        perror("gethostname");
-        goto clean_and_exit;
-    }
-    memset(&ai_hints, 0, sizeof(ai_hints));
-    ai_hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
-    gai_error = getaddrinfo(localname, (char *)NULL, &ai_hints, &ai);
-    if (gai_error) {
-        ret = EINVAL;
-        fprintf(stderr, "getaddrinfo(%s): %s\n", localname,
-                gai_strerror(gai_error));
-        goto clean_and_exit;
-    }
-    if (ai->ai_canonname == NULL) {
-        ret = EINVAL;
-        fprintf(stderr, _("getaddrinfo(%s): Cannot determine canonical "
-                          "hostname.\n"), localname);
-        freeaddrinfo(ai);
-        goto clean_and_exit;
-    }
-    for (p = ai->ai_canonname; *p; p++) {
-#ifdef isascii
-        if (!isascii(*p))
-            continue;
-#else
-        if (*p < ' ')
-            continue;
-        if (*p > '~')
-            continue;
-#endif
-        if (!isupper(*p))
-            continue;
-        *p = tolower(*p);
-    }
-    if (asprintf(&service_name, "kadmin/%s", ai->ai_canonname) < 0) {
-        ret = ENOMEM;
-        fprintf(stderr, _("Out of memory\n"));
-        freeaddrinfo(ai);
-        goto clean_and_exit;
-    }
-    if (asprintf(&kiprop_name, "kiprop/%s", ai->ai_canonname) < 0) {
-        ret = ENOMEM;
-        fprintf(stderr, _("Out of memory\n"));
-        freeaddrinfo(ai);
-        goto clean_and_exit;
-    }
-    freeaddrinfo(ai);
 
-    if ((ret = add_admin_princ(handle, context,
-                               service_name, realm,
-                               KRB5_KDB_DISALLOW_TGT_BASED,
-                               ADMIN_LIFETIME)))
+    if ((ret = add_admin_sname_princ(handle, context,
+                                     KADM5_ADMIN_HOST_SERVICE, realm,
+                                     KRB5_KDB_DISALLOW_TGT_BASED,
+                                     ADMIN_LIFETIME)))
         goto clean_and_exit;
 
     if ((ret = add_admin_princ(handle, context,
@@ -218,17 +171,60 @@ static int add_admin_princs(void *handle, krb5_context context, char *realm)
                                CHANGEPW_LIFETIME)))
         goto clean_and_exit;
 
-    ret = add_admin_princ(handle, context, kiprop_name, realm, 0, 0);
+    ret = add_admin_sname_princ(handle, context, KADM5_KIPROP_HOST_SERVICE,
+                                realm, 0, 0);
 
 clean_and_exit:
-    free(service_name);
-    free(kiprop_name);
-
     return ret;
 }
 
+static int add_admin_princ(void *handle, krb5_context context,
+                    char *name, char *realm, int attrs, int lifetime)
+{
+    krb5_error_code ret;
+    char *fullname;
+    krb5_principal principal;
+
+    if (asprintf(&fullname, "%s@%s", name, realm) < 0) {
+        com_err(progname, ENOMEM, _("while appending realm to principal"));
+        return ERR;
+    }
+    ret = krb5_parse_name(context, fullname, &principal);
+    if (ret) {
+        com_err(progname, ret, _("while parsing admin principal name"));
+        return(ERR);
+    }
+    free (fullname);
+
+    return add_admin_princ_common(handle, context, principal, attrs, lifetime);
+}
+
+static int add_admin_sname_princ(void *handle, krb5_context context,
+                                 char *sname, char *realm, int attrs,
+                                 int lifetime)
+{
+    krb5_error_code ret;
+    krb5_principal principal;
+    char *lrealm;
+
+    ret = krb5_sname_to_principal(context, NULL, sname, KRB5_NT_SRV_HST,
+                                  &principal);
+    if (ret) {
+        com_err(progname, ret, _("while parsing admin SPN"));
+        return(ERR);
+    }
+
+    ret = krb5_set_principal_realm(context, principal, realm);
+    if (ret) {
+        com_err(progname, ret, _("while supplying realm to principal"));
+        return ERR;
+    }
+
+    return add_admin_princ_common(handle, context, principal, attrs, lifetime);
+}
+
 /*
- * Function: add_admin_princ
+ * Function: add_admin_princ_common
  *
  * Arguments:
  *
@@ -255,9 +251,9 @@ clean_and_exit:
  * Otherwise, the principal is created with mod_by creator and
  * attributes attrs and max life of lifetime (if not zero).
  */
-
-int add_admin_princ(void *handle, krb5_context context,
-                    char *name, char *realm, int attrs, int lifetime)
+static int add_admin_princ_common(void *handle, krb5_context context,
+                                  krb5_principal principal, int attrs,
+                                  int lifetime)
 {
     char *fullname;
     krb5_error_code ret;
@@ -266,15 +262,7 @@ int add_admin_princ(void *handle, krb5_context context,
 
     memset(&ent, 0, sizeof(ent));
 
-    if (asprintf(&fullname, "%s@%s", name, realm) < 0) {
-        com_err(progname, ENOMEM, _("while appending realm to principal"));
-        return ERR;
-    }
-    ret = krb5_parse_name(context, fullname, &ent.principal);
-    if (ret) {
-        com_err(progname, ret, _("while parsing admin principal name"));
-        return(ERR);
-    }
+    ent.principal = principal;
     ent.max_life = lifetime;
     ent.attributes = attrs;
 
@@ -283,6 +271,7 @@ int add_admin_princ(void *handle, krb5_context context,
         flags |= KADM5_MAX_LIFE;
     ret = kadm5_create_principal(handle, &ent, flags, NULL);
     if (ret && ret != KADM5_DUP) {
+        krb5_unparse_name(context, principal, &fullname);
         com_err(progname, ret, _("while creating principal %s"), fullname);
         krb5_free_principal(context, ent.principal);
         free(fullname);
@@ -290,7 +279,6 @@ int add_admin_princ(void *handle, krb5_context context,
     }
 
     krb5_free_principal(context, ent.principal);
-    free(fullname);
 
     return OK;
 }
--- a/src/lib/kadm5/admin.h
+++ b/src/lib/kadm5/admin.h
@@ -64,7 +64,9 @@ KADM5INT_BEGIN_DECLS
 #define KADM5_ADMIN_SERVICE     "kadmin/admin"
 #define KADM5_CHANGEPW_SERVICE  "kadmin/changepw"
 #define KADM5_HIST_PRINCIPAL    "kadmin/history"
-#define KADM5_KIPROP_HOST_SERVICE "kiprop"
+
+#define KADM5_KIPROP_HOST_SERVICE	"kiprop"
+#define	KADM5_ADMIN_HOST_SERVICE	"kadmin"
 
 typedef krb5_principal  kadm5_princ_t;
 typedef char            *kadm5_policy_t;