Add text about smbk5pwd overlay from Buchan Milne.
[heimdal.git] / lib / krb5 / kcm.c
blobcdfff9345f4584ce118e30f0f9436346b70ef202
1 /*
2 * Copyright (c) 2005, PADL Software Pty Ltd.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 #include "krb5_locl.h"
35 #ifdef HAVE_KCM
37 * Client library for Kerberos Credentials Manager (KCM) daemon
40 #ifdef HAVE_SYS_UN_H
41 #include <sys/un.h>
42 #endif
44 #include "kcm.h"
46 RCSID("$Id$");
48 typedef struct krb5_kcmcache {
49 char *name;
50 struct sockaddr_un path;
51 char *door_path;
52 } krb5_kcmcache;
54 #define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data)
55 #define CACHENAME(X) (KCMCACHE(X)->name)
56 #define KCMCURSOR(C) (*(uint32_t *)(C))
58 static krb5_error_code
59 try_door(krb5_context context,
60 krb5_data *request_data,
61 krb5_data *response_data)
63 #ifdef HAVE_DOOR_CREATE
64 door_arg_t arg;
65 int fd;
66 int ret;
68 memset(&arg, 0, sizeof(arg));
70 fd = open(k->door_path, O_RDWR);
71 if (fd < 0)
72 return KRB5_CC_IO;
74 arg.data_ptr = request_data->data;
75 arg.data_size = request_data->length;
76 arg.desc_ptr = NULL;
77 arg.desc_num = 0;
78 arg.rbuf = NULL;
79 arg.rsize = 0;
81 ret = door_call(fd, &arg);
82 close(fd);
83 if (ret != 0)
84 return KRB5_CC_IO;
86 ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize);
87 munmap(arg.rbuf, arg.rsize);
88 if (ret)
89 return ret;
91 return 0;
92 #else
93 return KRB5_CC_IO;
94 #endif
97 static krb5_error_code
98 try_unix_socket(krb5_context context,
99 krb5_kcmcache *k,
100 krb5_data *request_data,
101 krb5_data *response_data)
103 krb5_error_code ret;
104 int fd;
106 fd = socket(AF_UNIX, SOCK_STREAM, 0);
107 if (fd < 0)
108 return KRB5_CC_IO;
110 if (connect(fd, rk_UNCONST(&k->path), sizeof(k->path)) != 0) {
111 close(fd);
112 return KRB5_CC_IO;
115 ret = _krb5_send_and_recv_tcp(fd, context->kdc_timeout,
116 request_data, response_data);
117 close(fd);
118 return ret;
121 static krb5_error_code
122 kcm_send_request(krb5_context context,
123 krb5_kcmcache *k,
124 krb5_storage *request,
125 krb5_data *response_data)
127 krb5_error_code ret;
128 krb5_data request_data;
129 int i;
131 response_data->data = NULL;
132 response_data->length = 0;
134 ret = krb5_storage_to_data(request, &request_data);
135 if (ret) {
136 krb5_clear_error_string(context);
137 return KRB5_CC_NOMEM;
140 ret = KRB5_CC_NOSUPP;
142 for (i = 0; i < context->max_retries; i++) {
143 ret = try_door(context, &request_data, response_data);
144 if (ret == 0 && response_data->length != 0)
145 break;
146 ret = try_unix_socket(context, k, &request_data, response_data);
147 if (ret == 0 && response_data->length != 0)
148 break;
151 krb5_data_free(&request_data);
153 if (ret) {
154 krb5_clear_error_string(context);
155 ret = KRB5_CC_NOSUPP;
158 return ret;
161 static krb5_error_code
162 kcm_storage_request(krb5_context context,
163 kcm_operation opcode,
164 krb5_storage **storage_p)
166 krb5_storage *sp;
167 krb5_error_code ret;
169 *storage_p = NULL;
171 sp = krb5_storage_emem();
172 if (sp == NULL) {
173 krb5_set_error_string(context, "malloc: out of memory");
174 return KRB5_CC_NOMEM;
177 /* Send MAJOR | VERSION | OPCODE */
178 ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR);
179 if (ret)
180 goto fail;
181 ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR);
182 if (ret)
183 goto fail;
184 ret = krb5_store_int16(sp, opcode);
185 if (ret)
186 goto fail;
188 *storage_p = sp;
189 fail:
190 if (ret) {
191 krb5_set_error_string(context, "Failed to encode request");
192 krb5_storage_free(sp);
195 return ret;
198 static krb5_error_code
199 kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
201 krb5_kcmcache *k;
202 const char *path;
204 k = malloc(sizeof(*k));
205 if (k == NULL) {
206 krb5_set_error_string(context, "malloc: out of memory");
207 return KRB5_CC_NOMEM;
210 if (name != NULL) {
211 k->name = strdup(name);
212 if (k->name == NULL) {
213 free(k);
214 krb5_set_error_string(context, "malloc: out of memory");
215 return KRB5_CC_NOMEM;
217 } else
218 k->name = NULL;
220 path = krb5_config_get_string_default(context, NULL,
221 _PATH_KCM_SOCKET,
222 "libdefaults",
223 "kcm_socket",
224 NULL);
226 k->path.sun_family = AF_UNIX;
227 strlcpy(k->path.sun_path, path, sizeof(k->path.sun_path));
229 path = krb5_config_get_string_default(context, NULL,
230 _PATH_KCM_DOOR,
231 "libdefaults",
232 "kcm_door",
233 NULL);
234 k->door_path = strdup(path);
236 (*id)->data.data = k;
237 (*id)->data.length = sizeof(*k);
239 return 0;
242 static krb5_error_code
243 kcm_call(krb5_context context,
244 krb5_kcmcache *k,
245 krb5_storage *request,
246 krb5_storage **response_p,
247 krb5_data *response_data_p)
249 krb5_data response_data;
250 krb5_error_code ret;
251 int32_t status;
252 krb5_storage *response;
254 if (response_p != NULL)
255 *response_p = NULL;
257 ret = kcm_send_request(context, k, request, &response_data);
258 if (ret) {
259 return ret;
262 response = krb5_storage_from_data(&response_data);
263 if (response == NULL) {
264 krb5_data_free(&response_data);
265 return KRB5_CC_IO;
268 ret = krb5_ret_int32(response, &status);
269 if (ret) {
270 krb5_storage_free(response);
271 krb5_data_free(&response_data);
272 return KRB5_CC_FORMAT;
275 if (status) {
276 krb5_storage_free(response);
277 krb5_data_free(&response_data);
278 return status;
281 if (response_p != NULL) {
282 *response_data_p = response_data;
283 *response_p = response;
285 return 0;
288 krb5_storage_free(response);
289 krb5_data_free(&response_data);
291 return 0;
294 static void
295 kcm_free(krb5_context context, krb5_ccache *id)
297 krb5_kcmcache *k = KCMCACHE(*id);
299 if (k != NULL) {
300 if (k->name != NULL)
301 free(k->name);
302 if (k->door_path)
303 free(k->door_path);
304 memset(k, 0, sizeof(*k));
305 krb5_data_free(&(*id)->data);
308 *id = NULL;
311 static const char *
312 kcm_get_name(krb5_context context,
313 krb5_ccache id)
315 return CACHENAME(id);
318 static krb5_error_code
319 kcm_resolve(krb5_context context, krb5_ccache *id, const char *res)
321 return kcm_alloc(context, res, id);
325 * Request:
327 * Response:
328 * NameZ
330 static krb5_error_code
331 kcm_gen_new(krb5_context context, krb5_ccache *id)
333 krb5_kcmcache *k;
334 krb5_error_code ret;
335 krb5_storage *request, *response;
336 krb5_data response_data;
338 ret = kcm_alloc(context, NULL, id);
339 if (ret)
340 return ret;
342 k = KCMCACHE(*id);
344 ret = kcm_storage_request(context, KCM_OP_GEN_NEW, &request);
345 if (ret) {
346 kcm_free(context, id);
347 return ret;
350 ret = kcm_call(context, k, request, &response, &response_data);
351 if (ret) {
352 krb5_storage_free(request);
353 kcm_free(context, id);
354 return ret;
357 ret = krb5_ret_stringz(response, &k->name);
358 if (ret)
359 ret = KRB5_CC_IO;
361 krb5_storage_free(request);
362 krb5_storage_free(response);
363 krb5_data_free(&response_data);
365 if (ret)
366 kcm_free(context, id);
368 return ret;
372 * Request:
373 * NameZ
374 * Principal
376 * Response:
379 static krb5_error_code
380 kcm_initialize(krb5_context context,
381 krb5_ccache id,
382 krb5_principal primary_principal)
384 krb5_error_code ret;
385 krb5_kcmcache *k = KCMCACHE(id);
386 krb5_storage *request;
388 ret = kcm_storage_request(context, KCM_OP_INITIALIZE, &request);
389 if (ret)
390 return ret;
392 ret = krb5_store_stringz(request, k->name);
393 if (ret) {
394 krb5_storage_free(request);
395 return ret;
398 ret = krb5_store_principal(request, primary_principal);
399 if (ret) {
400 krb5_storage_free(request);
401 return ret;
404 ret = kcm_call(context, k, request, NULL, NULL);
406 krb5_storage_free(request);
407 return ret;
410 static krb5_error_code
411 kcm_close(krb5_context context,
412 krb5_ccache id)
414 kcm_free(context, &id);
415 return 0;
419 * Request:
420 * NameZ
422 * Response:
425 static krb5_error_code
426 kcm_destroy(krb5_context context,
427 krb5_ccache id)
429 krb5_error_code ret;
430 krb5_kcmcache *k = KCMCACHE(id);
431 krb5_storage *request;
433 ret = kcm_storage_request(context, KCM_OP_DESTROY, &request);
434 if (ret)
435 return ret;
437 ret = krb5_store_stringz(request, k->name);
438 if (ret) {
439 krb5_storage_free(request);
440 return ret;
443 ret = kcm_call(context, k, request, NULL, NULL);
445 krb5_storage_free(request);
446 return ret;
450 * Request:
451 * NameZ
452 * Creds
454 * Response:
457 static krb5_error_code
458 kcm_store_cred(krb5_context context,
459 krb5_ccache id,
460 krb5_creds *creds)
462 krb5_error_code ret;
463 krb5_kcmcache *k = KCMCACHE(id);
464 krb5_storage *request;
466 ret = kcm_storage_request(context, KCM_OP_STORE, &request);
467 if (ret)
468 return ret;
470 ret = krb5_store_stringz(request, k->name);
471 if (ret) {
472 krb5_storage_free(request);
473 return ret;
476 ret = krb5_store_creds(request, creds);
477 if (ret) {
478 krb5_storage_free(request);
479 return ret;
482 ret = kcm_call(context, k, request, NULL, NULL);
484 krb5_storage_free(request);
485 return ret;
489 * Request:
490 * NameZ
491 * WhichFields
492 * MatchCreds
494 * Response:
495 * Creds
498 static krb5_error_code
499 kcm_retrieve(krb5_context context,
500 krb5_ccache id,
501 krb5_flags which,
502 const krb5_creds *mcred,
503 krb5_creds *creds)
505 krb5_error_code ret;
506 krb5_kcmcache *k = KCMCACHE(id);
507 krb5_storage *request, *response;
508 krb5_data response_data;
510 ret = kcm_storage_request(context, KCM_OP_RETRIEVE, &request);
511 if (ret)
512 return ret;
514 ret = krb5_store_stringz(request, k->name);
515 if (ret) {
516 krb5_storage_free(request);
517 return ret;
520 ret = krb5_store_int32(request, which);
521 if (ret) {
522 krb5_storage_free(request);
523 return ret;
526 ret = krb5_store_creds_tag(request, rk_UNCONST(mcred));
527 if (ret) {
528 krb5_storage_free(request);
529 return ret;
532 ret = kcm_call(context, k, request, &response, &response_data);
533 if (ret) {
534 krb5_storage_free(request);
535 return ret;
538 ret = krb5_ret_creds(response, creds);
539 if (ret)
540 ret = KRB5_CC_IO;
542 krb5_storage_free(request);
543 krb5_storage_free(response);
544 krb5_data_free(&response_data);
546 return ret;
550 * Request:
551 * NameZ
553 * Response:
554 * Principal
556 static krb5_error_code
557 kcm_get_principal(krb5_context context,
558 krb5_ccache id,
559 krb5_principal *principal)
561 krb5_error_code ret;
562 krb5_kcmcache *k = KCMCACHE(id);
563 krb5_storage *request, *response;
564 krb5_data response_data;
566 ret = kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request);
567 if (ret)
568 return ret;
570 ret = krb5_store_stringz(request, k->name);
571 if (ret) {
572 krb5_storage_free(request);
573 return ret;
576 ret = kcm_call(context, k, request, &response, &response_data);
577 if (ret) {
578 krb5_storage_free(request);
579 return ret;
582 ret = krb5_ret_principal(response, principal);
583 if (ret)
584 ret = KRB5_CC_IO;
586 krb5_storage_free(request);
587 krb5_storage_free(response);
588 krb5_data_free(&response_data);
590 return ret;
594 * Request:
595 * NameZ
597 * Response:
598 * Cursor
601 static krb5_error_code
602 kcm_get_first (krb5_context context,
603 krb5_ccache id,
604 krb5_cc_cursor *cursor)
606 krb5_error_code ret;
607 krb5_kcmcache *k = KCMCACHE(id);
608 krb5_storage *request, *response;
609 krb5_data response_data;
610 int32_t tmp;
612 ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request);
613 if (ret)
614 return ret;
616 ret = krb5_store_stringz(request, k->name);
617 if (ret) {
618 krb5_storage_free(request);
619 return ret;
622 ret = kcm_call(context, k, request, &response, &response_data);
623 if (ret) {
624 krb5_storage_free(request);
625 return ret;
628 ret = krb5_ret_int32(response, &tmp);
629 if (ret || tmp < 0)
630 ret = KRB5_CC_IO;
632 krb5_storage_free(request);
633 krb5_storage_free(response);
634 krb5_data_free(&response_data);
636 if (ret)
637 return ret;
639 *cursor = malloc(sizeof(tmp));
640 if (*cursor == NULL)
641 return KRB5_CC_NOMEM;
643 KCMCURSOR(*cursor) = tmp;
645 return 0;
649 * Request:
650 * NameZ
651 * Cursor
653 * Response:
654 * Creds
656 static krb5_error_code
657 kcm_get_next (krb5_context context,
658 krb5_ccache id,
659 krb5_cc_cursor *cursor,
660 krb5_creds *creds)
662 krb5_error_code ret;
663 krb5_kcmcache *k = KCMCACHE(id);
664 krb5_storage *request, *response;
665 krb5_data response_data;
667 ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request);
668 if (ret)
669 return ret;
671 ret = krb5_store_stringz(request, k->name);
672 if (ret) {
673 krb5_storage_free(request);
674 return ret;
677 ret = krb5_store_int32(request, KCMCURSOR(*cursor));
678 if (ret) {
679 krb5_storage_free(request);
680 return ret;
683 ret = kcm_call(context, k, request, &response, &response_data);
684 if (ret) {
685 krb5_storage_free(request);
686 return ret;
689 ret = krb5_ret_creds(response, creds);
690 if (ret)
691 ret = KRB5_CC_IO;
693 krb5_storage_free(request);
694 krb5_storage_free(response);
695 krb5_data_free(&response_data);
697 return ret;
701 * Request:
702 * NameZ
703 * Cursor
705 * Response:
708 static krb5_error_code
709 kcm_end_get (krb5_context context,
710 krb5_ccache id,
711 krb5_cc_cursor *cursor)
713 krb5_error_code ret;
714 krb5_kcmcache *k = KCMCACHE(id);
715 krb5_storage *request;
717 ret = kcm_storage_request(context, KCM_OP_END_GET, &request);
718 if (ret)
719 return ret;
721 ret = krb5_store_stringz(request, k->name);
722 if (ret) {
723 krb5_storage_free(request);
724 return ret;
727 ret = krb5_store_int32(request, KCMCURSOR(*cursor));
728 if (ret) {
729 krb5_storage_free(request);
730 return ret;
733 ret = kcm_call(context, k, request, NULL, NULL);
734 if (ret) {
735 krb5_storage_free(request);
736 return ret;
739 krb5_storage_free(request);
741 KCMCURSOR(*cursor) = 0;
742 free(*cursor);
743 *cursor = NULL;
745 return ret;
749 * Request:
750 * NameZ
751 * WhichFields
752 * MatchCreds
754 * Response:
757 static krb5_error_code
758 kcm_remove_cred(krb5_context context,
759 krb5_ccache id,
760 krb5_flags which,
761 krb5_creds *cred)
763 krb5_error_code ret;
764 krb5_kcmcache *k = KCMCACHE(id);
765 krb5_storage *request;
767 ret = kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request);
768 if (ret)
769 return ret;
771 ret = krb5_store_stringz(request, k->name);
772 if (ret) {
773 krb5_storage_free(request);
774 return ret;
777 ret = krb5_store_int32(request, which);
778 if (ret) {
779 krb5_storage_free(request);
780 return ret;
783 ret = krb5_store_creds_tag(request, cred);
784 if (ret) {
785 krb5_storage_free(request);
786 return ret;
789 ret = kcm_call(context, k, request, NULL, NULL);
791 krb5_storage_free(request);
792 return ret;
795 static krb5_error_code
796 kcm_set_flags(krb5_context context,
797 krb5_ccache id,
798 krb5_flags flags)
800 krb5_error_code ret;
801 krb5_kcmcache *k = KCMCACHE(id);
802 krb5_storage *request;
804 ret = kcm_storage_request(context, KCM_OP_SET_FLAGS, &request);
805 if (ret)
806 return ret;
808 ret = krb5_store_stringz(request, k->name);
809 if (ret) {
810 krb5_storage_free(request);
811 return ret;
814 ret = krb5_store_int32(request, flags);
815 if (ret) {
816 krb5_storage_free(request);
817 return ret;
820 ret = kcm_call(context, k, request, NULL, NULL);
822 krb5_storage_free(request);
823 return ret;
826 static krb5_error_code
827 kcm_get_version(krb5_context context,
828 krb5_ccache id)
830 return 0;
833 static krb5_error_code
834 kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to)
836 krb5_error_code ret;
837 krb5_kcmcache *oldk = KCMCACHE(from);
838 krb5_kcmcache *newk = KCMCACHE(to);
839 krb5_storage *request;
841 ret = kcm_storage_request(context, KCM_OP_MOVE_CACHE, &request);
842 if (ret)
843 return ret;
845 ret = krb5_store_stringz(request, oldk->name);
846 if (ret) {
847 krb5_storage_free(request);
848 return ret;
851 ret = krb5_store_stringz(request, newk->name);
852 if (ret) {
853 krb5_storage_free(request);
854 return ret;
856 ret = kcm_call(context, oldk, request, NULL, NULL);
858 krb5_storage_free(request);
859 return ret;
862 static krb5_error_code
863 kcm_default_name(krb5_context context, char **str)
865 return _krb5_expand_default_cc_name(context,
866 KRB5_DEFAULT_CCNAME_KCM,
867 str);
871 * Variable containing the KCM based credential cache implemention.
873 * @ingroup krb5_ccache
876 const krb5_cc_ops krb5_kcm_ops = {
877 KRB5_CC_OPS_VERSION,
878 "KCM",
879 kcm_get_name,
880 kcm_resolve,
881 kcm_gen_new,
882 kcm_initialize,
883 kcm_destroy,
884 kcm_close,
885 kcm_store_cred,
886 kcm_retrieve,
887 kcm_get_principal,
888 kcm_get_first,
889 kcm_get_next,
890 kcm_end_get,
891 kcm_remove_cred,
892 kcm_set_flags,
893 kcm_get_version,
894 NULL,
895 NULL,
896 NULL,
897 kcm_move,
898 kcm_default_name
901 krb5_boolean
902 _krb5_kcm_is_running(krb5_context context)
904 krb5_error_code ret;
905 krb5_ccache_data ccdata;
906 krb5_ccache id = &ccdata;
907 krb5_boolean running;
909 ret = kcm_alloc(context, NULL, &id);
910 if (ret)
911 return 0;
913 running = (_krb5_kcm_noop(context, id) == 0);
915 kcm_free(context, &id);
917 return running;
921 * Request:
923 * Response:
926 krb5_error_code
927 _krb5_kcm_noop(krb5_context context,
928 krb5_ccache id)
930 krb5_error_code ret;
931 krb5_kcmcache *k = KCMCACHE(id);
932 krb5_storage *request;
934 ret = kcm_storage_request(context, KCM_OP_NOOP, &request);
935 if (ret)
936 return ret;
938 ret = kcm_call(context, k, request, NULL, NULL);
940 krb5_storage_free(request);
941 return ret;
946 * Request:
947 * NameZ
948 * Mode
950 * Response:
953 krb5_error_code
954 _krb5_kcm_chmod(krb5_context context,
955 krb5_ccache id,
956 uint16_t mode)
958 krb5_error_code ret;
959 krb5_kcmcache *k = KCMCACHE(id);
960 krb5_storage *request;
962 ret = kcm_storage_request(context, KCM_OP_CHMOD, &request);
963 if (ret)
964 return ret;
966 ret = krb5_store_stringz(request, k->name);
967 if (ret) {
968 krb5_storage_free(request);
969 return ret;
972 ret = krb5_store_int16(request, mode);
973 if (ret) {
974 krb5_storage_free(request);
975 return ret;
978 ret = kcm_call(context, k, request, NULL, NULL);
980 krb5_storage_free(request);
981 return ret;
986 * Request:
987 * NameZ
988 * UID
989 * GID
991 * Response:
994 krb5_error_code
995 _krb5_kcm_chown(krb5_context context,
996 krb5_ccache id,
997 uint32_t uid,
998 uint32_t gid)
1000 krb5_error_code ret;
1001 krb5_kcmcache *k = KCMCACHE(id);
1002 krb5_storage *request;
1004 ret = kcm_storage_request(context, KCM_OP_CHOWN, &request);
1005 if (ret)
1006 return ret;
1008 ret = krb5_store_stringz(request, k->name);
1009 if (ret) {
1010 krb5_storage_free(request);
1011 return ret;
1014 ret = krb5_store_int32(request, uid);
1015 if (ret) {
1016 krb5_storage_free(request);
1017 return ret;
1020 ret = krb5_store_int32(request, gid);
1021 if (ret) {
1022 krb5_storage_free(request);
1023 return ret;
1026 ret = kcm_call(context, k, request, NULL, NULL);
1028 krb5_storage_free(request);
1029 return ret;
1034 * Request:
1035 * NameZ
1036 * ServerPrincipalPresent
1037 * ServerPrincipal OPTIONAL
1038 * Key
1040 * Repsonse:
1043 krb5_error_code
1044 _krb5_kcm_get_initial_ticket(krb5_context context,
1045 krb5_ccache id,
1046 krb5_principal server,
1047 krb5_keyblock *key)
1049 krb5_error_code ret;
1050 krb5_kcmcache *k = KCMCACHE(id);
1051 krb5_storage *request;
1053 ret = kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request);
1054 if (ret)
1055 return ret;
1057 ret = krb5_store_stringz(request, k->name);
1058 if (ret) {
1059 krb5_storage_free(request);
1060 return ret;
1063 ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
1064 if (ret) {
1065 krb5_storage_free(request);
1066 return ret;
1069 if (server != NULL) {
1070 ret = krb5_store_principal(request, server);
1071 if (ret) {
1072 krb5_storage_free(request);
1073 return ret;
1077 ret = krb5_store_keyblock(request, *key);
1078 if (ret) {
1079 krb5_storage_free(request);
1080 return ret;
1083 ret = kcm_call(context, k, request, NULL, NULL);
1085 krb5_storage_free(request);
1086 return ret;
1091 * Request:
1092 * NameZ
1093 * KDCFlags
1094 * EncryptionType
1095 * ServerPrincipal
1097 * Repsonse:
1100 krb5_error_code
1101 _krb5_kcm_get_ticket(krb5_context context,
1102 krb5_ccache id,
1103 krb5_kdc_flags flags,
1104 krb5_enctype enctype,
1105 krb5_principal server)
1107 krb5_error_code ret;
1108 krb5_kcmcache *k = KCMCACHE(id);
1109 krb5_storage *request;
1111 ret = kcm_storage_request(context, KCM_OP_GET_TICKET, &request);
1112 if (ret)
1113 return ret;
1115 ret = krb5_store_stringz(request, k->name);
1116 if (ret) {
1117 krb5_storage_free(request);
1118 return ret;
1121 ret = krb5_store_int32(request, flags.i);
1122 if (ret) {
1123 krb5_storage_free(request);
1124 return ret;
1127 ret = krb5_store_int32(request, enctype);
1128 if (ret) {
1129 krb5_storage_free(request);
1130 return ret;
1133 ret = krb5_store_principal(request, server);
1134 if (ret) {
1135 krb5_storage_free(request);
1136 return ret;
1139 ret = kcm_call(context, k, request, NULL, NULL);
1141 krb5_storage_free(request);
1142 return ret;
1145 #endif /* HAVE_KCM */