root/source4/heimdal/lib/krb5/kcm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. try_door
  2. try_unix_socket
  3. kcm_send_request
  4. kcm_storage_request
  5. kcm_alloc
  6. kcm_call
  7. kcm_free
  8. kcm_get_name
  9. kcm_resolve
  10. kcm_gen_new
  11. kcm_initialize
  12. kcm_close
  13. kcm_destroy
  14. kcm_store_cred
  15. kcm_retrieve
  16. kcm_get_principal
  17. kcm_get_first
  18. kcm_get_next
  19. kcm_end_get
  20. kcm_remove_cred
  21. kcm_set_flags
  22. kcm_get_version
  23. kcm_move
  24. kcm_default_name
  25. kcm_lastchange
  26. _krb5_kcm_is_running
  27. _krb5_kcm_noop
  28. _krb5_kcm_chmod
  29. _krb5_kcm_chown
  30. _krb5_kcm_get_initial_ticket
  31. _krb5_kcm_get_ticket

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

/* [<][>][^][v][top][bottom][index][help] */