r11294: Update Heimdal in Samba4 to lorikeet-heimdal (which is in turn updated
[jelmer/samba4-debian.git] / source / heimdal / lib / krb5 / acache.c
index 75f5315c7101c3f02ff3399daed84317bc7de501..7cf2c65d89eba95ef2e4f555f18e4e25df852557 100644 (file)
@@ -37,7 +37,7 @@
 #include <dlfcn.h>
 #endif
 
-RCSID("$Id: acache.c,v 1.11 2005/06/16 19:32:44 lha Exp $");
+RCSID("$Id: acache.c,v 1.14 2005/10/03 08:44:18 lha Exp $");
 
 /* XXX should we fetch these for each open ? */
 static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
@@ -67,7 +67,7 @@ static const struct {
     { ccErrContextNotFound,    KRB5_CC_NOTFOUND },
     { ccIteratorEnd,           KRB5_CC_END },
     { ccErrNoMem,              KRB5_CC_NOMEM },
-    { ccErrServerUnavailable,  KRB5_CC_BADNAME },
+    { ccErrServerUnavailable,  KRB5_CC_NOSUPP },
     { ccNoError,               0 }
 };
 
@@ -110,7 +110,7 @@ init_ccapi(krb5_context context)
     if (cc_handle == NULL) {
        HEIMDAL_MUTEX_unlock(&acc_mutex);
        krb5_set_error_string(context, "Failed to load %s", lib);
-       return ccErrServerUnavailable;
+       return KRB5_CC_NOSUPP;
     }
 
     init_func = dlsym(cc_handle, "cc_initialize");
@@ -119,14 +119,14 @@ init_ccapi(krb5_context context)
        krb5_set_error_string(context, "Failed to find cc_initialize"
                              "in %s: %s", lib, dlerror());
        dlclose(cc_handle);
-       return ccErrServerUnavailable;
+       return KRB5_CC_NOSUPP;
     }
 
     return 0;
 #else
     HEIMDAL_MUTEX_unlock(&acc_mutex);
     krb5_set_error_string(context, "no support for shared object");
-    return ccErrServerUnavailable;
+    return KRB5_CC_NOSUPP;
 #endif
 }    
 
@@ -633,8 +633,10 @@ acc_get_first (krb5_context context,
     int32_t error;
     
     error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
-    if (error)
+    if (error) {
+       krb5_clear_error_string(context);
        return ENOENT;
+    }
     *cursor = iter;
     return 0;
 }
@@ -761,6 +763,97 @@ acc_get_version(krb5_context context,
     return 0;
 }
                    
+struct cache_iter {
+    cc_context_t context;
+    cc_ccache_iterator_t iter;
+};
+
+static krb5_error_code
+acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
+{
+    struct cache_iter *iter;
+    krb5_error_code ret;
+    cc_int32 error;
+
+    ret = init_ccapi(context);
+    if (ret)
+       return ret;
+
+    iter = calloc(1, sizeof(*iter));
+    if (iter == NULL) {
+       krb5_set_error_string(context, "malloc - out of memory");
+       return ENOMEM;
+    }
+
+    error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL);
+    if (error) {
+       free(iter);
+       return translate_cc_error(context, error);
+    }
+
+    error = (*iter->context->func->new_ccache_iterator)(iter->context,
+                                                       &iter->iter);
+    if (error) {
+       free(iter);
+       krb5_clear_error_string(context);
+       return ENOENT;
+    }
+    *cursor = iter;
+    return 0;
+}
+
+static krb5_error_code
+acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
+{
+    struct cache_iter *iter = cursor;
+    cc_ccache_t cache;
+    krb5_acc *a;
+    krb5_error_code ret;
+    int32_t error;
+
+    error = (*iter->iter->func->next)(iter->iter, &cache);
+    if (error)
+       return translate_cc_error(context, error);
+
+    ret = _krb5_cc_allocate(context, &krb5_acc_ops, id);
+    if (ret) {
+       (*cache->func->release)(cache);
+       return ret;
+    }
+
+    ret = acc_alloc(context, id);
+    if (ret) {
+       (*cache->func->release)(cache);
+       free(*id);
+       return ret;
+    }
+
+    a = ACACHE(*id);
+    a->ccache = cache;
+
+    a->cache_name = get_cc_name(a->ccache);
+    if (a->cache_name == NULL) {
+       acc_close(context, *id);
+       *id = NULL;
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }  
+    return 0;
+}
+
+static krb5_error_code
+acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
+{
+    struct cache_iter *iter = cursor;
+
+    (*iter->iter->func->release)(iter->iter);
+    iter->iter = NULL;
+    (*iter->context->func->release)(iter->context);
+    iter->context = NULL;
+    free(iter);
+    return 0;
+}
+
 const krb5_cc_ops krb5_acc_ops = {
     "API",
     acc_get_name,
@@ -777,5 +870,8 @@ const krb5_cc_ops krb5_acc_ops = {
     acc_end_get,
     acc_remove_cred,
     acc_set_flags,
-    acc_get_version
+    acc_get_version,
+    acc_get_cache_first,
+    acc_get_cache_next,
+    acc_end_cache_get
 };