1/*
2 * Copyright (c) 2009 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include "gsskrb5_locl.h"
37#include <heim_threads.h>
38
39static void
40iter_creds_f(OM_uint32 flags,
41	     gss_OID type,
42	     void *userctx ,
43	     void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
44{
45    krb5_context context;
46    krb5_cccol_cursor cursor;
47    krb5_error_code ret;
48    krb5_ccache id;
49
50    GSSAPI_KRB5_INIT_VOID(&context);
51
52    ret = krb5_cccol_cursor_new (context, &cursor);
53    if (ret)
54	goto out;
55
56    while (krb5_cccol_cursor_next (context, cursor, &id) == 0 && id != NULL) {
57	gsskrb5_cred handle;
58	OM_uint32 junk;
59	krb5_principal principal;
60	krb5_data data;
61	gss_OID resolved_type = NULL;
62
63	ret = krb5_cc_get_principal(context, id, &principal);
64	if (ret) {
65	    krb5_cc_close(context, id);
66	    continue;
67	}
68
69	if (krb5_principal_is_pku2u(context, principal))
70	    resolved_type = GSS_PKU2U_MECHANISM;
71	else if (krb5_cc_get_config(context, id, NULL, "iakerb", &data) == 0) {
72	    resolved_type = GSS_IAKERB_MECHANISM;
73	    krb5_data_free(&data);
74	} else {
75	    resolved_type = GSS_KRB5_MECHANISM;
76	}
77
78	if (!gss_oid_equal(type, resolved_type)) {
79	    krb5_free_principal(context, principal);
80	    krb5_cc_close(context, id);
81	    continue;
82	}
83
84	handle = calloc(1, sizeof(*handle));
85	if (handle == NULL) {
86	    krb5_cc_close(context, id);
87	    goto out;
88	}
89
90	HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
91
92	handle->usage = GSS_C_INITIATE;
93	handle->principal = principal;
94
95	__gsskrb5_ccache_lifetime(&junk, context, id,
96				  handle->principal, &handle->endtime);
97	handle->keytab = NULL;
98	handle->ccache = id;
99
100	cred_iter(userctx, type, (gss_cred_id_t)handle);
101    }
102
103    krb5_cccol_cursor_free(context, &cursor);
104
105 out:
106    cred_iter(userctx, NULL, NULL);
107}
108
109void
110_gss_pku2u_iter_creds_f(OM_uint32 flags,
111			void *userctx ,
112			void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
113{
114    iter_creds_f(flags, GSS_PKU2U_MECHANISM, userctx, cred_iter);
115}
116
117void
118_gss_krb5_iter_creds_f(OM_uint32 flags,
119		       void *userctx ,
120		       void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
121{
122    iter_creds_f(flags, GSS_KRB5_MECHANISM, userctx, cred_iter);
123}
124
125void
126_gss_iakerb_iter_creds_f(OM_uint32 flags,
127		       void *userctx ,
128		       void (*cred_iter)(void *, gss_OID, gss_cred_id_t))
129{
130    iter_creds_f(flags, GSS_IAKERB_MECHANISM, userctx, cred_iter);
131}
132