2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
35 #include <krb5_ccapi.h>
40 static HEIMDAL_MUTEX acc_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
41 static cc_initialize_func init_func
;
43 static void *cc_handle
;
46 typedef struct krb5_acc
{
52 static krb5_error_code
acc_close(krb5_context
, krb5_ccache
);
54 #define ACACHE(X) ((krb5_acc *)(X)->data.data)
60 { ccErrBadName
, KRB5_CC_BADNAME
},
61 { ccErrCredentialsNotFound
, KRB5_CC_NOTFOUND
},
62 { ccErrCCacheNotFound
, KRB5_FCC_NOFILE
},
63 { ccErrContextNotFound
, KRB5_CC_NOTFOUND
},
64 { ccIteratorEnd
, KRB5_CC_END
},
65 { ccErrNoMem
, KRB5_CC_NOMEM
},
66 { ccErrServerUnavailable
, KRB5_CC_NOSUPP
},
67 { ccErrInvalidCCache
, KRB5_CC_BADNAME
},
71 static krb5_error_code
72 translate_cc_error(krb5_context context
, cc_int32 error
)
75 krb5_clear_error_message(context
);
76 for(i
= 0; i
< sizeof(cc_errors
)/sizeof(cc_errors
[0]); i
++)
77 if (cc_errors
[i
].error
== error
)
78 return cc_errors
[i
].ret
;
79 return KRB5_FCC_INTERNAL
;
82 static krb5_error_code
83 init_ccapi(krb5_context context
)
87 HEIMDAL_MUTEX_lock(&acc_mutex
);
89 HEIMDAL_MUTEX_unlock(&acc_mutex
);
90 krb5_clear_error_message(context
);
94 lib
= krb5_config_get_string(context
, NULL
,
95 "libdefaults", "ccapi_library",
99 lib
= "/System/Library/Frameworks/Kerberos.framework/Kerberos";
101 lib
= "/usr/lib/libkrb5_cc.so";
111 cc_handle
= dlopen(lib
, RTLD_LAZY
);
112 if (cc_handle
== NULL
) {
113 HEIMDAL_MUTEX_unlock(&acc_mutex
);
114 krb5_set_error_message(context
, KRB5_CC_NOSUPP
,
115 N_("Failed to load API cache module %s", "file"),
117 return KRB5_CC_NOSUPP
;
120 init_func
= (cc_initialize_func
)dlsym(cc_handle
, "cc_initialize");
121 HEIMDAL_MUTEX_unlock(&acc_mutex
);
122 if (init_func
== NULL
) {
123 krb5_set_error_message(context
, KRB5_CC_NOSUPP
,
124 N_("Failed to find cc_initialize"
125 "in %s: %s", "file, error"), lib
, dlerror());
127 return KRB5_CC_NOSUPP
;
132 HEIMDAL_MUTEX_unlock(&acc_mutex
);
133 krb5_set_error_message(context
, KRB5_CC_NOSUPP
,
134 N_("no support for shared object", ""));
135 return KRB5_CC_NOSUPP
;
139 static krb5_error_code
140 make_cred_from_ccred(krb5_context context
,
141 const cc_credentials_v5_t
*incred
,
147 memset(cred
, 0, sizeof(*cred
));
149 ret
= krb5_parse_name(context
, incred
->client
, &cred
->client
);
153 ret
= krb5_parse_name(context
, incred
->server
, &cred
->server
);
157 cred
->session
.keytype
= incred
->keyblock
.type
;
158 cred
->session
.keyvalue
.length
= incred
->keyblock
.length
;
159 cred
->session
.keyvalue
.data
= malloc(incred
->keyblock
.length
);
160 if (cred
->session
.keyvalue
.data
== NULL
)
162 memcpy(cred
->session
.keyvalue
.data
, incred
->keyblock
.data
,
163 incred
->keyblock
.length
);
165 cred
->times
.authtime
= incred
->authtime
;
166 cred
->times
.starttime
= incred
->starttime
;
167 cred
->times
.endtime
= incred
->endtime
;
168 cred
->times
.renew_till
= incred
->renew_till
;
170 ret
= krb5_data_copy(&cred
->ticket
,
172 incred
->ticket
.length
);
176 ret
= krb5_data_copy(&cred
->second_ticket
,
177 incred
->second_ticket
.data
,
178 incred
->second_ticket
.length
);
182 cred
->authdata
.val
= NULL
;
183 cred
->authdata
.len
= 0;
185 cred
->addresses
.val
= NULL
;
186 cred
->addresses
.len
= 0;
188 for (i
= 0; incred
->authdata
&& incred
->authdata
[i
]; i
++)
192 cred
->authdata
.val
= calloc(i
, sizeof(cred
->authdata
.val
[0]));
193 if (cred
->authdata
.val
== NULL
)
195 cred
->authdata
.len
= i
;
196 for (i
= 0; i
< cred
->authdata
.len
; i
++) {
197 cred
->authdata
.val
[i
].ad_type
= incred
->authdata
[i
]->type
;
198 ret
= krb5_data_copy(&cred
->authdata
.val
[i
].ad_data
,
199 incred
->authdata
[i
]->data
,
200 incred
->authdata
[i
]->length
);
206 for (i
= 0; incred
->addresses
&& incred
->addresses
[i
]; i
++)
210 cred
->addresses
.val
= calloc(i
, sizeof(cred
->addresses
.val
[0]));
211 if (cred
->addresses
.val
== NULL
)
213 cred
->addresses
.len
= i
;
215 for (i
= 0; i
< cred
->addresses
.len
; i
++) {
216 cred
->addresses
.val
[i
].addr_type
= incred
->addresses
[i
]->type
;
217 ret
= krb5_data_copy(&cred
->addresses
.val
[i
].address
,
218 incred
->addresses
[i
]->data
,
219 incred
->addresses
[i
]->length
);
226 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_FORWARDABLE
)
227 cred
->flags
.b
.forwardable
= 1;
228 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_FORWARDED
)
229 cred
->flags
.b
.forwarded
= 1;
230 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_PROXIABLE
)
231 cred
->flags
.b
.proxiable
= 1;
232 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_PROXY
)
233 cred
->flags
.b
.proxy
= 1;
234 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_MAY_POSTDATE
)
235 cred
->flags
.b
.may_postdate
= 1;
236 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_POSTDATED
)
237 cred
->flags
.b
.postdated
= 1;
238 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_INVALID
)
239 cred
->flags
.b
.invalid
= 1;
240 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_RENEWABLE
)
241 cred
->flags
.b
.renewable
= 1;
242 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_INITIAL
)
243 cred
->flags
.b
.initial
= 1;
244 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_PRE_AUTH
)
245 cred
->flags
.b
.pre_authent
= 1;
246 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_HW_AUTH
)
247 cred
->flags
.b
.hw_authent
= 1;
248 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED
)
249 cred
->flags
.b
.transited_policy_checked
= 1;
250 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE
)
251 cred
->flags
.b
.ok_as_delegate
= 1;
252 if (incred
->ticket_flags
& KRB5_CCAPI_TKT_FLG_ANONYMOUS
)
253 cred
->flags
.b
.anonymous
= 1;
259 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", "malloc"));
262 krb5_free_cred_contents(context
, cred
);
267 free_ccred(cc_credentials_v5_t
*cred
)
271 if (cred
->addresses
) {
272 for (i
= 0; cred
->addresses
[i
] != 0; i
++) {
273 if (cred
->addresses
[i
]->data
)
274 free(cred
->addresses
[i
]->data
);
275 free(cred
->addresses
[i
]);
277 free(cred
->addresses
);
283 memset(cred
, 0, sizeof(*cred
));
286 static krb5_error_code
287 make_ccred_from_cred(krb5_context context
,
288 const krb5_creds
*incred
,
289 cc_credentials_v5_t
*cred
)
294 memset(cred
, 0, sizeof(*cred
));
296 ret
= krb5_unparse_name(context
, incred
->client
, &cred
->client
);
300 ret
= krb5_unparse_name(context
, incred
->server
, &cred
->server
);
304 cred
->keyblock
.type
= incred
->session
.keytype
;
305 cred
->keyblock
.length
= incred
->session
.keyvalue
.length
;
306 cred
->keyblock
.data
= incred
->session
.keyvalue
.data
;
308 cred
->authtime
= incred
->times
.authtime
;
309 cred
->starttime
= incred
->times
.starttime
;
310 cred
->endtime
= incred
->times
.endtime
;
311 cred
->renew_till
= incred
->times
.renew_till
;
313 cred
->ticket
.length
= incred
->ticket
.length
;
314 cred
->ticket
.data
= incred
->ticket
.data
;
316 cred
->second_ticket
.length
= incred
->second_ticket
.length
;
317 cred
->second_ticket
.data
= incred
->second_ticket
.data
;
319 /* XXX this one should also be filled in */
320 cred
->authdata
= NULL
;
322 cred
->addresses
= calloc(incred
->addresses
.len
+ 1,
323 sizeof(cred
->addresses
[0]));
324 if (cred
->addresses
== NULL
) {
330 for (i
= 0; i
< incred
->addresses
.len
; i
++) {
332 addr
= malloc(sizeof(*addr
));
337 addr
->type
= incred
->addresses
.val
[i
].addr_type
;
338 addr
->length
= incred
->addresses
.val
[i
].address
.length
;
339 addr
->data
= malloc(addr
->length
);
340 if (addr
->data
== NULL
) {
345 memcpy(addr
->data
, incred
->addresses
.val
[i
].address
.data
,
347 cred
->addresses
[i
] = addr
;
349 cred
->addresses
[i
] = NULL
;
351 cred
->ticket_flags
= 0;
352 if (incred
->flags
.b
.forwardable
)
353 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_FORWARDABLE
;
354 if (incred
->flags
.b
.forwarded
)
355 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_FORWARDED
;
356 if (incred
->flags
.b
.proxiable
)
357 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_PROXIABLE
;
358 if (incred
->flags
.b
.proxy
)
359 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_PROXY
;
360 if (incred
->flags
.b
.may_postdate
)
361 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE
;
362 if (incred
->flags
.b
.postdated
)
363 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_POSTDATED
;
364 if (incred
->flags
.b
.invalid
)
365 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_INVALID
;
366 if (incred
->flags
.b
.renewable
)
367 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_RENEWABLE
;
368 if (incred
->flags
.b
.initial
)
369 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_INITIAL
;
370 if (incred
->flags
.b
.pre_authent
)
371 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_PRE_AUTH
;
372 if (incred
->flags
.b
.hw_authent
)
373 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_HW_AUTH
;
374 if (incred
->flags
.b
.transited_policy_checked
)
375 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED
;
376 if (incred
->flags
.b
.ok_as_delegate
)
377 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE
;
378 if (incred
->flags
.b
.anonymous
)
379 cred
->ticket_flags
|= KRB5_CCAPI_TKT_FLG_ANONYMOUS
;
386 krb5_clear_error_message(context
);
391 get_cc_name(krb5_acc
*a
)
396 error
= (*a
->ccache
->func
->get_name
)(a
->ccache
, &name
);
400 a
->cache_name
= strdup(name
->data
);
401 (*name
->func
->release
)(name
);
402 if (a
->cache_name
== NULL
)
409 acc_get_name(krb5_context context
,
412 krb5_acc
*a
= ACACHE(id
);
415 if (a
->cache_name
== NULL
) {
417 krb5_principal principal
;
420 ret
= _krb5_get_default_principal_local(context
, &principal
);
424 ret
= krb5_unparse_name(context
, principal
, &name
);
425 krb5_free_principal(context
, principal
);
429 error
= (*a
->context
->func
->create_new_ccache
)(a
->context
,
437 error
= get_cc_name(a
);
442 return a
->cache_name
;
445 static krb5_error_code
446 acc_alloc(krb5_context context
, krb5_ccache
*id
)
452 ret
= init_ccapi(context
);
456 ret
= krb5_data_alloc(&(*id
)->data
, sizeof(*a
));
458 krb5_clear_error_message(context
);
464 error
= (*init_func
)(&a
->context
, ccapi_version_3
, NULL
, NULL
);
466 krb5_data_free(&(*id
)->data
);
467 return translate_cc_error(context
, error
);
470 a
->cache_name
= NULL
;
475 static krb5_error_code
476 acc_resolve(krb5_context context
, krb5_ccache
*id
, const char *res
)
482 ret
= acc_alloc(context
, id
);
488 error
= (*a
->context
->func
->open_ccache
)(a
->context
, res
, &a
->ccache
);
489 if (error
== ccNoError
) {
491 error
= get_cc_name(a
);
492 if (error
!= ccNoError
) {
493 acc_close(context
, *id
);
495 return translate_cc_error(context
, error
);
498 error
= (*a
->ccache
->func
->get_kdc_time_offset
)(a
->ccache
,
502 context
->kdc_sec_offset
= offset
;
504 } else if (error
== ccErrCCacheNotFound
) {
506 a
->cache_name
= NULL
;
509 return translate_cc_error(context
, error
);
515 static krb5_error_code
516 acc_gen_new(krb5_context context
, krb5_ccache
*id
)
521 ret
= acc_alloc(context
, id
);
528 a
->cache_name
= NULL
;
533 static krb5_error_code
534 acc_initialize(krb5_context context
,
536 krb5_principal primary_principal
)
538 krb5_acc
*a
= ACACHE(id
);
543 ret
= krb5_unparse_name(context
, primary_principal
, &name
);
547 if (a
->cache_name
== NULL
) {
548 error
= (*a
->context
->func
->create_new_ccache
)(a
->context
,
553 if (error
== ccNoError
)
554 error
= get_cc_name(a
);
556 cc_credentials_iterator_t iter
;
557 cc_credentials_t ccred
;
559 error
= (*a
->ccache
->func
->new_credentials_iterator
)(a
->ccache
, &iter
);
562 return translate_cc_error(context
, error
);
566 error
= (*iter
->func
->next
)(iter
, &ccred
);
569 (*a
->ccache
->func
->remove_credentials
)(a
->ccache
, ccred
);
570 (*ccred
->func
->release
)(ccred
);
572 (*iter
->func
->release
)(iter
);
574 error
= (*a
->ccache
->func
->set_principal
)(a
->ccache
,
579 if (error
== 0 && context
->kdc_sec_offset
)
580 error
= (*a
->ccache
->func
->set_kdc_time_offset
)(a
->ccache
,
582 context
->kdc_sec_offset
);
584 return translate_cc_error(context
, error
);
587 static krb5_error_code
588 acc_close(krb5_context context
,
591 krb5_acc
*a
= ACACHE(id
);
594 (*a
->ccache
->func
->release
)(a
->ccache
);
599 a
->cache_name
= NULL
;
602 (*a
->context
->func
->release
)(a
->context
);
605 krb5_data_free(&id
->data
);
609 static krb5_error_code
610 acc_destroy(krb5_context context
,
613 krb5_acc
*a
= ACACHE(id
);
617 error
= (*a
->ccache
->func
->destroy
)(a
->ccache
);
621 error
= (a
->context
->func
->release
)(a
->context
);
624 return translate_cc_error(context
, error
);
627 static krb5_error_code
628 acc_store_cred(krb5_context context
,
632 krb5_acc
*a
= ACACHE(id
);
633 cc_credentials_union cred
;
634 cc_credentials_v5_t v5cred
;
638 if (a
->ccache
== NULL
) {
639 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
640 N_("No API credential found", ""));
641 return KRB5_CC_NOTFOUND
;
644 cred
.version
= cc_credentials_v5
;
645 cred
.credentials
.credentials_v5
= &v5cred
;
647 ret
= make_ccred_from_cred(context
,
653 error
= (*a
->ccache
->func
->store_credentials
)(a
->ccache
, &cred
);
655 ret
= translate_cc_error(context
, error
);
662 static krb5_error_code
663 acc_get_principal(krb5_context context
,
665 krb5_principal
*principal
)
667 krb5_acc
*a
= ACACHE(id
);
672 if (a
->ccache
== NULL
) {
673 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
674 N_("No API credential found", ""));
675 return KRB5_CC_NOTFOUND
;
678 error
= (*a
->ccache
->func
->get_principal
)(a
->ccache
,
682 return translate_cc_error(context
, error
);
684 ret
= krb5_parse_name(context
, name
->data
, principal
);
686 (*name
->func
->release
)(name
);
690 static krb5_error_code
691 acc_get_first (krb5_context context
,
693 krb5_cc_cursor
*cursor
)
695 cc_credentials_iterator_t iter
;
696 krb5_acc
*a
= ACACHE(id
);
699 if (a
->ccache
== NULL
) {
700 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
701 N_("No API credential found", ""));
702 return KRB5_CC_NOTFOUND
;
705 error
= (*a
->ccache
->func
->new_credentials_iterator
)(a
->ccache
, &iter
);
707 krb5_clear_error_message(context
);
715 static krb5_error_code
716 acc_get_next (krb5_context context
,
718 krb5_cc_cursor
*cursor
,
721 cc_credentials_iterator_t iter
= *cursor
;
722 cc_credentials_t cred
;
727 error
= (*iter
->func
->next
)(iter
, &cred
);
729 return translate_cc_error(context
, error
);
730 if (cred
->data
->version
== cc_credentials_v5
)
732 (*cred
->func
->release
)(cred
);
735 ret
= make_cred_from_ccred(context
,
736 cred
->data
->credentials
.credentials_v5
,
738 (*cred
->func
->release
)(cred
);
742 static krb5_error_code
743 acc_end_get (krb5_context context
,
745 krb5_cc_cursor
*cursor
)
747 cc_credentials_iterator_t iter
= *cursor
;
748 (*iter
->func
->release
)(iter
);
752 static krb5_error_code
753 acc_remove_cred(krb5_context context
,
758 cc_credentials_iterator_t iter
;
759 krb5_acc
*a
= ACACHE(id
);
760 cc_credentials_t ccred
;
763 char *client
, *server
;
765 if (a
->ccache
== NULL
) {
766 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
767 N_("No API credential found", ""));
768 return KRB5_CC_NOTFOUND
;
772 ret
= krb5_unparse_name(context
, cred
->client
, &client
);
778 ret
= krb5_unparse_name(context
, cred
->server
, &server
);
784 error
= (*a
->ccache
->func
->new_credentials_iterator
)(a
->ccache
, &iter
);
788 return translate_cc_error(context
, error
);
791 ret
= KRB5_CC_NOTFOUND
;
793 cc_credentials_v5_t
*v5cred
;
795 error
= (*iter
->func
->next
)(iter
, &ccred
);
799 if (ccred
->data
->version
!= cc_credentials_v5
)
802 v5cred
= ccred
->data
->credentials
.credentials_v5
;
804 if (client
&& strcmp(v5cred
->client
, client
) != 0)
807 if (strcmp(v5cred
->server
, server
) != 0)
810 (*a
->ccache
->func
->remove_credentials
)(a
->ccache
, ccred
);
813 (*ccred
->func
->release
)(ccred
);
816 (*iter
->func
->release
)(iter
);
819 krb5_set_error_message(context
, ret
,
820 N_("Can't find credential %s in cache",
821 "principal"), server
);
828 static krb5_error_code
829 acc_set_flags(krb5_context context
,
837 acc_get_version(krb5_context context
,
844 cc_context_t context
;
845 cc_ccache_iterator_t iter
;
848 static krb5_error_code
849 acc_get_cache_first(krb5_context context
, krb5_cc_cursor
*cursor
)
851 struct cache_iter
*iter
;
855 ret
= init_ccapi(context
);
859 iter
= calloc(1, sizeof(*iter
));
861 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
865 error
= (*init_func
)(&iter
->context
, ccapi_version_3
, NULL
, NULL
);
868 return translate_cc_error(context
, error
);
871 error
= (*iter
->context
->func
->new_ccache_iterator
)(iter
->context
,
875 krb5_clear_error_message(context
);
882 static krb5_error_code
883 acc_get_cache_next(krb5_context context
, krb5_cc_cursor cursor
, krb5_ccache
*id
)
885 struct cache_iter
*iter
= cursor
;
891 error
= (*iter
->iter
->func
->next
)(iter
->iter
, &cache
);
893 return translate_cc_error(context
, error
);
895 ret
= _krb5_cc_allocate(context
, &krb5_acc_ops
, id
);
897 (*cache
->func
->release
)(cache
);
901 ret
= acc_alloc(context
, id
);
903 (*cache
->func
->release
)(cache
);
911 error
= get_cc_name(a
);
913 acc_close(context
, *id
);
915 return translate_cc_error(context
, error
);
920 static krb5_error_code
921 acc_end_cache_get(krb5_context context
, krb5_cc_cursor cursor
)
923 struct cache_iter
*iter
= cursor
;
925 (*iter
->iter
->func
->release
)(iter
->iter
);
927 (*iter
->context
->func
->release
)(iter
->context
);
928 iter
->context
= NULL
;
933 static krb5_error_code
934 acc_move(krb5_context context
, krb5_ccache from
, krb5_ccache to
)
936 krb5_acc
*afrom
= ACACHE(from
);
937 krb5_acc
*ato
= ACACHE(to
);
940 if (ato
->ccache
== NULL
) {
943 error
= (*afrom
->ccache
->func
->get_principal
)(afrom
->ccache
,
947 return translate_cc_error(context
, error
);
949 error
= (*ato
->context
->func
->create_new_ccache
)(ato
->context
,
953 (*name
->func
->release
)(name
);
955 return translate_cc_error(context
, error
);
958 error
= (*ato
->ccache
->func
->move
)(afrom
->ccache
, ato
->ccache
);
960 acc_destroy(context
, from
);
962 return translate_cc_error(context
, error
);
965 static krb5_error_code
966 acc_get_default_name(krb5_context context
, char **str
)
973 ret
= init_ccapi(context
);
977 error
= (*init_func
)(&cc
, ccapi_version_3
, NULL
, NULL
);
979 return translate_cc_error(context
, error
);
981 error
= (*cc
->func
->get_default_ccache_name
)(cc
, &name
);
983 (*cc
->func
->release
)(cc
);
984 return translate_cc_error(context
, error
);
987 asprintf(str
, "API:%s", name
->data
);
988 (*name
->func
->release
)(name
);
989 (*cc
->func
->release
)(cc
);
992 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
998 static krb5_error_code
999 acc_set_default(krb5_context context
, krb5_ccache id
)
1001 krb5_acc
*a
= ACACHE(id
);
1004 if (a
->ccache
== NULL
) {
1005 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
1006 N_("No API credential found", ""));
1007 return KRB5_CC_NOTFOUND
;
1010 error
= (*a
->ccache
->func
->set_default
)(a
->ccache
);
1012 return translate_cc_error(context
, error
);
1017 static krb5_error_code
1018 acc_lastchange(krb5_context context
, krb5_ccache id
, krb5_timestamp
*mtime
)
1020 krb5_acc
*a
= ACACHE(id
);
1024 if (a
->ccache
== NULL
) {
1025 krb5_set_error_message(context
, KRB5_CC_NOTFOUND
,
1026 N_("No API credential found", ""));
1027 return KRB5_CC_NOTFOUND
;
1030 error
= (*a
->ccache
->func
->get_change_time
)(a
->ccache
, &t
);
1032 return translate_cc_error(context
, error
);
1040 * Variable containing the API based credential cache implemention.
1042 * @ingroup krb5_ccache
1045 KRB5_LIB_VARIABLE
const krb5_cc_ops krb5_acc_ops
= {
1046 KRB5_CC_OPS_VERSION
,
1055 NULL
, /* acc_retrieve */
1063 acc_get_cache_first
,
1067 acc_get_default_name
,