diff options
Diffstat (limited to 'source4/heimdal/lib/krb5/kcm.c')
-rw-r--r-- | source4/heimdal/lib/krb5/kcm.c | 121 |
1 files changed, 79 insertions, 42 deletions
diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index 8a8f1efc11..f034341972 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,17 +43,24 @@ #include "kcm.h" -RCSID("$Id$"); - typedef struct krb5_kcmcache { char *name; struct sockaddr_un path; char *door_path; } krb5_kcmcache; +typedef struct krb5_kcm_cursor { + unsigned long offset; + unsigned long length; + kcmuuid_t *uuids; +} *krb5_kcm_cursor; + + #define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data) #define CACHENAME(X) (KCMCACHE(X)->name) -#define KCMCURSOR(C) (*(uint32_t *)(C)) +#define KCMCURSOR(C) ((krb5_kcm_cursor)(C)) + +#ifdef HAVE_DOOR_CREATE static krb5_error_code try_door(krb5_context context, @@ -61,7 +68,6 @@ try_door(krb5_context context, krb5_data *request_data, krb5_data *response_data) { -#ifdef HAVE_DOOR_CREATE door_arg_t arg; int fd; int ret; @@ -91,10 +97,8 @@ try_door(krb5_context context, return ret; return 0; -#else - return KRB5_CC_IO; -#endif } +#endif /* HAVE_DOOR_CREATE */ static krb5_error_code try_unix_socket(krb5_context context, @@ -143,9 +147,11 @@ kcm_send_request(krb5_context context, ret = KRB5_CC_NOSUPP; for (i = 0; i < context->max_retries; i++) { +#ifdef HAVE_DOOR_CREATE ret = try_door(context, k, &request_data, response_data); if (ret == 0 && response_data->length != 0) break; +#endif ret = try_unix_socket(context, k, &request_data, response_data); if (ret == 0 && response_data->length != 0) break; @@ -207,7 +213,8 @@ kcm_alloc(krb5_context context, const char *name, krb5_ccache *id) k = malloc(sizeof(*k)); if (k == NULL) { - krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", "")); + krb5_set_error_message(context, KRB5_CC_NOMEM, + N_("malloc: out of memory", "")); return KRB5_CC_NOMEM; } @@ -309,8 +316,6 @@ kcm_free(krb5_context context, krb5_ccache *id) memset(k, 0, sizeof(*k)); krb5_data_free(&(*id)->data); } - - *id = NULL; } static const char * @@ -609,10 +614,10 @@ kcm_get_first (krb5_context context, krb5_cc_cursor *cursor) { krb5_error_code ret; + krb5_kcm_cursor c; krb5_kcmcache *k = KCMCACHE(id); krb5_storage *request, *response; krb5_data response_data; - int32_t tmp; ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request); if (ret) @@ -625,27 +630,56 @@ kcm_get_first (krb5_context context, } ret = kcm_call(context, k, request, &response, &response_data); - if (ret) { - krb5_storage_free(request); + krb5_storage_free(request); + if (ret) + return ret; + + c = calloc(1, sizeof(*c)); + if (c == NULL) { + ret = ENOMEM; + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); return ret; } - ret = krb5_ret_int32(response, &tmp); - if (ret || tmp < 0) - ret = KRB5_CC_IO; + while (1) { + ssize_t sret; + kcmuuid_t uuid; + void *ptr; + + sret = krb5_storage_read(response, &uuid, sizeof(uuid)); + if (sret == 0) { + ret = 0; + break; + } else if (sret != sizeof(uuid)) { + ret = EINVAL; + break; + } + + ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1)); + if (ptr == NULL) { + free(c->uuids); + free(c); + krb5_set_error_message(context, ENOMEM, + N_("malloc: out of memory", "")); + return ENOMEM; + } + c->uuids = ptr; + + memcpy(&c->uuids[c->length], &uuid, sizeof(uuid)); + c->length += 1; + } - krb5_storage_free(request); krb5_storage_free(response); krb5_data_free(&response_data); - if (ret) + if (ret) { + free(c->uuids); + free(c); return ret; + } - *cursor = malloc(sizeof(tmp)); - if (*cursor == NULL) - return KRB5_CC_NOMEM; - - KCMCURSOR(*cursor) = tmp; + *cursor = c; return 0; } @@ -666,8 +700,15 @@ kcm_get_next (krb5_context context, { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); + krb5_kcm_cursor c = KCMCURSOR(*cursor); krb5_storage *request, *response; krb5_data response_data; + ssize_t sret; + + again: + + if (c->offset >= c->length) + return KRB5_CC_END; ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request); if (ret) @@ -679,23 +720,26 @@ kcm_get_next (krb5_context context, return ret; } - ret = krb5_store_int32(request, KCMCURSOR(*cursor)); - if (ret) { + sret = krb5_storage_write(request, + &c->uuids[c->offset], + sizeof(c->uuids[c->offset])); + c->offset++; + if (sret != sizeof(c->uuids[c->offset])) { krb5_storage_free(request); - return ret; + krb5_clear_error_message(context); + return ENOMEM; } ret = kcm_call(context, k, request, &response, &response_data); - if (ret) { - krb5_storage_free(request); - return ret; + krb5_storage_free(request); + if (ret == KRB5_CC_END) { + goto again; } ret = krb5_ret_creds(response, creds); if (ret) ret = KRB5_CC_IO; - krb5_storage_free(request); krb5_storage_free(response); krb5_data_free(&response_data); @@ -717,6 +761,7 @@ kcm_end_get (krb5_context context, { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); + krb5_kcm_cursor c = KCMCURSOR(*cursor); krb5_storage *request; ret = kcm_storage_request(context, KCM_OP_END_GET, &request); @@ -729,22 +774,14 @@ kcm_end_get (krb5_context context, return ret; } - ret = krb5_store_int32(request, KCMCURSOR(*cursor)); - if (ret) { - krb5_storage_free(request); - return ret; - } - ret = kcm_call(context, k, request, NULL, NULL); - if (ret) { - krb5_storage_free(request); + krb5_storage_free(request); + if (ret) return ret; - } - krb5_storage_free(request); + free(c->uuids); + free(c); - KCMCURSOR(*cursor) = 0; - free(*cursor); *cursor = NULL; return ret; |