--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/patches/027-add_admin_sname_princ.patch Wed Feb 24 10:43:57 2016 -0600
@@ -0,0 +1,223 @@
+#
+# 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
+#
+diff -pur old/src/kadmin/dbutil/kadm5_create.c new/src/kadmin/dbutil/kadm5_create.c
+--- old/src/kadmin/dbutil/kadm5_create.c
++++ new/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_conf
+ 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
+ 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_c
+
+ 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_c
+ 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_c
+ }
+
+ krb5_free_principal(context, ent.principal);
+- free(fullname);
+
+ return OK;
+ }
+diff -pur old/src/lib/kadm5/admin.h new/src/lib/kadm5/admin.h
+--- old/src/lib/kadm5/admin.h
++++ new/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;