krb5_error_code KRB5_CALLCONV krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred) { krb5_creds *tempcred; krb5_error_code retval; if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred)))) return ENOMEM; retval = k5_copy_creds_contents(context, incred, tempcred); if (retval) free(tempcred); else *outcred = tempcred; return retval; }
/* * Requires: * cursor is a krb5_cc_cursor originally obtained from * krb5_mcc_start_seq_get. * * Modifes: * cursor, creds * * Effects: * Fills in creds with the "next" credentals structure from the cache * id. The actual order the creds are returned in is arbitrary. * Space is allocated for the variable length fields in the * credentials structure, so the object returned must be passed to * krb5_destroy_credential. * * The cursor is updated for the next call to krb5_mcc_next_cred. * * Errors: * system errors */ krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, krb5_creds *creds) { struct mcc_cursor *mcursor; krb5_error_code retval; krb5_mcc_data *d = id->data; memset(creds, 0, sizeof(krb5_creds)); mcursor = *cursor; if (mcursor->next_link == NULL) return KRB5_CC_END; /* * Check the cursor generation against the cache generation in case the * cache has been reinitialized or destroyed, freeing the pointer in the * cursor. Keep the cache locked while we copy the creds and advance the * pointer, in case another thread reinitializes the cache after we check * the generation. */ k5_cc_mutex_lock(context, &d->lock); if (mcursor->generation != d->generation) { retval = KRB5_CC_END; goto done; } /* Skip over removed creds. */ while (mcursor->next_link != NULL && mcursor->next_link->creds == NULL) mcursor->next_link = mcursor->next_link->next; if (mcursor->next_link == NULL) { retval = KRB5_CC_END; goto done; } retval = k5_copy_creds_contents(context, mcursor->next_link->creds, creds); if (retval == 0) mcursor->next_link = mcursor->next_link->next; done: k5_cc_mutex_unlock(context, &d->lock); return retval; }
/* * Requires: * cursor is a krb5_cc_cursor originally obtained from * krb5_mcc_start_seq_get. * * Modifes: * cursor, creds * * Effects: * Fills in creds with the "next" credentals structure from the cache * id. The actual order the creds are returned in is arbitrary. * Space is allocated for the variable length fields in the * credentials structure, so the object returned must be passed to * krb5_destroy_credential. * * The cursor is updated for the next call to krb5_mcc_next_cred. * * Errors: * system errors */ krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, krb5_creds *creds) { krb5_mcc_cursor mcursor; krb5_error_code retval; /* Once the node in the linked list is created, it's never modified, so we don't need to worry about locking here. (Note that we don't support _remove_cred.) */ mcursor = (krb5_mcc_cursor) *cursor; if (mcursor == NULL) return KRB5_CC_END; memset(creds, 0, sizeof(krb5_creds)); if (mcursor->creds) { retval = k5_copy_creds_contents(context, mcursor->creds, creds); if (retval) return retval; } *cursor = (krb5_cc_cursor)mcursor->next; return KRB5_OK; }