krb5_build_principal_va does not allocate krb5_principal
authorAlexandra Ellwood <lxs@mit.edu>
Fri, 24 Oct 2008 19:46:41 +0000 (19:46 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Fri, 24 Oct 2008 19:46:41 +0000 (19:46 +0000)
krb5_build_principal_va does not allocate the outer krb5_principal,
making it useless for generating krb5_principals which can be freed
with krb5_free_principal.  Added krb5_build_principal_alloc_va which
allocates the krb5_principal.

Added krb5int_build_principal_alloc_va which is used by KIM to avoid
code duplication. KIM's kim_identity_create_from_components takes
the first component as an argument because principals with no
components cannot be represented with the KIM UI.  Modified KIM
to use this new API.

ticket: new

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

src/include/k5-int.h
src/include/krb5/krb5.hin
src/kim/lib/kim_identity.c
src/lib/krb5/krb/bld_princ.c
src/lib/krb5/libkrb5.exports

index f05adecf39424b5afa1d169db5153202364f56e6..cbc810e77638e6029a22e24db1211b8c48a2d55d 100644 (file)
@@ -2518,6 +2518,15 @@ void KRB5_CALLCONV krb5_realm_iterator_free
 void KRB5_CALLCONV krb5_free_realm_string
        (krb5_context context, char *str);
 
+/* Internal principal function used by KIM to avoid code duplication */
+krb5_error_code KRB5_CALLCONV
+krb5int_build_principal_alloc_va(krb5_context context, 
+                                 krb5_principal *princ, 
+                                 unsigned int rlen, 
+                                 const char *realm, 
+                                 const char *first,
+                                 va_list ap);
+
 /* Some data comparison and conversion functions.  */
 #if 0
 static inline int data_cmp(krb5_data d1, krb5_data d2)
index 82e52ab523d8ef167f811bad197fefaf3a46a87e..62fd90df4e6356c84d3aab60f4ef0c8c05b2c30a 100644 (file)
@@ -1599,9 +1599,15 @@ krb5_error_code KRB5_CALLCONV_C krb5_build_principal
     __attribute__ ((sentinel))
 #endif
     ;
-krb5_error_code KRB5_CALLCONV krb5_build_principal_va
+#if KRB5_DEPRECATED
+KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_build_principal_va
        (krb5_context,
                krb5_principal, unsigned int, const char *, va_list);
+#endif
+
+/* Version of krb5_build_principal_va which allocates krb5_principal_data */
+krb5_error_code KRB5_CALLCONV krb5_build_principal_alloc_va
+        (krb5_context, krb5_principal *, unsigned int, const char *, va_list);
 
 krb5_error_code KRB5_CALLCONV krb5_425_conv_principal
        (krb5_context,
index 834b8d614c05e4717b1df6c08a7e85fa30eda46f..6592d09c8f15f069501f1931431463e65021c710 100644 (file)
@@ -24,8 +24,8 @@
  * or implied warranty.
  */
 
+#include "k5-int.h"
 #include <krb5.h>
-#include <gssapi/gssapi.h>
 #include "kim_private.h"
 
 /* ------------------------------------------------------------------------ */
@@ -110,7 +110,6 @@ kim_error kim_identity_create_from_components (kim_identity *out_identity,
 {
     kim_error err = KIM_NO_ERROR;
     kim_identity identity = NULL;
-    krb5_principal_data principal_data;  /* allocated by KIM so can't be returned */
     
     if (!err && !out_identity    ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !in_realm        ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
@@ -126,64 +125,23 @@ kim_error kim_identity_create_from_components (kim_identity *out_identity,
     
     if (!err) {
         va_list args;
-        kim_count component_count = 1;
-        
+
         va_start (args, in_1st_component);
-        while (va_arg (args, kim_string)) { component_count++; }
+        err = krb5_error (identity->context,
+                          krb5int_build_principal_alloc_va (identity->context,
+                                                            &identity->principal,
+                                                            strlen(in_realm),
+                                                            in_realm,
+                                                            in_1st_component,
+                                                            args));
         va_end (args);
-        
-        principal_data.length = component_count;
-        principal_data.data = (krb5_data *) malloc (component_count * sizeof (krb5_data));
-        if (!principal_data.data) { err = KIM_OUT_OF_MEMORY_ERR; }
     }   
-    
-    if (!err) {
-        va_list args;
-        krb5_int32 i;
-        
-        krb5_princ_set_realm_length (context, &principal_data, strlen (in_realm));
-        krb5_princ_set_realm_data (context, &principal_data, (char *) in_realm);
-        
-        va_start (args, in_1st_component);
-        for (i = 0; !err && (i < principal_data.length); i++) {
-            kim_string component = NULL;
-            if (i == 0) {
-                err = kim_string_copy (&component, in_1st_component);
-            } else {
-                err = kim_string_copy (&component, va_arg (args, kim_string));
-            }
-            
-            if (!err) {
-                principal_data.data[i].data = (char *) component;
-                principal_data.data[i].length = strlen (component);
-            }
-        }            
-        va_end (args);
-    }
-    
-    if (!err) {
-        /* make a copy that has actually been allocated by the krb5 
-         * library so krb5_free_principal can be called on it */
-        err = krb5_error (identity->context,
-                          krb5_copy_principal (identity->context, 
-                                               &principal_data, 
-                                               &identity->principal));
-    }    
-    
+
     if (!err) {
         *out_identity = identity;
         identity = NULL;
     }
     
-    if (principal_data.data) { 
-        krb5_int32 i;
-        
-        for (i = 0; i < principal_data.length; i++) {
-            kim_string component = principal_data.data[i].data;
-            kim_string_free (&component);
-        }
-        free (principal_data.data); 
-    }
     kim_identity_free (&identity);
     
     return check_error (err);
index 03bf1267e3824a88cff7cad63abbe2b428e304cd..1b9a894477d94df04e2dcb48bd0f3c537d933043 100644 (file)
 #include <stdarg.h>
 #include "k5-int.h"
 
-krb5_error_code
-KRB5_CALLCONV
-krb5_build_principal_va(krb5_context context, krb5_principal princ, unsigned int rlen, const char *realm, va_list ap)
+/* Takes first component as argument for KIM API, 
+ * which does not allow realms with zero components */
+static krb5_error_code
+krb5int_build_principal_va(krb5_context context, 
+                           krb5_principal princ, 
+                           unsigned int rlen, 
+                           const char *realm, 
+                           const char *first,
+                           va_list ap)
 {
-    register int i, count = 0;
-    register char *next;
-    char *tmpdata;
-    krb5_data *data;
-
-    /* guess at an initial sufficent count of 2 pieces */
-    count = 2;
-
-    /* get space for array and realm, and insert realm */
-    data = (krb5_data *) malloc(sizeof(krb5_data) * count);
-    if (data == 0)
-       return ENOMEM;
-    krb5_princ_set_realm_length(context, princ, rlen);
-    tmpdata = malloc(rlen);
-    if (!tmpdata) {
-       free (data);
-       return ENOMEM;
+    krb5_error_code retval = 0;
+    char *r = NULL;
+    krb5_data *data = NULL;
+    krb5_int32 count = 0;
+    krb5_int32 size = 2;  /* initial guess at needed space */
+    char *component = NULL;
+    
+    data = malloc(size * sizeof(krb5_data));
+    if (!data) { retval = ENOMEM; }
+    
+    if (!retval) {
+        r = strdup(realm);
+        if (!r) { retval = ENOMEM; }
+    }
+    
+    if (!retval && first) {
+        data[0].length = strlen(first);
+        data[0].data = strdup(first);
+        if (!data[0].data) { retval = ENOMEM; }
+        count++;
+        
+        /* ap is only valid if first is non-NULL */
+        while (!retval && (component = va_arg(ap, char *))) {
+            if (count == size) {
+                krb5_data *new_data = NULL;
+                
+                size *= 2;
+                new_data = realloc ((char *) data, sizeof(krb5_data) * size);
+                if (new_data) {
+                    data = new_data;
+                } else {
+                    retval = ENOMEM;
+                }
+            }
+            
+            if (!retval) {
+                data[count].length = strlen(component);
+                data[count].data = strdup(component);  
+                if (!data[count].data) { retval = ENOMEM; }
+                count++;
+            }
+        }
+    }
+    
+    if (!retval) {
+        princ->type = KRB5_NT_UNKNOWN;
+        princ->magic = KV5M_PRINCIPAL;
+        krb5_princ_set_realm_data(context, princ, r);
+        krb5_princ_set_realm_length(context, princ, strlen(r));
+        princ->data = data;
+        princ->length = count;
+        r = NULL;    /* take ownership */
+        data = NULL; /* take ownership */
+    }
+    
+    if (data) {
+        while (--count >= 0) {
+            krb5_xfree(data[count].data);
+        }
+        krb5_xfree(data);
     }
-    krb5_princ_set_realm_data(context, princ, tmpdata);
-    memcpy(tmpdata, realm, rlen);
+    krb5_xfree(r);
+    
+    return retval;
+}
 
-    /* process rest of components */
+krb5_error_code KRB5_CALLCONV
+krb5_build_principal_va(krb5_context context, 
+                        krb5_principal princ, 
+                        unsigned int rlen, 
+                        const char *realm, 
+                        va_list ap)
+{
+    char *first = va_arg(ap, char *);
+    
+    return krb5int_build_principal_va(context, princ, rlen, realm, first, ap);
+}
 
-    for (i = 0, next = va_arg(ap, char *);
-        next;
-        next = va_arg(ap, char *), i++) {
-       if (i == count) {
-           /* not big enough.  realloc the array */
-           krb5_data *p_tmp;
-           p_tmp = (krb5_data *) realloc((char *)data,
-                                         sizeof(krb5_data)*(count*2));
-           if (!p_tmp) {
-           free_out:
-                   while (--i >= 0)
-                       krb5_xfree(data[i].data);
-                   krb5_xfree(data);
-                   krb5_xfree(tmpdata);
-                   return (ENOMEM);
-           }
-           count *= 2;
-           data = p_tmp;
-       }
+/* Takes first component as argument for KIM API, 
+ * which does not allow realms with zero components */
+krb5_error_code KRB5_CALLCONV
+krb5int_build_principal_alloc_va(krb5_context context, 
+                                 krb5_principal *princ, 
+                                 unsigned int rlen, 
+                                 const char *realm, 
+                                 const char *first,
+                                 va_list ap)
+{
+    krb5_error_code retval = 0;
+    
+    krb5_principal p = malloc(sizeof(krb5_principal_data));
+    if (!p) { retval = ENOMEM; }
+    
+    if (!retval) {
+        retval = krb5int_build_principal_va(context, p, rlen, realm, first, ap);
+    }
+    
+    if (!retval) {
+       *princ = p;
+    } else {
+        krb5_xfree(p);
+    }
+    
+    return retval;    
+}
 
-       data[i].length = strlen(next);
-       data[i].data = strdup(next);
-       if (!data[i].data)
-           goto free_out;
+krb5_error_code KRB5_CALLCONV
+krb5_build_principal_alloc_va(krb5_context context, 
+                              krb5_principal *princ, 
+                              unsigned int rlen, 
+                              const char *realm, 
+                              va_list ap)
+{
+    krb5_error_code retval = 0;
+    
+    krb5_principal p = malloc(sizeof(krb5_principal_data));
+    if (!p) { retval = ENOMEM; }
+   
+    if (!retval) {
+        retval = krb5_build_principal_va(context, p, rlen, realm, ap);
+    }
+    
+    if (!retval) {
+       *princ = p;
+    } else {
+        krb5_xfree(p);
     }
-    princ->data = data;
-    princ->length = i;
-    princ->type = KRB5_NT_UNKNOWN;
-    princ->magic = KV5M_PRINCIPAL;
-    return 0;
+
+    return retval;
 }
 
 krb5_error_code KRB5_CALLCONV_C
-krb5_build_principal(krb5_context context,  krb5_principal * princ, 
+krb5_build_principal(krb5_context context, 
+                     krb5_principal * princ, 
                     unsigned int rlen,
                     const char * realm, ...)
 {
+    krb5_error_code retval = 0;
     va_list ap;
-    krb5_error_code retval;
-    krb5_principal pr_ret = (krb5_principal)malloc(sizeof(krb5_principal_data));
-
-    if (!pr_ret)
-       return ENOMEM;
-
+    
     va_start(ap, realm);
-    retval = krb5_build_principal_va(context, pr_ret, rlen, realm, ap);
+    retval = krb5_build_principal_alloc_va(context, princ, rlen, realm, ap);
     va_end(ap);
-    if (retval == 0)
-       *princ = pr_ret;
-    else
-        krb5_xfree(pr_ret);
-
+    
     return retval;
 }
index 2d503b85108f3ef1ec7d7c256684d258680fcb70..9b12be9855c8534484469196c5760d21d2d98008 100644 (file)
@@ -120,6 +120,7 @@ krb5_auth_to_rep
 krb5_build_principal
 krb5_build_principal_ext
 krb5_build_principal_va
+krb5_build_principal_alloc_va
 krb5_cc_close
 krb5_cc_copy_creds
 krb5_cc_default