From 8372a0c91d6da34cbc6174313f891529b6a13fc9 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Thu, 28 Apr 2011 02:52:38 -0400
Subject: [PATCH] Added some kerberos functions for building compatibility

Function sss_krb5_unparse_name_flags and some of its supporting functions have
been added in order to ensure compilation on systems having kerberos < 1.8
---
 configure.ac                    |    7 ++
 src/providers/krb5/krb5_child.c |    4 +-
 src/util/sss_krb5.c             |  172 +++++++++++++++++++++++++++++++++++++-
 src/util/sss_krb5.h             |    4 +
 4 files changed, 180 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index 18aa823b9f523bafc6c45efce896574d442309b2..6cd179ad0e5030afb6c434c1f562737e557cfb1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -143,6 +143,13 @@ if test x$has_dbus != xno; then
     LIBS="$SAFE_LIBS"
 fi
 
+SAFE_LIBS="$LIBS"
+LIBS="-lkrb5"
+AC_CHECK_FUNC([krb5_unparse_name_flags],
+              AC_DEFINE([HAVE_KRB5_UNPARSE_NAME_FLAGS], [1],
+                        [Define if krb5_unparse_name_flags exists]))
+LIBS="$SAFE_LIBS"
+
 if test x$HAVE_MANPAGES != x; then
     CHECK_XML_TOOLS
     CHECK_STYLESHEET([$SGML_CATALOG_FILES],
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index fcd108aac872cf0eb9b9f5c30c54c28d7b657a12..ffc6c798de5e525388aa2224861e7af9cf6604a0 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -1460,11 +1460,11 @@ static int krb5_child_setup(struct krb5_req *kr, uint32_t offline)
                     DEBUG(1, ("krb5_parse_name failed.\n"));
                     goto failed;
                 }
-                kerr = krb5_unparse_name_flags(kr->ctx, fast_princ_struct,
+                kerr = sss_krb5_unparse_name_flags(kr->ctx, fast_princ_struct,
                                                KRB5_PRINCIPAL_UNPARSE_NO_REALM,
                                                &tmp_str);
                 if (kerr) {
-                    DEBUG(1, ("krb5_unparse_name_flags failed.\n"));
+                    DEBUG(1, ("sss_krb5_unparse_name_flags failed.\n"));
                     goto failed;
                 }
                 fast_principal = talloc_strdup(kr, tmp_str);
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 064bc6b1284f6f8e141243ffe23103496165d226..25614b57142f9e9fd0ee3d712063e8e387151fc5 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -143,9 +143,9 @@ errno_t select_principal_from_keytab(TALLOC_CTX *mem_ctx,
         }
 
         if (_primary) {
-            kerr = krb5_unparse_name_flags(krb_ctx, client_princ,
-                                           KRB5_PRINCIPAL_UNPARSE_NO_REALM,
-                                           &principal_string);
+            kerr = sss_krb5_unparse_name_flags(krb_ctx, client_princ,
+                                               KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+                                               &principal_string);
             if (kerr) {
                 DEBUG(1, ("krb5_unparse_name failed"));
                 ret = EFAULT;
@@ -410,8 +410,8 @@ static bool match_principal(krb5_context ctx,
             primary_str_len = tmp_len-1;
         }
 
-        krb5_unparse_name_flags(ctx, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
-                                &primary);
+        sss_krb5_unparse_name_flags(ctx, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+                                    &primary);
 
         len_diff = strlen(primary)-primary_str_len;
 
@@ -741,3 +741,165 @@ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags(
     return 0;
 #endif
 }
+
+
+#ifndef HAVE_KRB5_UNPARSE_NAME_FLAGS
+
+#define KRB5_PRINCIPAL_UNPARSE_SHORT 0x1
+#define KRB5_PRINCIPAL_UNPARSE_NO_REALM 0x2
+#define KRB5_PRINCIPAL_UNPARSE_DISPLAY 0x4
+#ifndef REALM_SEP
+    #define REALM_SEP       '@'
+#endif
+#ifndef COMPONENT_SEP
+    #define COMPONENT_SEP   '/'
+#endif
+
+static int
+sss_krb5_copy_component_quoting(char *dest, const krb5_data *src, int flags)
+{
+    int j;
+    const char *cp = src->data;
+    char *q = dest;
+    int length = src->length;
+
+    if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
+        memcpy(dest, src->data, src->length);
+        return src->length;
+    }
+
+    for (j=0; j < length; j++,cp++) {
+        int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
+            !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
+
+        switch (*cp) {
+        case REALM_SEP:
+            if (no_realm) {
+                *q++ = *cp;
+                break;
+            }
+        case COMPONENT_SEP:
+        case '\\':
+            *q++ = '\\';
+            *q++ = *cp;
+            break;
+        case '\t':
+            *q++ = '\\';
+            *q++ = 't';
+            break;
+        case '\n':
+            *q++ = '\\';
+            *q++ = 'n';
+            break;
+        case '\b':
+            *q++ = '\\';
+            *q++ = 'b';
+            break;
+        case '\0':
+            *q++ = '\\';
+            *q++ = '0';
+            break;
+        default:
+            *q++ = *cp;
+        }
+    }
+    return q - dest;
+}
+
+static int
+sss_krb5_component_length_quoted(const krb5_data *src, int flags)
+{
+    const char *cp = src->data;
+    int length = src->length;
+    int j;
+    int size = length;
+
+    if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
+        int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
+            !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
+
+        for (j = 0; j < length; j++,cp++)
+            if ((!no_realm && *cp == REALM_SEP) ||
+                *cp == COMPONENT_SEP ||
+                *cp == '\0' || *cp == '\\' || *cp == '\t' ||
+                *cp == '\n' || *cp == '\b')
+                size++;
+    }
+
+    return size;
+}
+
+#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
+
+
+krb5_error_code
+sss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
+                        int flags, char **name)
+{
+#ifdef HAVE_KRB5_UNPARSE_NAME_FLAGS
+    return krb5_unparse_name_flags(context, principal, flags, name);
+#else
+    char *cp, *q;
+    int i;
+    int length;
+    krb5_int32 nelem;
+    unsigned int totalsize = 0;
+    char *default_realm = NULL;
+    krb5_error_code ret = 0;
+
+    if (name != NULL)
+        *name = NULL;
+
+    if (!principal || !name)
+        return KRB5_PARSE_MALFORMED;
+
+    if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
+        totalsize += sss_krb5_component_length_quoted(krb5_princ_realm(context,
+                                                              principal),
+                                             flags);
+        totalsize++;
+    }
+
+    nelem = krb5_princ_size(context, principal);
+    for (i = 0; i < (int) nelem; i++) {
+        cp = krb5_princ_component(context, principal, i)->data;
+        totalsize += sss_krb5_component_length_quoted(krb5_princ_component(context, principal, i), flags);
+        totalsize++;
+    }
+    if (nelem == 0)
+        totalsize++;
+
+    *name = malloc(totalsize);
+
+    if (!*name) {
+        ret = ENOMEM;
+        goto cleanup;
+    }
+
+    q = *name;
+
+    for (i = 0; i < (int) nelem; i++) {
+        cp = krb5_princ_component(context, principal, i)->data;
+        length = krb5_princ_component(context, principal, i)->length;
+        q += sss_krb5_copy_component_quoting(q,
+                                    krb5_princ_component(context,
+                                                         principal,
+                                                         i),
+                                    flags);
+        *q++ = COMPONENT_SEP;
+    }
+
+    if (i > 0)
+        q--;
+    if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
+        *q++ = REALM_SEP;
+        q += sss_krb5_copy_component_quoting(q, krb5_princ_realm(context, principal), flags);
+    }
+    *q++ = '\0';
+
+cleanup:
+    free(default_realm);
+
+    return ret;
+#endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
+}
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index d17bfe9691d1bcc6c4f04b71ed0392753c91f0f6..16ed05b2ac1aeb52c5c984173ead170b032fb239 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -102,4 +102,8 @@ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags(
 #define SSS_KRB5_FAST_REQUIRED 0
 #endif
 
+krb5_error_code
+sss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
+                            int flags, char **name);
+
 #endif /* __SSS_KRB5_H__ */
-- 
1.7.4.1

