1/*
2 * Copyright (c) 2005, PADL Software Pty Ltd.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "kcm_locl.h"
34
35RCSID("$Id$");
36
37/*
38 * Server-side loopback glue for credentials cache operations; this
39 * must be initialized with kcm_internal_ccache(), it is not for real
40 * use. This entire file assumes the cache is locked, it does not do
41 * any concurrency checking for multithread applications.
42 */
43
44#define KCMCACHE(X)	((kcm_ccache)(X)->data.data)
45#define CACHENAME(X)	(KCMCACHE(X)->name)
46
47static const char *
48kcmss_get_name(krb5_context context,
49	       krb5_ccache id)
50{
51    return CACHENAME(id);
52}
53
54static krb5_error_code
55kcmss_resolve(krb5_context context, krb5_ccache *id, const char *res)
56{
57    return KRB5_FCC_INTERNAL;
58}
59
60static krb5_error_code
61kcmss_gen_new(krb5_context context, krb5_ccache *id)
62{
63    return KRB5_FCC_INTERNAL;
64}
65
66static krb5_error_code
67kcmss_initialize(krb5_context context,
68		 krb5_ccache id,
69		 krb5_principal primary_principal)
70{
71    krb5_error_code ret;
72    kcm_ccache c = KCMCACHE(id);
73
74    KCM_ASSERT_VALID(c);
75
76    ret = kcm_zero_ccache_data_internal(context, c);
77    if (ret)
78	return ret;
79
80    ret = krb5_copy_principal(context, primary_principal,
81			      &c->client);
82
83    return ret;
84}
85
86static krb5_error_code
87kcmss_close(krb5_context context,
88	    krb5_ccache id)
89{
90    kcm_ccache c = KCMCACHE(id);
91
92    KCM_ASSERT_VALID(c);
93
94    id->data.data = NULL;
95    id->data.length = 0;
96
97    return 0;
98}
99
100static krb5_error_code
101kcmss_destroy(krb5_context context,
102	      krb5_ccache id)
103{
104    krb5_error_code ret;
105    kcm_ccache c = KCMCACHE(id);
106
107    KCM_ASSERT_VALID(c);
108
109    ret = kcm_ccache_destroy(context, CACHENAME(id));
110
111    return ret;
112}
113
114static krb5_error_code
115kcmss_store_cred(krb5_context context,
116		 krb5_ccache id,
117		 krb5_creds *creds)
118{
119    krb5_error_code ret;
120    kcm_ccache c = KCMCACHE(id);
121    krb5_creds *tmp;
122
123    KCM_ASSERT_VALID(c);
124
125    ret = kcm_ccache_store_cred_internal(context, c, creds, 1, &tmp);
126
127    return ret;
128}
129
130static krb5_error_code
131kcmss_retrieve(krb5_context context,
132	       krb5_ccache id,
133	       krb5_flags which,
134	       const krb5_creds *mcred,
135	       krb5_creds *creds)
136{
137    krb5_error_code ret;
138    kcm_ccache c = KCMCACHE(id);
139    krb5_creds *credp;
140
141    KCM_ASSERT_VALID(c);
142
143    ret = kcm_ccache_retrieve_cred_internal(context, c, which,
144					    mcred, &credp);
145    if (ret)
146	return ret;
147
148    ret = krb5_copy_creds_contents(context, credp, creds);
149    if (ret)
150	return ret;
151
152    return 0;
153}
154
155static krb5_error_code
156kcmss_get_principal(krb5_context context,
157		    krb5_ccache id,
158		    krb5_principal *principal)
159{
160    krb5_error_code ret;
161    kcm_ccache c = KCMCACHE(id);
162
163    KCM_ASSERT_VALID(c);
164
165    ret = krb5_copy_principal(context, c->client,
166			      principal);
167
168    return ret;
169}
170
171static krb5_error_code
172kcmss_get_first (krb5_context context,
173		 krb5_ccache id,
174		 krb5_cc_cursor *cursor)
175{
176    kcm_ccache c = KCMCACHE(id);
177
178    KCM_ASSERT_VALID(c);
179
180    *cursor = c->creds;
181
182    return (*cursor == NULL) ? KRB5_CC_END : 0;
183}
184
185static krb5_error_code
186kcmss_get_next (krb5_context context,
187		krb5_ccache id,
188		krb5_cc_cursor *cursor,
189		krb5_creds *creds)
190{
191    krb5_error_code ret;
192    kcm_ccache c = KCMCACHE(id);
193
194    KCM_ASSERT_VALID(c);
195
196    ret = krb5_copy_creds_contents(context,
197				   &((struct kcm_creds *)cursor)->cred,
198				   creds);
199    if (ret)
200	return ret;
201
202    *cursor = ((struct kcm_creds *)cursor)->next;
203    if (*cursor == 0)
204	ret = KRB5_CC_END;
205
206    return ret;
207}
208
209static krb5_error_code
210kcmss_end_get (krb5_context context,
211	       krb5_ccache id,
212	       krb5_cc_cursor *cursor)
213{
214    *cursor = NULL;
215    return 0;
216}
217
218static krb5_error_code
219kcmss_remove_cred(krb5_context context,
220		  krb5_ccache id,
221		  krb5_flags which,
222		  krb5_creds *cred)
223{
224    krb5_error_code ret;
225    kcm_ccache c = KCMCACHE(id);
226
227    KCM_ASSERT_VALID(c);
228
229    ret = kcm_ccache_remove_cred_internal(context, c, which, cred);
230
231    return ret;
232}
233
234static krb5_error_code
235kcmss_set_flags(krb5_context context,
236		krb5_ccache id,
237		krb5_flags flags)
238{
239    return 0;
240}
241
242static krb5_error_code
243kcmss_get_version(krb5_context context,
244		  krb5_ccache id)
245{
246    return 0;
247}
248
249static const krb5_cc_ops krb5_kcmss_ops = {
250    KRB5_CC_OPS_VERSION,
251    "KCM",
252    kcmss_get_name,
253    kcmss_resolve,
254    kcmss_gen_new,
255    kcmss_initialize,
256    kcmss_destroy,
257    kcmss_close,
258    kcmss_store_cred,
259    kcmss_retrieve,
260    kcmss_get_principal,
261    kcmss_get_first,
262    kcmss_get_next,
263    kcmss_end_get,
264    kcmss_remove_cred,
265    kcmss_set_flags,
266    kcmss_get_version
267};
268
269krb5_error_code
270kcm_internal_ccache(krb5_context context,
271		    kcm_ccache c,
272		    krb5_ccache id)
273{
274    id->ops = &krb5_kcmss_ops;
275    id->data.length = sizeof(*c);
276    id->data.data = c;
277
278    return 0;
279}
280
281