xref: /minix/crypto/external/bsd/heimdal/dist/lib/krb5/kcm.c (revision 0a6a1f1d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: kcm.c,v 1.1.1.2 2014/04/24 12:45:50 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2005, PADL Software Pty Ltd.
5ebfedea0SLionel Sambuc  * All rights reserved.
6ebfedea0SLionel Sambuc  *
7ebfedea0SLionel Sambuc  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8ebfedea0SLionel Sambuc  *
9ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
10ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
11ebfedea0SLionel Sambuc  * are met:
12ebfedea0SLionel Sambuc  *
13ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15ebfedea0SLionel Sambuc  *
16ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
17ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
18ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
19ebfedea0SLionel Sambuc  *
20ebfedea0SLionel Sambuc  * 3. Neither the name of PADL Software nor the names of its contributors
21ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
22ebfedea0SLionel Sambuc  *    without specific prior written permission.
23ebfedea0SLionel Sambuc  *
24ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
25ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
28ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34ebfedea0SLionel Sambuc  * SUCH DAMAGE.
35ebfedea0SLionel Sambuc  */
36ebfedea0SLionel Sambuc 
37ebfedea0SLionel Sambuc #include "krb5_locl.h"
38ebfedea0SLionel Sambuc 
39ebfedea0SLionel Sambuc #ifdef HAVE_KCM
40ebfedea0SLionel Sambuc /*
41ebfedea0SLionel Sambuc  * Client library for Kerberos Credentials Manager (KCM) daemon
42ebfedea0SLionel Sambuc  */
43ebfedea0SLionel Sambuc 
44ebfedea0SLionel Sambuc #include <krb5/kcm.h>
45ebfedea0SLionel Sambuc #include <heim-ipc.h>
46ebfedea0SLionel Sambuc 
47ebfedea0SLionel Sambuc static krb5_error_code
48ebfedea0SLionel Sambuc kcm_set_kdc_offset(krb5_context, krb5_ccache, krb5_deltat);
49ebfedea0SLionel Sambuc 
50ebfedea0SLionel Sambuc static const char *kcm_ipc_name = "ANY:org.h5l.kcm";
51ebfedea0SLionel Sambuc 
52ebfedea0SLionel Sambuc typedef struct krb5_kcmcache {
53ebfedea0SLionel Sambuc     char *name;
54ebfedea0SLionel Sambuc } krb5_kcmcache;
55ebfedea0SLionel Sambuc 
56ebfedea0SLionel Sambuc typedef struct krb5_kcm_cursor {
57ebfedea0SLionel Sambuc     unsigned long offset;
58ebfedea0SLionel Sambuc     unsigned long length;
59ebfedea0SLionel Sambuc     kcmuuid_t *uuids;
60ebfedea0SLionel Sambuc } *krb5_kcm_cursor;
61ebfedea0SLionel Sambuc 
62ebfedea0SLionel Sambuc 
63ebfedea0SLionel Sambuc #define KCMCACHE(X)	((krb5_kcmcache *)(X)->data.data)
64ebfedea0SLionel Sambuc #define CACHENAME(X)	(KCMCACHE(X)->name)
65ebfedea0SLionel Sambuc #define KCMCURSOR(C)	((krb5_kcm_cursor)(C))
66ebfedea0SLionel Sambuc 
67ebfedea0SLionel Sambuc static HEIMDAL_MUTEX kcm_mutex = HEIMDAL_MUTEX_INITIALIZER;
68ebfedea0SLionel Sambuc static heim_ipc kcm_ipc = NULL;
69ebfedea0SLionel Sambuc 
70ebfedea0SLionel Sambuc static krb5_error_code
kcm_send_request(krb5_context context,krb5_storage * request,krb5_data * response_data)71ebfedea0SLionel Sambuc kcm_send_request(krb5_context context,
72ebfedea0SLionel Sambuc 		 krb5_storage *request,
73ebfedea0SLionel Sambuc 		 krb5_data *response_data)
74ebfedea0SLionel Sambuc {
75ebfedea0SLionel Sambuc     krb5_error_code ret = 0;
76ebfedea0SLionel Sambuc     krb5_data request_data;
77ebfedea0SLionel Sambuc 
78ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_lock(&kcm_mutex);
79ebfedea0SLionel Sambuc     if (kcm_ipc == NULL)
80ebfedea0SLionel Sambuc 	ret = heim_ipc_init_context(kcm_ipc_name, &kcm_ipc);
81ebfedea0SLionel Sambuc     HEIMDAL_MUTEX_unlock(&kcm_mutex);
82ebfedea0SLionel Sambuc     if (ret)
83ebfedea0SLionel Sambuc 	return KRB5_CC_NOSUPP;
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc     ret = krb5_storage_to_data(request, &request_data);
86ebfedea0SLionel Sambuc     if (ret) {
87ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
88ebfedea0SLionel Sambuc 	return KRB5_CC_NOMEM;
89ebfedea0SLionel Sambuc     }
90ebfedea0SLionel Sambuc 
91ebfedea0SLionel Sambuc     ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL);
92ebfedea0SLionel Sambuc     krb5_data_free(&request_data);
93ebfedea0SLionel Sambuc 
94ebfedea0SLionel Sambuc     if (ret) {
95ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
96ebfedea0SLionel Sambuc 	ret = KRB5_CC_NOSUPP;
97ebfedea0SLionel Sambuc     }
98ebfedea0SLionel Sambuc 
99ebfedea0SLionel Sambuc     return ret;
100ebfedea0SLionel Sambuc }
101ebfedea0SLionel Sambuc 
102ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kcm_storage_request(krb5_context context,uint16_t opcode,krb5_storage ** storage_p)103ebfedea0SLionel Sambuc krb5_kcm_storage_request(krb5_context context,
104ebfedea0SLionel Sambuc 			 uint16_t opcode,
105ebfedea0SLionel Sambuc 			 krb5_storage **storage_p)
106ebfedea0SLionel Sambuc {
107ebfedea0SLionel Sambuc     krb5_storage *sp;
108ebfedea0SLionel Sambuc     krb5_error_code ret;
109ebfedea0SLionel Sambuc 
110ebfedea0SLionel Sambuc     *storage_p = NULL;
111ebfedea0SLionel Sambuc 
112ebfedea0SLionel Sambuc     sp = krb5_storage_emem();
113ebfedea0SLionel Sambuc     if (sp == NULL) {
114ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", ""));
115ebfedea0SLionel Sambuc 	return KRB5_CC_NOMEM;
116ebfedea0SLionel Sambuc     }
117ebfedea0SLionel Sambuc 
118ebfedea0SLionel Sambuc     /* Send MAJOR | VERSION | OPCODE */
119ebfedea0SLionel Sambuc     ret  = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR);
120ebfedea0SLionel Sambuc     if (ret)
121ebfedea0SLionel Sambuc 	goto fail;
122ebfedea0SLionel Sambuc     ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR);
123ebfedea0SLionel Sambuc     if (ret)
124ebfedea0SLionel Sambuc 	goto fail;
125ebfedea0SLionel Sambuc     ret = krb5_store_int16(sp, opcode);
126ebfedea0SLionel Sambuc     if (ret)
127ebfedea0SLionel Sambuc 	goto fail;
128ebfedea0SLionel Sambuc 
129ebfedea0SLionel Sambuc     *storage_p = sp;
130ebfedea0SLionel Sambuc  fail:
131ebfedea0SLionel Sambuc     if (ret) {
132ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ret,
133ebfedea0SLionel Sambuc 			       N_("Failed to encode KCM request", ""));
134ebfedea0SLionel Sambuc 	krb5_storage_free(sp);
135ebfedea0SLionel Sambuc     }
136ebfedea0SLionel Sambuc 
137ebfedea0SLionel Sambuc     return ret;
138ebfedea0SLionel Sambuc }
139ebfedea0SLionel Sambuc 
140ebfedea0SLionel Sambuc static krb5_error_code
kcm_alloc(krb5_context context,const char * name,krb5_ccache * id)141ebfedea0SLionel Sambuc kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
142ebfedea0SLionel Sambuc {
143ebfedea0SLionel Sambuc     krb5_kcmcache *k;
144ebfedea0SLionel Sambuc 
145ebfedea0SLionel Sambuc     k = malloc(sizeof(*k));
146ebfedea0SLionel Sambuc     if (k == NULL) {
147ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_CC_NOMEM,
148ebfedea0SLionel Sambuc 			       N_("malloc: out of memory", ""));
149ebfedea0SLionel Sambuc 	return KRB5_CC_NOMEM;
150ebfedea0SLionel Sambuc     }
151ebfedea0SLionel Sambuc 
152ebfedea0SLionel Sambuc     if (name != NULL) {
153ebfedea0SLionel Sambuc 	k->name = strdup(name);
154ebfedea0SLionel Sambuc 	if (k->name == NULL) {
155ebfedea0SLionel Sambuc 	    free(k);
156ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, KRB5_CC_NOMEM,
157ebfedea0SLionel Sambuc 				   N_("malloc: out of memory", ""));
158ebfedea0SLionel Sambuc 	    return KRB5_CC_NOMEM;
159ebfedea0SLionel Sambuc 	}
160ebfedea0SLionel Sambuc     } else
161ebfedea0SLionel Sambuc 	k->name = NULL;
162ebfedea0SLionel Sambuc 
163ebfedea0SLionel Sambuc     (*id)->data.data = k;
164ebfedea0SLionel Sambuc     (*id)->data.length = sizeof(*k);
165ebfedea0SLionel Sambuc 
166ebfedea0SLionel Sambuc     return 0;
167ebfedea0SLionel Sambuc }
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kcm_call(krb5_context context,krb5_storage * request,krb5_storage ** response_p,krb5_data * response_data_p)170ebfedea0SLionel Sambuc krb5_kcm_call(krb5_context context,
171ebfedea0SLionel Sambuc 	      krb5_storage *request,
172ebfedea0SLionel Sambuc 	      krb5_storage **response_p,
173ebfedea0SLionel Sambuc 	      krb5_data *response_data_p)
174ebfedea0SLionel Sambuc {
175ebfedea0SLionel Sambuc     krb5_data response_data;
176ebfedea0SLionel Sambuc     krb5_error_code ret;
177ebfedea0SLionel Sambuc     int32_t status;
178ebfedea0SLionel Sambuc     krb5_storage *response;
179ebfedea0SLionel Sambuc 
180ebfedea0SLionel Sambuc     if (response_p != NULL)
181ebfedea0SLionel Sambuc 	*response_p = NULL;
182ebfedea0SLionel Sambuc 
183ebfedea0SLionel Sambuc     krb5_data_zero(&response_data);
184ebfedea0SLionel Sambuc 
185ebfedea0SLionel Sambuc     ret = kcm_send_request(context, request, &response_data);
186ebfedea0SLionel Sambuc     if (ret)
187ebfedea0SLionel Sambuc 	return ret;
188ebfedea0SLionel Sambuc 
189ebfedea0SLionel Sambuc     response = krb5_storage_from_data(&response_data);
190ebfedea0SLionel Sambuc     if (response == NULL) {
191ebfedea0SLionel Sambuc 	krb5_data_free(&response_data);
192ebfedea0SLionel Sambuc 	return KRB5_CC_IO;
193ebfedea0SLionel Sambuc     }
194ebfedea0SLionel Sambuc 
195ebfedea0SLionel Sambuc     ret = krb5_ret_int32(response, &status);
196ebfedea0SLionel Sambuc     if (ret) {
197ebfedea0SLionel Sambuc 	krb5_storage_free(response);
198ebfedea0SLionel Sambuc 	krb5_data_free(&response_data);
199ebfedea0SLionel Sambuc 	return KRB5_CC_FORMAT;
200ebfedea0SLionel Sambuc     }
201ebfedea0SLionel Sambuc 
202ebfedea0SLionel Sambuc     if (status) {
203ebfedea0SLionel Sambuc 	krb5_storage_free(response);
204ebfedea0SLionel Sambuc 	krb5_data_free(&response_data);
205ebfedea0SLionel Sambuc 	return status;
206ebfedea0SLionel Sambuc     }
207ebfedea0SLionel Sambuc 
208ebfedea0SLionel Sambuc     if (response_p != NULL) {
209ebfedea0SLionel Sambuc 	*response_data_p = response_data;
210ebfedea0SLionel Sambuc 	*response_p = response;
211ebfedea0SLionel Sambuc 
212ebfedea0SLionel Sambuc 	return 0;
213ebfedea0SLionel Sambuc     }
214ebfedea0SLionel Sambuc 
215ebfedea0SLionel Sambuc     krb5_storage_free(response);
216ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
217ebfedea0SLionel Sambuc 
218ebfedea0SLionel Sambuc     return 0;
219ebfedea0SLionel Sambuc }
220ebfedea0SLionel Sambuc 
221ebfedea0SLionel Sambuc static void
kcm_free(krb5_context context,krb5_ccache * id)222ebfedea0SLionel Sambuc kcm_free(krb5_context context, krb5_ccache *id)
223ebfedea0SLionel Sambuc {
224ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(*id);
225ebfedea0SLionel Sambuc 
226ebfedea0SLionel Sambuc     if (k != NULL) {
227ebfedea0SLionel Sambuc 	if (k->name != NULL)
228ebfedea0SLionel Sambuc 	    free(k->name);
229ebfedea0SLionel Sambuc 	memset(k, 0, sizeof(*k));
230ebfedea0SLionel Sambuc 	krb5_data_free(&(*id)->data);
231ebfedea0SLionel Sambuc     }
232ebfedea0SLionel Sambuc }
233ebfedea0SLionel Sambuc 
234ebfedea0SLionel Sambuc static const char *
kcm_get_name(krb5_context context,krb5_ccache id)235ebfedea0SLionel Sambuc kcm_get_name(krb5_context context,
236ebfedea0SLionel Sambuc 	     krb5_ccache id)
237ebfedea0SLionel Sambuc {
238ebfedea0SLionel Sambuc     return CACHENAME(id);
239ebfedea0SLionel Sambuc }
240ebfedea0SLionel Sambuc 
241ebfedea0SLionel Sambuc static krb5_error_code
kcm_resolve(krb5_context context,krb5_ccache * id,const char * res)242ebfedea0SLionel Sambuc kcm_resolve(krb5_context context, krb5_ccache *id, const char *res)
243ebfedea0SLionel Sambuc {
244ebfedea0SLionel Sambuc     return kcm_alloc(context, res, id);
245ebfedea0SLionel Sambuc }
246ebfedea0SLionel Sambuc 
247ebfedea0SLionel Sambuc /*
248ebfedea0SLionel Sambuc  * Request:
249ebfedea0SLionel Sambuc  *
250ebfedea0SLionel Sambuc  * Response:
251ebfedea0SLionel Sambuc  *      NameZ
252ebfedea0SLionel Sambuc  */
253ebfedea0SLionel Sambuc static krb5_error_code
kcm_gen_new(krb5_context context,krb5_ccache * id)254ebfedea0SLionel Sambuc kcm_gen_new(krb5_context context, krb5_ccache *id)
255ebfedea0SLionel Sambuc {
256ebfedea0SLionel Sambuc     krb5_kcmcache *k;
257ebfedea0SLionel Sambuc     krb5_error_code ret;
258ebfedea0SLionel Sambuc     krb5_storage *request, *response;
259ebfedea0SLionel Sambuc     krb5_data response_data;
260ebfedea0SLionel Sambuc 
261ebfedea0SLionel Sambuc     ret = kcm_alloc(context, NULL, id);
262ebfedea0SLionel Sambuc     if (ret)
263ebfedea0SLionel Sambuc 	return ret;
264ebfedea0SLionel Sambuc 
265ebfedea0SLionel Sambuc     k = KCMCACHE(*id);
266ebfedea0SLionel Sambuc 
267ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GEN_NEW, &request);
268ebfedea0SLionel Sambuc     if (ret) {
269ebfedea0SLionel Sambuc 	kcm_free(context, id);
270ebfedea0SLionel Sambuc 	return ret;
271ebfedea0SLionel Sambuc     }
272ebfedea0SLionel Sambuc 
273ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
274ebfedea0SLionel Sambuc     if (ret) {
275ebfedea0SLionel Sambuc 	krb5_storage_free(request);
276ebfedea0SLionel Sambuc 	kcm_free(context, id);
277ebfedea0SLionel Sambuc 	return ret;
278ebfedea0SLionel Sambuc     }
279ebfedea0SLionel Sambuc 
280ebfedea0SLionel Sambuc     ret = krb5_ret_stringz(response, &k->name);
281ebfedea0SLionel Sambuc     if (ret)
282ebfedea0SLionel Sambuc 	ret = KRB5_CC_IO;
283ebfedea0SLionel Sambuc 
284ebfedea0SLionel Sambuc     krb5_storage_free(request);
285ebfedea0SLionel Sambuc     krb5_storage_free(response);
286ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
287ebfedea0SLionel Sambuc 
288ebfedea0SLionel Sambuc     if (ret)
289ebfedea0SLionel Sambuc 	kcm_free(context, id);
290ebfedea0SLionel Sambuc 
291ebfedea0SLionel Sambuc     return ret;
292ebfedea0SLionel Sambuc }
293ebfedea0SLionel Sambuc 
294ebfedea0SLionel Sambuc /*
295ebfedea0SLionel Sambuc  * Request:
296ebfedea0SLionel Sambuc  *      NameZ
297ebfedea0SLionel Sambuc  *      Principal
298ebfedea0SLionel Sambuc  *
299ebfedea0SLionel Sambuc  * Response:
300ebfedea0SLionel Sambuc  *
301ebfedea0SLionel Sambuc  */
302ebfedea0SLionel Sambuc static krb5_error_code
kcm_initialize(krb5_context context,krb5_ccache id,krb5_principal primary_principal)303ebfedea0SLionel Sambuc kcm_initialize(krb5_context context,
304ebfedea0SLionel Sambuc 	       krb5_ccache id,
305ebfedea0SLionel Sambuc 	       krb5_principal primary_principal)
306ebfedea0SLionel Sambuc {
307ebfedea0SLionel Sambuc     krb5_error_code ret;
308ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
309ebfedea0SLionel Sambuc     krb5_storage *request;
310ebfedea0SLionel Sambuc 
311ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_INITIALIZE, &request);
312ebfedea0SLionel Sambuc     if (ret)
313ebfedea0SLionel Sambuc 	return ret;
314ebfedea0SLionel Sambuc 
315ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
316ebfedea0SLionel Sambuc     if (ret) {
317ebfedea0SLionel Sambuc 	krb5_storage_free(request);
318ebfedea0SLionel Sambuc 	return ret;
319ebfedea0SLionel Sambuc     }
320ebfedea0SLionel Sambuc 
321ebfedea0SLionel Sambuc     ret = krb5_store_principal(request, primary_principal);
322ebfedea0SLionel Sambuc     if (ret) {
323ebfedea0SLionel Sambuc 	krb5_storage_free(request);
324ebfedea0SLionel Sambuc 	return ret;
325ebfedea0SLionel Sambuc     }
326ebfedea0SLionel Sambuc 
327ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
328ebfedea0SLionel Sambuc 
329ebfedea0SLionel Sambuc     krb5_storage_free(request);
330ebfedea0SLionel Sambuc 
331ebfedea0SLionel Sambuc     if (context->kdc_sec_offset)
332ebfedea0SLionel Sambuc 	kcm_set_kdc_offset(context, id, context->kdc_sec_offset);
333ebfedea0SLionel Sambuc 
334ebfedea0SLionel Sambuc     return ret;
335ebfedea0SLionel Sambuc }
336ebfedea0SLionel Sambuc 
337ebfedea0SLionel Sambuc static krb5_error_code
kcm_close(krb5_context context,krb5_ccache id)338ebfedea0SLionel Sambuc kcm_close(krb5_context context,
339ebfedea0SLionel Sambuc 	  krb5_ccache id)
340ebfedea0SLionel Sambuc {
341ebfedea0SLionel Sambuc     kcm_free(context, &id);
342ebfedea0SLionel Sambuc     return 0;
343ebfedea0SLionel Sambuc }
344ebfedea0SLionel Sambuc 
345ebfedea0SLionel Sambuc /*
346ebfedea0SLionel Sambuc  * Request:
347ebfedea0SLionel Sambuc  *      NameZ
348ebfedea0SLionel Sambuc  *
349ebfedea0SLionel Sambuc  * Response:
350ebfedea0SLionel Sambuc  *
351ebfedea0SLionel Sambuc  */
352ebfedea0SLionel Sambuc static krb5_error_code
kcm_destroy(krb5_context context,krb5_ccache id)353ebfedea0SLionel Sambuc kcm_destroy(krb5_context context,
354ebfedea0SLionel Sambuc 	    krb5_ccache id)
355ebfedea0SLionel Sambuc {
356ebfedea0SLionel Sambuc     krb5_error_code ret;
357ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
358ebfedea0SLionel Sambuc     krb5_storage *request;
359ebfedea0SLionel Sambuc 
360ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_DESTROY, &request);
361ebfedea0SLionel Sambuc     if (ret)
362ebfedea0SLionel Sambuc 	return ret;
363ebfedea0SLionel Sambuc 
364ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
365ebfedea0SLionel Sambuc     if (ret) {
366ebfedea0SLionel Sambuc 	krb5_storage_free(request);
367ebfedea0SLionel Sambuc 	return ret;
368ebfedea0SLionel Sambuc     }
369ebfedea0SLionel Sambuc 
370ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
371ebfedea0SLionel Sambuc 
372ebfedea0SLionel Sambuc     krb5_storage_free(request);
373ebfedea0SLionel Sambuc     return ret;
374ebfedea0SLionel Sambuc }
375ebfedea0SLionel Sambuc 
376ebfedea0SLionel Sambuc /*
377ebfedea0SLionel Sambuc  * Request:
378ebfedea0SLionel Sambuc  *      NameZ
379ebfedea0SLionel Sambuc  *      Creds
380ebfedea0SLionel Sambuc  *
381ebfedea0SLionel Sambuc  * Response:
382ebfedea0SLionel Sambuc  *
383ebfedea0SLionel Sambuc  */
384ebfedea0SLionel Sambuc static krb5_error_code
kcm_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)385ebfedea0SLionel Sambuc kcm_store_cred(krb5_context context,
386ebfedea0SLionel Sambuc 	       krb5_ccache id,
387ebfedea0SLionel Sambuc 	       krb5_creds *creds)
388ebfedea0SLionel Sambuc {
389ebfedea0SLionel Sambuc     krb5_error_code ret;
390ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
391ebfedea0SLionel Sambuc     krb5_storage *request;
392ebfedea0SLionel Sambuc 
393ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_STORE, &request);
394ebfedea0SLionel Sambuc     if (ret)
395ebfedea0SLionel Sambuc 	return ret;
396ebfedea0SLionel Sambuc 
397ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
398ebfedea0SLionel Sambuc     if (ret) {
399ebfedea0SLionel Sambuc 	krb5_storage_free(request);
400ebfedea0SLionel Sambuc 	return ret;
401ebfedea0SLionel Sambuc     }
402ebfedea0SLionel Sambuc 
403ebfedea0SLionel Sambuc     ret = krb5_store_creds(request, creds);
404ebfedea0SLionel Sambuc     if (ret) {
405ebfedea0SLionel Sambuc 	krb5_storage_free(request);
406ebfedea0SLionel Sambuc 	return ret;
407ebfedea0SLionel Sambuc     }
408ebfedea0SLionel Sambuc 
409ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
410ebfedea0SLionel Sambuc 
411ebfedea0SLionel Sambuc     krb5_storage_free(request);
412ebfedea0SLionel Sambuc     return ret;
413ebfedea0SLionel Sambuc }
414ebfedea0SLionel Sambuc 
415ebfedea0SLionel Sambuc #if 0
416ebfedea0SLionel Sambuc /*
417ebfedea0SLionel Sambuc  * Request:
418ebfedea0SLionel Sambuc  *      NameZ
419ebfedea0SLionel Sambuc  *      WhichFields
420ebfedea0SLionel Sambuc  *      MatchCreds
421ebfedea0SLionel Sambuc  *
422ebfedea0SLionel Sambuc  * Response:
423ebfedea0SLionel Sambuc  *      Creds
424ebfedea0SLionel Sambuc  *
425ebfedea0SLionel Sambuc  */
426ebfedea0SLionel Sambuc static krb5_error_code
427ebfedea0SLionel Sambuc kcm_retrieve(krb5_context context,
428ebfedea0SLionel Sambuc 	     krb5_ccache id,
429ebfedea0SLionel Sambuc 	     krb5_flags which,
430ebfedea0SLionel Sambuc 	     const krb5_creds *mcred,
431ebfedea0SLionel Sambuc 	     krb5_creds *creds)
432ebfedea0SLionel Sambuc {
433ebfedea0SLionel Sambuc     krb5_error_code ret;
434ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
435ebfedea0SLionel Sambuc     krb5_storage *request, *response;
436ebfedea0SLionel Sambuc     krb5_data response_data;
437ebfedea0SLionel Sambuc 
438ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_RETRIEVE, &request);
439ebfedea0SLionel Sambuc     if (ret)
440ebfedea0SLionel Sambuc 	return ret;
441ebfedea0SLionel Sambuc 
442ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
443ebfedea0SLionel Sambuc     if (ret) {
444ebfedea0SLionel Sambuc 	krb5_storage_free(request);
445ebfedea0SLionel Sambuc 	return ret;
446ebfedea0SLionel Sambuc     }
447ebfedea0SLionel Sambuc 
448ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, which);
449ebfedea0SLionel Sambuc     if (ret) {
450ebfedea0SLionel Sambuc 	krb5_storage_free(request);
451ebfedea0SLionel Sambuc 	return ret;
452ebfedea0SLionel Sambuc     }
453ebfedea0SLionel Sambuc 
454ebfedea0SLionel Sambuc     ret = krb5_store_creds_tag(request, rk_UNCONST(mcred));
455ebfedea0SLionel Sambuc     if (ret) {
456ebfedea0SLionel Sambuc 	krb5_storage_free(request);
457ebfedea0SLionel Sambuc 	return ret;
458ebfedea0SLionel Sambuc     }
459ebfedea0SLionel Sambuc 
460ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
461ebfedea0SLionel Sambuc     if (ret) {
462ebfedea0SLionel Sambuc 	krb5_storage_free(request);
463ebfedea0SLionel Sambuc 	return ret;
464ebfedea0SLionel Sambuc     }
465ebfedea0SLionel Sambuc 
466ebfedea0SLionel Sambuc     ret = krb5_ret_creds(response, creds);
467ebfedea0SLionel Sambuc     if (ret)
468ebfedea0SLionel Sambuc 	ret = KRB5_CC_IO;
469ebfedea0SLionel Sambuc 
470ebfedea0SLionel Sambuc     krb5_storage_free(request);
471ebfedea0SLionel Sambuc     krb5_storage_free(response);
472ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
473ebfedea0SLionel Sambuc 
474ebfedea0SLionel Sambuc     return ret;
475ebfedea0SLionel Sambuc }
476ebfedea0SLionel Sambuc #endif
477ebfedea0SLionel Sambuc 
478ebfedea0SLionel Sambuc /*
479ebfedea0SLionel Sambuc  * Request:
480ebfedea0SLionel Sambuc  *      NameZ
481ebfedea0SLionel Sambuc  *
482ebfedea0SLionel Sambuc  * Response:
483ebfedea0SLionel Sambuc  *      Principal
484ebfedea0SLionel Sambuc  */
485ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_principal(krb5_context context,krb5_ccache id,krb5_principal * principal)486ebfedea0SLionel Sambuc kcm_get_principal(krb5_context context,
487ebfedea0SLionel Sambuc 		  krb5_ccache id,
488ebfedea0SLionel Sambuc 		  krb5_principal *principal)
489ebfedea0SLionel Sambuc {
490ebfedea0SLionel Sambuc     krb5_error_code ret;
491ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
492ebfedea0SLionel Sambuc     krb5_storage *request, *response;
493ebfedea0SLionel Sambuc     krb5_data response_data;
494ebfedea0SLionel Sambuc 
495ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request);
496ebfedea0SLionel Sambuc     if (ret)
497ebfedea0SLionel Sambuc 	return ret;
498ebfedea0SLionel Sambuc 
499ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
500ebfedea0SLionel Sambuc     if (ret) {
501ebfedea0SLionel Sambuc 	krb5_storage_free(request);
502ebfedea0SLionel Sambuc 	return ret;
503ebfedea0SLionel Sambuc     }
504ebfedea0SLionel Sambuc 
505ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
506ebfedea0SLionel Sambuc     if (ret) {
507ebfedea0SLionel Sambuc 	krb5_storage_free(request);
508ebfedea0SLionel Sambuc 	return ret;
509ebfedea0SLionel Sambuc     }
510ebfedea0SLionel Sambuc 
511ebfedea0SLionel Sambuc     ret = krb5_ret_principal(response, principal);
512ebfedea0SLionel Sambuc     if (ret)
513ebfedea0SLionel Sambuc 	ret = KRB5_CC_IO;
514ebfedea0SLionel Sambuc 
515ebfedea0SLionel Sambuc     krb5_storage_free(request);
516ebfedea0SLionel Sambuc     krb5_storage_free(response);
517ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
518ebfedea0SLionel Sambuc 
519ebfedea0SLionel Sambuc     return ret;
520ebfedea0SLionel Sambuc }
521ebfedea0SLionel Sambuc 
522ebfedea0SLionel Sambuc /*
523ebfedea0SLionel Sambuc  * Request:
524ebfedea0SLionel Sambuc  *      NameZ
525ebfedea0SLionel Sambuc  *
526ebfedea0SLionel Sambuc  * Response:
527ebfedea0SLionel Sambuc  *      Cursor
528ebfedea0SLionel Sambuc  *
529ebfedea0SLionel Sambuc  */
530ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_first(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)531ebfedea0SLionel Sambuc kcm_get_first (krb5_context context,
532ebfedea0SLionel Sambuc 	       krb5_ccache id,
533ebfedea0SLionel Sambuc 	       krb5_cc_cursor *cursor)
534ebfedea0SLionel Sambuc {
535ebfedea0SLionel Sambuc     krb5_error_code ret;
536ebfedea0SLionel Sambuc     krb5_kcm_cursor c;
537ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
538ebfedea0SLionel Sambuc     krb5_storage *request, *response;
539ebfedea0SLionel Sambuc     krb5_data response_data;
540ebfedea0SLionel Sambuc 
541ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_CRED_UUID_LIST, &request);
542ebfedea0SLionel Sambuc     if (ret)
543ebfedea0SLionel Sambuc 	return ret;
544ebfedea0SLionel Sambuc 
545ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
546ebfedea0SLionel Sambuc     if (ret) {
547ebfedea0SLionel Sambuc 	krb5_storage_free(request);
548ebfedea0SLionel Sambuc 	return ret;
549ebfedea0SLionel Sambuc     }
550ebfedea0SLionel Sambuc 
551ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
552ebfedea0SLionel Sambuc     krb5_storage_free(request);
553ebfedea0SLionel Sambuc     if (ret)
554ebfedea0SLionel Sambuc 	return ret;
555ebfedea0SLionel Sambuc 
556ebfedea0SLionel Sambuc     c = calloc(1, sizeof(*c));
557ebfedea0SLionel Sambuc     if (c == NULL) {
558ebfedea0SLionel Sambuc 	ret = ENOMEM;
559ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ret,
560ebfedea0SLionel Sambuc 			       N_("malloc: out of memory", ""));
561ebfedea0SLionel Sambuc 	return ret;
562ebfedea0SLionel Sambuc     }
563ebfedea0SLionel Sambuc 
564ebfedea0SLionel Sambuc     while (1) {
565ebfedea0SLionel Sambuc 	ssize_t sret;
566ebfedea0SLionel Sambuc 	kcmuuid_t uuid;
567ebfedea0SLionel Sambuc 	void *ptr;
568ebfedea0SLionel Sambuc 
569ebfedea0SLionel Sambuc 	sret = krb5_storage_read(response, &uuid, sizeof(uuid));
570ebfedea0SLionel Sambuc 	if (sret == 0) {
571ebfedea0SLionel Sambuc 	    ret = 0;
572ebfedea0SLionel Sambuc 	    break;
573ebfedea0SLionel Sambuc 	} else if (sret != sizeof(uuid)) {
574ebfedea0SLionel Sambuc 	    ret = EINVAL;
575ebfedea0SLionel Sambuc 	    break;
576ebfedea0SLionel Sambuc 	}
577ebfedea0SLionel Sambuc 
578ebfedea0SLionel Sambuc 	ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1));
579ebfedea0SLionel Sambuc 	if (ptr == NULL) {
580ebfedea0SLionel Sambuc 	    free(c->uuids);
581ebfedea0SLionel Sambuc 	    free(c);
582ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ENOMEM,
583ebfedea0SLionel Sambuc 				   N_("malloc: out of memory", ""));
584ebfedea0SLionel Sambuc 	    return ENOMEM;
585ebfedea0SLionel Sambuc 	}
586ebfedea0SLionel Sambuc 	c->uuids = ptr;
587ebfedea0SLionel Sambuc 
588ebfedea0SLionel Sambuc 	memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
589ebfedea0SLionel Sambuc 	c->length += 1;
590ebfedea0SLionel Sambuc     }
591ebfedea0SLionel Sambuc 
592ebfedea0SLionel Sambuc     krb5_storage_free(response);
593ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
594ebfedea0SLionel Sambuc 
595ebfedea0SLionel Sambuc     if (ret) {
596ebfedea0SLionel Sambuc         free(c->uuids);
597ebfedea0SLionel Sambuc         free(c);
598ebfedea0SLionel Sambuc 	return ret;
599ebfedea0SLionel Sambuc     }
600ebfedea0SLionel Sambuc 
601ebfedea0SLionel Sambuc     *cursor = c;
602ebfedea0SLionel Sambuc 
603ebfedea0SLionel Sambuc     return 0;
604ebfedea0SLionel Sambuc }
605ebfedea0SLionel Sambuc 
606ebfedea0SLionel Sambuc /*
607ebfedea0SLionel Sambuc  * Request:
608ebfedea0SLionel Sambuc  *      NameZ
609ebfedea0SLionel Sambuc  *      Cursor
610ebfedea0SLionel Sambuc  *
611ebfedea0SLionel Sambuc  * Response:
612ebfedea0SLionel Sambuc  *      Creds
613ebfedea0SLionel Sambuc  */
614ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)615ebfedea0SLionel Sambuc kcm_get_next (krb5_context context,
616ebfedea0SLionel Sambuc 		krb5_ccache id,
617ebfedea0SLionel Sambuc 		krb5_cc_cursor *cursor,
618ebfedea0SLionel Sambuc 		krb5_creds *creds)
619ebfedea0SLionel Sambuc {
620ebfedea0SLionel Sambuc     krb5_error_code ret;
621ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
622ebfedea0SLionel Sambuc     krb5_kcm_cursor c = KCMCURSOR(*cursor);
623ebfedea0SLionel Sambuc     krb5_storage *request, *response;
624ebfedea0SLionel Sambuc     krb5_data response_data;
625ebfedea0SLionel Sambuc     ssize_t sret;
626ebfedea0SLionel Sambuc 
627ebfedea0SLionel Sambuc  again:
628ebfedea0SLionel Sambuc 
629ebfedea0SLionel Sambuc     if (c->offset >= c->length)
630ebfedea0SLionel Sambuc 	return KRB5_CC_END;
631ebfedea0SLionel Sambuc 
632ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_CRED_BY_UUID, &request);
633ebfedea0SLionel Sambuc     if (ret)
634ebfedea0SLionel Sambuc 	return ret;
635ebfedea0SLionel Sambuc 
636ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
637ebfedea0SLionel Sambuc     if (ret) {
638ebfedea0SLionel Sambuc 	krb5_storage_free(request);
639ebfedea0SLionel Sambuc 	return ret;
640ebfedea0SLionel Sambuc     }
641ebfedea0SLionel Sambuc 
642ebfedea0SLionel Sambuc     sret = krb5_storage_write(request,
643ebfedea0SLionel Sambuc 			      &c->uuids[c->offset],
644ebfedea0SLionel Sambuc 			      sizeof(c->uuids[c->offset]));
645ebfedea0SLionel Sambuc     c->offset++;
646ebfedea0SLionel Sambuc     if (sret != sizeof(c->uuids[c->offset])) {
647ebfedea0SLionel Sambuc 	krb5_storage_free(request);
648ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
649ebfedea0SLionel Sambuc 	return ENOMEM;
650ebfedea0SLionel Sambuc     }
651ebfedea0SLionel Sambuc 
652ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
653ebfedea0SLionel Sambuc     krb5_storage_free(request);
654ebfedea0SLionel Sambuc     if (ret == KRB5_CC_END) {
655ebfedea0SLionel Sambuc 	goto again;
656ebfedea0SLionel Sambuc     }
657ebfedea0SLionel Sambuc 
658ebfedea0SLionel Sambuc     ret = krb5_ret_creds(response, creds);
659ebfedea0SLionel Sambuc     if (ret)
660ebfedea0SLionel Sambuc 	ret = KRB5_CC_IO;
661ebfedea0SLionel Sambuc 
662ebfedea0SLionel Sambuc     krb5_storage_free(response);
663ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
664ebfedea0SLionel Sambuc 
665ebfedea0SLionel Sambuc     return ret;
666ebfedea0SLionel Sambuc }
667ebfedea0SLionel Sambuc 
668ebfedea0SLionel Sambuc /*
669ebfedea0SLionel Sambuc  * Request:
670ebfedea0SLionel Sambuc  *      NameZ
671ebfedea0SLionel Sambuc  *      Cursor
672ebfedea0SLionel Sambuc  *
673ebfedea0SLionel Sambuc  * Response:
674ebfedea0SLionel Sambuc  *
675ebfedea0SLionel Sambuc  */
676ebfedea0SLionel Sambuc static krb5_error_code
kcm_end_get(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)677ebfedea0SLionel Sambuc kcm_end_get (krb5_context context,
678ebfedea0SLionel Sambuc 	     krb5_ccache id,
679ebfedea0SLionel Sambuc 	     krb5_cc_cursor *cursor)
680ebfedea0SLionel Sambuc {
681ebfedea0SLionel Sambuc     krb5_kcm_cursor c = KCMCURSOR(*cursor);
682ebfedea0SLionel Sambuc 
683ebfedea0SLionel Sambuc     free(c->uuids);
684ebfedea0SLionel Sambuc     free(c);
685ebfedea0SLionel Sambuc 
686ebfedea0SLionel Sambuc     *cursor = NULL;
687ebfedea0SLionel Sambuc 
688ebfedea0SLionel Sambuc     return 0;
689ebfedea0SLionel Sambuc }
690ebfedea0SLionel Sambuc 
691ebfedea0SLionel Sambuc /*
692ebfedea0SLionel Sambuc  * Request:
693ebfedea0SLionel Sambuc  *      NameZ
694ebfedea0SLionel Sambuc  *      WhichFields
695ebfedea0SLionel Sambuc  *      MatchCreds
696ebfedea0SLionel Sambuc  *
697ebfedea0SLionel Sambuc  * Response:
698ebfedea0SLionel Sambuc  *
699ebfedea0SLionel Sambuc  */
700ebfedea0SLionel Sambuc static krb5_error_code
kcm_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * cred)701ebfedea0SLionel Sambuc kcm_remove_cred(krb5_context context,
702ebfedea0SLionel Sambuc 		krb5_ccache id,
703ebfedea0SLionel Sambuc 		krb5_flags which,
704ebfedea0SLionel Sambuc 		krb5_creds *cred)
705ebfedea0SLionel Sambuc {
706ebfedea0SLionel Sambuc     krb5_error_code ret;
707ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
708ebfedea0SLionel Sambuc     krb5_storage *request;
709ebfedea0SLionel Sambuc 
710ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request);
711ebfedea0SLionel Sambuc     if (ret)
712ebfedea0SLionel Sambuc 	return ret;
713ebfedea0SLionel Sambuc 
714ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
715ebfedea0SLionel Sambuc     if (ret) {
716ebfedea0SLionel Sambuc 	krb5_storage_free(request);
717ebfedea0SLionel Sambuc 	return ret;
718ebfedea0SLionel Sambuc     }
719ebfedea0SLionel Sambuc 
720ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, which);
721ebfedea0SLionel Sambuc     if (ret) {
722ebfedea0SLionel Sambuc 	krb5_storage_free(request);
723ebfedea0SLionel Sambuc 	return ret;
724ebfedea0SLionel Sambuc     }
725ebfedea0SLionel Sambuc 
726ebfedea0SLionel Sambuc     ret = krb5_store_creds_tag(request, cred);
727ebfedea0SLionel Sambuc     if (ret) {
728ebfedea0SLionel Sambuc 	krb5_storage_free(request);
729ebfedea0SLionel Sambuc 	return ret;
730ebfedea0SLionel Sambuc     }
731ebfedea0SLionel Sambuc 
732ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
733ebfedea0SLionel Sambuc 
734ebfedea0SLionel Sambuc     krb5_storage_free(request);
735ebfedea0SLionel Sambuc     return ret;
736ebfedea0SLionel Sambuc }
737ebfedea0SLionel Sambuc 
738ebfedea0SLionel Sambuc static krb5_error_code
kcm_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)739ebfedea0SLionel Sambuc kcm_set_flags(krb5_context context,
740ebfedea0SLionel Sambuc 	      krb5_ccache id,
741ebfedea0SLionel Sambuc 	      krb5_flags flags)
742ebfedea0SLionel Sambuc {
743ebfedea0SLionel Sambuc     krb5_error_code ret;
744ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
745ebfedea0SLionel Sambuc     krb5_storage *request;
746ebfedea0SLionel Sambuc 
747ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_SET_FLAGS, &request);
748ebfedea0SLionel Sambuc     if (ret)
749ebfedea0SLionel Sambuc 	return ret;
750ebfedea0SLionel Sambuc 
751ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
752ebfedea0SLionel Sambuc     if (ret) {
753ebfedea0SLionel Sambuc 	krb5_storage_free(request);
754ebfedea0SLionel Sambuc 	return ret;
755ebfedea0SLionel Sambuc     }
756ebfedea0SLionel Sambuc 
757ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, flags);
758ebfedea0SLionel Sambuc     if (ret) {
759ebfedea0SLionel Sambuc 	krb5_storage_free(request);
760ebfedea0SLionel Sambuc 	return ret;
761ebfedea0SLionel Sambuc     }
762ebfedea0SLionel Sambuc 
763ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
764ebfedea0SLionel Sambuc 
765ebfedea0SLionel Sambuc     krb5_storage_free(request);
766ebfedea0SLionel Sambuc     return ret;
767ebfedea0SLionel Sambuc }
768ebfedea0SLionel Sambuc 
769ebfedea0SLionel Sambuc static int
kcm_get_version(krb5_context context,krb5_ccache id)770ebfedea0SLionel Sambuc kcm_get_version(krb5_context context,
771ebfedea0SLionel Sambuc 		krb5_ccache id)
772ebfedea0SLionel Sambuc {
773ebfedea0SLionel Sambuc     return 0;
774ebfedea0SLionel Sambuc }
775ebfedea0SLionel Sambuc 
776ebfedea0SLionel Sambuc /*
777ebfedea0SLionel Sambuc  * Send nothing
778ebfedea0SLionel Sambuc  * get back list of uuids
779ebfedea0SLionel Sambuc  */
780ebfedea0SLionel Sambuc 
781ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_cache_first(krb5_context context,krb5_cc_cursor * cursor)782ebfedea0SLionel Sambuc kcm_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
783ebfedea0SLionel Sambuc {
784ebfedea0SLionel Sambuc     krb5_error_code ret;
785ebfedea0SLionel Sambuc     krb5_kcm_cursor c;
786ebfedea0SLionel Sambuc     krb5_storage *request, *response;
787ebfedea0SLionel Sambuc     krb5_data response_data;
788ebfedea0SLionel Sambuc 
789ebfedea0SLionel Sambuc     *cursor = NULL;
790ebfedea0SLionel Sambuc 
791ebfedea0SLionel Sambuc     c = calloc(1, sizeof(*c));
792ebfedea0SLionel Sambuc     if (c == NULL) {
793ebfedea0SLionel Sambuc 	ret = ENOMEM;
794ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ret,
795ebfedea0SLionel Sambuc 			       N_("malloc: out of memory", ""));
796ebfedea0SLionel Sambuc 	goto out;
797ebfedea0SLionel Sambuc     }
798ebfedea0SLionel Sambuc 
799ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_UUID_LIST, &request);
800ebfedea0SLionel Sambuc     if (ret)
801ebfedea0SLionel Sambuc 	goto out;
802ebfedea0SLionel Sambuc 
803ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
804ebfedea0SLionel Sambuc     krb5_storage_free(request);
805ebfedea0SLionel Sambuc     if (ret)
806ebfedea0SLionel Sambuc 	goto out;
807ebfedea0SLionel Sambuc 
808ebfedea0SLionel Sambuc     while (1) {
809ebfedea0SLionel Sambuc 	ssize_t sret;
810ebfedea0SLionel Sambuc 	kcmuuid_t uuid;
811ebfedea0SLionel Sambuc 	void *ptr;
812ebfedea0SLionel Sambuc 
813ebfedea0SLionel Sambuc 	sret = krb5_storage_read(response, &uuid, sizeof(uuid));
814ebfedea0SLionel Sambuc 	if (sret == 0) {
815ebfedea0SLionel Sambuc 	    ret = 0;
816ebfedea0SLionel Sambuc 	    break;
817ebfedea0SLionel Sambuc 	} else if (sret != sizeof(uuid)) {
818ebfedea0SLionel Sambuc 	    ret = EINVAL;
819ebfedea0SLionel Sambuc 	    goto out;
820ebfedea0SLionel Sambuc 	}
821ebfedea0SLionel Sambuc 
822ebfedea0SLionel Sambuc 	ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1));
823ebfedea0SLionel Sambuc 	if (ptr == NULL) {
824ebfedea0SLionel Sambuc 	    ret = ENOMEM;
825ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret,
826ebfedea0SLionel Sambuc 				   N_("malloc: out of memory", ""));
827ebfedea0SLionel Sambuc 	    goto out;
828ebfedea0SLionel Sambuc 	}
829ebfedea0SLionel Sambuc 	c->uuids = ptr;
830ebfedea0SLionel Sambuc 
831ebfedea0SLionel Sambuc 	memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
832ebfedea0SLionel Sambuc 	c->length += 1;
833ebfedea0SLionel Sambuc     }
834ebfedea0SLionel Sambuc 
835ebfedea0SLionel Sambuc     krb5_storage_free(response);
836ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
837ebfedea0SLionel Sambuc 
838ebfedea0SLionel Sambuc  out:
839ebfedea0SLionel Sambuc     if (ret && c) {
840ebfedea0SLionel Sambuc         free(c->uuids);
841ebfedea0SLionel Sambuc         free(c);
842ebfedea0SLionel Sambuc     } else
843ebfedea0SLionel Sambuc 	*cursor = c;
844ebfedea0SLionel Sambuc 
845ebfedea0SLionel Sambuc     return ret;
846ebfedea0SLionel Sambuc }
847ebfedea0SLionel Sambuc 
848ebfedea0SLionel Sambuc /*
849ebfedea0SLionel Sambuc  * Send uuid
850ebfedea0SLionel Sambuc  * Recv cache name
851ebfedea0SLionel Sambuc  */
852ebfedea0SLionel Sambuc 
853ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_cache_next(krb5_context context,krb5_cc_cursor cursor,const krb5_cc_ops * ops,krb5_ccache * id)854ebfedea0SLionel Sambuc kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_ops *ops, krb5_ccache *id)
855ebfedea0SLionel Sambuc {
856ebfedea0SLionel Sambuc     krb5_error_code ret;
857ebfedea0SLionel Sambuc     krb5_kcm_cursor c = KCMCURSOR(cursor);
858ebfedea0SLionel Sambuc     krb5_storage *request, *response;
859ebfedea0SLionel Sambuc     krb5_data response_data;
860ebfedea0SLionel Sambuc     ssize_t sret;
861ebfedea0SLionel Sambuc     char *name;
862ebfedea0SLionel Sambuc 
863ebfedea0SLionel Sambuc     *id = NULL;
864ebfedea0SLionel Sambuc 
865ebfedea0SLionel Sambuc  again:
866ebfedea0SLionel Sambuc 
867ebfedea0SLionel Sambuc     if (c->offset >= c->length)
868ebfedea0SLionel Sambuc 	return KRB5_CC_END;
869ebfedea0SLionel Sambuc 
870ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request);
871ebfedea0SLionel Sambuc     if (ret)
872ebfedea0SLionel Sambuc 	return ret;
873ebfedea0SLionel Sambuc 
874ebfedea0SLionel Sambuc     sret = krb5_storage_write(request,
875ebfedea0SLionel Sambuc 			      &c->uuids[c->offset],
876ebfedea0SLionel Sambuc 			      sizeof(c->uuids[c->offset]));
877ebfedea0SLionel Sambuc     c->offset++;
878ebfedea0SLionel Sambuc     if (sret != sizeof(c->uuids[c->offset])) {
879ebfedea0SLionel Sambuc 	krb5_storage_free(request);
880ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
881ebfedea0SLionel Sambuc 	return ENOMEM;
882ebfedea0SLionel Sambuc     }
883ebfedea0SLionel Sambuc 
884ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
885ebfedea0SLionel Sambuc     krb5_storage_free(request);
886ebfedea0SLionel Sambuc     if (ret == KRB5_CC_END)
887ebfedea0SLionel Sambuc 	goto again;
888ebfedea0SLionel Sambuc 
889ebfedea0SLionel Sambuc     ret = krb5_ret_stringz(response, &name);
890ebfedea0SLionel Sambuc     krb5_storage_free(response);
891ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
892ebfedea0SLionel Sambuc 
893ebfedea0SLionel Sambuc     if (ret == 0) {
894ebfedea0SLionel Sambuc 	ret = _krb5_cc_allocate(context, ops, id);
895ebfedea0SLionel Sambuc 	if (ret == 0)
896ebfedea0SLionel Sambuc 	    ret = kcm_alloc(context, name, id);
897ebfedea0SLionel Sambuc 	krb5_xfree(name);
898ebfedea0SLionel Sambuc     }
899ebfedea0SLionel Sambuc 
900ebfedea0SLionel Sambuc     return ret;
901ebfedea0SLionel Sambuc }
902ebfedea0SLionel Sambuc 
903ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_cache_next_kcm(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)904ebfedea0SLionel Sambuc kcm_get_cache_next_kcm(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
905ebfedea0SLionel Sambuc {
906ebfedea0SLionel Sambuc #ifndef KCM_IS_API_CACHE
907ebfedea0SLionel Sambuc     return kcm_get_cache_next(context, cursor, &krb5_kcm_ops, id);
908ebfedea0SLionel Sambuc #else
909ebfedea0SLionel Sambuc     return KRB5_CC_END;
910ebfedea0SLionel Sambuc #endif
911ebfedea0SLionel Sambuc }
912ebfedea0SLionel Sambuc 
913ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_cache_next_api(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)914ebfedea0SLionel Sambuc kcm_get_cache_next_api(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
915ebfedea0SLionel Sambuc {
916ebfedea0SLionel Sambuc     return kcm_get_cache_next(context, cursor, &krb5_akcm_ops, id);
917ebfedea0SLionel Sambuc }
918ebfedea0SLionel Sambuc 
919ebfedea0SLionel Sambuc 
920ebfedea0SLionel Sambuc static krb5_error_code
kcm_end_cache_get(krb5_context context,krb5_cc_cursor cursor)921ebfedea0SLionel Sambuc kcm_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
922ebfedea0SLionel Sambuc {
923ebfedea0SLionel Sambuc     krb5_kcm_cursor c = KCMCURSOR(cursor);
924ebfedea0SLionel Sambuc 
925ebfedea0SLionel Sambuc     free(c->uuids);
926ebfedea0SLionel Sambuc     free(c);
927ebfedea0SLionel Sambuc     return 0;
928ebfedea0SLionel Sambuc }
929ebfedea0SLionel Sambuc 
930ebfedea0SLionel Sambuc 
931ebfedea0SLionel Sambuc static krb5_error_code
kcm_move(krb5_context context,krb5_ccache from,krb5_ccache to)932ebfedea0SLionel Sambuc kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to)
933ebfedea0SLionel Sambuc {
934ebfedea0SLionel Sambuc     krb5_error_code ret;
935ebfedea0SLionel Sambuc     krb5_kcmcache *oldk = KCMCACHE(from);
936ebfedea0SLionel Sambuc     krb5_kcmcache *newk = KCMCACHE(to);
937ebfedea0SLionel Sambuc     krb5_storage *request;
938ebfedea0SLionel Sambuc 
939ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_MOVE_CACHE, &request);
940ebfedea0SLionel Sambuc     if (ret)
941ebfedea0SLionel Sambuc 	return ret;
942ebfedea0SLionel Sambuc 
943ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, oldk->name);
944ebfedea0SLionel Sambuc     if (ret) {
945ebfedea0SLionel Sambuc 	krb5_storage_free(request);
946ebfedea0SLionel Sambuc 	return ret;
947ebfedea0SLionel Sambuc     }
948ebfedea0SLionel Sambuc 
949ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, newk->name);
950ebfedea0SLionel Sambuc     if (ret) {
951ebfedea0SLionel Sambuc 	krb5_storage_free(request);
952ebfedea0SLionel Sambuc 	return ret;
953ebfedea0SLionel Sambuc     }
954ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
955ebfedea0SLionel Sambuc 
956ebfedea0SLionel Sambuc     krb5_storage_free(request);
957ebfedea0SLionel Sambuc     return ret;
958ebfedea0SLionel Sambuc }
959ebfedea0SLionel Sambuc 
960ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_default_name(krb5_context context,const krb5_cc_ops * ops,const char * defstr,char ** str)961ebfedea0SLionel Sambuc kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops,
962ebfedea0SLionel Sambuc 		     const char *defstr, char **str)
963ebfedea0SLionel Sambuc {
964ebfedea0SLionel Sambuc     krb5_error_code ret;
965ebfedea0SLionel Sambuc     krb5_storage *request, *response;
966ebfedea0SLionel Sambuc     krb5_data response_data;
967ebfedea0SLionel Sambuc     char *name;
968ebfedea0SLionel Sambuc 
969ebfedea0SLionel Sambuc     *str = NULL;
970ebfedea0SLionel Sambuc 
971ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_DEFAULT_CACHE, &request);
972ebfedea0SLionel Sambuc     if (ret)
973ebfedea0SLionel Sambuc 	return ret;
974ebfedea0SLionel Sambuc 
975ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
976ebfedea0SLionel Sambuc     krb5_storage_free(request);
977ebfedea0SLionel Sambuc     if (ret)
978ebfedea0SLionel Sambuc 	return _krb5_expand_default_cc_name(context, defstr, str);
979ebfedea0SLionel Sambuc 
980ebfedea0SLionel Sambuc     ret = krb5_ret_stringz(response, &name);
981ebfedea0SLionel Sambuc     krb5_storage_free(response);
982ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
983ebfedea0SLionel Sambuc     if (ret)
984ebfedea0SLionel Sambuc 	return ret;
985ebfedea0SLionel Sambuc 
986ebfedea0SLionel Sambuc     asprintf(str, "%s:%s", ops->prefix, name);
987ebfedea0SLionel Sambuc     free(name);
988ebfedea0SLionel Sambuc     if (str == NULL)
989ebfedea0SLionel Sambuc 	return ENOMEM;
990ebfedea0SLionel Sambuc 
991ebfedea0SLionel Sambuc     return 0;
992ebfedea0SLionel Sambuc }
993ebfedea0SLionel Sambuc 
994ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_default_name_api(krb5_context context,char ** str)995ebfedea0SLionel Sambuc kcm_get_default_name_api(krb5_context context, char **str)
996ebfedea0SLionel Sambuc {
997ebfedea0SLionel Sambuc     return kcm_get_default_name(context, &krb5_akcm_ops,
998ebfedea0SLionel Sambuc 				KRB5_DEFAULT_CCNAME_KCM_API, str);
999ebfedea0SLionel Sambuc }
1000ebfedea0SLionel Sambuc 
1001ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_default_name_kcm(krb5_context context,char ** str)1002ebfedea0SLionel Sambuc kcm_get_default_name_kcm(krb5_context context, char **str)
1003ebfedea0SLionel Sambuc {
1004ebfedea0SLionel Sambuc     return kcm_get_default_name(context, &krb5_kcm_ops,
1005ebfedea0SLionel Sambuc 				KRB5_DEFAULT_CCNAME_KCM_KCM, str);
1006ebfedea0SLionel Sambuc }
1007ebfedea0SLionel Sambuc 
1008ebfedea0SLionel Sambuc static krb5_error_code
kcm_set_default(krb5_context context,krb5_ccache id)1009ebfedea0SLionel Sambuc kcm_set_default(krb5_context context, krb5_ccache id)
1010ebfedea0SLionel Sambuc {
1011ebfedea0SLionel Sambuc     krb5_error_code ret;
1012ebfedea0SLionel Sambuc     krb5_storage *request;
1013ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
1014ebfedea0SLionel Sambuc 
1015ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_SET_DEFAULT_CACHE, &request);
1016ebfedea0SLionel Sambuc     if (ret)
1017ebfedea0SLionel Sambuc 	return ret;
1018ebfedea0SLionel Sambuc 
1019ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
1020ebfedea0SLionel Sambuc     if (ret) {
1021ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1022ebfedea0SLionel Sambuc 	return ret;
1023ebfedea0SLionel Sambuc     }
1024ebfedea0SLionel Sambuc 
1025ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
1026ebfedea0SLionel Sambuc     krb5_storage_free(request);
1027ebfedea0SLionel Sambuc 
1028ebfedea0SLionel Sambuc     return ret;
1029ebfedea0SLionel Sambuc }
1030ebfedea0SLionel Sambuc 
1031ebfedea0SLionel Sambuc static krb5_error_code
kcm_lastchange(krb5_context context,krb5_ccache id,krb5_timestamp * mtime)1032ebfedea0SLionel Sambuc kcm_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
1033ebfedea0SLionel Sambuc {
1034ebfedea0SLionel Sambuc     *mtime = time(NULL);
1035ebfedea0SLionel Sambuc     return 0;
1036ebfedea0SLionel Sambuc }
1037ebfedea0SLionel Sambuc 
1038ebfedea0SLionel Sambuc static krb5_error_code
kcm_set_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat kdc_offset)1039ebfedea0SLionel Sambuc kcm_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
1040ebfedea0SLionel Sambuc {
1041ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
1042ebfedea0SLionel Sambuc     krb5_error_code ret;
1043ebfedea0SLionel Sambuc     krb5_storage *request;
1044ebfedea0SLionel Sambuc 
1045ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_SET_KDC_OFFSET, &request);
1046ebfedea0SLionel Sambuc     if (ret)
1047ebfedea0SLionel Sambuc 	return ret;
1048ebfedea0SLionel Sambuc 
1049ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
1050ebfedea0SLionel Sambuc     if (ret) {
1051ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1052ebfedea0SLionel Sambuc 	return ret;
1053ebfedea0SLionel Sambuc     }
1054ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, kdc_offset);
1055ebfedea0SLionel Sambuc     if (ret) {
1056ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1057ebfedea0SLionel Sambuc 	return ret;
1058ebfedea0SLionel Sambuc     }
1059ebfedea0SLionel Sambuc 
1060ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
1061ebfedea0SLionel Sambuc     krb5_storage_free(request);
1062ebfedea0SLionel Sambuc 
1063ebfedea0SLionel Sambuc     return ret;
1064ebfedea0SLionel Sambuc }
1065ebfedea0SLionel Sambuc 
1066ebfedea0SLionel Sambuc static krb5_error_code
kcm_get_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat * kdc_offset)1067ebfedea0SLionel Sambuc kcm_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
1068ebfedea0SLionel Sambuc {
1069ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
1070ebfedea0SLionel Sambuc     krb5_error_code ret;
1071ebfedea0SLionel Sambuc     krb5_storage *request, *response;
1072ebfedea0SLionel Sambuc     krb5_data response_data;
1073ebfedea0SLionel Sambuc     int32_t offset;
1074ebfedea0SLionel Sambuc 
1075ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_KDC_OFFSET, &request);
1076ebfedea0SLionel Sambuc     if (ret)
1077ebfedea0SLionel Sambuc 	return ret;
1078ebfedea0SLionel Sambuc 
1079ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
1080ebfedea0SLionel Sambuc     if (ret) {
1081ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1082ebfedea0SLionel Sambuc 	return ret;
1083ebfedea0SLionel Sambuc     }
1084ebfedea0SLionel Sambuc 
1085ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, &response, &response_data);
1086ebfedea0SLionel Sambuc     krb5_storage_free(request);
1087ebfedea0SLionel Sambuc     if (ret)
1088ebfedea0SLionel Sambuc 	return ret;
1089ebfedea0SLionel Sambuc 
1090ebfedea0SLionel Sambuc     ret = krb5_ret_int32(response, &offset);
1091ebfedea0SLionel Sambuc     krb5_storage_free(response);
1092ebfedea0SLionel Sambuc     krb5_data_free(&response_data);
1093ebfedea0SLionel Sambuc     if (ret)
1094ebfedea0SLionel Sambuc 	return ret;
1095ebfedea0SLionel Sambuc 
1096ebfedea0SLionel Sambuc     *kdc_offset = offset;
1097ebfedea0SLionel Sambuc 
1098ebfedea0SLionel Sambuc     return 0;
1099ebfedea0SLionel Sambuc }
1100ebfedea0SLionel Sambuc 
1101ebfedea0SLionel Sambuc /**
1102ebfedea0SLionel Sambuc  * Variable containing the KCM based credential cache implemention.
1103ebfedea0SLionel Sambuc  *
1104ebfedea0SLionel Sambuc  * @ingroup krb5_ccache
1105ebfedea0SLionel Sambuc  */
1106ebfedea0SLionel Sambuc 
1107ebfedea0SLionel Sambuc KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = {
1108ebfedea0SLionel Sambuc     KRB5_CC_OPS_VERSION,
1109ebfedea0SLionel Sambuc     "KCM",
1110ebfedea0SLionel Sambuc     kcm_get_name,
1111ebfedea0SLionel Sambuc     kcm_resolve,
1112ebfedea0SLionel Sambuc     kcm_gen_new,
1113ebfedea0SLionel Sambuc     kcm_initialize,
1114ebfedea0SLionel Sambuc     kcm_destroy,
1115ebfedea0SLionel Sambuc     kcm_close,
1116ebfedea0SLionel Sambuc     kcm_store_cred,
1117ebfedea0SLionel Sambuc     NULL /* kcm_retrieve */,
1118ebfedea0SLionel Sambuc     kcm_get_principal,
1119ebfedea0SLionel Sambuc     kcm_get_first,
1120ebfedea0SLionel Sambuc     kcm_get_next,
1121ebfedea0SLionel Sambuc     kcm_end_get,
1122ebfedea0SLionel Sambuc     kcm_remove_cred,
1123ebfedea0SLionel Sambuc     kcm_set_flags,
1124ebfedea0SLionel Sambuc     kcm_get_version,
1125ebfedea0SLionel Sambuc     kcm_get_cache_first,
1126ebfedea0SLionel Sambuc     kcm_get_cache_next_kcm,
1127ebfedea0SLionel Sambuc     kcm_end_cache_get,
1128ebfedea0SLionel Sambuc     kcm_move,
1129ebfedea0SLionel Sambuc     kcm_get_default_name_kcm,
1130ebfedea0SLionel Sambuc     kcm_set_default,
1131ebfedea0SLionel Sambuc     kcm_lastchange,
1132ebfedea0SLionel Sambuc     kcm_set_kdc_offset,
1133ebfedea0SLionel Sambuc     kcm_get_kdc_offset
1134ebfedea0SLionel Sambuc };
1135ebfedea0SLionel Sambuc 
1136ebfedea0SLionel Sambuc KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = {
1137ebfedea0SLionel Sambuc     KRB5_CC_OPS_VERSION,
1138ebfedea0SLionel Sambuc     "API",
1139ebfedea0SLionel Sambuc     kcm_get_name,
1140ebfedea0SLionel Sambuc     kcm_resolve,
1141ebfedea0SLionel Sambuc     kcm_gen_new,
1142ebfedea0SLionel Sambuc     kcm_initialize,
1143ebfedea0SLionel Sambuc     kcm_destroy,
1144ebfedea0SLionel Sambuc     kcm_close,
1145ebfedea0SLionel Sambuc     kcm_store_cred,
1146ebfedea0SLionel Sambuc     NULL /* kcm_retrieve */,
1147ebfedea0SLionel Sambuc     kcm_get_principal,
1148ebfedea0SLionel Sambuc     kcm_get_first,
1149ebfedea0SLionel Sambuc     kcm_get_next,
1150ebfedea0SLionel Sambuc     kcm_end_get,
1151ebfedea0SLionel Sambuc     kcm_remove_cred,
1152ebfedea0SLionel Sambuc     kcm_set_flags,
1153ebfedea0SLionel Sambuc     kcm_get_version,
1154ebfedea0SLionel Sambuc     kcm_get_cache_first,
1155ebfedea0SLionel Sambuc     kcm_get_cache_next_api,
1156ebfedea0SLionel Sambuc     kcm_end_cache_get,
1157ebfedea0SLionel Sambuc     kcm_move,
1158ebfedea0SLionel Sambuc     kcm_get_default_name_api,
1159ebfedea0SLionel Sambuc     kcm_set_default,
1160*0a6a1f1dSLionel Sambuc     kcm_lastchange,
1161*0a6a1f1dSLionel Sambuc     NULL,
1162*0a6a1f1dSLionel Sambuc     NULL
1163ebfedea0SLionel Sambuc };
1164ebfedea0SLionel Sambuc 
1165ebfedea0SLionel Sambuc 
1166*0a6a1f1dSLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
_krb5_kcm_is_running(krb5_context context)1167ebfedea0SLionel Sambuc _krb5_kcm_is_running(krb5_context context)
1168ebfedea0SLionel Sambuc {
1169ebfedea0SLionel Sambuc     krb5_error_code ret;
1170ebfedea0SLionel Sambuc     krb5_ccache_data ccdata;
1171ebfedea0SLionel Sambuc     krb5_ccache id = &ccdata;
1172ebfedea0SLionel Sambuc     krb5_boolean running;
1173ebfedea0SLionel Sambuc 
1174ebfedea0SLionel Sambuc     ret = kcm_alloc(context, NULL, &id);
1175ebfedea0SLionel Sambuc     if (ret)
1176ebfedea0SLionel Sambuc 	return 0;
1177ebfedea0SLionel Sambuc 
1178ebfedea0SLionel Sambuc     running = (_krb5_kcm_noop(context, id) == 0);
1179ebfedea0SLionel Sambuc 
1180ebfedea0SLionel Sambuc     kcm_free(context, &id);
1181ebfedea0SLionel Sambuc 
1182ebfedea0SLionel Sambuc     return running;
1183ebfedea0SLionel Sambuc }
1184ebfedea0SLionel Sambuc 
1185ebfedea0SLionel Sambuc /*
1186ebfedea0SLionel Sambuc  * Request:
1187ebfedea0SLionel Sambuc  *
1188ebfedea0SLionel Sambuc  * Response:
1189ebfedea0SLionel Sambuc  *
1190ebfedea0SLionel Sambuc  */
1191*0a6a1f1dSLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_noop(krb5_context context,krb5_ccache id)1192ebfedea0SLionel Sambuc _krb5_kcm_noop(krb5_context context,
1193ebfedea0SLionel Sambuc 	       krb5_ccache id)
1194ebfedea0SLionel Sambuc {
1195ebfedea0SLionel Sambuc     krb5_error_code ret;
1196ebfedea0SLionel Sambuc     krb5_storage *request;
1197ebfedea0SLionel Sambuc 
1198ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_NOOP, &request);
1199ebfedea0SLionel Sambuc     if (ret)
1200ebfedea0SLionel Sambuc 	return ret;
1201ebfedea0SLionel Sambuc 
1202ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
1203ebfedea0SLionel Sambuc 
1204ebfedea0SLionel Sambuc     krb5_storage_free(request);
1205ebfedea0SLionel Sambuc     return ret;
1206ebfedea0SLionel Sambuc }
1207ebfedea0SLionel Sambuc 
1208ebfedea0SLionel Sambuc 
1209ebfedea0SLionel Sambuc /*
1210ebfedea0SLionel Sambuc  * Request:
1211ebfedea0SLionel Sambuc  *      NameZ
1212ebfedea0SLionel Sambuc  *      ServerPrincipalPresent
1213ebfedea0SLionel Sambuc  *      ServerPrincipal OPTIONAL
1214ebfedea0SLionel Sambuc  *      Key
1215ebfedea0SLionel Sambuc  *
1216ebfedea0SLionel Sambuc  * Repsonse:
1217ebfedea0SLionel Sambuc  *
1218ebfedea0SLionel Sambuc  */
1219*0a6a1f1dSLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_get_initial_ticket(krb5_context context,krb5_ccache id,krb5_principal server,krb5_keyblock * key)1220ebfedea0SLionel Sambuc _krb5_kcm_get_initial_ticket(krb5_context context,
1221ebfedea0SLionel Sambuc 			     krb5_ccache id,
1222ebfedea0SLionel Sambuc 			     krb5_principal server,
1223ebfedea0SLionel Sambuc 			     krb5_keyblock *key)
1224ebfedea0SLionel Sambuc {
1225ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
1226ebfedea0SLionel Sambuc     krb5_error_code ret;
1227ebfedea0SLionel Sambuc     krb5_storage *request;
1228ebfedea0SLionel Sambuc 
1229ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request);
1230ebfedea0SLionel Sambuc     if (ret)
1231ebfedea0SLionel Sambuc 	return ret;
1232ebfedea0SLionel Sambuc 
1233ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
1234ebfedea0SLionel Sambuc     if (ret) {
1235ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1236ebfedea0SLionel Sambuc 	return ret;
1237ebfedea0SLionel Sambuc     }
1238ebfedea0SLionel Sambuc 
1239ebfedea0SLionel Sambuc     ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
1240ebfedea0SLionel Sambuc     if (ret) {
1241ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1242ebfedea0SLionel Sambuc 	return ret;
1243ebfedea0SLionel Sambuc     }
1244ebfedea0SLionel Sambuc 
1245ebfedea0SLionel Sambuc     if (server != NULL) {
1246ebfedea0SLionel Sambuc 	ret = krb5_store_principal(request, server);
1247ebfedea0SLionel Sambuc 	if (ret) {
1248ebfedea0SLionel Sambuc 	    krb5_storage_free(request);
1249ebfedea0SLionel Sambuc 	    return ret;
1250ebfedea0SLionel Sambuc 	}
1251ebfedea0SLionel Sambuc     }
1252ebfedea0SLionel Sambuc 
1253ebfedea0SLionel Sambuc     ret = krb5_store_keyblock(request, *key);
1254ebfedea0SLionel Sambuc     if (ret) {
1255ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1256ebfedea0SLionel Sambuc 	return ret;
1257ebfedea0SLionel Sambuc     }
1258ebfedea0SLionel Sambuc 
1259ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
1260ebfedea0SLionel Sambuc 
1261ebfedea0SLionel Sambuc     krb5_storage_free(request);
1262ebfedea0SLionel Sambuc     return ret;
1263ebfedea0SLionel Sambuc }
1264ebfedea0SLionel Sambuc 
1265ebfedea0SLionel Sambuc 
1266ebfedea0SLionel Sambuc /*
1267ebfedea0SLionel Sambuc  * Request:
1268ebfedea0SLionel Sambuc  *      NameZ
1269ebfedea0SLionel Sambuc  *      KDCFlags
1270ebfedea0SLionel Sambuc  *      EncryptionType
1271ebfedea0SLionel Sambuc  *      ServerPrincipal
1272ebfedea0SLionel Sambuc  *
1273ebfedea0SLionel Sambuc  * Repsonse:
1274ebfedea0SLionel Sambuc  *
1275ebfedea0SLionel Sambuc  */
1276*0a6a1f1dSLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kcm_get_ticket(krb5_context context,krb5_ccache id,krb5_kdc_flags flags,krb5_enctype enctype,krb5_principal server)1277ebfedea0SLionel Sambuc _krb5_kcm_get_ticket(krb5_context context,
1278ebfedea0SLionel Sambuc 		     krb5_ccache id,
1279ebfedea0SLionel Sambuc 		     krb5_kdc_flags flags,
1280ebfedea0SLionel Sambuc 		     krb5_enctype enctype,
1281ebfedea0SLionel Sambuc 		     krb5_principal server)
1282ebfedea0SLionel Sambuc {
1283ebfedea0SLionel Sambuc     krb5_error_code ret;
1284ebfedea0SLionel Sambuc     krb5_kcmcache *k = KCMCACHE(id);
1285ebfedea0SLionel Sambuc     krb5_storage *request;
1286ebfedea0SLionel Sambuc 
1287ebfedea0SLionel Sambuc     ret = krb5_kcm_storage_request(context, KCM_OP_GET_TICKET, &request);
1288ebfedea0SLionel Sambuc     if (ret)
1289ebfedea0SLionel Sambuc 	return ret;
1290ebfedea0SLionel Sambuc 
1291ebfedea0SLionel Sambuc     ret = krb5_store_stringz(request, k->name);
1292ebfedea0SLionel Sambuc     if (ret) {
1293ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1294ebfedea0SLionel Sambuc 	return ret;
1295ebfedea0SLionel Sambuc     }
1296ebfedea0SLionel Sambuc 
1297ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, flags.i);
1298ebfedea0SLionel Sambuc     if (ret) {
1299ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1300ebfedea0SLionel Sambuc 	return ret;
1301ebfedea0SLionel Sambuc     }
1302ebfedea0SLionel Sambuc 
1303ebfedea0SLionel Sambuc     ret = krb5_store_int32(request, enctype);
1304ebfedea0SLionel Sambuc     if (ret) {
1305ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1306ebfedea0SLionel Sambuc 	return ret;
1307ebfedea0SLionel Sambuc     }
1308ebfedea0SLionel Sambuc 
1309ebfedea0SLionel Sambuc     ret = krb5_store_principal(request, server);
1310ebfedea0SLionel Sambuc     if (ret) {
1311ebfedea0SLionel Sambuc 	krb5_storage_free(request);
1312ebfedea0SLionel Sambuc 	return ret;
1313ebfedea0SLionel Sambuc     }
1314ebfedea0SLionel Sambuc 
1315ebfedea0SLionel Sambuc     ret = krb5_kcm_call(context, request, NULL, NULL);
1316ebfedea0SLionel Sambuc 
1317ebfedea0SLionel Sambuc     krb5_storage_free(request);
1318ebfedea0SLionel Sambuc     return ret;
1319ebfedea0SLionel Sambuc }
1320ebfedea0SLionel Sambuc 
1321ebfedea0SLionel Sambuc #endif /* HAVE_KCM */
1322