turn off v4 conversion stuff
[heimdal.git] / lib / krb5 / kcm.c
blobc94dea551f865613cd2dbb233ecefb3d3485bbe2
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 typedef struct krb5_kcmcache {
47 char *name;
48 struct sockaddr_un path;
49 char *door_path;
50 } krb5_kcmcache;
52 typedef struct krb5_kcm_cursor {
53 unsigned long offset;
54 unsigned long length;
55 kcmuuid_t *uuids;
56 } *krb5_kcm_cursor;
59 #define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data)
60 #define CACHENAME(X) (KCMCACHE(X)->name)
61 #define KCMCURSOR(C) ((krb5_kcm_cursor)(C))
63 #ifdef HAVE_DOOR_CREATE
65 static krb5_error_code
66 try_door(krb5_context context,
67 krb5_kcmcache *k,
68 krb5_data *request_data,
69 krb5_data *response_data)
71 door_arg_t arg;
72 int fd;
73 int ret;
75 memset(&arg, 0, sizeof(arg));
77 fd = open(k->door_path, O_RDWR);
78 if (fd < 0)
79 return KRB5_CC_IO;
80 rk_cloexec(fd);
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;
89 ret = door_call(fd, &arg);
90 close(fd);
91 if (ret != 0)
92 return KRB5_CC_IO;
94 ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize);
95 munmap(arg.rbuf, arg.rsize);
96 if (ret)
97 return ret;
99 return 0;
101 #endif /* HAVE_DOOR_CREATE */
103 static krb5_error_code
104 try_unix_socket(krb5_context context,
105 krb5_kcmcache *k,
106 krb5_data *request_data,
107 krb5_data *response_data)
109 krb5_error_code ret;
110 int fd;
112 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
113 if (fd < 0)
114 return KRB5_CC_IO;
115 rk_cloexec(fd);
117 if (connect(fd, rk_UNCONST(&k->path), sizeof(k->path)) != 0) {
118 close(fd);
119 return KRB5_CC_IO;
122 ret = _krb5_send_and_recv_tcp(fd, context->kdc_timeout,
123 request_data, response_data);
124 close(fd);
125 return ret;
128 static krb5_error_code
129 kcm_send_request(krb5_context context,
130 krb5_kcmcache *k,
131 krb5_storage *request,
132 krb5_data *response_data)
134 krb5_error_code ret;
135 krb5_data request_data;
136 int i;
138 response_data->data = NULL;
139 response_data->length = 0;
141 ret = krb5_storage_to_data(request, &request_data);
142 if (ret) {
143 krb5_clear_error_message(context);
144 return KRB5_CC_NOMEM;
147 ret = KRB5_CC_NOSUPP;
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;
160 krb5_data_free(&request_data);
162 if (ret) {
163 krb5_clear_error_message(context);
164 ret = KRB5_CC_NOSUPP;
167 return ret;
170 static krb5_error_code
171 kcm_storage_request(krb5_context context,
172 kcm_operation opcode,
173 krb5_storage **storage_p)
175 krb5_storage *sp;
176 krb5_error_code ret;
178 *storage_p = NULL;
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;
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;
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);
205 return ret;
208 static krb5_error_code
209 kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
211 krb5_kcmcache *k;
212 const char *path;
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;
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;
229 } else
230 k->name = NULL;
232 path = krb5_config_get_string_default(context, NULL,
233 _PATH_KCM_SOCKET,
234 "libdefaults",
235 "kcm_socket",
236 NULL);
238 k->path.sun_family = AF_UNIX;
239 strlcpy(k->path.sun_path, path, sizeof(k->path.sun_path));
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);
248 (*id)->data.data = k;
249 (*id)->data.length = sizeof(*k);
251 return 0;
254 static krb5_error_code
255 kcm_call(krb5_context context,
256 krb5_kcmcache *k,
257 krb5_storage *request,
258 krb5_storage **response_p,
259 krb5_data *response_data_p)
261 krb5_data response_data;
262 krb5_error_code ret;
263 int32_t status;
264 krb5_storage *response;
266 if (response_p != NULL)
267 *response_p = NULL;
269 ret = kcm_send_request(context, k, request, &response_data);
270 if (ret) {
271 return ret;
274 response = krb5_storage_from_data(&response_data);
275 if (response == NULL) {
276 krb5_data_free(&response_data);
277 return KRB5_CC_IO;
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;
287 if (status) {
288 krb5_storage_free(response);
289 krb5_data_free(&response_data);
290 return status;
293 if (response_p != NULL) {
294 *response_data_p = response_data;
295 *response_p = response;
297 return 0;
300 krb5_storage_free(response);
301 krb5_data_free(&response_data);
303 return 0;
306 static void
307 kcm_free(krb5_context context, krb5_ccache *id)
309 krb5_kcmcache *k = KCMCACHE(*id);
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);
321 static const char *
322 kcm_get_name(krb5_context context,
323 krb5_ccache id)
325 return CACHENAME(id);
328 static krb5_error_code
329 kcm_resolve(krb5_context context, krb5_ccache *id, const char *res)
331 return kcm_alloc(context, res, id);
335 * Request:
337 * Response:
338 * NameZ
340 static krb5_error_code
341 kcm_gen_new(krb5_context context, krb5_ccache *id)
343 krb5_kcmcache *k;
344 krb5_error_code ret;
345 krb5_storage *request, *response;
346 krb5_data response_data;
348 ret = kcm_alloc(context, NULL, id);
349 if (ret)
350 return ret;
352 k = KCMCACHE(*id);
354 ret = kcm_storage_request(context, KCM_OP_GEN_NEW, &request);
355 if (ret) {
356 kcm_free(context, id);
357 return ret;
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;
367 ret = krb5_ret_stringz(response, &k->name);
368 if (ret)
369 ret = KRB5_CC_IO;
371 krb5_storage_free(request);
372 krb5_storage_free(response);
373 krb5_data_free(&response_data);
375 if (ret)
376 kcm_free(context, id);
378 return ret;
382 * Request:
383 * NameZ
384 * Principal
386 * Response:
389 static krb5_error_code
390 kcm_initialize(krb5_context context,
391 krb5_ccache id,
392 krb5_principal primary_principal)
394 krb5_error_code ret;
395 krb5_kcmcache *k = KCMCACHE(id);
396 krb5_storage *request;
398 ret = kcm_storage_request(context, KCM_OP_INITIALIZE, &request);
399 if (ret)
400 return ret;
402 ret = krb5_store_stringz(request, k->name);
403 if (ret) {
404 krb5_storage_free(request);
405 return ret;
408 ret = krb5_store_principal(request, primary_principal);
409 if (ret) {
410 krb5_storage_free(request);
411 return ret;
414 ret = kcm_call(context, k, request, NULL, NULL);
416 krb5_storage_free(request);
417 return ret;
420 static krb5_error_code
421 kcm_close(krb5_context context,
422 krb5_ccache id)
424 kcm_free(context, &id);
425 return 0;
429 * Request:
430 * NameZ
432 * Response:
435 static krb5_error_code
436 kcm_destroy(krb5_context context,
437 krb5_ccache id)
439 krb5_error_code ret;
440 krb5_kcmcache *k = KCMCACHE(id);
441 krb5_storage *request;
443 ret = kcm_storage_request(context, KCM_OP_DESTROY, &request);
444 if (ret)
445 return ret;
447 ret = krb5_store_stringz(request, k->name);
448 if (ret) {
449 krb5_storage_free(request);
450 return ret;
453 ret = kcm_call(context, k, request, NULL, NULL);
455 krb5_storage_free(request);
456 return ret;
460 * Request:
461 * NameZ
462 * Creds
464 * Response:
467 static krb5_error_code
468 kcm_store_cred(krb5_context context,
469 krb5_ccache id,
470 krb5_creds *creds)
472 krb5_error_code ret;
473 krb5_kcmcache *k = KCMCACHE(id);
474 krb5_storage *request;
476 ret = kcm_storage_request(context, KCM_OP_STORE, &request);
477 if (ret)
478 return ret;
480 ret = krb5_store_stringz(request, k->name);
481 if (ret) {
482 krb5_storage_free(request);
483 return ret;
486 ret = krb5_store_creds(request, creds);
487 if (ret) {
488 krb5_storage_free(request);
489 return ret;
492 ret = kcm_call(context, k, request, NULL, NULL);
494 krb5_storage_free(request);
495 return ret;
499 * Request:
500 * NameZ
501 * WhichFields
502 * MatchCreds
504 * Response:
505 * Creds
508 static krb5_error_code
509 kcm_retrieve(krb5_context context,
510 krb5_ccache id,
511 krb5_flags which,
512 const krb5_creds *mcred,
513 krb5_creds *creds)
515 krb5_error_code ret;
516 krb5_kcmcache *k = KCMCACHE(id);
517 krb5_storage *request, *response;
518 krb5_data response_data;
520 ret = kcm_storage_request(context, KCM_OP_RETRIEVE, &request);
521 if (ret)
522 return ret;
524 ret = krb5_store_stringz(request, k->name);
525 if (ret) {
526 krb5_storage_free(request);
527 return ret;
530 ret = krb5_store_int32(request, which);
531 if (ret) {
532 krb5_storage_free(request);
533 return ret;
536 ret = krb5_store_creds_tag(request, rk_UNCONST(mcred));
537 if (ret) {
538 krb5_storage_free(request);
539 return ret;
542 ret = kcm_call(context, k, request, &response, &response_data);
543 if (ret) {
544 krb5_storage_free(request);
545 return ret;
548 ret = krb5_ret_creds(response, creds);
549 if (ret)
550 ret = KRB5_CC_IO;
552 krb5_storage_free(request);
553 krb5_storage_free(response);
554 krb5_data_free(&response_data);
556 return ret;
560 * Request:
561 * NameZ
563 * Response:
564 * Principal
566 static krb5_error_code
567 kcm_get_principal(krb5_context context,
568 krb5_ccache id,
569 krb5_principal *principal)
571 krb5_error_code ret;
572 krb5_kcmcache *k = KCMCACHE(id);
573 krb5_storage *request, *response;
574 krb5_data response_data;
576 ret = kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request);
577 if (ret)
578 return ret;
580 ret = krb5_store_stringz(request, k->name);
581 if (ret) {
582 krb5_storage_free(request);
583 return ret;
586 ret = kcm_call(context, k, request, &response, &response_data);
587 if (ret) {
588 krb5_storage_free(request);
589 return ret;
592 ret = krb5_ret_principal(response, principal);
593 if (ret)
594 ret = KRB5_CC_IO;
596 krb5_storage_free(request);
597 krb5_storage_free(response);
598 krb5_data_free(&response_data);
600 return ret;
604 * Request:
605 * NameZ
607 * Response:
608 * Cursor
611 static krb5_error_code
612 kcm_get_first (krb5_context context,
613 krb5_ccache id,
614 krb5_cc_cursor *cursor)
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;
622 ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request);
623 if (ret)
624 return ret;
626 ret = krb5_store_stringz(request, k->name);
627 if (ret) {
628 krb5_storage_free(request);
629 return ret;
632 ret = kcm_call(context, k, request, &response, &response_data);
633 krb5_storage_free(request);
634 if (ret)
635 return ret;
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;
645 while (1) {
646 ssize_t sret;
647 kcmuuid_t uuid;
648 void *ptr;
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;
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;
667 c->uuids = ptr;
669 memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
670 c->length += 1;
673 krb5_storage_free(response);
674 krb5_data_free(&response_data);
676 if (ret) {
677 free(c->uuids);
678 free(c);
679 return ret;
682 *cursor = c;
684 return 0;
688 * Request:
689 * NameZ
690 * Cursor
692 * Response:
693 * Creds
695 static krb5_error_code
696 kcm_get_next (krb5_context context,
697 krb5_ccache id,
698 krb5_cc_cursor *cursor,
699 krb5_creds *creds)
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;
708 again:
710 if (c->offset >= c->length)
711 return KRB5_CC_END;
713 ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request);
714 if (ret)
715 return ret;
717 ret = krb5_store_stringz(request, k->name);
718 if (ret) {
719 krb5_storage_free(request);
720 return ret;
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;
733 ret = kcm_call(context, k, request, &response, &response_data);
734 krb5_storage_free(request);
735 if (ret == KRB5_CC_END) {
736 goto again;
739 ret = krb5_ret_creds(response, creds);
740 if (ret)
741 ret = KRB5_CC_IO;
743 krb5_storage_free(response);
744 krb5_data_free(&response_data);
746 return ret;
750 * Request:
751 * NameZ
752 * Cursor
754 * Response:
757 static krb5_error_code
758 kcm_end_get (krb5_context context,
759 krb5_ccache id,
760 krb5_cc_cursor *cursor)
762 krb5_error_code ret;
763 krb5_kcmcache *k = KCMCACHE(id);
764 krb5_kcm_cursor c = KCMCURSOR(*cursor);
765 krb5_storage *request;
767 ret = kcm_storage_request(context, KCM_OP_END_GET, &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 = kcm_call(context, k, request, NULL, NULL);
778 krb5_storage_free(request);
779 if (ret)
780 return ret;
782 free(c->uuids);
783 free(c);
785 *cursor = NULL;
787 return ret;
791 * Request:
792 * NameZ
793 * WhichFields
794 * MatchCreds
796 * Response:
799 static krb5_error_code
800 kcm_remove_cred(krb5_context context,
801 krb5_ccache id,
802 krb5_flags which,
803 krb5_creds *cred)
805 krb5_error_code ret;
806 krb5_kcmcache *k = KCMCACHE(id);
807 krb5_storage *request;
809 ret = kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request);
810 if (ret)
811 return ret;
813 ret = krb5_store_stringz(request, k->name);
814 if (ret) {
815 krb5_storage_free(request);
816 return ret;
819 ret = krb5_store_int32(request, which);
820 if (ret) {
821 krb5_storage_free(request);
822 return ret;
825 ret = krb5_store_creds_tag(request, cred);
826 if (ret) {
827 krb5_storage_free(request);
828 return ret;
831 ret = kcm_call(context, k, request, NULL, NULL);
833 krb5_storage_free(request);
834 return ret;
837 static krb5_error_code
838 kcm_set_flags(krb5_context context,
839 krb5_ccache id,
840 krb5_flags flags)
842 krb5_error_code ret;
843 krb5_kcmcache *k = KCMCACHE(id);
844 krb5_storage *request;
846 ret = kcm_storage_request(context, KCM_OP_SET_FLAGS, &request);
847 if (ret)
848 return ret;
850 ret = krb5_store_stringz(request, k->name);
851 if (ret) {
852 krb5_storage_free(request);
853 return ret;
856 ret = krb5_store_int32(request, flags);
857 if (ret) {
858 krb5_storage_free(request);
859 return ret;
862 ret = kcm_call(context, k, request, NULL, NULL);
864 krb5_storage_free(request);
865 return ret;
868 static int
869 kcm_get_version(krb5_context context,
870 krb5_ccache id)
872 return 0;
875 static krb5_error_code
876 kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to)
878 krb5_error_code ret;
879 krb5_kcmcache *oldk = KCMCACHE(from);
880 krb5_kcmcache *newk = KCMCACHE(to);
881 krb5_storage *request;
883 ret = kcm_storage_request(context, KCM_OP_MOVE_CACHE, &request);
884 if (ret)
885 return ret;
887 ret = krb5_store_stringz(request, oldk->name);
888 if (ret) {
889 krb5_storage_free(request);
890 return ret;
893 ret = krb5_store_stringz(request, newk->name);
894 if (ret) {
895 krb5_storage_free(request);
896 return ret;
898 ret = kcm_call(context, oldk, request, NULL, NULL);
900 krb5_storage_free(request);
901 return ret;
904 static krb5_error_code
905 kcm_default_name(krb5_context context, char **str)
907 return _krb5_expand_default_cc_name(context,
908 KRB5_DEFAULT_CCNAME_KCM,
909 str);
912 static krb5_error_code
913 kcm_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
915 *mtime = time(NULL);
916 return 0;
920 * Variable containing the KCM based credential cache implemention.
922 * @ingroup krb5_ccache
925 KRB5_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
952 krb5_boolean
953 _krb5_kcm_is_running(krb5_context context)
955 krb5_error_code ret;
956 krb5_ccache_data ccdata;
957 krb5_ccache id = &ccdata;
958 krb5_boolean running;
960 ret = kcm_alloc(context, NULL, &id);
961 if (ret)
962 return 0;
964 running = (_krb5_kcm_noop(context, id) == 0);
966 kcm_free(context, &id);
968 return running;
972 * Request:
974 * Response:
977 krb5_error_code
978 _krb5_kcm_noop(krb5_context context,
979 krb5_ccache id)
981 krb5_error_code ret;
982 krb5_kcmcache *k = KCMCACHE(id);
983 krb5_storage *request;
985 ret = kcm_storage_request(context, KCM_OP_NOOP, &request);
986 if (ret)
987 return ret;
989 ret = kcm_call(context, k, request, NULL, NULL);
991 krb5_storage_free(request);
992 return ret;
997 * Request:
998 * NameZ
999 * Mode
1001 * Response:
1004 krb5_error_code
1005 _krb5_kcm_chmod(krb5_context context,
1006 krb5_ccache id,
1007 uint16_t mode)
1009 krb5_error_code ret;
1010 krb5_kcmcache *k = KCMCACHE(id);
1011 krb5_storage *request;
1013 ret = kcm_storage_request(context, KCM_OP_CHMOD, &request);
1014 if (ret)
1015 return ret;
1017 ret = krb5_store_stringz(request, k->name);
1018 if (ret) {
1019 krb5_storage_free(request);
1020 return ret;
1023 ret = krb5_store_int16(request, mode);
1024 if (ret) {
1025 krb5_storage_free(request);
1026 return ret;
1029 ret = kcm_call(context, k, request, NULL, NULL);
1031 krb5_storage_free(request);
1032 return ret;
1037 * Request:
1038 * NameZ
1039 * UID
1040 * GID
1042 * Response:
1045 krb5_error_code
1046 _krb5_kcm_chown(krb5_context context,
1047 krb5_ccache id,
1048 uint32_t uid,
1049 uint32_t gid)
1051 krb5_error_code ret;
1052 krb5_kcmcache *k = KCMCACHE(id);
1053 krb5_storage *request;
1055 ret = kcm_storage_request(context, KCM_OP_CHOWN, &request);
1056 if (ret)
1057 return ret;
1059 ret = krb5_store_stringz(request, k->name);
1060 if (ret) {
1061 krb5_storage_free(request);
1062 return ret;
1065 ret = krb5_store_int32(request, uid);
1066 if (ret) {
1067 krb5_storage_free(request);
1068 return ret;
1071 ret = krb5_store_int32(request, gid);
1072 if (ret) {
1073 krb5_storage_free(request);
1074 return ret;
1077 ret = kcm_call(context, k, request, NULL, NULL);
1079 krb5_storage_free(request);
1080 return ret;
1085 * Request:
1086 * NameZ
1087 * ServerPrincipalPresent
1088 * ServerPrincipal OPTIONAL
1089 * Key
1091 * Repsonse:
1094 krb5_error_code
1095 _krb5_kcm_get_initial_ticket(krb5_context context,
1096 krb5_ccache id,
1097 krb5_principal server,
1098 krb5_keyblock *key)
1100 krb5_kcmcache *k = KCMCACHE(id);
1101 krb5_error_code ret;
1102 krb5_storage *request;
1104 ret = kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request);
1105 if (ret)
1106 return ret;
1108 ret = krb5_store_stringz(request, k->name);
1109 if (ret) {
1110 krb5_storage_free(request);
1111 return ret;
1114 ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
1115 if (ret) {
1116 krb5_storage_free(request);
1117 return ret;
1120 if (server != NULL) {
1121 ret = krb5_store_principal(request, server);
1122 if (ret) {
1123 krb5_storage_free(request);
1124 return ret;
1128 ret = krb5_store_keyblock(request, *key);
1129 if (ret) {
1130 krb5_storage_free(request);
1131 return ret;
1134 ret = kcm_call(context, k, request, NULL, NULL);
1136 krb5_storage_free(request);
1137 return ret;
1142 * Request:
1143 * NameZ
1144 * KDCFlags
1145 * EncryptionType
1146 * ServerPrincipal
1148 * Repsonse:
1151 krb5_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)
1158 krb5_error_code ret;
1159 krb5_kcmcache *k = KCMCACHE(id);
1160 krb5_storage *request;
1162 ret = kcm_storage_request(context, KCM_OP_GET_TICKET, &request);
1163 if (ret)
1164 return ret;
1166 ret = krb5_store_stringz(request, k->name);
1167 if (ret) {
1168 krb5_storage_free(request);
1169 return ret;
1172 ret = krb5_store_int32(request, flags.i);
1173 if (ret) {
1174 krb5_storage_free(request);
1175 return ret;
1178 ret = krb5_store_int32(request, enctype);
1179 if (ret) {
1180 krb5_storage_free(request);
1181 return ret;
1184 ret = krb5_store_principal(request, server);
1185 if (ret) {
1186 krb5_storage_free(request);
1187 return ret;
1190 ret = kcm_call(context, k, request, NULL, NULL);
1192 krb5_storage_free(request);
1193 return ret;
1196 #endif /* HAVE_KCM */