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