1*0a6a1f1dSLionel Sambuc /* $NetBSD: protocol.c,v 1.1.1.2 2014/04/24 12:45:27 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 "kcm_locl.h"
38ebfedea0SLionel Sambuc #include <krb5/heimntlm.h>
39ebfedea0SLionel Sambuc
40ebfedea0SLionel Sambuc static void
41ebfedea0SLionel Sambuc kcm_drop_default_cache(krb5_context context, kcm_client *client, char *name);
42ebfedea0SLionel Sambuc
43ebfedea0SLionel Sambuc
44ebfedea0SLionel Sambuc int
kcm_is_same_session(kcm_client * client,uid_t uid,pid_t session)45ebfedea0SLionel Sambuc kcm_is_same_session(kcm_client *client, uid_t uid, pid_t session)
46ebfedea0SLionel Sambuc {
47ebfedea0SLionel Sambuc #if 0 /* XXX pppd is running in diffrent session the user */
48ebfedea0SLionel Sambuc if (session != -1)
49ebfedea0SLionel Sambuc return (client->session == session);
50ebfedea0SLionel Sambuc else
51ebfedea0SLionel Sambuc #endif
52ebfedea0SLionel Sambuc return (client->uid == uid);
53ebfedea0SLionel Sambuc }
54ebfedea0SLionel Sambuc
55ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_noop(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)56ebfedea0SLionel Sambuc kcm_op_noop(krb5_context context,
57ebfedea0SLionel Sambuc kcm_client *client,
58ebfedea0SLionel Sambuc kcm_operation opcode,
59ebfedea0SLionel Sambuc krb5_storage *request,
60ebfedea0SLionel Sambuc krb5_storage *response)
61ebfedea0SLionel Sambuc {
62ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
63ebfedea0SLionel Sambuc
64ebfedea0SLionel Sambuc return 0;
65ebfedea0SLionel Sambuc }
66ebfedea0SLionel Sambuc
67ebfedea0SLionel Sambuc /*
68ebfedea0SLionel Sambuc * Request:
69ebfedea0SLionel Sambuc * NameZ
70ebfedea0SLionel Sambuc * Response:
71ebfedea0SLionel Sambuc * NameZ
72ebfedea0SLionel Sambuc *
73ebfedea0SLionel Sambuc */
74ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_name(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)75ebfedea0SLionel Sambuc kcm_op_get_name(krb5_context context,
76ebfedea0SLionel Sambuc kcm_client *client,
77ebfedea0SLionel Sambuc kcm_operation opcode,
78ebfedea0SLionel Sambuc krb5_storage *request,
79ebfedea0SLionel Sambuc krb5_storage *response)
80ebfedea0SLionel Sambuc
81ebfedea0SLionel Sambuc {
82ebfedea0SLionel Sambuc krb5_error_code ret;
83ebfedea0SLionel Sambuc char *name = NULL;
84ebfedea0SLionel Sambuc kcm_ccache ccache;
85ebfedea0SLionel Sambuc
86ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
87ebfedea0SLionel Sambuc if (ret)
88ebfedea0SLionel Sambuc return ret;
89ebfedea0SLionel Sambuc
90ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
91ebfedea0SLionel Sambuc
92ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
93ebfedea0SLionel Sambuc name, &ccache);
94ebfedea0SLionel Sambuc if (ret) {
95ebfedea0SLionel Sambuc free(name);
96ebfedea0SLionel Sambuc return ret;
97ebfedea0SLionel Sambuc }
98ebfedea0SLionel Sambuc
99ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, ccache->name);
100ebfedea0SLionel Sambuc if (ret) {
101ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
102ebfedea0SLionel Sambuc free(name);
103ebfedea0SLionel Sambuc return ret;
104ebfedea0SLionel Sambuc }
105ebfedea0SLionel Sambuc
106ebfedea0SLionel Sambuc free(name);
107ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
108ebfedea0SLionel Sambuc return 0;
109ebfedea0SLionel Sambuc }
110ebfedea0SLionel Sambuc
111ebfedea0SLionel Sambuc /*
112ebfedea0SLionel Sambuc * Request:
113ebfedea0SLionel Sambuc *
114ebfedea0SLionel Sambuc * Response:
115ebfedea0SLionel Sambuc * NameZ
116ebfedea0SLionel Sambuc */
117ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_gen_new(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)118ebfedea0SLionel Sambuc kcm_op_gen_new(krb5_context context,
119ebfedea0SLionel Sambuc kcm_client *client,
120ebfedea0SLionel Sambuc kcm_operation opcode,
121ebfedea0SLionel Sambuc krb5_storage *request,
122ebfedea0SLionel Sambuc krb5_storage *response)
123ebfedea0SLionel Sambuc {
124ebfedea0SLionel Sambuc krb5_error_code ret;
125ebfedea0SLionel Sambuc char *name;
126ebfedea0SLionel Sambuc
127ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
128ebfedea0SLionel Sambuc
129ebfedea0SLionel Sambuc name = kcm_ccache_nextid(client->pid, client->uid, client->gid);
130ebfedea0SLionel Sambuc if (name == NULL) {
131ebfedea0SLionel Sambuc return KRB5_CC_NOMEM;
132ebfedea0SLionel Sambuc }
133ebfedea0SLionel Sambuc
134ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, name);
135ebfedea0SLionel Sambuc free(name);
136ebfedea0SLionel Sambuc
137ebfedea0SLionel Sambuc return ret;
138ebfedea0SLionel Sambuc }
139ebfedea0SLionel Sambuc
140ebfedea0SLionel Sambuc /*
141ebfedea0SLionel Sambuc * Request:
142ebfedea0SLionel Sambuc * NameZ
143ebfedea0SLionel Sambuc * Principal
144ebfedea0SLionel Sambuc *
145ebfedea0SLionel Sambuc * Response:
146ebfedea0SLionel Sambuc *
147ebfedea0SLionel Sambuc */
148ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_initialize(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)149ebfedea0SLionel Sambuc kcm_op_initialize(krb5_context context,
150ebfedea0SLionel Sambuc kcm_client *client,
151ebfedea0SLionel Sambuc kcm_operation opcode,
152ebfedea0SLionel Sambuc krb5_storage *request,
153ebfedea0SLionel Sambuc krb5_storage *response)
154ebfedea0SLionel Sambuc {
155ebfedea0SLionel Sambuc kcm_ccache ccache;
156ebfedea0SLionel Sambuc krb5_principal principal;
157ebfedea0SLionel Sambuc krb5_error_code ret;
158ebfedea0SLionel Sambuc char *name;
159ebfedea0SLionel Sambuc #if 0
160ebfedea0SLionel Sambuc kcm_event event;
161ebfedea0SLionel Sambuc #endif
162ebfedea0SLionel Sambuc
163ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
164ebfedea0SLionel Sambuc
165ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
166ebfedea0SLionel Sambuc if (ret)
167ebfedea0SLionel Sambuc return ret;
168ebfedea0SLionel Sambuc
169ebfedea0SLionel Sambuc ret = krb5_ret_principal(request, &principal);
170ebfedea0SLionel Sambuc if (ret) {
171ebfedea0SLionel Sambuc free(name);
172ebfedea0SLionel Sambuc return ret;
173ebfedea0SLionel Sambuc }
174ebfedea0SLionel Sambuc
175ebfedea0SLionel Sambuc ret = kcm_ccache_new_client(context, client, name, &ccache);
176ebfedea0SLionel Sambuc if (ret) {
177ebfedea0SLionel Sambuc free(name);
178ebfedea0SLionel Sambuc krb5_free_principal(context, principal);
179ebfedea0SLionel Sambuc return ret;
180ebfedea0SLionel Sambuc }
181ebfedea0SLionel Sambuc
182ebfedea0SLionel Sambuc ccache->client = principal;
183ebfedea0SLionel Sambuc
184ebfedea0SLionel Sambuc free(name);
185ebfedea0SLionel Sambuc
186ebfedea0SLionel Sambuc #if 0
187ebfedea0SLionel Sambuc /*
188ebfedea0SLionel Sambuc * Create a new credentials cache. To mitigate DoS attacks we will
189ebfedea0SLionel Sambuc * expire it in 30 minutes unless it has some credentials added
190ebfedea0SLionel Sambuc * to it
191ebfedea0SLionel Sambuc */
192ebfedea0SLionel Sambuc
193ebfedea0SLionel Sambuc event.fire_time = 30 * 60;
194ebfedea0SLionel Sambuc event.expire_time = 0;
195ebfedea0SLionel Sambuc event.backoff_time = 0;
196ebfedea0SLionel Sambuc event.action = KCM_EVENT_DESTROY_EMPTY_CACHE;
197ebfedea0SLionel Sambuc event.ccache = ccache;
198ebfedea0SLionel Sambuc
199ebfedea0SLionel Sambuc ret = kcm_enqueue_event_relative(context, &event);
200ebfedea0SLionel Sambuc #endif
201ebfedea0SLionel Sambuc
202ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
203ebfedea0SLionel Sambuc
204ebfedea0SLionel Sambuc return ret;
205ebfedea0SLionel Sambuc }
206ebfedea0SLionel Sambuc
207ebfedea0SLionel Sambuc /*
208ebfedea0SLionel Sambuc * Request:
209ebfedea0SLionel Sambuc * NameZ
210ebfedea0SLionel Sambuc *
211ebfedea0SLionel Sambuc * Response:
212ebfedea0SLionel Sambuc *
213ebfedea0SLionel Sambuc */
214ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_destroy(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)215ebfedea0SLionel Sambuc kcm_op_destroy(krb5_context context,
216ebfedea0SLionel Sambuc kcm_client *client,
217ebfedea0SLionel Sambuc kcm_operation opcode,
218ebfedea0SLionel Sambuc krb5_storage *request,
219ebfedea0SLionel Sambuc krb5_storage *response)
220ebfedea0SLionel Sambuc {
221ebfedea0SLionel Sambuc krb5_error_code ret;
222ebfedea0SLionel Sambuc char *name;
223ebfedea0SLionel Sambuc
224ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
225ebfedea0SLionel Sambuc if (ret)
226ebfedea0SLionel Sambuc return ret;
227ebfedea0SLionel Sambuc
228ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
229ebfedea0SLionel Sambuc
230ebfedea0SLionel Sambuc ret = kcm_ccache_destroy_client(context, client, name);
231ebfedea0SLionel Sambuc if (ret == 0)
232ebfedea0SLionel Sambuc kcm_drop_default_cache(context, client, name);
233ebfedea0SLionel Sambuc
234ebfedea0SLionel Sambuc free(name);
235ebfedea0SLionel Sambuc
236ebfedea0SLionel Sambuc return ret;
237ebfedea0SLionel Sambuc }
238ebfedea0SLionel Sambuc
239ebfedea0SLionel Sambuc /*
240ebfedea0SLionel Sambuc * Request:
241ebfedea0SLionel Sambuc * NameZ
242ebfedea0SLionel Sambuc * Creds
243ebfedea0SLionel Sambuc *
244ebfedea0SLionel Sambuc * Response:
245ebfedea0SLionel Sambuc *
246ebfedea0SLionel Sambuc */
247ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_store(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)248ebfedea0SLionel Sambuc kcm_op_store(krb5_context context,
249ebfedea0SLionel Sambuc kcm_client *client,
250ebfedea0SLionel Sambuc kcm_operation opcode,
251ebfedea0SLionel Sambuc krb5_storage *request,
252ebfedea0SLionel Sambuc krb5_storage *response)
253ebfedea0SLionel Sambuc {
254ebfedea0SLionel Sambuc krb5_creds creds;
255ebfedea0SLionel Sambuc krb5_error_code ret;
256ebfedea0SLionel Sambuc kcm_ccache ccache;
257ebfedea0SLionel Sambuc char *name;
258ebfedea0SLionel Sambuc
259ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
260ebfedea0SLionel Sambuc if (ret)
261ebfedea0SLionel Sambuc return ret;
262ebfedea0SLionel Sambuc
263ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
264ebfedea0SLionel Sambuc
265ebfedea0SLionel Sambuc ret = krb5_ret_creds(request, &creds);
266ebfedea0SLionel Sambuc if (ret) {
267ebfedea0SLionel Sambuc free(name);
268ebfedea0SLionel Sambuc return ret;
269ebfedea0SLionel Sambuc }
270ebfedea0SLionel Sambuc
271ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
272ebfedea0SLionel Sambuc name, &ccache);
273ebfedea0SLionel Sambuc if (ret) {
274ebfedea0SLionel Sambuc free(name);
275ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &creds);
276ebfedea0SLionel Sambuc return ret;
277ebfedea0SLionel Sambuc }
278ebfedea0SLionel Sambuc
279ebfedea0SLionel Sambuc ret = kcm_ccache_store_cred(context, ccache, &creds, 0);
280ebfedea0SLionel Sambuc if (ret) {
281ebfedea0SLionel Sambuc free(name);
282ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &creds);
283ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
284ebfedea0SLionel Sambuc return ret;
285ebfedea0SLionel Sambuc }
286ebfedea0SLionel Sambuc
287ebfedea0SLionel Sambuc kcm_ccache_enqueue_default(context, ccache, &creds);
288ebfedea0SLionel Sambuc
289ebfedea0SLionel Sambuc free(name);
290ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
291ebfedea0SLionel Sambuc
292ebfedea0SLionel Sambuc return 0;
293ebfedea0SLionel Sambuc }
294ebfedea0SLionel Sambuc
295ebfedea0SLionel Sambuc /*
296ebfedea0SLionel Sambuc * Request:
297ebfedea0SLionel Sambuc * NameZ
298ebfedea0SLionel Sambuc * WhichFields
299ebfedea0SLionel Sambuc * MatchCreds
300ebfedea0SLionel Sambuc *
301ebfedea0SLionel Sambuc * Response:
302ebfedea0SLionel Sambuc * Creds
303ebfedea0SLionel Sambuc *
304ebfedea0SLionel Sambuc */
305ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_retrieve(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)306ebfedea0SLionel Sambuc kcm_op_retrieve(krb5_context context,
307ebfedea0SLionel Sambuc kcm_client *client,
308ebfedea0SLionel Sambuc kcm_operation opcode,
309ebfedea0SLionel Sambuc krb5_storage *request,
310ebfedea0SLionel Sambuc krb5_storage *response)
311ebfedea0SLionel Sambuc {
312ebfedea0SLionel Sambuc uint32_t flags;
313ebfedea0SLionel Sambuc krb5_creds mcreds;
314ebfedea0SLionel Sambuc krb5_error_code ret;
315ebfedea0SLionel Sambuc kcm_ccache ccache;
316ebfedea0SLionel Sambuc char *name;
317ebfedea0SLionel Sambuc krb5_creds *credp;
318ebfedea0SLionel Sambuc int free_creds = 0;
319ebfedea0SLionel Sambuc
320ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
321ebfedea0SLionel Sambuc if (ret)
322ebfedea0SLionel Sambuc return ret;
323ebfedea0SLionel Sambuc
324ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
325ebfedea0SLionel Sambuc
326ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &flags);
327ebfedea0SLionel Sambuc if (ret) {
328ebfedea0SLionel Sambuc free(name);
329ebfedea0SLionel Sambuc return ret;
330ebfedea0SLionel Sambuc }
331ebfedea0SLionel Sambuc
332ebfedea0SLionel Sambuc ret = krb5_ret_creds_tag(request, &mcreds);
333ebfedea0SLionel Sambuc if (ret) {
334ebfedea0SLionel Sambuc free(name);
335ebfedea0SLionel Sambuc return ret;
336ebfedea0SLionel Sambuc }
337ebfedea0SLionel Sambuc
338ebfedea0SLionel Sambuc if (disallow_getting_krbtgt &&
339ebfedea0SLionel Sambuc mcreds.server->name.name_string.len == 2 &&
340ebfedea0SLionel Sambuc strcmp(mcreds.server->name.name_string.val[0], KRB5_TGS_NAME) == 0)
341ebfedea0SLionel Sambuc {
342ebfedea0SLionel Sambuc free(name);
343ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &mcreds);
344ebfedea0SLionel Sambuc return KRB5_FCC_PERM;
345ebfedea0SLionel Sambuc }
346ebfedea0SLionel Sambuc
347ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
348ebfedea0SLionel Sambuc name, &ccache);
349ebfedea0SLionel Sambuc if (ret) {
350ebfedea0SLionel Sambuc free(name);
351ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &mcreds);
352ebfedea0SLionel Sambuc return ret;
353ebfedea0SLionel Sambuc }
354ebfedea0SLionel Sambuc
355ebfedea0SLionel Sambuc ret = kcm_ccache_retrieve_cred(context, ccache, flags,
356ebfedea0SLionel Sambuc &mcreds, &credp);
357ebfedea0SLionel Sambuc if (ret && ((flags & KRB5_GC_CACHED) == 0) &&
358ebfedea0SLionel Sambuc !krb5_is_config_principal(context, mcreds.server)) {
359ebfedea0SLionel Sambuc krb5_ccache_data ccdata;
360ebfedea0SLionel Sambuc
361ebfedea0SLionel Sambuc /* try and acquire */
362ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
363ebfedea0SLionel Sambuc
364ebfedea0SLionel Sambuc /* Fake up an internal ccache */
365ebfedea0SLionel Sambuc kcm_internal_ccache(context, ccache, &ccdata);
366ebfedea0SLionel Sambuc
367ebfedea0SLionel Sambuc /* glue cc layer will store creds */
368ebfedea0SLionel Sambuc ret = krb5_get_credentials(context, 0, &ccdata, &mcreds, &credp);
369ebfedea0SLionel Sambuc if (ret == 0)
370ebfedea0SLionel Sambuc free_creds = 1;
371ebfedea0SLionel Sambuc
372ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
373ebfedea0SLionel Sambuc }
374ebfedea0SLionel Sambuc
375ebfedea0SLionel Sambuc if (ret == 0) {
376ebfedea0SLionel Sambuc ret = krb5_store_creds(response, credp);
377ebfedea0SLionel Sambuc }
378ebfedea0SLionel Sambuc
379ebfedea0SLionel Sambuc free(name);
380ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &mcreds);
381ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
382ebfedea0SLionel Sambuc
383ebfedea0SLionel Sambuc if (free_creds)
384ebfedea0SLionel Sambuc krb5_free_cred_contents(context, credp);
385ebfedea0SLionel Sambuc
386ebfedea0SLionel Sambuc return ret;
387ebfedea0SLionel Sambuc }
388ebfedea0SLionel Sambuc
389ebfedea0SLionel Sambuc /*
390ebfedea0SLionel Sambuc * Request:
391ebfedea0SLionel Sambuc * NameZ
392ebfedea0SLionel Sambuc *
393ebfedea0SLionel Sambuc * Response:
394ebfedea0SLionel Sambuc * Principal
395ebfedea0SLionel Sambuc */
396ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_principal(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)397ebfedea0SLionel Sambuc kcm_op_get_principal(krb5_context context,
398ebfedea0SLionel Sambuc kcm_client *client,
399ebfedea0SLionel Sambuc kcm_operation opcode,
400ebfedea0SLionel Sambuc krb5_storage *request,
401ebfedea0SLionel Sambuc krb5_storage *response)
402ebfedea0SLionel Sambuc {
403ebfedea0SLionel Sambuc krb5_error_code ret;
404ebfedea0SLionel Sambuc kcm_ccache ccache;
405ebfedea0SLionel Sambuc char *name;
406ebfedea0SLionel Sambuc
407ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
408ebfedea0SLionel Sambuc if (ret)
409ebfedea0SLionel Sambuc return ret;
410ebfedea0SLionel Sambuc
411ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
412ebfedea0SLionel Sambuc
413ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
414ebfedea0SLionel Sambuc name, &ccache);
415ebfedea0SLionel Sambuc if (ret) {
416ebfedea0SLionel Sambuc free(name);
417ebfedea0SLionel Sambuc return ret;
418ebfedea0SLionel Sambuc }
419ebfedea0SLionel Sambuc
420ebfedea0SLionel Sambuc if (ccache->client == NULL)
421ebfedea0SLionel Sambuc ret = KRB5_CC_NOTFOUND;
422ebfedea0SLionel Sambuc else
423ebfedea0SLionel Sambuc ret = krb5_store_principal(response, ccache->client);
424ebfedea0SLionel Sambuc
425ebfedea0SLionel Sambuc free(name);
426ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
427ebfedea0SLionel Sambuc
428ebfedea0SLionel Sambuc return 0;
429ebfedea0SLionel Sambuc }
430ebfedea0SLionel Sambuc
431ebfedea0SLionel Sambuc /*
432ebfedea0SLionel Sambuc * Request:
433ebfedea0SLionel Sambuc * NameZ
434ebfedea0SLionel Sambuc *
435ebfedea0SLionel Sambuc * Response:
436ebfedea0SLionel Sambuc * UUIDs
437ebfedea0SLionel Sambuc *
438ebfedea0SLionel Sambuc */
439ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_cred_uuid_list(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)440ebfedea0SLionel Sambuc kcm_op_get_cred_uuid_list(krb5_context context,
441ebfedea0SLionel Sambuc kcm_client *client,
442ebfedea0SLionel Sambuc kcm_operation opcode,
443ebfedea0SLionel Sambuc krb5_storage *request,
444ebfedea0SLionel Sambuc krb5_storage *response)
445ebfedea0SLionel Sambuc {
446ebfedea0SLionel Sambuc struct kcm_creds *creds;
447ebfedea0SLionel Sambuc krb5_error_code ret;
448ebfedea0SLionel Sambuc kcm_ccache ccache;
449ebfedea0SLionel Sambuc char *name;
450ebfedea0SLionel Sambuc
451ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
452ebfedea0SLionel Sambuc if (ret)
453ebfedea0SLionel Sambuc return ret;
454ebfedea0SLionel Sambuc
455ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
456ebfedea0SLionel Sambuc
457ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
458ebfedea0SLionel Sambuc name, &ccache);
459ebfedea0SLionel Sambuc free(name);
460ebfedea0SLionel Sambuc if (ret)
461ebfedea0SLionel Sambuc return ret;
462ebfedea0SLionel Sambuc
463ebfedea0SLionel Sambuc for (creds = ccache->creds ; creds ; creds = creds->next) {
464ebfedea0SLionel Sambuc ssize_t sret;
465ebfedea0SLionel Sambuc sret = krb5_storage_write(response, &creds->uuid, sizeof(creds->uuid));
466ebfedea0SLionel Sambuc if (sret != sizeof(creds->uuid)) {
467ebfedea0SLionel Sambuc ret = ENOMEM;
468ebfedea0SLionel Sambuc break;
469ebfedea0SLionel Sambuc }
470ebfedea0SLionel Sambuc }
471ebfedea0SLionel Sambuc
472ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
473ebfedea0SLionel Sambuc
474ebfedea0SLionel Sambuc return ret;
475ebfedea0SLionel Sambuc }
476ebfedea0SLionel Sambuc
477ebfedea0SLionel Sambuc /*
478ebfedea0SLionel Sambuc * Request:
479ebfedea0SLionel Sambuc * NameZ
480ebfedea0SLionel Sambuc * Cursor
481ebfedea0SLionel Sambuc *
482ebfedea0SLionel Sambuc * Response:
483ebfedea0SLionel Sambuc * Creds
484ebfedea0SLionel Sambuc */
485ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_cred_by_uuid(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)486ebfedea0SLionel Sambuc kcm_op_get_cred_by_uuid(krb5_context context,
487ebfedea0SLionel Sambuc kcm_client *client,
488ebfedea0SLionel Sambuc kcm_operation opcode,
489ebfedea0SLionel Sambuc krb5_storage *request,
490ebfedea0SLionel Sambuc krb5_storage *response)
491ebfedea0SLionel Sambuc {
492ebfedea0SLionel Sambuc krb5_error_code ret;
493ebfedea0SLionel Sambuc kcm_ccache ccache;
494ebfedea0SLionel Sambuc char *name;
495ebfedea0SLionel Sambuc struct kcm_creds *c;
496ebfedea0SLionel Sambuc kcmuuid_t uuid;
497ebfedea0SLionel Sambuc ssize_t sret;
498ebfedea0SLionel Sambuc
499ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
500ebfedea0SLionel Sambuc if (ret)
501ebfedea0SLionel Sambuc return ret;
502ebfedea0SLionel Sambuc
503ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
504ebfedea0SLionel Sambuc
505ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
506ebfedea0SLionel Sambuc name, &ccache);
507ebfedea0SLionel Sambuc free(name);
508ebfedea0SLionel Sambuc if (ret)
509ebfedea0SLionel Sambuc return ret;
510ebfedea0SLionel Sambuc
511ebfedea0SLionel Sambuc sret = krb5_storage_read(request, &uuid, sizeof(uuid));
512ebfedea0SLionel Sambuc if (sret != sizeof(uuid)) {
513ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
514ebfedea0SLionel Sambuc krb5_clear_error_message(context);
515ebfedea0SLionel Sambuc return KRB5_CC_IO;
516ebfedea0SLionel Sambuc }
517ebfedea0SLionel Sambuc
518ebfedea0SLionel Sambuc c = kcm_ccache_find_cred_uuid(context, ccache, uuid);
519ebfedea0SLionel Sambuc if (c == NULL) {
520ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
521ebfedea0SLionel Sambuc return KRB5_CC_END;
522ebfedea0SLionel Sambuc }
523ebfedea0SLionel Sambuc
524ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
525ebfedea0SLionel Sambuc ret = krb5_store_creds(response, &c->cred);
526ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
527ebfedea0SLionel Sambuc
528ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
529ebfedea0SLionel Sambuc
530ebfedea0SLionel Sambuc return ret;
531ebfedea0SLionel Sambuc }
532ebfedea0SLionel Sambuc
533ebfedea0SLionel Sambuc /*
534ebfedea0SLionel Sambuc * Request:
535ebfedea0SLionel Sambuc * NameZ
536ebfedea0SLionel Sambuc * WhichFields
537ebfedea0SLionel Sambuc * MatchCreds
538ebfedea0SLionel Sambuc *
539ebfedea0SLionel Sambuc * Response:
540ebfedea0SLionel Sambuc *
541ebfedea0SLionel Sambuc */
542ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_remove_cred(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)543ebfedea0SLionel Sambuc kcm_op_remove_cred(krb5_context context,
544ebfedea0SLionel Sambuc kcm_client *client,
545ebfedea0SLionel Sambuc kcm_operation opcode,
546ebfedea0SLionel Sambuc krb5_storage *request,
547ebfedea0SLionel Sambuc krb5_storage *response)
548ebfedea0SLionel Sambuc {
549ebfedea0SLionel Sambuc uint32_t whichfields;
550ebfedea0SLionel Sambuc krb5_creds mcreds;
551ebfedea0SLionel Sambuc krb5_error_code ret;
552ebfedea0SLionel Sambuc kcm_ccache ccache;
553ebfedea0SLionel Sambuc char *name;
554ebfedea0SLionel Sambuc
555ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
556ebfedea0SLionel Sambuc if (ret)
557ebfedea0SLionel Sambuc return ret;
558ebfedea0SLionel Sambuc
559ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
560ebfedea0SLionel Sambuc
561ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &whichfields);
562ebfedea0SLionel Sambuc if (ret) {
563ebfedea0SLionel Sambuc free(name);
564ebfedea0SLionel Sambuc return ret;
565ebfedea0SLionel Sambuc }
566ebfedea0SLionel Sambuc
567ebfedea0SLionel Sambuc ret = krb5_ret_creds_tag(request, &mcreds);
568ebfedea0SLionel Sambuc if (ret) {
569ebfedea0SLionel Sambuc free(name);
570ebfedea0SLionel Sambuc return ret;
571ebfedea0SLionel Sambuc }
572ebfedea0SLionel Sambuc
573ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
574ebfedea0SLionel Sambuc name, &ccache);
575ebfedea0SLionel Sambuc if (ret) {
576ebfedea0SLionel Sambuc free(name);
577ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &mcreds);
578ebfedea0SLionel Sambuc return ret;
579ebfedea0SLionel Sambuc }
580ebfedea0SLionel Sambuc
581ebfedea0SLionel Sambuc ret = kcm_ccache_remove_cred(context, ccache, whichfields, &mcreds);
582ebfedea0SLionel Sambuc
583ebfedea0SLionel Sambuc /* XXX need to remove any events that match */
584ebfedea0SLionel Sambuc
585ebfedea0SLionel Sambuc free(name);
586ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &mcreds);
587ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
588ebfedea0SLionel Sambuc
589ebfedea0SLionel Sambuc return ret;
590ebfedea0SLionel Sambuc }
591ebfedea0SLionel Sambuc
592ebfedea0SLionel Sambuc /*
593ebfedea0SLionel Sambuc * Request:
594ebfedea0SLionel Sambuc * NameZ
595ebfedea0SLionel Sambuc * Flags
596ebfedea0SLionel Sambuc *
597ebfedea0SLionel Sambuc * Response:
598ebfedea0SLionel Sambuc *
599ebfedea0SLionel Sambuc */
600ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_set_flags(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)601ebfedea0SLionel Sambuc kcm_op_set_flags(krb5_context context,
602ebfedea0SLionel Sambuc kcm_client *client,
603ebfedea0SLionel Sambuc kcm_operation opcode,
604ebfedea0SLionel Sambuc krb5_storage *request,
605ebfedea0SLionel Sambuc krb5_storage *response)
606ebfedea0SLionel Sambuc {
607ebfedea0SLionel Sambuc uint32_t flags;
608ebfedea0SLionel Sambuc krb5_error_code ret;
609ebfedea0SLionel Sambuc kcm_ccache ccache;
610ebfedea0SLionel Sambuc char *name;
611ebfedea0SLionel Sambuc
612ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
613ebfedea0SLionel Sambuc if (ret)
614ebfedea0SLionel Sambuc return ret;
615ebfedea0SLionel Sambuc
616ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
617ebfedea0SLionel Sambuc
618ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &flags);
619ebfedea0SLionel Sambuc if (ret) {
620ebfedea0SLionel Sambuc free(name);
621ebfedea0SLionel Sambuc return ret;
622ebfedea0SLionel Sambuc }
623ebfedea0SLionel Sambuc
624ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
625ebfedea0SLionel Sambuc name, &ccache);
626ebfedea0SLionel Sambuc if (ret) {
627ebfedea0SLionel Sambuc free(name);
628ebfedea0SLionel Sambuc return ret;
629ebfedea0SLionel Sambuc }
630ebfedea0SLionel Sambuc
631ebfedea0SLionel Sambuc /* we don't really support any flags yet */
632ebfedea0SLionel Sambuc free(name);
633ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
634ebfedea0SLionel Sambuc
635ebfedea0SLionel Sambuc return 0;
636ebfedea0SLionel Sambuc }
637ebfedea0SLionel Sambuc
638ebfedea0SLionel Sambuc /*
639ebfedea0SLionel Sambuc * Request:
640ebfedea0SLionel Sambuc * NameZ
641ebfedea0SLionel Sambuc * UID
642ebfedea0SLionel Sambuc * GID
643ebfedea0SLionel Sambuc *
644ebfedea0SLionel Sambuc * Response:
645ebfedea0SLionel Sambuc *
646ebfedea0SLionel Sambuc */
647ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_chown(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)648ebfedea0SLionel Sambuc kcm_op_chown(krb5_context context,
649ebfedea0SLionel Sambuc kcm_client *client,
650ebfedea0SLionel Sambuc kcm_operation opcode,
651ebfedea0SLionel Sambuc krb5_storage *request,
652ebfedea0SLionel Sambuc krb5_storage *response)
653ebfedea0SLionel Sambuc {
654ebfedea0SLionel Sambuc uint32_t uid;
655ebfedea0SLionel Sambuc uint32_t gid;
656ebfedea0SLionel Sambuc krb5_error_code ret;
657ebfedea0SLionel Sambuc kcm_ccache ccache;
658ebfedea0SLionel Sambuc char *name;
659ebfedea0SLionel Sambuc
660ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
661ebfedea0SLionel Sambuc if (ret)
662ebfedea0SLionel Sambuc return ret;
663ebfedea0SLionel Sambuc
664ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
665ebfedea0SLionel Sambuc
666ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &uid);
667ebfedea0SLionel Sambuc if (ret) {
668ebfedea0SLionel Sambuc free(name);
669ebfedea0SLionel Sambuc return ret;
670ebfedea0SLionel Sambuc }
671ebfedea0SLionel Sambuc
672ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &gid);
673ebfedea0SLionel Sambuc if (ret) {
674ebfedea0SLionel Sambuc free(name);
675ebfedea0SLionel Sambuc return ret;
676ebfedea0SLionel Sambuc }
677ebfedea0SLionel Sambuc
678ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
679ebfedea0SLionel Sambuc name, &ccache);
680ebfedea0SLionel Sambuc if (ret) {
681ebfedea0SLionel Sambuc free(name);
682ebfedea0SLionel Sambuc return ret;
683ebfedea0SLionel Sambuc }
684ebfedea0SLionel Sambuc
685ebfedea0SLionel Sambuc ret = kcm_chown(context, client, ccache, uid, gid);
686ebfedea0SLionel Sambuc
687ebfedea0SLionel Sambuc free(name);
688ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
689ebfedea0SLionel Sambuc
690ebfedea0SLionel Sambuc return ret;
691ebfedea0SLionel Sambuc }
692ebfedea0SLionel Sambuc
693ebfedea0SLionel Sambuc /*
694ebfedea0SLionel Sambuc * Request:
695ebfedea0SLionel Sambuc * NameZ
696ebfedea0SLionel Sambuc * Mode
697ebfedea0SLionel Sambuc *
698ebfedea0SLionel Sambuc * Response:
699ebfedea0SLionel Sambuc *
700ebfedea0SLionel Sambuc */
701ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_chmod(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)702ebfedea0SLionel Sambuc kcm_op_chmod(krb5_context context,
703ebfedea0SLionel Sambuc kcm_client *client,
704ebfedea0SLionel Sambuc kcm_operation opcode,
705ebfedea0SLionel Sambuc krb5_storage *request,
706ebfedea0SLionel Sambuc krb5_storage *response)
707ebfedea0SLionel Sambuc {
708ebfedea0SLionel Sambuc uint16_t mode;
709ebfedea0SLionel Sambuc krb5_error_code ret;
710ebfedea0SLionel Sambuc kcm_ccache ccache;
711ebfedea0SLionel Sambuc char *name;
712ebfedea0SLionel Sambuc
713ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
714ebfedea0SLionel Sambuc if (ret)
715ebfedea0SLionel Sambuc return ret;
716ebfedea0SLionel Sambuc
717ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
718ebfedea0SLionel Sambuc
719ebfedea0SLionel Sambuc ret = krb5_ret_uint16(request, &mode);
720ebfedea0SLionel Sambuc if (ret) {
721ebfedea0SLionel Sambuc free(name);
722ebfedea0SLionel Sambuc return ret;
723ebfedea0SLionel Sambuc }
724ebfedea0SLionel Sambuc
725ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
726ebfedea0SLionel Sambuc name, &ccache);
727ebfedea0SLionel Sambuc if (ret) {
728ebfedea0SLionel Sambuc free(name);
729ebfedea0SLionel Sambuc return ret;
730ebfedea0SLionel Sambuc }
731ebfedea0SLionel Sambuc
732ebfedea0SLionel Sambuc ret = kcm_chmod(context, client, ccache, mode);
733ebfedea0SLionel Sambuc
734ebfedea0SLionel Sambuc free(name);
735ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
736ebfedea0SLionel Sambuc
737ebfedea0SLionel Sambuc return ret;
738ebfedea0SLionel Sambuc }
739ebfedea0SLionel Sambuc
740ebfedea0SLionel Sambuc /*
741ebfedea0SLionel Sambuc * Protocol extensions for moving ticket acquisition responsibility
742ebfedea0SLionel Sambuc * from client to KCM follow.
743ebfedea0SLionel Sambuc */
744ebfedea0SLionel Sambuc
745ebfedea0SLionel Sambuc /*
746ebfedea0SLionel Sambuc * Request:
747ebfedea0SLionel Sambuc * NameZ
748ebfedea0SLionel Sambuc * ServerPrincipalPresent
749ebfedea0SLionel Sambuc * ServerPrincipal OPTIONAL
750ebfedea0SLionel Sambuc * Key
751ebfedea0SLionel Sambuc *
752ebfedea0SLionel Sambuc * Repsonse:
753ebfedea0SLionel Sambuc *
754ebfedea0SLionel Sambuc */
755ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_initial_ticket(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)756ebfedea0SLionel Sambuc kcm_op_get_initial_ticket(krb5_context context,
757ebfedea0SLionel Sambuc kcm_client *client,
758ebfedea0SLionel Sambuc kcm_operation opcode,
759ebfedea0SLionel Sambuc krb5_storage *request,
760ebfedea0SLionel Sambuc krb5_storage *response)
761ebfedea0SLionel Sambuc {
762ebfedea0SLionel Sambuc krb5_error_code ret;
763ebfedea0SLionel Sambuc kcm_ccache ccache;
764ebfedea0SLionel Sambuc char *name;
765ebfedea0SLionel Sambuc int8_t not_tgt = 0;
766ebfedea0SLionel Sambuc krb5_principal server = NULL;
767ebfedea0SLionel Sambuc krb5_keyblock key;
768ebfedea0SLionel Sambuc
769ebfedea0SLionel Sambuc krb5_keyblock_zero(&key);
770ebfedea0SLionel Sambuc
771ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
772ebfedea0SLionel Sambuc if (ret)
773ebfedea0SLionel Sambuc return ret;
774ebfedea0SLionel Sambuc
775ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
776ebfedea0SLionel Sambuc
777ebfedea0SLionel Sambuc ret = krb5_ret_int8(request, ¬_tgt);
778ebfedea0SLionel Sambuc if (ret) {
779ebfedea0SLionel Sambuc free(name);
780ebfedea0SLionel Sambuc return ret;
781ebfedea0SLionel Sambuc }
782ebfedea0SLionel Sambuc
783ebfedea0SLionel Sambuc if (not_tgt) {
784ebfedea0SLionel Sambuc ret = krb5_ret_principal(request, &server);
785ebfedea0SLionel Sambuc if (ret) {
786ebfedea0SLionel Sambuc free(name);
787ebfedea0SLionel Sambuc return ret;
788ebfedea0SLionel Sambuc }
789ebfedea0SLionel Sambuc }
790ebfedea0SLionel Sambuc
791ebfedea0SLionel Sambuc ret = krb5_ret_keyblock(request, &key);
792ebfedea0SLionel Sambuc if (ret) {
793ebfedea0SLionel Sambuc free(name);
794ebfedea0SLionel Sambuc if (server != NULL)
795ebfedea0SLionel Sambuc krb5_free_principal(context, server);
796ebfedea0SLionel Sambuc return ret;
797ebfedea0SLionel Sambuc }
798ebfedea0SLionel Sambuc
799ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
800ebfedea0SLionel Sambuc name, &ccache);
801ebfedea0SLionel Sambuc if (ret == 0) {
802ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
803ebfedea0SLionel Sambuc
804ebfedea0SLionel Sambuc if (ccache->server != NULL) {
805ebfedea0SLionel Sambuc krb5_free_principal(context, ccache->server);
806ebfedea0SLionel Sambuc ccache->server = NULL;
807ebfedea0SLionel Sambuc }
808ebfedea0SLionel Sambuc
809ebfedea0SLionel Sambuc krb5_free_keyblock(context, &ccache->key.keyblock);
810ebfedea0SLionel Sambuc
811ebfedea0SLionel Sambuc ccache->server = server;
812ebfedea0SLionel Sambuc ccache->key.keyblock = key;
813ebfedea0SLionel Sambuc ccache->flags |= KCM_FLAGS_USE_CACHED_KEY;
814ebfedea0SLionel Sambuc
815ebfedea0SLionel Sambuc ret = kcm_ccache_enqueue_default(context, ccache, NULL);
816ebfedea0SLionel Sambuc if (ret) {
817ebfedea0SLionel Sambuc ccache->server = NULL;
818ebfedea0SLionel Sambuc krb5_keyblock_zero(&ccache->key.keyblock);
819ebfedea0SLionel Sambuc ccache->flags &= ~(KCM_FLAGS_USE_CACHED_KEY);
820ebfedea0SLionel Sambuc }
821ebfedea0SLionel Sambuc
822ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
823ebfedea0SLionel Sambuc }
824ebfedea0SLionel Sambuc
825ebfedea0SLionel Sambuc free(name);
826ebfedea0SLionel Sambuc
827ebfedea0SLionel Sambuc if (ret != 0) {
828ebfedea0SLionel Sambuc krb5_free_principal(context, server);
829ebfedea0SLionel Sambuc krb5_free_keyblock(context, &key);
830ebfedea0SLionel Sambuc }
831ebfedea0SLionel Sambuc
832ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
833ebfedea0SLionel Sambuc
834ebfedea0SLionel Sambuc return ret;
835ebfedea0SLionel Sambuc }
836ebfedea0SLionel Sambuc
837ebfedea0SLionel Sambuc /*
838ebfedea0SLionel Sambuc * Request:
839ebfedea0SLionel Sambuc * NameZ
840ebfedea0SLionel Sambuc * ServerPrincipal
841ebfedea0SLionel Sambuc * KDCFlags
842ebfedea0SLionel Sambuc * EncryptionType
843ebfedea0SLionel Sambuc *
844ebfedea0SLionel Sambuc * Repsonse:
845ebfedea0SLionel Sambuc *
846ebfedea0SLionel Sambuc */
847ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_ticket(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)848ebfedea0SLionel Sambuc kcm_op_get_ticket(krb5_context context,
849ebfedea0SLionel Sambuc kcm_client *client,
850ebfedea0SLionel Sambuc kcm_operation opcode,
851ebfedea0SLionel Sambuc krb5_storage *request,
852ebfedea0SLionel Sambuc krb5_storage *response)
853ebfedea0SLionel Sambuc {
854ebfedea0SLionel Sambuc krb5_error_code ret;
855ebfedea0SLionel Sambuc kcm_ccache ccache;
856ebfedea0SLionel Sambuc char *name;
857ebfedea0SLionel Sambuc krb5_principal server = NULL;
858ebfedea0SLionel Sambuc krb5_ccache_data ccdata;
859ebfedea0SLionel Sambuc krb5_creds in, *out;
860ebfedea0SLionel Sambuc krb5_kdc_flags flags;
861ebfedea0SLionel Sambuc
862ebfedea0SLionel Sambuc memset(&in, 0, sizeof(in));
863ebfedea0SLionel Sambuc
864ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
865ebfedea0SLionel Sambuc if (ret)
866ebfedea0SLionel Sambuc return ret;
867ebfedea0SLionel Sambuc
868ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
869ebfedea0SLionel Sambuc
870ebfedea0SLionel Sambuc ret = krb5_ret_uint32(request, &flags.i);
871ebfedea0SLionel Sambuc if (ret) {
872ebfedea0SLionel Sambuc free(name);
873ebfedea0SLionel Sambuc return ret;
874ebfedea0SLionel Sambuc }
875ebfedea0SLionel Sambuc
876ebfedea0SLionel Sambuc ret = krb5_ret_int32(request, &in.session.keytype);
877ebfedea0SLionel Sambuc if (ret) {
878ebfedea0SLionel Sambuc free(name);
879ebfedea0SLionel Sambuc return ret;
880ebfedea0SLionel Sambuc }
881ebfedea0SLionel Sambuc
882ebfedea0SLionel Sambuc ret = krb5_ret_principal(request, &server);
883ebfedea0SLionel Sambuc if (ret) {
884ebfedea0SLionel Sambuc free(name);
885ebfedea0SLionel Sambuc return ret;
886ebfedea0SLionel Sambuc }
887ebfedea0SLionel Sambuc
888ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode,
889ebfedea0SLionel Sambuc name, &ccache);
890ebfedea0SLionel Sambuc if (ret) {
891ebfedea0SLionel Sambuc krb5_free_principal(context, server);
892ebfedea0SLionel Sambuc free(name);
893ebfedea0SLionel Sambuc return ret;
894ebfedea0SLionel Sambuc }
895ebfedea0SLionel Sambuc
896ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
897ebfedea0SLionel Sambuc
898ebfedea0SLionel Sambuc /* Fake up an internal ccache */
899ebfedea0SLionel Sambuc kcm_internal_ccache(context, ccache, &ccdata);
900ebfedea0SLionel Sambuc
901ebfedea0SLionel Sambuc in.client = ccache->client;
902ebfedea0SLionel Sambuc in.server = server;
903ebfedea0SLionel Sambuc in.times.endtime = 0;
904ebfedea0SLionel Sambuc
905ebfedea0SLionel Sambuc /* glue cc layer will store creds */
906ebfedea0SLionel Sambuc ret = krb5_get_credentials_with_flags(context, 0, flags,
907ebfedea0SLionel Sambuc &ccdata, &in, &out);
908ebfedea0SLionel Sambuc
909ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
910ebfedea0SLionel Sambuc
911ebfedea0SLionel Sambuc krb5_free_principal(context, server);
912ebfedea0SLionel Sambuc
913ebfedea0SLionel Sambuc if (ret == 0)
914ebfedea0SLionel Sambuc krb5_free_cred_contents(context, out);
915ebfedea0SLionel Sambuc
916ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
917ebfedea0SLionel Sambuc free(name);
918ebfedea0SLionel Sambuc
919ebfedea0SLionel Sambuc return ret;
920ebfedea0SLionel Sambuc }
921ebfedea0SLionel Sambuc
922ebfedea0SLionel Sambuc /*
923ebfedea0SLionel Sambuc * Request:
924ebfedea0SLionel Sambuc * OldNameZ
925ebfedea0SLionel Sambuc * NewNameZ
926ebfedea0SLionel Sambuc *
927ebfedea0SLionel Sambuc * Repsonse:
928ebfedea0SLionel Sambuc *
929ebfedea0SLionel Sambuc */
930ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_move_cache(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)931ebfedea0SLionel Sambuc kcm_op_move_cache(krb5_context context,
932ebfedea0SLionel Sambuc kcm_client *client,
933ebfedea0SLionel Sambuc kcm_operation opcode,
934ebfedea0SLionel Sambuc krb5_storage *request,
935ebfedea0SLionel Sambuc krb5_storage *response)
936ebfedea0SLionel Sambuc {
937ebfedea0SLionel Sambuc krb5_error_code ret;
938ebfedea0SLionel Sambuc kcm_ccache oldid, newid;
939ebfedea0SLionel Sambuc char *oldname, *newname;
940ebfedea0SLionel Sambuc
941ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &oldname);
942ebfedea0SLionel Sambuc if (ret)
943ebfedea0SLionel Sambuc return ret;
944ebfedea0SLionel Sambuc
945ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, oldname);
946ebfedea0SLionel Sambuc
947ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &newname);
948ebfedea0SLionel Sambuc if (ret) {
949ebfedea0SLionel Sambuc free(oldname);
950ebfedea0SLionel Sambuc return ret;
951ebfedea0SLionel Sambuc }
952ebfedea0SLionel Sambuc
953ebfedea0SLionel Sambuc /* move to ourself is simple, done! */
954ebfedea0SLionel Sambuc if (strcmp(oldname, newname) == 0) {
955ebfedea0SLionel Sambuc free(oldname);
956ebfedea0SLionel Sambuc free(newname);
957ebfedea0SLionel Sambuc return 0;
958ebfedea0SLionel Sambuc }
959ebfedea0SLionel Sambuc
960ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode, oldname, &oldid);
961ebfedea0SLionel Sambuc if (ret) {
962ebfedea0SLionel Sambuc free(oldname);
963ebfedea0SLionel Sambuc free(newname);
964ebfedea0SLionel Sambuc return ret;
965ebfedea0SLionel Sambuc }
966ebfedea0SLionel Sambuc
967ebfedea0SLionel Sambuc /* Check if new credential cache exists, if not create one. */
968ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode, newname, &newid);
969ebfedea0SLionel Sambuc if (ret == KRB5_FCC_NOFILE)
970ebfedea0SLionel Sambuc ret = kcm_ccache_new_client(context, client, newname, &newid);
971ebfedea0SLionel Sambuc free(newname);
972ebfedea0SLionel Sambuc
973ebfedea0SLionel Sambuc if (ret) {
974ebfedea0SLionel Sambuc free(oldname);
975ebfedea0SLionel Sambuc kcm_release_ccache(context, oldid);
976ebfedea0SLionel Sambuc return ret;
977ebfedea0SLionel Sambuc }
978ebfedea0SLionel Sambuc
979ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&oldid->mutex);
980ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&newid->mutex);
981ebfedea0SLionel Sambuc
982ebfedea0SLionel Sambuc /* move content */
983ebfedea0SLionel Sambuc {
984ebfedea0SLionel Sambuc kcm_ccache_data tmp;
985ebfedea0SLionel Sambuc
986ebfedea0SLionel Sambuc #define MOVE(n,o,f) { tmp.f = n->f ; n->f = o->f; o->f = tmp.f; }
987ebfedea0SLionel Sambuc
988ebfedea0SLionel Sambuc MOVE(newid, oldid, flags);
989ebfedea0SLionel Sambuc MOVE(newid, oldid, client);
990ebfedea0SLionel Sambuc MOVE(newid, oldid, server);
991ebfedea0SLionel Sambuc MOVE(newid, oldid, creds);
992ebfedea0SLionel Sambuc MOVE(newid, oldid, tkt_life);
993ebfedea0SLionel Sambuc MOVE(newid, oldid, renew_life);
994ebfedea0SLionel Sambuc MOVE(newid, oldid, key);
995ebfedea0SLionel Sambuc MOVE(newid, oldid, kdc_offset);
996ebfedea0SLionel Sambuc #undef MOVE
997ebfedea0SLionel Sambuc }
998ebfedea0SLionel Sambuc
999ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&oldid->mutex);
1000ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&newid->mutex);
1001ebfedea0SLionel Sambuc
1002ebfedea0SLionel Sambuc kcm_release_ccache(context, oldid);
1003ebfedea0SLionel Sambuc kcm_release_ccache(context, newid);
1004ebfedea0SLionel Sambuc
1005ebfedea0SLionel Sambuc ret = kcm_ccache_destroy_client(context, client, oldname);
1006ebfedea0SLionel Sambuc if (ret == 0)
1007ebfedea0SLionel Sambuc kcm_drop_default_cache(context, client, oldname);
1008ebfedea0SLionel Sambuc
1009ebfedea0SLionel Sambuc free(oldname);
1010ebfedea0SLionel Sambuc
1011ebfedea0SLionel Sambuc return ret;
1012ebfedea0SLionel Sambuc }
1013ebfedea0SLionel Sambuc
1014ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_cache_uuid_list(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1015ebfedea0SLionel Sambuc kcm_op_get_cache_uuid_list(krb5_context context,
1016ebfedea0SLionel Sambuc kcm_client *client,
1017ebfedea0SLionel Sambuc kcm_operation opcode,
1018ebfedea0SLionel Sambuc krb5_storage *request,
1019ebfedea0SLionel Sambuc krb5_storage *response)
1020ebfedea0SLionel Sambuc {
1021ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
1022ebfedea0SLionel Sambuc
1023ebfedea0SLionel Sambuc return kcm_ccache_get_uuids(context, client, opcode, response);
1024ebfedea0SLionel Sambuc }
1025ebfedea0SLionel Sambuc
1026ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_cache_by_uuid(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1027ebfedea0SLionel Sambuc kcm_op_get_cache_by_uuid(krb5_context context,
1028ebfedea0SLionel Sambuc kcm_client *client,
1029ebfedea0SLionel Sambuc kcm_operation opcode,
1030ebfedea0SLionel Sambuc krb5_storage *request,
1031ebfedea0SLionel Sambuc krb5_storage *response)
1032ebfedea0SLionel Sambuc {
1033ebfedea0SLionel Sambuc krb5_error_code ret;
1034ebfedea0SLionel Sambuc kcmuuid_t uuid;
1035ebfedea0SLionel Sambuc ssize_t sret;
1036ebfedea0SLionel Sambuc kcm_ccache cache;
1037ebfedea0SLionel Sambuc
1038ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
1039ebfedea0SLionel Sambuc
1040ebfedea0SLionel Sambuc sret = krb5_storage_read(request, &uuid, sizeof(uuid));
1041ebfedea0SLionel Sambuc if (sret != sizeof(uuid)) {
1042ebfedea0SLionel Sambuc krb5_clear_error_message(context);
1043ebfedea0SLionel Sambuc return KRB5_CC_IO;
1044ebfedea0SLionel Sambuc }
1045ebfedea0SLionel Sambuc
1046ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_by_uuid(context, uuid, &cache);
1047ebfedea0SLionel Sambuc if (ret)
1048ebfedea0SLionel Sambuc return ret;
1049ebfedea0SLionel Sambuc
1050ebfedea0SLionel Sambuc ret = kcm_access(context, client, opcode, cache);
1051ebfedea0SLionel Sambuc if (ret)
1052ebfedea0SLionel Sambuc ret = KRB5_FCC_NOFILE;
1053ebfedea0SLionel Sambuc
1054ebfedea0SLionel Sambuc if (ret == 0)
1055ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, cache->name);
1056ebfedea0SLionel Sambuc
1057ebfedea0SLionel Sambuc kcm_release_ccache(context, cache);
1058ebfedea0SLionel Sambuc
1059ebfedea0SLionel Sambuc return ret;
1060ebfedea0SLionel Sambuc }
1061ebfedea0SLionel Sambuc
1062ebfedea0SLionel Sambuc struct kcm_default_cache *default_caches;
1063ebfedea0SLionel Sambuc
1064ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_default_cache(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1065ebfedea0SLionel Sambuc kcm_op_get_default_cache(krb5_context context,
1066ebfedea0SLionel Sambuc kcm_client *client,
1067ebfedea0SLionel Sambuc kcm_operation opcode,
1068ebfedea0SLionel Sambuc krb5_storage *request,
1069ebfedea0SLionel Sambuc krb5_storage *response)
1070ebfedea0SLionel Sambuc {
1071ebfedea0SLionel Sambuc struct kcm_default_cache *c;
1072ebfedea0SLionel Sambuc krb5_error_code ret;
1073ebfedea0SLionel Sambuc const char *name = NULL;
1074ebfedea0SLionel Sambuc char *n = NULL;
1075ebfedea0SLionel Sambuc
1076ebfedea0SLionel Sambuc KCM_LOG_REQUEST(context, client, opcode);
1077ebfedea0SLionel Sambuc
1078ebfedea0SLionel Sambuc for (c = default_caches; c != NULL; c = c->next) {
1079ebfedea0SLionel Sambuc if (kcm_is_same_session(client, c->uid, c->session)) {
1080ebfedea0SLionel Sambuc name = c->name;
1081ebfedea0SLionel Sambuc break;
1082ebfedea0SLionel Sambuc }
1083ebfedea0SLionel Sambuc }
1084ebfedea0SLionel Sambuc if (name == NULL)
1085ebfedea0SLionel Sambuc name = n = kcm_ccache_first_name(client);
1086ebfedea0SLionel Sambuc
1087ebfedea0SLionel Sambuc if (name == NULL) {
1088ebfedea0SLionel Sambuc asprintf(&n, "%d", (int)client->uid);
1089ebfedea0SLionel Sambuc name = n;
1090ebfedea0SLionel Sambuc }
1091ebfedea0SLionel Sambuc if (name == NULL)
1092ebfedea0SLionel Sambuc return ENOMEM;
1093ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, name);
1094ebfedea0SLionel Sambuc if (n)
1095ebfedea0SLionel Sambuc free(n);
1096ebfedea0SLionel Sambuc return ret;
1097ebfedea0SLionel Sambuc }
1098ebfedea0SLionel Sambuc
1099ebfedea0SLionel Sambuc static void
kcm_drop_default_cache(krb5_context context,kcm_client * client,char * name)1100ebfedea0SLionel Sambuc kcm_drop_default_cache(krb5_context context, kcm_client *client, char *name)
1101ebfedea0SLionel Sambuc {
1102ebfedea0SLionel Sambuc struct kcm_default_cache **c;
1103ebfedea0SLionel Sambuc
1104ebfedea0SLionel Sambuc for (c = &default_caches; *c != NULL; c = &(*c)->next) {
1105ebfedea0SLionel Sambuc if (!kcm_is_same_session(client, (*c)->uid, (*c)->session))
1106ebfedea0SLionel Sambuc continue;
1107ebfedea0SLionel Sambuc if (strcmp((*c)->name, name) == 0) {
1108ebfedea0SLionel Sambuc struct kcm_default_cache *h = *c;
1109ebfedea0SLionel Sambuc *c = (*c)->next;
1110ebfedea0SLionel Sambuc free(h->name);
1111ebfedea0SLionel Sambuc free(h);
1112ebfedea0SLionel Sambuc break;
1113ebfedea0SLionel Sambuc }
1114ebfedea0SLionel Sambuc }
1115ebfedea0SLionel Sambuc }
1116ebfedea0SLionel Sambuc
1117ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_set_default_cache(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1118ebfedea0SLionel Sambuc kcm_op_set_default_cache(krb5_context context,
1119ebfedea0SLionel Sambuc kcm_client *client,
1120ebfedea0SLionel Sambuc kcm_operation opcode,
1121ebfedea0SLionel Sambuc krb5_storage *request,
1122ebfedea0SLionel Sambuc krb5_storage *response)
1123ebfedea0SLionel Sambuc {
1124ebfedea0SLionel Sambuc struct kcm_default_cache *c;
1125ebfedea0SLionel Sambuc krb5_error_code ret;
1126ebfedea0SLionel Sambuc char *name;
1127ebfedea0SLionel Sambuc
1128ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
1129ebfedea0SLionel Sambuc if (ret)
1130ebfedea0SLionel Sambuc return ret;
1131ebfedea0SLionel Sambuc
1132ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
1133ebfedea0SLionel Sambuc
1134ebfedea0SLionel Sambuc for (c = default_caches; c != NULL; c = c->next) {
1135ebfedea0SLionel Sambuc if (kcm_is_same_session(client, c->uid, c->session))
1136ebfedea0SLionel Sambuc break;
1137ebfedea0SLionel Sambuc }
1138ebfedea0SLionel Sambuc if (c == NULL) {
1139ebfedea0SLionel Sambuc c = malloc(sizeof(*c));
1140ebfedea0SLionel Sambuc if (c == NULL)
1141ebfedea0SLionel Sambuc return ENOMEM;
1142ebfedea0SLionel Sambuc c->session = client->session;
1143ebfedea0SLionel Sambuc c->uid = client->uid;
1144ebfedea0SLionel Sambuc c->name = strdup(name);
1145ebfedea0SLionel Sambuc
1146ebfedea0SLionel Sambuc c->next = default_caches;
1147ebfedea0SLionel Sambuc default_caches = c;
1148ebfedea0SLionel Sambuc } else {
1149ebfedea0SLionel Sambuc free(c->name);
1150ebfedea0SLionel Sambuc c->name = strdup(name);
1151ebfedea0SLionel Sambuc }
1152ebfedea0SLionel Sambuc
1153ebfedea0SLionel Sambuc return 0;
1154ebfedea0SLionel Sambuc }
1155ebfedea0SLionel Sambuc
1156ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_kdc_offset(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1157ebfedea0SLionel Sambuc kcm_op_get_kdc_offset(krb5_context context,
1158ebfedea0SLionel Sambuc kcm_client *client,
1159ebfedea0SLionel Sambuc kcm_operation opcode,
1160ebfedea0SLionel Sambuc krb5_storage *request,
1161ebfedea0SLionel Sambuc krb5_storage *response)
1162ebfedea0SLionel Sambuc {
1163ebfedea0SLionel Sambuc krb5_error_code ret;
1164ebfedea0SLionel Sambuc kcm_ccache ccache;
1165ebfedea0SLionel Sambuc char *name;
1166ebfedea0SLionel Sambuc
1167ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
1168ebfedea0SLionel Sambuc if (ret)
1169ebfedea0SLionel Sambuc return ret;
1170ebfedea0SLionel Sambuc
1171ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
1172ebfedea0SLionel Sambuc
1173ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache);
1174ebfedea0SLionel Sambuc free(name);
1175ebfedea0SLionel Sambuc if (ret)
1176ebfedea0SLionel Sambuc return ret;
1177ebfedea0SLionel Sambuc
1178ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
1179ebfedea0SLionel Sambuc ret = krb5_store_int32(response, ccache->kdc_offset);
1180ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
1181ebfedea0SLionel Sambuc
1182ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
1183ebfedea0SLionel Sambuc
1184ebfedea0SLionel Sambuc return ret;
1185ebfedea0SLionel Sambuc }
1186ebfedea0SLionel Sambuc
1187ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_set_kdc_offset(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1188ebfedea0SLionel Sambuc kcm_op_set_kdc_offset(krb5_context context,
1189ebfedea0SLionel Sambuc kcm_client *client,
1190ebfedea0SLionel Sambuc kcm_operation opcode,
1191ebfedea0SLionel Sambuc krb5_storage *request,
1192ebfedea0SLionel Sambuc krb5_storage *response)
1193ebfedea0SLionel Sambuc {
1194ebfedea0SLionel Sambuc krb5_error_code ret;
1195ebfedea0SLionel Sambuc kcm_ccache ccache;
1196ebfedea0SLionel Sambuc int32_t offset;
1197ebfedea0SLionel Sambuc char *name;
1198ebfedea0SLionel Sambuc
1199ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &name);
1200ebfedea0SLionel Sambuc if (ret)
1201ebfedea0SLionel Sambuc return ret;
1202ebfedea0SLionel Sambuc
1203ebfedea0SLionel Sambuc KCM_LOG_REQUEST_NAME(context, client, opcode, name);
1204ebfedea0SLionel Sambuc
1205ebfedea0SLionel Sambuc ret = krb5_ret_int32(request, &offset);
1206ebfedea0SLionel Sambuc if (ret) {
1207ebfedea0SLionel Sambuc free(name);
1208ebfedea0SLionel Sambuc return ret;
1209ebfedea0SLionel Sambuc }
1210ebfedea0SLionel Sambuc
1211ebfedea0SLionel Sambuc ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache);
1212ebfedea0SLionel Sambuc free(name);
1213ebfedea0SLionel Sambuc if (ret)
1214ebfedea0SLionel Sambuc return ret;
1215ebfedea0SLionel Sambuc
1216ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&ccache->mutex);
1217ebfedea0SLionel Sambuc ccache->kdc_offset = offset;
1218ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&ccache->mutex);
1219ebfedea0SLionel Sambuc
1220ebfedea0SLionel Sambuc kcm_release_ccache(context, ccache);
1221ebfedea0SLionel Sambuc
1222ebfedea0SLionel Sambuc return ret;
1223ebfedea0SLionel Sambuc }
1224ebfedea0SLionel Sambuc
1225ebfedea0SLionel Sambuc struct kcm_ntlm_cred {
1226ebfedea0SLionel Sambuc kcmuuid_t uuid;
1227ebfedea0SLionel Sambuc char *user;
1228ebfedea0SLionel Sambuc char *domain;
1229ebfedea0SLionel Sambuc krb5_data nthash;
1230ebfedea0SLionel Sambuc uid_t uid;
1231ebfedea0SLionel Sambuc pid_t session;
1232ebfedea0SLionel Sambuc struct kcm_ntlm_cred *next;
1233ebfedea0SLionel Sambuc };
1234ebfedea0SLionel Sambuc
1235ebfedea0SLionel Sambuc static struct kcm_ntlm_cred *ntlm_head;
1236ebfedea0SLionel Sambuc
1237ebfedea0SLionel Sambuc static void
free_cred(struct kcm_ntlm_cred * cred)1238ebfedea0SLionel Sambuc free_cred(struct kcm_ntlm_cred *cred)
1239ebfedea0SLionel Sambuc {
1240ebfedea0SLionel Sambuc free(cred->user);
1241ebfedea0SLionel Sambuc free(cred->domain);
1242ebfedea0SLionel Sambuc krb5_data_free(&cred->nthash);
1243ebfedea0SLionel Sambuc free(cred);
1244ebfedea0SLionel Sambuc }
1245ebfedea0SLionel Sambuc
1246ebfedea0SLionel Sambuc
1247ebfedea0SLionel Sambuc /*
1248ebfedea0SLionel Sambuc * name
1249ebfedea0SLionel Sambuc * domain
1250ebfedea0SLionel Sambuc * ntlm hash
1251ebfedea0SLionel Sambuc *
1252ebfedea0SLionel Sambuc * Reply:
1253ebfedea0SLionel Sambuc * uuid
1254ebfedea0SLionel Sambuc */
1255ebfedea0SLionel Sambuc
1256ebfedea0SLionel Sambuc static struct kcm_ntlm_cred *
find_ntlm_cred(const char * user,const char * domain,kcm_client * client)1257ebfedea0SLionel Sambuc find_ntlm_cred(const char *user, const char *domain, kcm_client *client)
1258ebfedea0SLionel Sambuc {
1259ebfedea0SLionel Sambuc struct kcm_ntlm_cred *c;
1260ebfedea0SLionel Sambuc
1261ebfedea0SLionel Sambuc for (c = ntlm_head; c != NULL; c = c->next)
1262ebfedea0SLionel Sambuc if ((user[0] == '\0' || strcmp(user, c->user) == 0) &&
1263ebfedea0SLionel Sambuc (domain == NULL || strcmp(domain, c->domain) == 0) &&
1264ebfedea0SLionel Sambuc kcm_is_same_session(client, c->uid, c->session))
1265ebfedea0SLionel Sambuc return c;
1266ebfedea0SLionel Sambuc
1267ebfedea0SLionel Sambuc return NULL;
1268ebfedea0SLionel Sambuc }
1269ebfedea0SLionel Sambuc
1270ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_add_ntlm_cred(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1271ebfedea0SLionel Sambuc kcm_op_add_ntlm_cred(krb5_context context,
1272ebfedea0SLionel Sambuc kcm_client *client,
1273ebfedea0SLionel Sambuc kcm_operation opcode,
1274ebfedea0SLionel Sambuc krb5_storage *request,
1275ebfedea0SLionel Sambuc krb5_storage *response)
1276ebfedea0SLionel Sambuc {
1277ebfedea0SLionel Sambuc struct kcm_ntlm_cred *cred, *c;
1278ebfedea0SLionel Sambuc krb5_error_code ret;
1279ebfedea0SLionel Sambuc
1280ebfedea0SLionel Sambuc cred = calloc(1, sizeof(*cred));
1281ebfedea0SLionel Sambuc if (cred == NULL)
1282ebfedea0SLionel Sambuc return ENOMEM;
1283ebfedea0SLionel Sambuc
1284ebfedea0SLionel Sambuc RAND_bytes(cred->uuid, sizeof(cred->uuid));
1285ebfedea0SLionel Sambuc
1286ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &cred->user);
1287ebfedea0SLionel Sambuc if (ret)
1288ebfedea0SLionel Sambuc goto error;
1289ebfedea0SLionel Sambuc
1290ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &cred->domain);
1291ebfedea0SLionel Sambuc if (ret)
1292ebfedea0SLionel Sambuc goto error;
1293ebfedea0SLionel Sambuc
1294ebfedea0SLionel Sambuc ret = krb5_ret_data(request, &cred->nthash);
1295ebfedea0SLionel Sambuc if (ret)
1296ebfedea0SLionel Sambuc goto error;
1297ebfedea0SLionel Sambuc
1298ebfedea0SLionel Sambuc /* search for dups */
1299ebfedea0SLionel Sambuc c = find_ntlm_cred(cred->user, cred->domain, client);
1300ebfedea0SLionel Sambuc if (c) {
1301ebfedea0SLionel Sambuc krb5_data hash = c->nthash;
1302ebfedea0SLionel Sambuc c->nthash = cred->nthash;
1303ebfedea0SLionel Sambuc cred->nthash = hash;
1304ebfedea0SLionel Sambuc free_cred(cred);
1305ebfedea0SLionel Sambuc cred = c;
1306ebfedea0SLionel Sambuc } else {
1307ebfedea0SLionel Sambuc cred->next = ntlm_head;
1308ebfedea0SLionel Sambuc ntlm_head = cred;
1309ebfedea0SLionel Sambuc }
1310ebfedea0SLionel Sambuc
1311ebfedea0SLionel Sambuc cred->uid = client->uid;
1312ebfedea0SLionel Sambuc cred->session = client->session;
1313ebfedea0SLionel Sambuc
1314ebfedea0SLionel Sambuc /* write response */
1315ebfedea0SLionel Sambuc (void)krb5_storage_write(response, &cred->uuid, sizeof(cred->uuid));
1316ebfedea0SLionel Sambuc
1317ebfedea0SLionel Sambuc return 0;
1318ebfedea0SLionel Sambuc
1319ebfedea0SLionel Sambuc error:
1320ebfedea0SLionel Sambuc free_cred(cred);
1321ebfedea0SLionel Sambuc
1322ebfedea0SLionel Sambuc return ret;
1323ebfedea0SLionel Sambuc }
1324ebfedea0SLionel Sambuc
1325ebfedea0SLionel Sambuc /*
1326ebfedea0SLionel Sambuc * { "HAVE_NTLM_CRED", NULL },
1327ebfedea0SLionel Sambuc *
1328ebfedea0SLionel Sambuc * input:
1329ebfedea0SLionel Sambuc * name
1330ebfedea0SLionel Sambuc * domain
1331ebfedea0SLionel Sambuc */
1332ebfedea0SLionel Sambuc
1333ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_have_ntlm_cred(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1334ebfedea0SLionel Sambuc kcm_op_have_ntlm_cred(krb5_context context,
1335ebfedea0SLionel Sambuc kcm_client *client,
1336ebfedea0SLionel Sambuc kcm_operation opcode,
1337ebfedea0SLionel Sambuc krb5_storage *request,
1338ebfedea0SLionel Sambuc krb5_storage *response)
1339ebfedea0SLionel Sambuc {
1340ebfedea0SLionel Sambuc struct kcm_ntlm_cred *c;
1341ebfedea0SLionel Sambuc char *user = NULL, *domain = NULL;
1342ebfedea0SLionel Sambuc krb5_error_code ret;
1343ebfedea0SLionel Sambuc
1344ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &user);
1345ebfedea0SLionel Sambuc if (ret)
1346ebfedea0SLionel Sambuc goto error;
1347ebfedea0SLionel Sambuc
1348ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &domain);
1349ebfedea0SLionel Sambuc if (ret)
1350ebfedea0SLionel Sambuc goto error;
1351ebfedea0SLionel Sambuc
1352ebfedea0SLionel Sambuc if (domain[0] == '\0') {
1353ebfedea0SLionel Sambuc free(domain);
1354ebfedea0SLionel Sambuc domain = NULL;
1355ebfedea0SLionel Sambuc }
1356ebfedea0SLionel Sambuc
1357ebfedea0SLionel Sambuc c = find_ntlm_cred(user, domain, client);
1358ebfedea0SLionel Sambuc if (c == NULL)
1359ebfedea0SLionel Sambuc ret = ENOENT;
1360ebfedea0SLionel Sambuc
1361ebfedea0SLionel Sambuc error:
1362ebfedea0SLionel Sambuc free(user);
1363ebfedea0SLionel Sambuc if (domain)
1364ebfedea0SLionel Sambuc free(domain);
1365ebfedea0SLionel Sambuc
1366ebfedea0SLionel Sambuc return ret;
1367ebfedea0SLionel Sambuc }
1368ebfedea0SLionel Sambuc
1369ebfedea0SLionel Sambuc /*
1370ebfedea0SLionel Sambuc * { "DEL_NTLM_CRED", NULL },
1371ebfedea0SLionel Sambuc *
1372ebfedea0SLionel Sambuc * input:
1373ebfedea0SLionel Sambuc * name
1374ebfedea0SLionel Sambuc * domain
1375ebfedea0SLionel Sambuc */
1376ebfedea0SLionel Sambuc
1377ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_del_ntlm_cred(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1378ebfedea0SLionel Sambuc kcm_op_del_ntlm_cred(krb5_context context,
1379ebfedea0SLionel Sambuc kcm_client *client,
1380ebfedea0SLionel Sambuc kcm_operation opcode,
1381ebfedea0SLionel Sambuc krb5_storage *request,
1382ebfedea0SLionel Sambuc krb5_storage *response)
1383ebfedea0SLionel Sambuc {
1384ebfedea0SLionel Sambuc struct kcm_ntlm_cred **cp, *c;
1385ebfedea0SLionel Sambuc char *user = NULL, *domain = NULL;
1386ebfedea0SLionel Sambuc krb5_error_code ret;
1387ebfedea0SLionel Sambuc
1388ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &user);
1389ebfedea0SLionel Sambuc if (ret)
1390ebfedea0SLionel Sambuc goto error;
1391ebfedea0SLionel Sambuc
1392ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &domain);
1393ebfedea0SLionel Sambuc if (ret)
1394ebfedea0SLionel Sambuc goto error;
1395ebfedea0SLionel Sambuc
1396ebfedea0SLionel Sambuc for (cp = &ntlm_head; *cp != NULL; cp = &(*cp)->next) {
1397ebfedea0SLionel Sambuc if (strcmp(user, (*cp)->user) == 0 && strcmp(domain, (*cp)->domain) == 0 &&
1398ebfedea0SLionel Sambuc kcm_is_same_session(client, (*cp)->uid, (*cp)->session))
1399ebfedea0SLionel Sambuc {
1400ebfedea0SLionel Sambuc c = *cp;
1401ebfedea0SLionel Sambuc *cp = c->next;
1402ebfedea0SLionel Sambuc
1403ebfedea0SLionel Sambuc free_cred(c);
1404ebfedea0SLionel Sambuc break;
1405ebfedea0SLionel Sambuc }
1406ebfedea0SLionel Sambuc }
1407ebfedea0SLionel Sambuc
1408ebfedea0SLionel Sambuc error:
1409ebfedea0SLionel Sambuc free(user);
1410ebfedea0SLionel Sambuc free(domain);
1411ebfedea0SLionel Sambuc
1412ebfedea0SLionel Sambuc return ret;
1413ebfedea0SLionel Sambuc }
1414ebfedea0SLionel Sambuc
1415ebfedea0SLionel Sambuc /*
1416ebfedea0SLionel Sambuc * { "DO_NTLM_AUTH", NULL },
1417ebfedea0SLionel Sambuc *
1418ebfedea0SLionel Sambuc * input:
1419ebfedea0SLionel Sambuc * name:string
1420ebfedea0SLionel Sambuc * domain:string
1421ebfedea0SLionel Sambuc * type2:data
1422ebfedea0SLionel Sambuc *
1423ebfedea0SLionel Sambuc * reply:
1424ebfedea0SLionel Sambuc * type3:data
1425ebfedea0SLionel Sambuc * flags:int32
1426ebfedea0SLionel Sambuc * session-key:data
1427ebfedea0SLionel Sambuc */
1428ebfedea0SLionel Sambuc
1429ebfedea0SLionel Sambuc #define NTLM_FLAG_SESSIONKEY 1
1430ebfedea0SLionel Sambuc #define NTLM_FLAG_NTLM2_SESSION 2
1431ebfedea0SLionel Sambuc #define NTLM_FLAG_KEYEX 4
1432ebfedea0SLionel Sambuc
1433ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_do_ntlm(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1434ebfedea0SLionel Sambuc kcm_op_do_ntlm(krb5_context context,
1435ebfedea0SLionel Sambuc kcm_client *client,
1436ebfedea0SLionel Sambuc kcm_operation opcode,
1437ebfedea0SLionel Sambuc krb5_storage *request,
1438ebfedea0SLionel Sambuc krb5_storage *response)
1439ebfedea0SLionel Sambuc {
1440ebfedea0SLionel Sambuc struct kcm_ntlm_cred *c;
1441ebfedea0SLionel Sambuc struct ntlm_type2 type2;
1442ebfedea0SLionel Sambuc struct ntlm_type3 type3;
1443ebfedea0SLionel Sambuc char *user = NULL, *domain = NULL;
1444ebfedea0SLionel Sambuc struct ntlm_buf ndata, sessionkey;
1445ebfedea0SLionel Sambuc krb5_data data;
1446ebfedea0SLionel Sambuc krb5_error_code ret;
1447ebfedea0SLionel Sambuc uint32_t flags = 0;
1448ebfedea0SLionel Sambuc
1449ebfedea0SLionel Sambuc memset(&type2, 0, sizeof(type2));
1450ebfedea0SLionel Sambuc memset(&type3, 0, sizeof(type3));
1451ebfedea0SLionel Sambuc sessionkey.data = NULL;
1452ebfedea0SLionel Sambuc sessionkey.length = 0;
1453ebfedea0SLionel Sambuc
1454ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &user);
1455ebfedea0SLionel Sambuc if (ret)
1456ebfedea0SLionel Sambuc goto error;
1457ebfedea0SLionel Sambuc
1458ebfedea0SLionel Sambuc ret = krb5_ret_stringz(request, &domain);
1459ebfedea0SLionel Sambuc if (ret)
1460ebfedea0SLionel Sambuc goto error;
1461ebfedea0SLionel Sambuc
1462ebfedea0SLionel Sambuc if (domain[0] == '\0') {
1463ebfedea0SLionel Sambuc free(domain);
1464ebfedea0SLionel Sambuc domain = NULL;
1465ebfedea0SLionel Sambuc }
1466ebfedea0SLionel Sambuc
1467ebfedea0SLionel Sambuc c = find_ntlm_cred(user, domain, client);
1468ebfedea0SLionel Sambuc if (c == NULL) {
1469ebfedea0SLionel Sambuc ret = EINVAL;
1470ebfedea0SLionel Sambuc goto error;
1471ebfedea0SLionel Sambuc }
1472ebfedea0SLionel Sambuc
1473ebfedea0SLionel Sambuc ret = krb5_ret_data(request, &data);
1474ebfedea0SLionel Sambuc if (ret)
1475ebfedea0SLionel Sambuc goto error;
1476ebfedea0SLionel Sambuc
1477ebfedea0SLionel Sambuc ndata.data = data.data;
1478ebfedea0SLionel Sambuc ndata.length = data.length;
1479ebfedea0SLionel Sambuc
1480ebfedea0SLionel Sambuc ret = heim_ntlm_decode_type2(&ndata, &type2);
1481ebfedea0SLionel Sambuc krb5_data_free(&data);
1482ebfedea0SLionel Sambuc if (ret)
1483ebfedea0SLionel Sambuc goto error;
1484ebfedea0SLionel Sambuc
1485ebfedea0SLionel Sambuc if (domain && strcmp(domain, type2.targetname) == 0) {
1486ebfedea0SLionel Sambuc ret = EINVAL;
1487ebfedea0SLionel Sambuc goto error;
1488ebfedea0SLionel Sambuc }
1489ebfedea0SLionel Sambuc
1490ebfedea0SLionel Sambuc type3.username = c->user;
1491ebfedea0SLionel Sambuc type3.flags = type2.flags;
1492ebfedea0SLionel Sambuc type3.targetname = type2.targetname;
1493ebfedea0SLionel Sambuc type3.ws = rk_UNCONST("workstation");
1494ebfedea0SLionel Sambuc
1495ebfedea0SLionel Sambuc /*
1496ebfedea0SLionel Sambuc * NTLM Version 1 if no targetinfo buffer.
1497ebfedea0SLionel Sambuc */
1498ebfedea0SLionel Sambuc
1499ebfedea0SLionel Sambuc if (1 || type2.targetinfo.length == 0) {
1500ebfedea0SLionel Sambuc struct ntlm_buf sessionkey;
1501ebfedea0SLionel Sambuc
1502ebfedea0SLionel Sambuc if (type2.flags & NTLM_NEG_NTLM2_SESSION) {
1503ebfedea0SLionel Sambuc unsigned char nonce[8];
1504ebfedea0SLionel Sambuc
1505ebfedea0SLionel Sambuc if (RAND_bytes(nonce, sizeof(nonce)) != 1) {
1506ebfedea0SLionel Sambuc ret = EINVAL;
1507ebfedea0SLionel Sambuc goto error;
1508ebfedea0SLionel Sambuc }
1509ebfedea0SLionel Sambuc
1510ebfedea0SLionel Sambuc ret = heim_ntlm_calculate_ntlm2_sess(nonce,
1511ebfedea0SLionel Sambuc type2.challenge,
1512ebfedea0SLionel Sambuc c->nthash.data,
1513ebfedea0SLionel Sambuc &type3.lm,
1514ebfedea0SLionel Sambuc &type3.ntlm);
1515ebfedea0SLionel Sambuc } else {
1516ebfedea0SLionel Sambuc ret = heim_ntlm_calculate_ntlm1(c->nthash.data,
1517ebfedea0SLionel Sambuc c->nthash.length,
1518ebfedea0SLionel Sambuc type2.challenge,
1519ebfedea0SLionel Sambuc &type3.ntlm);
1520ebfedea0SLionel Sambuc
1521ebfedea0SLionel Sambuc }
1522ebfedea0SLionel Sambuc if (ret)
1523ebfedea0SLionel Sambuc goto error;
1524ebfedea0SLionel Sambuc
1525ebfedea0SLionel Sambuc ret = heim_ntlm_build_ntlm1_master(c->nthash.data,
1526ebfedea0SLionel Sambuc c->nthash.length,
1527ebfedea0SLionel Sambuc &sessionkey,
1528ebfedea0SLionel Sambuc &type3.sessionkey);
1529ebfedea0SLionel Sambuc if (ret) {
1530ebfedea0SLionel Sambuc if (type3.lm.data)
1531ebfedea0SLionel Sambuc free(type3.lm.data);
1532ebfedea0SLionel Sambuc if (type3.ntlm.data)
1533ebfedea0SLionel Sambuc free(type3.ntlm.data);
1534ebfedea0SLionel Sambuc goto error;
1535ebfedea0SLionel Sambuc }
1536ebfedea0SLionel Sambuc
1537ebfedea0SLionel Sambuc free(sessionkey.data);
1538ebfedea0SLionel Sambuc if (ret) {
1539ebfedea0SLionel Sambuc if (type3.lm.data)
1540ebfedea0SLionel Sambuc free(type3.lm.data);
1541ebfedea0SLionel Sambuc if (type3.ntlm.data)
1542ebfedea0SLionel Sambuc free(type3.ntlm.data);
1543ebfedea0SLionel Sambuc goto error;
1544ebfedea0SLionel Sambuc }
1545ebfedea0SLionel Sambuc flags |= NTLM_FLAG_SESSIONKEY;
1546ebfedea0SLionel Sambuc #if 0
1547ebfedea0SLionel Sambuc } else {
1548ebfedea0SLionel Sambuc struct ntlm_buf sessionkey;
1549ebfedea0SLionel Sambuc unsigned char ntlmv2[16];
1550ebfedea0SLionel Sambuc struct ntlm_targetinfo ti;
1551ebfedea0SLionel Sambuc
1552ebfedea0SLionel Sambuc /* verify infotarget */
1553ebfedea0SLionel Sambuc
1554ebfedea0SLionel Sambuc ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti);
1555ebfedea0SLionel Sambuc if(ret) {
1556ebfedea0SLionel Sambuc _gss_ntlm_delete_sec_context(minor_status,
1557ebfedea0SLionel Sambuc context_handle, NULL);
1558ebfedea0SLionel Sambuc *minor_status = ret;
1559ebfedea0SLionel Sambuc return GSS_S_FAILURE;
1560ebfedea0SLionel Sambuc }
1561ebfedea0SLionel Sambuc
1562ebfedea0SLionel Sambuc if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) {
1563ebfedea0SLionel Sambuc _gss_ntlm_delete_sec_context(minor_status,
1564ebfedea0SLionel Sambuc context_handle, NULL);
1565ebfedea0SLionel Sambuc *minor_status = EINVAL;
1566ebfedea0SLionel Sambuc return GSS_S_FAILURE;
1567ebfedea0SLionel Sambuc }
1568ebfedea0SLionel Sambuc
1569ebfedea0SLionel Sambuc ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data,
1570ebfedea0SLionel Sambuc ctx->client->key.length,
1571ebfedea0SLionel Sambuc type3.username,
1572ebfedea0SLionel Sambuc name->domain,
1573ebfedea0SLionel Sambuc type2.challenge,
1574ebfedea0SLionel Sambuc &type2.targetinfo,
1575ebfedea0SLionel Sambuc ntlmv2,
1576ebfedea0SLionel Sambuc &type3.ntlm);
1577ebfedea0SLionel Sambuc if (ret) {
1578ebfedea0SLionel Sambuc _gss_ntlm_delete_sec_context(minor_status,
1579ebfedea0SLionel Sambuc context_handle, NULL);
1580ebfedea0SLionel Sambuc *minor_status = ret;
1581ebfedea0SLionel Sambuc return GSS_S_FAILURE;
1582ebfedea0SLionel Sambuc }
1583ebfedea0SLionel Sambuc
1584ebfedea0SLionel Sambuc ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2),
1585ebfedea0SLionel Sambuc &sessionkey,
1586ebfedea0SLionel Sambuc &type3.sessionkey);
1587ebfedea0SLionel Sambuc memset(ntlmv2, 0, sizeof(ntlmv2));
1588ebfedea0SLionel Sambuc if (ret) {
1589ebfedea0SLionel Sambuc _gss_ntlm_delete_sec_context(minor_status,
1590ebfedea0SLionel Sambuc context_handle, NULL);
1591ebfedea0SLionel Sambuc *minor_status = ret;
1592ebfedea0SLionel Sambuc return GSS_S_FAILURE;
1593ebfedea0SLionel Sambuc }
1594ebfedea0SLionel Sambuc
1595ebfedea0SLionel Sambuc flags |= NTLM_FLAG_NTLM2_SESSION |
1596ebfedea0SLionel Sambuc NTLM_FLAG_SESSION;
1597ebfedea0SLionel Sambuc
1598ebfedea0SLionel Sambuc if (type3.flags & NTLM_NEG_KEYEX)
1599ebfedea0SLionel Sambuc flags |= NTLM_FLAG_KEYEX;
1600ebfedea0SLionel Sambuc
1601ebfedea0SLionel Sambuc ret = krb5_data_copy(&ctx->sessionkey,
1602ebfedea0SLionel Sambuc sessionkey.data, sessionkey.length);
1603ebfedea0SLionel Sambuc free(sessionkey.data);
1604ebfedea0SLionel Sambuc if (ret) {
1605ebfedea0SLionel Sambuc _gss_ntlm_delete_sec_context(minor_status,
1606ebfedea0SLionel Sambuc context_handle, NULL);
1607ebfedea0SLionel Sambuc *minor_status = ret;
1608ebfedea0SLionel Sambuc return GSS_S_FAILURE;
1609ebfedea0SLionel Sambuc }
1610ebfedea0SLionel Sambuc #endif
1611ebfedea0SLionel Sambuc }
1612ebfedea0SLionel Sambuc
1613ebfedea0SLionel Sambuc #if 0
1614ebfedea0SLionel Sambuc if (flags & NTLM_FLAG_NTLM2_SESSION) {
1615ebfedea0SLionel Sambuc _gss_ntlm_set_key(&ctx->u.v2.send, 0, (ctx->flags & NTLM_NEG_KEYEX),
1616ebfedea0SLionel Sambuc ctx->sessionkey.data,
1617ebfedea0SLionel Sambuc ctx->sessionkey.length);
1618ebfedea0SLionel Sambuc _gss_ntlm_set_key(&ctx->u.v2.recv, 1, (ctx->flags & NTLM_NEG_KEYEX),
1619ebfedea0SLionel Sambuc ctx->sessionkey.data,
1620ebfedea0SLionel Sambuc ctx->sessionkey.length);
1621ebfedea0SLionel Sambuc } else {
1622ebfedea0SLionel Sambuc flags |= NTLM_FLAG_SESSION;
1623ebfedea0SLionel Sambuc RC4_set_key(&ctx->u.v1.crypto_recv.key,
1624ebfedea0SLionel Sambuc ctx->sessionkey.length,
1625ebfedea0SLionel Sambuc ctx->sessionkey.data);
1626ebfedea0SLionel Sambuc RC4_set_key(&ctx->u.v1.crypto_send.key,
1627ebfedea0SLionel Sambuc ctx->sessionkey.length,
1628ebfedea0SLionel Sambuc ctx->sessionkey.data);
1629ebfedea0SLionel Sambuc }
1630ebfedea0SLionel Sambuc #endif
1631ebfedea0SLionel Sambuc
1632ebfedea0SLionel Sambuc ret = heim_ntlm_encode_type3(&type3, &ndata);
1633ebfedea0SLionel Sambuc if (ret)
1634ebfedea0SLionel Sambuc goto error;
1635ebfedea0SLionel Sambuc
1636ebfedea0SLionel Sambuc data.data = ndata.data;
1637ebfedea0SLionel Sambuc data.length = ndata.length;
1638ebfedea0SLionel Sambuc ret = krb5_store_data(response, data);
1639ebfedea0SLionel Sambuc heim_ntlm_free_buf(&ndata);
1640ebfedea0SLionel Sambuc if (ret) goto error;
1641ebfedea0SLionel Sambuc
1642ebfedea0SLionel Sambuc ret = krb5_store_int32(response, flags);
1643ebfedea0SLionel Sambuc if (ret) goto error;
1644ebfedea0SLionel Sambuc
1645ebfedea0SLionel Sambuc data.data = sessionkey.data;
1646ebfedea0SLionel Sambuc data.length = sessionkey.length;
1647ebfedea0SLionel Sambuc
1648ebfedea0SLionel Sambuc ret = krb5_store_data(response, data);
1649ebfedea0SLionel Sambuc if (ret) goto error;
1650ebfedea0SLionel Sambuc
1651ebfedea0SLionel Sambuc error:
1652ebfedea0SLionel Sambuc free(type3.username);
1653ebfedea0SLionel Sambuc heim_ntlm_free_type2(&type2);
1654ebfedea0SLionel Sambuc free(user);
1655ebfedea0SLionel Sambuc if (domain)
1656ebfedea0SLionel Sambuc free(domain);
1657ebfedea0SLionel Sambuc
1658ebfedea0SLionel Sambuc return ret;
1659ebfedea0SLionel Sambuc }
1660ebfedea0SLionel Sambuc
1661ebfedea0SLionel Sambuc
1662ebfedea0SLionel Sambuc /*
1663ebfedea0SLionel Sambuc * { "GET_NTLM_UUID_LIST", NULL }
1664ebfedea0SLionel Sambuc *
1665ebfedea0SLionel Sambuc * reply:
1666ebfedea0SLionel Sambuc * 1 user domain
1667ebfedea0SLionel Sambuc * 0 [ end of list ]
1668ebfedea0SLionel Sambuc */
1669ebfedea0SLionel Sambuc
1670ebfedea0SLionel Sambuc static krb5_error_code
kcm_op_get_ntlm_user_list(krb5_context context,kcm_client * client,kcm_operation opcode,krb5_storage * request,krb5_storage * response)1671ebfedea0SLionel Sambuc kcm_op_get_ntlm_user_list(krb5_context context,
1672ebfedea0SLionel Sambuc kcm_client *client,
1673ebfedea0SLionel Sambuc kcm_operation opcode,
1674ebfedea0SLionel Sambuc krb5_storage *request,
1675ebfedea0SLionel Sambuc krb5_storage *response)
1676ebfedea0SLionel Sambuc {
1677ebfedea0SLionel Sambuc struct kcm_ntlm_cred *c;
1678ebfedea0SLionel Sambuc krb5_error_code ret;
1679ebfedea0SLionel Sambuc
1680ebfedea0SLionel Sambuc for (c = ntlm_head; c != NULL; c = c->next) {
1681ebfedea0SLionel Sambuc if (!kcm_is_same_session(client, c->uid, c->session))
1682ebfedea0SLionel Sambuc continue;
1683ebfedea0SLionel Sambuc
1684ebfedea0SLionel Sambuc ret = krb5_store_uint32(response, 1);
1685ebfedea0SLionel Sambuc if (ret)
1686ebfedea0SLionel Sambuc return ret;
1687ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, c->user);
1688ebfedea0SLionel Sambuc if (ret)
1689ebfedea0SLionel Sambuc return ret;
1690ebfedea0SLionel Sambuc ret = krb5_store_stringz(response, c->domain);
1691ebfedea0SLionel Sambuc if (ret)
1692ebfedea0SLionel Sambuc return ret;
1693ebfedea0SLionel Sambuc }
1694ebfedea0SLionel Sambuc return krb5_store_uint32(response, 0);
1695ebfedea0SLionel Sambuc }
1696ebfedea0SLionel Sambuc
1697ebfedea0SLionel Sambuc /*
1698ebfedea0SLionel Sambuc *
1699ebfedea0SLionel Sambuc */
1700ebfedea0SLionel Sambuc
1701ebfedea0SLionel Sambuc static struct kcm_op kcm_ops[] = {
1702ebfedea0SLionel Sambuc { "NOOP", kcm_op_noop },
1703ebfedea0SLionel Sambuc { "GET_NAME", kcm_op_get_name },
1704ebfedea0SLionel Sambuc { "RESOLVE", kcm_op_noop },
1705ebfedea0SLionel Sambuc { "GEN_NEW", kcm_op_gen_new },
1706ebfedea0SLionel Sambuc { "INITIALIZE", kcm_op_initialize },
1707ebfedea0SLionel Sambuc { "DESTROY", kcm_op_destroy },
1708ebfedea0SLionel Sambuc { "STORE", kcm_op_store },
1709ebfedea0SLionel Sambuc { "RETRIEVE", kcm_op_retrieve },
1710ebfedea0SLionel Sambuc { "GET_PRINCIPAL", kcm_op_get_principal },
1711ebfedea0SLionel Sambuc { "GET_CRED_UUID_LIST", kcm_op_get_cred_uuid_list },
1712ebfedea0SLionel Sambuc { "GET_CRED_BY_UUID", kcm_op_get_cred_by_uuid },
1713ebfedea0SLionel Sambuc { "REMOVE_CRED", kcm_op_remove_cred },
1714ebfedea0SLionel Sambuc { "SET_FLAGS", kcm_op_set_flags },
1715ebfedea0SLionel Sambuc { "CHOWN", kcm_op_chown },
1716ebfedea0SLionel Sambuc { "CHMOD", kcm_op_chmod },
1717ebfedea0SLionel Sambuc { "GET_INITIAL_TICKET", kcm_op_get_initial_ticket },
1718ebfedea0SLionel Sambuc { "GET_TICKET", kcm_op_get_ticket },
1719ebfedea0SLionel Sambuc { "MOVE_CACHE", kcm_op_move_cache },
1720ebfedea0SLionel Sambuc { "GET_CACHE_UUID_LIST", kcm_op_get_cache_uuid_list },
1721ebfedea0SLionel Sambuc { "GET_CACHE_BY_UUID", kcm_op_get_cache_by_uuid },
1722ebfedea0SLionel Sambuc { "GET_DEFAULT_CACHE", kcm_op_get_default_cache },
1723ebfedea0SLionel Sambuc { "SET_DEFAULT_CACHE", kcm_op_set_default_cache },
1724ebfedea0SLionel Sambuc { "GET_KDC_OFFSET", kcm_op_get_kdc_offset },
1725ebfedea0SLionel Sambuc { "SET_KDC_OFFSET", kcm_op_set_kdc_offset },
1726ebfedea0SLionel Sambuc { "ADD_NTLM_CRED", kcm_op_add_ntlm_cred },
1727ebfedea0SLionel Sambuc { "HAVE_USER_CRED", kcm_op_have_ntlm_cred },
1728ebfedea0SLionel Sambuc { "DEL_NTLM_CRED", kcm_op_del_ntlm_cred },
1729ebfedea0SLionel Sambuc { "DO_NTLM_AUTH", kcm_op_do_ntlm },
1730ebfedea0SLionel Sambuc { "GET_NTLM_USER_LIST", kcm_op_get_ntlm_user_list }
1731ebfedea0SLionel Sambuc };
1732ebfedea0SLionel Sambuc
1733ebfedea0SLionel Sambuc
1734ebfedea0SLionel Sambuc const char *
kcm_op2string(kcm_operation opcode)1735ebfedea0SLionel Sambuc kcm_op2string(kcm_operation opcode)
1736ebfedea0SLionel Sambuc {
1737ebfedea0SLionel Sambuc if (opcode >= sizeof(kcm_ops)/sizeof(kcm_ops[0]))
1738ebfedea0SLionel Sambuc return "Unknown operation";
1739ebfedea0SLionel Sambuc
1740ebfedea0SLionel Sambuc return kcm_ops[opcode].name;
1741ebfedea0SLionel Sambuc }
1742ebfedea0SLionel Sambuc
1743ebfedea0SLionel Sambuc krb5_error_code
kcm_dispatch(krb5_context context,kcm_client * client,krb5_data * req_data,krb5_data * resp_data)1744ebfedea0SLionel Sambuc kcm_dispatch(krb5_context context,
1745ebfedea0SLionel Sambuc kcm_client *client,
1746ebfedea0SLionel Sambuc krb5_data *req_data,
1747ebfedea0SLionel Sambuc krb5_data *resp_data)
1748ebfedea0SLionel Sambuc {
1749ebfedea0SLionel Sambuc krb5_error_code ret;
1750ebfedea0SLionel Sambuc kcm_method method;
1751ebfedea0SLionel Sambuc krb5_storage *req_sp = NULL;
1752ebfedea0SLionel Sambuc krb5_storage *resp_sp = NULL;
1753ebfedea0SLionel Sambuc uint16_t opcode;
1754ebfedea0SLionel Sambuc
1755ebfedea0SLionel Sambuc resp_sp = krb5_storage_emem();
1756ebfedea0SLionel Sambuc if (resp_sp == NULL) {
1757ebfedea0SLionel Sambuc return ENOMEM;
1758ebfedea0SLionel Sambuc }
1759ebfedea0SLionel Sambuc
1760ebfedea0SLionel Sambuc if (client->pid == -1) {
1761ebfedea0SLionel Sambuc kcm_log(0, "Client had invalid process number");
1762ebfedea0SLionel Sambuc ret = KRB5_FCC_INTERNAL;
1763ebfedea0SLionel Sambuc goto out;
1764ebfedea0SLionel Sambuc }
1765ebfedea0SLionel Sambuc
1766ebfedea0SLionel Sambuc req_sp = krb5_storage_from_data(req_data);
1767ebfedea0SLionel Sambuc if (req_sp == NULL) {
1768ebfedea0SLionel Sambuc kcm_log(0, "Process %d: failed to initialize storage from data",
1769ebfedea0SLionel Sambuc client->pid);
1770ebfedea0SLionel Sambuc ret = KRB5_CC_IO;
1771ebfedea0SLionel Sambuc goto out;
1772ebfedea0SLionel Sambuc }
1773ebfedea0SLionel Sambuc
1774ebfedea0SLionel Sambuc ret = krb5_ret_uint16(req_sp, &opcode);
1775ebfedea0SLionel Sambuc if (ret) {
1776ebfedea0SLionel Sambuc kcm_log(0, "Process %d: didn't send a message", client->pid);
1777ebfedea0SLionel Sambuc goto out;
1778ebfedea0SLionel Sambuc }
1779ebfedea0SLionel Sambuc
1780ebfedea0SLionel Sambuc if (opcode >= sizeof(kcm_ops)/sizeof(kcm_ops[0])) {
1781ebfedea0SLionel Sambuc kcm_log(0, "Process %d: invalid operation code %d",
1782ebfedea0SLionel Sambuc client->pid, opcode);
1783ebfedea0SLionel Sambuc ret = KRB5_FCC_INTERNAL;
1784ebfedea0SLionel Sambuc goto out;
1785ebfedea0SLionel Sambuc }
1786ebfedea0SLionel Sambuc method = kcm_ops[opcode].method;
1787ebfedea0SLionel Sambuc if (method == NULL) {
1788ebfedea0SLionel Sambuc kcm_log(0, "Process %d: operation code %s not implemented",
1789ebfedea0SLionel Sambuc client->pid, kcm_op2string(opcode));
1790ebfedea0SLionel Sambuc ret = KRB5_FCC_INTERNAL;
1791ebfedea0SLionel Sambuc goto out;
1792ebfedea0SLionel Sambuc }
1793ebfedea0SLionel Sambuc
1794ebfedea0SLionel Sambuc /* seek past place for status code */
1795ebfedea0SLionel Sambuc krb5_storage_seek(resp_sp, 4, SEEK_SET);
1796ebfedea0SLionel Sambuc
1797ebfedea0SLionel Sambuc ret = (*method)(context, client, opcode, req_sp, resp_sp);
1798ebfedea0SLionel Sambuc
1799ebfedea0SLionel Sambuc out:
1800ebfedea0SLionel Sambuc if (req_sp != NULL) {
1801ebfedea0SLionel Sambuc krb5_storage_free(req_sp);
1802ebfedea0SLionel Sambuc }
1803ebfedea0SLionel Sambuc
1804ebfedea0SLionel Sambuc krb5_storage_seek(resp_sp, 0, SEEK_SET);
1805ebfedea0SLionel Sambuc krb5_store_int32(resp_sp, ret);
1806ebfedea0SLionel Sambuc
1807ebfedea0SLionel Sambuc ret = krb5_storage_to_data(resp_sp, resp_data);
1808ebfedea0SLionel Sambuc krb5_storage_free(resp_sp);
1809ebfedea0SLionel Sambuc
1810ebfedea0SLionel Sambuc return ret;
1811ebfedea0SLionel Sambuc }
1812ebfedea0SLionel Sambuc
1813