source: branches/samba-3.5.x/source4/heimdal/lib/krb5/kcm.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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