1178825Sdfr/* 2178825Sdfr * Copyright (c) 2005, PADL Software Pty Ltd. 3178825Sdfr * All rights reserved. 4178825Sdfr * 5233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6233294Sstas * 7178825Sdfr * Redistribution and use in source and binary forms, with or without 8178825Sdfr * modification, are permitted provided that the following conditions 9178825Sdfr * are met: 10178825Sdfr * 11178825Sdfr * 1. Redistributions of source code must retain the above copyright 12178825Sdfr * notice, this list of conditions and the following disclaimer. 13178825Sdfr * 14178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 15178825Sdfr * notice, this list of conditions and the following disclaimer in the 16178825Sdfr * documentation and/or other materials provided with the distribution. 17178825Sdfr * 18178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors 19178825Sdfr * may be used to endorse or promote products derived from this software 20178825Sdfr * without specific prior written permission. 21178825Sdfr * 22178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32178825Sdfr * SUCH DAMAGE. 33178825Sdfr */ 34178825Sdfr 35178825Sdfr#include "krb5_locl.h" 36178825Sdfr 37178825Sdfr#ifdef HAVE_KCM 38178825Sdfr/* 39178825Sdfr * Client library for Kerberos Credentials Manager (KCM) daemon 40178825Sdfr */ 41178825Sdfr 42178825Sdfr#include "kcm.h" 43233294Sstas#include <heim-ipc.h> 44178825Sdfr 45233294Sstasstatic krb5_error_code 46233294Sstaskcm_set_kdc_offset(krb5_context, krb5_ccache, krb5_deltat); 47178825Sdfr 48233294Sstasstatic const char *kcm_ipc_name = "ANY:org.h5l.kcm"; 49233294Sstas 50178825Sdfrtypedef struct krb5_kcmcache { 51178825Sdfr char *name; 52178825Sdfr} krb5_kcmcache; 53178825Sdfr 54233294Sstastypedef struct krb5_kcm_cursor { 55233294Sstas unsigned long offset; 56233294Sstas unsigned long length; 57233294Sstas kcmuuid_t *uuids; 58233294Sstas} *krb5_kcm_cursor; 59233294Sstas 60233294Sstas 61178825Sdfr#define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data) 62178825Sdfr#define CACHENAME(X) (KCMCACHE(X)->name) 63233294Sstas#define KCMCURSOR(C) ((krb5_kcm_cursor)(C)) 64178825Sdfr 65233294Sstasstatic HEIMDAL_MUTEX kcm_mutex = HEIMDAL_MUTEX_INITIALIZER; 66233294Sstasstatic heim_ipc kcm_ipc = NULL; 67178825Sdfr 68178825Sdfrstatic krb5_error_code 69178825Sdfrkcm_send_request(krb5_context context, 70178825Sdfr krb5_storage *request, 71178825Sdfr krb5_data *response_data) 72178825Sdfr{ 73233294Sstas krb5_error_code ret = 0; 74178825Sdfr krb5_data request_data; 75178825Sdfr 76233294Sstas HEIMDAL_MUTEX_lock(&kcm_mutex); 77233294Sstas if (kcm_ipc == NULL) 78233294Sstas ret = heim_ipc_init_context(kcm_ipc_name, &kcm_ipc); 79233294Sstas HEIMDAL_MUTEX_unlock(&kcm_mutex); 80233294Sstas if (ret) 81233294Sstas return KRB5_CC_NOSUPP; 82178825Sdfr 83178825Sdfr ret = krb5_storage_to_data(request, &request_data); 84178825Sdfr if (ret) { 85233294Sstas krb5_clear_error_message(context); 86178825Sdfr return KRB5_CC_NOMEM; 87178825Sdfr } 88178825Sdfr 89233294Sstas ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL); 90178825Sdfr krb5_data_free(&request_data); 91178825Sdfr 92178825Sdfr if (ret) { 93233294Sstas krb5_clear_error_message(context); 94233294Sstas ret = KRB5_CC_NOSUPP; 95178825Sdfr } 96178825Sdfr 97178825Sdfr return ret; 98178825Sdfr} 99178825Sdfr 100233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 101233294Sstaskrb5_kcm_storage_request(krb5_context context, 102233294Sstas uint16_t opcode, 103233294Sstas krb5_storage **storage_p) 104178825Sdfr{ 105178825Sdfr krb5_storage *sp; 106178825Sdfr krb5_error_code ret; 107178825Sdfr 108178825Sdfr *storage_p = NULL; 109178825Sdfr 110178825Sdfr sp = krb5_storage_emem(); 111178825Sdfr if (sp == NULL) { 112233294Sstas krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", "")); 113178825Sdfr return KRB5_CC_NOMEM; 114178825Sdfr } 115178825Sdfr 116178825Sdfr /* Send MAJOR | VERSION | OPCODE */ 117178825Sdfr ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR); 118178825Sdfr if (ret) 119178825Sdfr goto fail; 120178825Sdfr ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR); 121178825Sdfr if (ret) 122178825Sdfr goto fail; 123178825Sdfr ret = krb5_store_int16(sp, opcode); 124178825Sdfr if (ret) 125178825Sdfr goto fail; 126178825Sdfr 127178825Sdfr *storage_p = sp; 128178825Sdfr fail: 129178825Sdfr if (ret) { 130233294Sstas krb5_set_error_message(context, ret, 131233294Sstas N_("Failed to encode KCM request", "")); 132178825Sdfr krb5_storage_free(sp); 133178825Sdfr } 134233294Sstas 135233294Sstas return ret; 136178825Sdfr} 137178825Sdfr 138178825Sdfrstatic krb5_error_code 139178825Sdfrkcm_alloc(krb5_context context, const char *name, krb5_ccache *id) 140178825Sdfr{ 141178825Sdfr krb5_kcmcache *k; 142178825Sdfr 143178825Sdfr k = malloc(sizeof(*k)); 144178825Sdfr if (k == NULL) { 145233294Sstas krb5_set_error_message(context, KRB5_CC_NOMEM, 146233294Sstas N_("malloc: out of memory", "")); 147178825Sdfr return KRB5_CC_NOMEM; 148178825Sdfr } 149178825Sdfr 150178825Sdfr if (name != NULL) { 151178825Sdfr k->name = strdup(name); 152178825Sdfr if (k->name == NULL) { 153178825Sdfr free(k); 154233294Sstas krb5_set_error_message(context, KRB5_CC_NOMEM, 155233294Sstas N_("malloc: out of memory", "")); 156178825Sdfr return KRB5_CC_NOMEM; 157178825Sdfr } 158178825Sdfr } else 159178825Sdfr k->name = NULL; 160178825Sdfr 161178825Sdfr (*id)->data.data = k; 162178825Sdfr (*id)->data.length = sizeof(*k); 163178825Sdfr 164178825Sdfr return 0; 165178825Sdfr} 166178825Sdfr 167233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 168233294Sstaskrb5_kcm_call(krb5_context context, 169233294Sstas krb5_storage *request, 170233294Sstas krb5_storage **response_p, 171233294Sstas krb5_data *response_data_p) 172178825Sdfr{ 173178825Sdfr krb5_data response_data; 174178825Sdfr krb5_error_code ret; 175178825Sdfr int32_t status; 176178825Sdfr krb5_storage *response; 177178825Sdfr 178178825Sdfr if (response_p != NULL) 179178825Sdfr *response_p = NULL; 180178825Sdfr 181233294Sstas krb5_data_zero(&response_data); 182233294Sstas 183233294Sstas ret = kcm_send_request(context, request, &response_data); 184233294Sstas if (ret) 185178825Sdfr return ret; 186178825Sdfr 187178825Sdfr response = krb5_storage_from_data(&response_data); 188178825Sdfr if (response == NULL) { 189178825Sdfr krb5_data_free(&response_data); 190178825Sdfr return KRB5_CC_IO; 191178825Sdfr } 192178825Sdfr 193178825Sdfr ret = krb5_ret_int32(response, &status); 194178825Sdfr if (ret) { 195178825Sdfr krb5_storage_free(response); 196178825Sdfr krb5_data_free(&response_data); 197178825Sdfr return KRB5_CC_FORMAT; 198178825Sdfr } 199178825Sdfr 200178825Sdfr if (status) { 201178825Sdfr krb5_storage_free(response); 202178825Sdfr krb5_data_free(&response_data); 203178825Sdfr return status; 204178825Sdfr } 205178825Sdfr 206178825Sdfr if (response_p != NULL) { 207178825Sdfr *response_data_p = response_data; 208178825Sdfr *response_p = response; 209178825Sdfr 210178825Sdfr return 0; 211178825Sdfr } 212178825Sdfr 213178825Sdfr krb5_storage_free(response); 214178825Sdfr krb5_data_free(&response_data); 215178825Sdfr 216178825Sdfr return 0; 217178825Sdfr} 218178825Sdfr 219178825Sdfrstatic void 220178825Sdfrkcm_free(krb5_context context, krb5_ccache *id) 221178825Sdfr{ 222178825Sdfr krb5_kcmcache *k = KCMCACHE(*id); 223178825Sdfr 224178825Sdfr if (k != NULL) { 225178825Sdfr if (k->name != NULL) 226178825Sdfr free(k->name); 227178825Sdfr memset(k, 0, sizeof(*k)); 228178825Sdfr krb5_data_free(&(*id)->data); 229178825Sdfr } 230178825Sdfr} 231178825Sdfr 232178825Sdfrstatic const char * 233178825Sdfrkcm_get_name(krb5_context context, 234178825Sdfr krb5_ccache id) 235178825Sdfr{ 236178825Sdfr return CACHENAME(id); 237178825Sdfr} 238178825Sdfr 239178825Sdfrstatic krb5_error_code 240178825Sdfrkcm_resolve(krb5_context context, krb5_ccache *id, const char *res) 241178825Sdfr{ 242178825Sdfr return kcm_alloc(context, res, id); 243178825Sdfr} 244178825Sdfr 245178825Sdfr/* 246178825Sdfr * Request: 247178825Sdfr * 248178825Sdfr * Response: 249178825Sdfr * NameZ 250178825Sdfr */ 251178825Sdfrstatic krb5_error_code 252178825Sdfrkcm_gen_new(krb5_context context, krb5_ccache *id) 253178825Sdfr{ 254178825Sdfr krb5_kcmcache *k; 255178825Sdfr krb5_error_code ret; 256178825Sdfr krb5_storage *request, *response; 257178825Sdfr krb5_data response_data; 258178825Sdfr 259178825Sdfr ret = kcm_alloc(context, NULL, id); 260178825Sdfr if (ret) 261178825Sdfr return ret; 262178825Sdfr 263178825Sdfr k = KCMCACHE(*id); 264178825Sdfr 265233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GEN_NEW, &request); 266178825Sdfr if (ret) { 267178825Sdfr kcm_free(context, id); 268178825Sdfr return ret; 269178825Sdfr } 270178825Sdfr 271233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 272178825Sdfr if (ret) { 273178825Sdfr krb5_storage_free(request); 274178825Sdfr kcm_free(context, id); 275178825Sdfr return ret; 276178825Sdfr } 277178825Sdfr 278178825Sdfr ret = krb5_ret_stringz(response, &k->name); 279178825Sdfr if (ret) 280178825Sdfr ret = KRB5_CC_IO; 281178825Sdfr 282178825Sdfr krb5_storage_free(request); 283178825Sdfr krb5_storage_free(response); 284178825Sdfr krb5_data_free(&response_data); 285178825Sdfr 286178825Sdfr if (ret) 287178825Sdfr kcm_free(context, id); 288178825Sdfr 289178825Sdfr return ret; 290178825Sdfr} 291178825Sdfr 292178825Sdfr/* 293178825Sdfr * Request: 294178825Sdfr * NameZ 295178825Sdfr * Principal 296178825Sdfr * 297178825Sdfr * Response: 298178825Sdfr * 299178825Sdfr */ 300178825Sdfrstatic krb5_error_code 301178825Sdfrkcm_initialize(krb5_context context, 302178825Sdfr krb5_ccache id, 303178825Sdfr krb5_principal primary_principal) 304178825Sdfr{ 305178825Sdfr krb5_error_code ret; 306178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 307178825Sdfr krb5_storage *request; 308178825Sdfr 309233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_INITIALIZE, &request); 310178825Sdfr if (ret) 311178825Sdfr return ret; 312178825Sdfr 313178825Sdfr ret = krb5_store_stringz(request, k->name); 314178825Sdfr if (ret) { 315178825Sdfr krb5_storage_free(request); 316178825Sdfr return ret; 317178825Sdfr } 318178825Sdfr 319178825Sdfr ret = krb5_store_principal(request, primary_principal); 320178825Sdfr if (ret) { 321178825Sdfr krb5_storage_free(request); 322178825Sdfr return ret; 323178825Sdfr } 324178825Sdfr 325233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 326178825Sdfr 327178825Sdfr krb5_storage_free(request); 328233294Sstas 329233294Sstas if (context->kdc_sec_offset) 330233294Sstas kcm_set_kdc_offset(context, id, context->kdc_sec_offset); 331233294Sstas 332178825Sdfr return ret; 333178825Sdfr} 334178825Sdfr 335178825Sdfrstatic krb5_error_code 336178825Sdfrkcm_close(krb5_context context, 337178825Sdfr krb5_ccache id) 338178825Sdfr{ 339178825Sdfr kcm_free(context, &id); 340178825Sdfr return 0; 341178825Sdfr} 342178825Sdfr 343178825Sdfr/* 344178825Sdfr * Request: 345178825Sdfr * NameZ 346178825Sdfr * 347178825Sdfr * Response: 348178825Sdfr * 349178825Sdfr */ 350178825Sdfrstatic krb5_error_code 351178825Sdfrkcm_destroy(krb5_context context, 352178825Sdfr krb5_ccache id) 353178825Sdfr{ 354178825Sdfr krb5_error_code ret; 355178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 356178825Sdfr krb5_storage *request; 357178825Sdfr 358233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_DESTROY, &request); 359178825Sdfr if (ret) 360178825Sdfr return ret; 361178825Sdfr 362178825Sdfr ret = krb5_store_stringz(request, k->name); 363178825Sdfr if (ret) { 364178825Sdfr krb5_storage_free(request); 365178825Sdfr return ret; 366178825Sdfr } 367178825Sdfr 368233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 369178825Sdfr 370178825Sdfr krb5_storage_free(request); 371178825Sdfr return ret; 372178825Sdfr} 373178825Sdfr 374178825Sdfr/* 375178825Sdfr * Request: 376178825Sdfr * NameZ 377178825Sdfr * Creds 378178825Sdfr * 379178825Sdfr * Response: 380178825Sdfr * 381178825Sdfr */ 382178825Sdfrstatic krb5_error_code 383178825Sdfrkcm_store_cred(krb5_context context, 384178825Sdfr krb5_ccache id, 385178825Sdfr krb5_creds *creds) 386178825Sdfr{ 387178825Sdfr krb5_error_code ret; 388178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 389178825Sdfr krb5_storage *request; 390178825Sdfr 391233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_STORE, &request); 392178825Sdfr if (ret) 393178825Sdfr return ret; 394178825Sdfr 395178825Sdfr ret = krb5_store_stringz(request, k->name); 396178825Sdfr if (ret) { 397178825Sdfr krb5_storage_free(request); 398178825Sdfr return ret; 399178825Sdfr } 400178825Sdfr 401178825Sdfr ret = krb5_store_creds(request, creds); 402178825Sdfr if (ret) { 403178825Sdfr krb5_storage_free(request); 404178825Sdfr return ret; 405178825Sdfr } 406178825Sdfr 407233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 408178825Sdfr 409178825Sdfr krb5_storage_free(request); 410178825Sdfr return ret; 411178825Sdfr} 412178825Sdfr 413233294Sstas#if 0 414178825Sdfr/* 415178825Sdfr * Request: 416178825Sdfr * NameZ 417178825Sdfr * WhichFields 418178825Sdfr * MatchCreds 419178825Sdfr * 420178825Sdfr * Response: 421178825Sdfr * Creds 422178825Sdfr * 423178825Sdfr */ 424178825Sdfrstatic krb5_error_code 425178825Sdfrkcm_retrieve(krb5_context context, 426178825Sdfr krb5_ccache id, 427178825Sdfr krb5_flags which, 428178825Sdfr const krb5_creds *mcred, 429178825Sdfr krb5_creds *creds) 430178825Sdfr{ 431178825Sdfr krb5_error_code ret; 432178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 433178825Sdfr krb5_storage *request, *response; 434178825Sdfr krb5_data response_data; 435178825Sdfr 436233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_RETRIEVE, &request); 437178825Sdfr if (ret) 438178825Sdfr return ret; 439178825Sdfr 440178825Sdfr ret = krb5_store_stringz(request, k->name); 441178825Sdfr if (ret) { 442178825Sdfr krb5_storage_free(request); 443178825Sdfr return ret; 444178825Sdfr } 445178825Sdfr 446178825Sdfr ret = krb5_store_int32(request, which); 447178825Sdfr if (ret) { 448178825Sdfr krb5_storage_free(request); 449178825Sdfr return ret; 450178825Sdfr } 451178825Sdfr 452178825Sdfr ret = krb5_store_creds_tag(request, rk_UNCONST(mcred)); 453178825Sdfr if (ret) { 454178825Sdfr krb5_storage_free(request); 455178825Sdfr return ret; 456178825Sdfr } 457178825Sdfr 458233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 459178825Sdfr if (ret) { 460178825Sdfr krb5_storage_free(request); 461178825Sdfr return ret; 462178825Sdfr } 463178825Sdfr 464178825Sdfr ret = krb5_ret_creds(response, creds); 465178825Sdfr if (ret) 466178825Sdfr ret = KRB5_CC_IO; 467178825Sdfr 468178825Sdfr krb5_storage_free(request); 469178825Sdfr krb5_storage_free(response); 470178825Sdfr krb5_data_free(&response_data); 471178825Sdfr 472178825Sdfr return ret; 473178825Sdfr} 474233294Sstas#endif 475178825Sdfr 476178825Sdfr/* 477178825Sdfr * Request: 478178825Sdfr * NameZ 479178825Sdfr * 480178825Sdfr * Response: 481178825Sdfr * Principal 482178825Sdfr */ 483178825Sdfrstatic krb5_error_code 484178825Sdfrkcm_get_principal(krb5_context context, 485178825Sdfr krb5_ccache id, 486178825Sdfr krb5_principal *principal) 487178825Sdfr{ 488178825Sdfr krb5_error_code ret; 489178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 490178825Sdfr krb5_storage *request, *response; 491178825Sdfr krb5_data response_data; 492178825Sdfr 493233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request); 494178825Sdfr if (ret) 495178825Sdfr return ret; 496178825Sdfr 497178825Sdfr ret = krb5_store_stringz(request, k->name); 498178825Sdfr if (ret) { 499178825Sdfr krb5_storage_free(request); 500178825Sdfr return ret; 501178825Sdfr } 502178825Sdfr 503233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 504178825Sdfr if (ret) { 505178825Sdfr krb5_storage_free(request); 506178825Sdfr return ret; 507178825Sdfr } 508178825Sdfr 509178825Sdfr ret = krb5_ret_principal(response, principal); 510178825Sdfr if (ret) 511178825Sdfr ret = KRB5_CC_IO; 512178825Sdfr 513178825Sdfr krb5_storage_free(request); 514178825Sdfr krb5_storage_free(response); 515178825Sdfr krb5_data_free(&response_data); 516178825Sdfr 517178825Sdfr return ret; 518178825Sdfr} 519178825Sdfr 520178825Sdfr/* 521178825Sdfr * Request: 522178825Sdfr * NameZ 523178825Sdfr * 524178825Sdfr * Response: 525178825Sdfr * Cursor 526178825Sdfr * 527178825Sdfr */ 528178825Sdfrstatic krb5_error_code 529178825Sdfrkcm_get_first (krb5_context context, 530178825Sdfr krb5_ccache id, 531178825Sdfr krb5_cc_cursor *cursor) 532178825Sdfr{ 533178825Sdfr krb5_error_code ret; 534233294Sstas krb5_kcm_cursor c; 535178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 536178825Sdfr krb5_storage *request, *response; 537178825Sdfr krb5_data response_data; 538178825Sdfr 539233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_CRED_UUID_LIST, &request); 540178825Sdfr if (ret) 541178825Sdfr return ret; 542178825Sdfr 543178825Sdfr ret = krb5_store_stringz(request, k->name); 544178825Sdfr if (ret) { 545178825Sdfr krb5_storage_free(request); 546178825Sdfr return ret; 547178825Sdfr } 548178825Sdfr 549233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 550233294Sstas krb5_storage_free(request); 551233294Sstas if (ret) 552178825Sdfr return ret; 553233294Sstas 554233294Sstas c = calloc(1, sizeof(*c)); 555233294Sstas if (c == NULL) { 556233294Sstas ret = ENOMEM; 557233294Sstas krb5_set_error_message(context, ret, 558233294Sstas N_("malloc: out of memory", "")); 559233294Sstas return ret; 560178825Sdfr } 561178825Sdfr 562233294Sstas while (1) { 563233294Sstas ssize_t sret; 564233294Sstas kcmuuid_t uuid; 565233294Sstas void *ptr; 566178825Sdfr 567233294Sstas sret = krb5_storage_read(response, &uuid, sizeof(uuid)); 568233294Sstas if (sret == 0) { 569233294Sstas ret = 0; 570233294Sstas break; 571233294Sstas } else if (sret != sizeof(uuid)) { 572233294Sstas ret = EINVAL; 573233294Sstas break; 574233294Sstas } 575233294Sstas 576233294Sstas ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1)); 577233294Sstas if (ptr == NULL) { 578233294Sstas free(c->uuids); 579233294Sstas free(c); 580233294Sstas krb5_set_error_message(context, ENOMEM, 581233294Sstas N_("malloc: out of memory", "")); 582233294Sstas return ENOMEM; 583233294Sstas } 584233294Sstas c->uuids = ptr; 585233294Sstas 586233294Sstas memcpy(&c->uuids[c->length], &uuid, sizeof(uuid)); 587233294Sstas c->length += 1; 588233294Sstas } 589233294Sstas 590178825Sdfr krb5_storage_free(response); 591178825Sdfr krb5_data_free(&response_data); 592178825Sdfr 593233294Sstas if (ret) { 594233294Sstas free(c->uuids); 595233294Sstas free(c); 596178825Sdfr return ret; 597233294Sstas } 598178825Sdfr 599233294Sstas *cursor = c; 600178825Sdfr 601178825Sdfr return 0; 602178825Sdfr} 603178825Sdfr 604178825Sdfr/* 605178825Sdfr * Request: 606178825Sdfr * NameZ 607178825Sdfr * Cursor 608178825Sdfr * 609178825Sdfr * Response: 610178825Sdfr * Creds 611178825Sdfr */ 612178825Sdfrstatic krb5_error_code 613178825Sdfrkcm_get_next (krb5_context context, 614178825Sdfr krb5_ccache id, 615178825Sdfr krb5_cc_cursor *cursor, 616178825Sdfr krb5_creds *creds) 617178825Sdfr{ 618178825Sdfr krb5_error_code ret; 619178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 620233294Sstas krb5_kcm_cursor c = KCMCURSOR(*cursor); 621178825Sdfr krb5_storage *request, *response; 622178825Sdfr krb5_data response_data; 623233294Sstas ssize_t sret; 624178825Sdfr 625233294Sstas again: 626233294Sstas 627233294Sstas if (c->offset >= c->length) 628233294Sstas return KRB5_CC_END; 629233294Sstas 630233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_CRED_BY_UUID, &request); 631178825Sdfr if (ret) 632178825Sdfr return ret; 633178825Sdfr 634178825Sdfr ret = krb5_store_stringz(request, k->name); 635178825Sdfr if (ret) { 636178825Sdfr krb5_storage_free(request); 637178825Sdfr return ret; 638178825Sdfr } 639178825Sdfr 640233294Sstas sret = krb5_storage_write(request, 641233294Sstas &c->uuids[c->offset], 642233294Sstas sizeof(c->uuids[c->offset])); 643233294Sstas c->offset++; 644233294Sstas if (sret != sizeof(c->uuids[c->offset])) { 645178825Sdfr krb5_storage_free(request); 646233294Sstas krb5_clear_error_message(context); 647233294Sstas return ENOMEM; 648178825Sdfr } 649178825Sdfr 650233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 651233294Sstas krb5_storage_free(request); 652233294Sstas if (ret == KRB5_CC_END) { 653233294Sstas goto again; 654178825Sdfr } 655178825Sdfr 656178825Sdfr ret = krb5_ret_creds(response, creds); 657178825Sdfr if (ret) 658178825Sdfr ret = KRB5_CC_IO; 659178825Sdfr 660178825Sdfr krb5_storage_free(response); 661178825Sdfr krb5_data_free(&response_data); 662178825Sdfr 663178825Sdfr return ret; 664178825Sdfr} 665178825Sdfr 666178825Sdfr/* 667178825Sdfr * Request: 668178825Sdfr * NameZ 669178825Sdfr * Cursor 670178825Sdfr * 671178825Sdfr * Response: 672178825Sdfr * 673178825Sdfr */ 674178825Sdfrstatic krb5_error_code 675178825Sdfrkcm_end_get (krb5_context context, 676178825Sdfr krb5_ccache id, 677178825Sdfr krb5_cc_cursor *cursor) 678178825Sdfr{ 679233294Sstas krb5_kcm_cursor c = KCMCURSOR(*cursor); 680178825Sdfr 681233294Sstas free(c->uuids); 682233294Sstas free(c); 683178825Sdfr 684178825Sdfr *cursor = NULL; 685178825Sdfr 686233294Sstas return 0; 687178825Sdfr} 688178825Sdfr 689178825Sdfr/* 690178825Sdfr * Request: 691178825Sdfr * NameZ 692178825Sdfr * WhichFields 693178825Sdfr * MatchCreds 694178825Sdfr * 695178825Sdfr * Response: 696178825Sdfr * 697178825Sdfr */ 698178825Sdfrstatic krb5_error_code 699178825Sdfrkcm_remove_cred(krb5_context context, 700178825Sdfr krb5_ccache id, 701178825Sdfr krb5_flags which, 702178825Sdfr krb5_creds *cred) 703178825Sdfr{ 704178825Sdfr krb5_error_code ret; 705178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 706178825Sdfr krb5_storage *request; 707178825Sdfr 708233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request); 709178825Sdfr if (ret) 710178825Sdfr return ret; 711178825Sdfr 712178825Sdfr ret = krb5_store_stringz(request, k->name); 713178825Sdfr if (ret) { 714178825Sdfr krb5_storage_free(request); 715178825Sdfr return ret; 716178825Sdfr } 717178825Sdfr 718178825Sdfr ret = krb5_store_int32(request, which); 719178825Sdfr if (ret) { 720178825Sdfr krb5_storage_free(request); 721178825Sdfr return ret; 722178825Sdfr } 723178825Sdfr 724178825Sdfr ret = krb5_store_creds_tag(request, cred); 725178825Sdfr if (ret) { 726178825Sdfr krb5_storage_free(request); 727178825Sdfr return ret; 728178825Sdfr } 729178825Sdfr 730233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 731178825Sdfr 732178825Sdfr krb5_storage_free(request); 733178825Sdfr return ret; 734178825Sdfr} 735178825Sdfr 736178825Sdfrstatic krb5_error_code 737178825Sdfrkcm_set_flags(krb5_context context, 738178825Sdfr krb5_ccache id, 739178825Sdfr krb5_flags flags) 740178825Sdfr{ 741178825Sdfr krb5_error_code ret; 742178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 743178825Sdfr krb5_storage *request; 744178825Sdfr 745233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_SET_FLAGS, &request); 746178825Sdfr if (ret) 747178825Sdfr return ret; 748178825Sdfr 749178825Sdfr ret = krb5_store_stringz(request, k->name); 750178825Sdfr if (ret) { 751178825Sdfr krb5_storage_free(request); 752178825Sdfr return ret; 753178825Sdfr } 754178825Sdfr 755178825Sdfr ret = krb5_store_int32(request, flags); 756178825Sdfr if (ret) { 757178825Sdfr krb5_storage_free(request); 758178825Sdfr return ret; 759178825Sdfr } 760178825Sdfr 761233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 762178825Sdfr 763178825Sdfr krb5_storage_free(request); 764178825Sdfr return ret; 765178825Sdfr} 766178825Sdfr 767233294Sstasstatic int 768178825Sdfrkcm_get_version(krb5_context context, 769178825Sdfr krb5_ccache id) 770178825Sdfr{ 771178825Sdfr return 0; 772178825Sdfr} 773178825Sdfr 774233294Sstas/* 775233294Sstas * Send nothing 776233294Sstas * get back list of uuids 777233294Sstas */ 778178825Sdfr 779178825Sdfrstatic krb5_error_code 780233294Sstaskcm_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) 781178825Sdfr{ 782233294Sstas krb5_error_code ret; 783233294Sstas krb5_kcm_cursor c; 784233294Sstas krb5_storage *request, *response; 785233294Sstas krb5_data response_data; 786178825Sdfr 787233294Sstas *cursor = NULL; 788178825Sdfr 789233294Sstas c = calloc(1, sizeof(*c)); 790233294Sstas if (c == NULL) { 791233294Sstas ret = ENOMEM; 792233294Sstas krb5_set_error_message(context, ret, 793233294Sstas N_("malloc: out of memory", "")); 794233294Sstas goto out; 795233294Sstas } 796178825Sdfr 797233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_UUID_LIST, &request); 798233294Sstas if (ret) 799233294Sstas goto out; 800178825Sdfr 801233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 802233294Sstas krb5_storage_free(request); 803178825Sdfr if (ret) 804233294Sstas goto out; 805178825Sdfr 806233294Sstas while (1) { 807233294Sstas ssize_t sret; 808233294Sstas kcmuuid_t uuid; 809233294Sstas void *ptr; 810178825Sdfr 811233294Sstas sret = krb5_storage_read(response, &uuid, sizeof(uuid)); 812233294Sstas if (sret == 0) { 813233294Sstas ret = 0; 814233294Sstas break; 815233294Sstas } else if (sret != sizeof(uuid)) { 816233294Sstas ret = EINVAL; 817233294Sstas goto out; 818233294Sstas } 819178825Sdfr 820233294Sstas ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1)); 821233294Sstas if (ptr == NULL) { 822233294Sstas ret = ENOMEM; 823233294Sstas krb5_set_error_message(context, ret, 824233294Sstas N_("malloc: out of memory", "")); 825233294Sstas goto out; 826233294Sstas } 827233294Sstas c->uuids = ptr; 828233294Sstas 829233294Sstas memcpy(&c->uuids[c->length], &uuid, sizeof(uuid)); 830233294Sstas c->length += 1; 831233294Sstas } 832233294Sstas 833233294Sstas krb5_storage_free(response); 834233294Sstas krb5_data_free(&response_data); 835233294Sstas 836233294Sstas out: 837233294Sstas if (ret && c) { 838233294Sstas free(c->uuids); 839233294Sstas free(c); 840233294Sstas } else 841233294Sstas *cursor = c; 842233294Sstas 843233294Sstas return ret; 844178825Sdfr} 845178825Sdfr 846178825Sdfr/* 847233294Sstas * Send uuid 848233294Sstas * Recv cache name 849178825Sdfr */ 850233294Sstas 851233294Sstasstatic krb5_error_code 852233294Sstaskcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_ops *ops, krb5_ccache *id) 853178825Sdfr{ 854178825Sdfr krb5_error_code ret; 855233294Sstas krb5_kcm_cursor c = KCMCURSOR(cursor); 856233294Sstas krb5_storage *request, *response; 857233294Sstas krb5_data response_data; 858233294Sstas ssize_t sret; 859233294Sstas char *name; 860178825Sdfr 861233294Sstas *id = NULL; 862233294Sstas 863233294Sstas again: 864233294Sstas 865233294Sstas if (c->offset >= c->length) 866233294Sstas return KRB5_CC_END; 867233294Sstas 868233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request); 869178825Sdfr if (ret) 870178825Sdfr return ret; 871178825Sdfr 872233294Sstas sret = krb5_storage_write(request, 873233294Sstas &c->uuids[c->offset], 874233294Sstas sizeof(c->uuids[c->offset])); 875233294Sstas c->offset++; 876233294Sstas if (sret != sizeof(c->uuids[c->offset])) { 877233294Sstas krb5_storage_free(request); 878233294Sstas krb5_clear_error_message(context); 879233294Sstas return ENOMEM; 880233294Sstas } 881178825Sdfr 882233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 883178825Sdfr krb5_storage_free(request); 884233294Sstas if (ret == KRB5_CC_END) 885233294Sstas goto again; 886233294Sstas 887233294Sstas ret = krb5_ret_stringz(response, &name); 888233294Sstas krb5_storage_free(response); 889233294Sstas krb5_data_free(&response_data); 890233294Sstas 891233294Sstas if (ret == 0) { 892233294Sstas ret = _krb5_cc_allocate(context, ops, id); 893233294Sstas if (ret == 0) 894233294Sstas ret = kcm_alloc(context, name, id); 895233294Sstas krb5_xfree(name); 896233294Sstas } 897233294Sstas 898178825Sdfr return ret; 899178825Sdfr} 900178825Sdfr 901233294Sstasstatic krb5_error_code 902233294Sstaskcm_get_cache_next_kcm(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) 903233294Sstas{ 904233294Sstas#ifndef KCM_IS_API_CACHE 905233294Sstas return kcm_get_cache_next(context, cursor, &krb5_kcm_ops, id); 906233294Sstas#else 907233294Sstas return KRB5_CC_END; 908233294Sstas#endif 909233294Sstas} 910178825Sdfr 911233294Sstasstatic krb5_error_code 912233294Sstaskcm_get_cache_next_api(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) 913178825Sdfr{ 914233294Sstas return kcm_get_cache_next(context, cursor, &krb5_akcm_ops, id); 915233294Sstas} 916233294Sstas 917233294Sstas 918233294Sstasstatic krb5_error_code 919233294Sstaskcm_end_cache_get(krb5_context context, krb5_cc_cursor cursor) 920233294Sstas{ 921233294Sstas krb5_kcm_cursor c = KCMCURSOR(cursor); 922233294Sstas 923233294Sstas free(c->uuids); 924233294Sstas free(c); 925233294Sstas return 0; 926233294Sstas} 927233294Sstas 928233294Sstas 929233294Sstasstatic krb5_error_code 930233294Sstaskcm_move(krb5_context context, krb5_ccache from, krb5_ccache to) 931233294Sstas{ 932178825Sdfr krb5_error_code ret; 933233294Sstas krb5_kcmcache *oldk = KCMCACHE(from); 934233294Sstas krb5_kcmcache *newk = KCMCACHE(to); 935178825Sdfr krb5_storage *request; 936178825Sdfr 937233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_MOVE_CACHE, &request); 938178825Sdfr if (ret) 939178825Sdfr return ret; 940178825Sdfr 941233294Sstas ret = krb5_store_stringz(request, oldk->name); 942178825Sdfr if (ret) { 943178825Sdfr krb5_storage_free(request); 944178825Sdfr return ret; 945178825Sdfr } 946178825Sdfr 947233294Sstas ret = krb5_store_stringz(request, newk->name); 948178825Sdfr if (ret) { 949178825Sdfr krb5_storage_free(request); 950178825Sdfr return ret; 951178825Sdfr } 952233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 953178825Sdfr 954178825Sdfr krb5_storage_free(request); 955178825Sdfr return ret; 956178825Sdfr} 957178825Sdfr 958233294Sstasstatic krb5_error_code 959233294Sstaskcm_get_default_name(krb5_context context, const krb5_cc_ops *ops, 960233294Sstas const char *defstr, char **str) 961233294Sstas{ 962233294Sstas krb5_error_code ret; 963233294Sstas krb5_storage *request, *response; 964233294Sstas krb5_data response_data; 965233294Sstas char *name; 966178825Sdfr 967233294Sstas *str = NULL; 968233294Sstas 969233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_DEFAULT_CACHE, &request); 970233294Sstas if (ret) 971233294Sstas return ret; 972233294Sstas 973233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 974233294Sstas krb5_storage_free(request); 975233294Sstas if (ret) 976233294Sstas return _krb5_expand_default_cc_name(context, defstr, str); 977233294Sstas 978233294Sstas ret = krb5_ret_stringz(response, &name); 979233294Sstas krb5_storage_free(response); 980233294Sstas krb5_data_free(&response_data); 981233294Sstas if (ret) 982233294Sstas return ret; 983233294Sstas 984233294Sstas asprintf(str, "%s:%s", ops->prefix, name); 985233294Sstas free(name); 986233294Sstas if (str == NULL) 987233294Sstas return ENOMEM; 988233294Sstas 989233294Sstas return 0; 990233294Sstas} 991233294Sstas 992233294Sstasstatic krb5_error_code 993233294Sstaskcm_get_default_name_api(krb5_context context, char **str) 994178825Sdfr{ 995233294Sstas return kcm_get_default_name(context, &krb5_akcm_ops, 996233294Sstas KRB5_DEFAULT_CCNAME_KCM_API, str); 997233294Sstas} 998233294Sstas 999233294Sstasstatic krb5_error_code 1000233294Sstaskcm_get_default_name_kcm(krb5_context context, char **str) 1001233294Sstas{ 1002233294Sstas return kcm_get_default_name(context, &krb5_kcm_ops, 1003233294Sstas KRB5_DEFAULT_CCNAME_KCM_KCM, str); 1004233294Sstas} 1005233294Sstas 1006233294Sstasstatic krb5_error_code 1007233294Sstaskcm_set_default(krb5_context context, krb5_ccache id) 1008233294Sstas{ 1009178825Sdfr krb5_error_code ret; 1010233294Sstas krb5_storage *request; 1011178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 1012178825Sdfr 1013233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_SET_DEFAULT_CACHE, &request); 1014178825Sdfr if (ret) 1015178825Sdfr return ret; 1016178825Sdfr 1017178825Sdfr ret = krb5_store_stringz(request, k->name); 1018178825Sdfr if (ret) { 1019178825Sdfr krb5_storage_free(request); 1020178825Sdfr return ret; 1021178825Sdfr } 1022178825Sdfr 1023233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 1024233294Sstas krb5_storage_free(request); 1025233294Sstas 1026233294Sstas return ret; 1027233294Sstas} 1028233294Sstas 1029233294Sstasstatic krb5_error_code 1030233294Sstaskcm_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime) 1031233294Sstas{ 1032233294Sstas *mtime = time(NULL); 1033233294Sstas return 0; 1034233294Sstas} 1035233294Sstas 1036233294Sstasstatic krb5_error_code 1037233294Sstaskcm_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset) 1038233294Sstas{ 1039233294Sstas krb5_kcmcache *k = KCMCACHE(id); 1040233294Sstas krb5_error_code ret; 1041233294Sstas krb5_storage *request; 1042233294Sstas 1043233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_SET_KDC_OFFSET, &request); 1044233294Sstas if (ret) 1045233294Sstas return ret; 1046233294Sstas 1047233294Sstas ret = krb5_store_stringz(request, k->name); 1048178825Sdfr if (ret) { 1049178825Sdfr krb5_storage_free(request); 1050178825Sdfr return ret; 1051178825Sdfr } 1052233294Sstas ret = krb5_store_int32(request, kdc_offset); 1053233294Sstas if (ret) { 1054233294Sstas krb5_storage_free(request); 1055233294Sstas return ret; 1056233294Sstas } 1057178825Sdfr 1058233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 1059233294Sstas krb5_storage_free(request); 1060233294Sstas 1061233294Sstas return ret; 1062233294Sstas} 1063233294Sstas 1064233294Sstasstatic krb5_error_code 1065233294Sstaskcm_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset) 1066233294Sstas{ 1067233294Sstas krb5_kcmcache *k = KCMCACHE(id); 1068233294Sstas krb5_error_code ret; 1069233294Sstas krb5_storage *request, *response; 1070233294Sstas krb5_data response_data; 1071233294Sstas int32_t offset; 1072233294Sstas 1073233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_KDC_OFFSET, &request); 1074233294Sstas if (ret) 1075233294Sstas return ret; 1076233294Sstas 1077233294Sstas ret = krb5_store_stringz(request, k->name); 1078178825Sdfr if (ret) { 1079178825Sdfr krb5_storage_free(request); 1080178825Sdfr return ret; 1081178825Sdfr } 1082178825Sdfr 1083233294Sstas ret = krb5_kcm_call(context, request, &response, &response_data); 1084233294Sstas krb5_storage_free(request); 1085233294Sstas if (ret) 1086233294Sstas return ret; 1087178825Sdfr 1088233294Sstas ret = krb5_ret_int32(response, &offset); 1089233294Sstas krb5_storage_free(response); 1090233294Sstas krb5_data_free(&response_data); 1091233294Sstas if (ret) 1092233294Sstas return ret; 1093233294Sstas 1094233294Sstas *kdc_offset = offset; 1095233294Sstas 1096233294Sstas return 0; 1097233294Sstas} 1098233294Sstas 1099233294Sstas/** 1100233294Sstas * Variable containing the KCM based credential cache implemention. 1101233294Sstas * 1102233294Sstas * @ingroup krb5_ccache 1103233294Sstas */ 1104233294Sstas 1105233294SstasKRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = { 1106233294Sstas KRB5_CC_OPS_VERSION, 1107233294Sstas "KCM", 1108233294Sstas kcm_get_name, 1109233294Sstas kcm_resolve, 1110233294Sstas kcm_gen_new, 1111233294Sstas kcm_initialize, 1112233294Sstas kcm_destroy, 1113233294Sstas kcm_close, 1114233294Sstas kcm_store_cred, 1115233294Sstas NULL /* kcm_retrieve */, 1116233294Sstas kcm_get_principal, 1117233294Sstas kcm_get_first, 1118233294Sstas kcm_get_next, 1119233294Sstas kcm_end_get, 1120233294Sstas kcm_remove_cred, 1121233294Sstas kcm_set_flags, 1122233294Sstas kcm_get_version, 1123233294Sstas kcm_get_cache_first, 1124233294Sstas kcm_get_cache_next_kcm, 1125233294Sstas kcm_end_cache_get, 1126233294Sstas kcm_move, 1127233294Sstas kcm_get_default_name_kcm, 1128233294Sstas kcm_set_default, 1129233294Sstas kcm_lastchange, 1130233294Sstas kcm_set_kdc_offset, 1131233294Sstas kcm_get_kdc_offset 1132233294Sstas}; 1133233294Sstas 1134233294SstasKRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = { 1135233294Sstas KRB5_CC_OPS_VERSION, 1136233294Sstas "API", 1137233294Sstas kcm_get_name, 1138233294Sstas kcm_resolve, 1139233294Sstas kcm_gen_new, 1140233294Sstas kcm_initialize, 1141233294Sstas kcm_destroy, 1142233294Sstas kcm_close, 1143233294Sstas kcm_store_cred, 1144233294Sstas NULL /* kcm_retrieve */, 1145233294Sstas kcm_get_principal, 1146233294Sstas kcm_get_first, 1147233294Sstas kcm_get_next, 1148233294Sstas kcm_end_get, 1149233294Sstas kcm_remove_cred, 1150233294Sstas kcm_set_flags, 1151233294Sstas kcm_get_version, 1152233294Sstas kcm_get_cache_first, 1153233294Sstas kcm_get_cache_next_api, 1154233294Sstas kcm_end_cache_get, 1155233294Sstas kcm_move, 1156233294Sstas kcm_get_default_name_api, 1157233294Sstas kcm_set_default, 1158233294Sstas kcm_lastchange, 1159233294Sstas NULL, 1160233294Sstas NULL 1161233294Sstas}; 1162233294Sstas 1163233294Sstas 1164233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 1165233294Sstas_krb5_kcm_is_running(krb5_context context) 1166233294Sstas{ 1167233294Sstas krb5_error_code ret; 1168233294Sstas krb5_ccache_data ccdata; 1169233294Sstas krb5_ccache id = &ccdata; 1170233294Sstas krb5_boolean running; 1171233294Sstas 1172233294Sstas ret = kcm_alloc(context, NULL, &id); 1173233294Sstas if (ret) 1174233294Sstas return 0; 1175233294Sstas 1176233294Sstas running = (_krb5_kcm_noop(context, id) == 0); 1177233294Sstas 1178233294Sstas kcm_free(context, &id); 1179233294Sstas 1180233294Sstas return running; 1181233294Sstas} 1182233294Sstas 1183233294Sstas/* 1184233294Sstas * Request: 1185233294Sstas * 1186233294Sstas * Response: 1187233294Sstas * 1188233294Sstas */ 1189233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1190233294Sstas_krb5_kcm_noop(krb5_context context, 1191233294Sstas krb5_ccache id) 1192233294Sstas{ 1193233294Sstas krb5_error_code ret; 1194233294Sstas krb5_storage *request; 1195233294Sstas 1196233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_NOOP, &request); 1197233294Sstas if (ret) 1198233294Sstas return ret; 1199233294Sstas 1200233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 1201233294Sstas 1202178825Sdfr krb5_storage_free(request); 1203178825Sdfr return ret; 1204178825Sdfr} 1205178825Sdfr 1206178825Sdfr 1207178825Sdfr/* 1208178825Sdfr * Request: 1209178825Sdfr * NameZ 1210178825Sdfr * ServerPrincipalPresent 1211178825Sdfr * ServerPrincipal OPTIONAL 1212178825Sdfr * Key 1213178825Sdfr * 1214178825Sdfr * Repsonse: 1215178825Sdfr * 1216178825Sdfr */ 1217233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1218178825Sdfr_krb5_kcm_get_initial_ticket(krb5_context context, 1219178825Sdfr krb5_ccache id, 1220178825Sdfr krb5_principal server, 1221178825Sdfr krb5_keyblock *key) 1222178825Sdfr{ 1223233294Sstas krb5_kcmcache *k = KCMCACHE(id); 1224178825Sdfr krb5_error_code ret; 1225178825Sdfr krb5_storage *request; 1226178825Sdfr 1227233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request); 1228178825Sdfr if (ret) 1229178825Sdfr return ret; 1230178825Sdfr 1231178825Sdfr ret = krb5_store_stringz(request, k->name); 1232178825Sdfr if (ret) { 1233178825Sdfr krb5_storage_free(request); 1234178825Sdfr return ret; 1235178825Sdfr } 1236178825Sdfr 1237178825Sdfr ret = krb5_store_int8(request, (server == NULL) ? 0 : 1); 1238178825Sdfr if (ret) { 1239178825Sdfr krb5_storage_free(request); 1240178825Sdfr return ret; 1241178825Sdfr } 1242178825Sdfr 1243178825Sdfr if (server != NULL) { 1244178825Sdfr ret = krb5_store_principal(request, server); 1245178825Sdfr if (ret) { 1246178825Sdfr krb5_storage_free(request); 1247178825Sdfr return ret; 1248178825Sdfr } 1249178825Sdfr } 1250178825Sdfr 1251178825Sdfr ret = krb5_store_keyblock(request, *key); 1252178825Sdfr if (ret) { 1253178825Sdfr krb5_storage_free(request); 1254178825Sdfr return ret; 1255178825Sdfr } 1256178825Sdfr 1257233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 1258178825Sdfr 1259178825Sdfr krb5_storage_free(request); 1260178825Sdfr return ret; 1261178825Sdfr} 1262178825Sdfr 1263178825Sdfr 1264178825Sdfr/* 1265178825Sdfr * Request: 1266178825Sdfr * NameZ 1267178825Sdfr * KDCFlags 1268178825Sdfr * EncryptionType 1269178825Sdfr * ServerPrincipal 1270178825Sdfr * 1271178825Sdfr * Repsonse: 1272178825Sdfr * 1273178825Sdfr */ 1274233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1275178825Sdfr_krb5_kcm_get_ticket(krb5_context context, 1276178825Sdfr krb5_ccache id, 1277178825Sdfr krb5_kdc_flags flags, 1278178825Sdfr krb5_enctype enctype, 1279178825Sdfr krb5_principal server) 1280178825Sdfr{ 1281178825Sdfr krb5_error_code ret; 1282178825Sdfr krb5_kcmcache *k = KCMCACHE(id); 1283178825Sdfr krb5_storage *request; 1284178825Sdfr 1285233294Sstas ret = krb5_kcm_storage_request(context, KCM_OP_GET_TICKET, &request); 1286178825Sdfr if (ret) 1287178825Sdfr return ret; 1288178825Sdfr 1289178825Sdfr ret = krb5_store_stringz(request, k->name); 1290178825Sdfr if (ret) { 1291178825Sdfr krb5_storage_free(request); 1292178825Sdfr return ret; 1293178825Sdfr } 1294178825Sdfr 1295178825Sdfr ret = krb5_store_int32(request, flags.i); 1296178825Sdfr if (ret) { 1297178825Sdfr krb5_storage_free(request); 1298178825Sdfr return ret; 1299178825Sdfr } 1300178825Sdfr 1301178825Sdfr ret = krb5_store_int32(request, enctype); 1302178825Sdfr if (ret) { 1303178825Sdfr krb5_storage_free(request); 1304178825Sdfr return ret; 1305178825Sdfr } 1306178825Sdfr 1307178825Sdfr ret = krb5_store_principal(request, server); 1308178825Sdfr if (ret) { 1309178825Sdfr krb5_storage_free(request); 1310178825Sdfr return ret; 1311178825Sdfr } 1312178825Sdfr 1313233294Sstas ret = krb5_kcm_call(context, request, NULL, NULL); 1314178825Sdfr 1315178825Sdfr krb5_storage_free(request); 1316178825Sdfr return ret; 1317178825Sdfr} 1318178825Sdfr 1319178825Sdfr#endif /* HAVE_KCM */ 1320