LCOV - code coverage report
Current view: top level - third_party/heimdal/kdc - process.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 107 229 46.7 %
Date: 2024-06-13 04:01:37 Functions: 12 25 48.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  *
       5             :  * All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  *
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  *
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer in the
      16             :  *    documentation and/or other materials provided with the distribution.
      17             :  *
      18             :  * 3. Neither the name of the Institute nor the names of its contributors
      19             :  *    may be used to endorse or promote products derived from this software
      20             :  *    without specific prior written permission.
      21             :  *
      22             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      23             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      26             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      27             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      28             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      29             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      30             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      31             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      32             :  * SUCH DAMAGE.
      33             :  */
      34             : 
      35             : #include "kdc_locl.h"
      36             : #include <vis.h>
      37             : 
      38             : /*
      39             :  *
      40             :  */
      41             : 
      42             : #undef  __attribute__
      43             : #define __attribute__(x)
      44             : 
      45             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      46           0 : kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap)
      47             :         __attribute__ ((__format__ (__printf__, 2, 0)))
      48             : {
      49           0 :     heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
      50           0 : }
      51             : 
      52             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      53        1512 : kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
      54             :         __attribute__ ((__format__ (__printf__, 2, 3)))
      55             : {
      56             :     va_list ap;
      57             : 
      58        1512 :     va_start(ap, fmt);
      59        1512 :     heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
      60        1512 :     va_end(ap);
      61        1512 : }
      62             : 
      63             : /*
      64             :  * append_token adds a token which is optionally a kv-pair and it
      65             :  * also optionally eats the whitespace.  If k == NULL, then it's
      66             :  * not a kv-pair.
      67             :  */
      68             : 
      69             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      70           0 : kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k,
      71             :                   const char *fmt, va_list ap)
      72             :         __attribute__ ((__format__ (__printf__, 4, 0)))
      73             : {
      74           0 :     heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
      75           0 : }
      76             : 
      77             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      78      291216 : kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
      79             :                  const char *fmt, ...)
      80             :         __attribute__ ((__format__ (__printf__, 4, 5)))
      81             : {
      82             :     va_list ap;
      83             : 
      84      291216 :     va_start(ap, fmt);
      85      291216 :     heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
      86      291216 :     va_end(ap);
      87      291216 : }
      88             : 
      89             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      90           0 : kdc_audit_addkv_timediff(kdc_request_t r, const char *k,
      91             :                           const struct timeval *start,
      92             :                           const struct timeval *end)
      93             : {
      94           0 :     heim_audit_addkv_timediff((heim_svc_req_desc)r,k, start, end);
      95           0 : }
      96             : 
      97             : KDC_LIB_FUNCTION void KDC_LIB_CALL
      98           0 : kdc_audit_setkv_bool(kdc_request_t r, const char *k, krb5_boolean v)
      99             : {
     100           0 :     heim_audit_setkv_bool((heim_svc_req_desc)r, k, (int)v);
     101           0 : }
     102             : 
     103             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     104           0 : kdc_audit_addkv_number(kdc_request_t r, const char *k, int64_t v)
     105             : {
     106           0 :     heim_audit_addkv_number((heim_svc_req_desc)r, k, v);
     107           0 : }
     108             : 
     109             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     110      258072 : kdc_audit_setkv_number(kdc_request_t r, const char *k, int64_t v)
     111             : {
     112      258072 :     heim_audit_setkv_number((heim_svc_req_desc)r, k, v);
     113      258072 : }
     114             : 
     115             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     116           0 : kdc_audit_addkv_object(kdc_request_t r, const char *k, kdc_object_t obj)
     117             : {
     118           0 :     heim_audit_addkv_object((heim_svc_req_desc)r, k, obj);
     119           0 : }
     120             : 
     121             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     122           0 : kdc_audit_setkv_object(kdc_request_t r, const char *k, kdc_object_t obj)
     123             : {
     124           0 :     heim_audit_setkv_object((heim_svc_req_desc)r, k, obj);
     125           0 : }
     126             : 
     127             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     128       18721 : kdc_audit_getkv(kdc_request_t r, const char *k)
     129             : {
     130       18721 :     return heim_audit_getkv((heim_svc_req_desc)r, k);
     131             : }
     132             : 
     133             : /*
     134             :  * Add up to 3 key value pairs to record HostAddresses from request body or
     135             :  * PA-TGS ticket or whatever.
     136             :  */
     137             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     138         407 : kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key)
     139             : {
     140             :     size_t i;
     141             :     char buf[128];
     142             : 
     143         407 :     if (a->len > 3) {
     144             :         char numkey[32];
     145             : 
     146           0 :         if (snprintf(numkey, sizeof(numkey), "num%s", key) >= sizeof(numkey))
     147           0 :             numkey[31] = '\0';
     148           0 :         kdc_audit_addkv(r, 0, numkey, "%llu", (unsigned long long)a->len);
     149             :     }
     150             : 
     151         515 :     for (i = 0; i < 3 && i < a->len; i++) {
     152         108 :         if (krb5_print_address(&a->val[i], buf, sizeof(buf), NULL) == 0)
     153         108 :             kdc_audit_addkv(r, 0, key, "%s", buf);
     154             :     }
     155         407 : }
     156             : 
     157             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     158       71023 : _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
     159             : {
     160       71023 :     const char *retname = NULL;
     161             : 
     162             :     /* Get a symbolic name for some error codes */
     163             : #define CASE(x) case x : retname = #x; break
     164       71023 :     switch (ret ? ret : r->error_code) {
     165           0 :     CASE(ENOMEM);
     166           0 :     CASE(EACCES);
     167        3053 :     CASE(HDB_ERR_NOT_FOUND_HERE);
     168           0 :     CASE(HDB_ERR_WRONG_REALM);
     169           0 :     CASE(HDB_ERR_EXISTS);
     170           0 :     CASE(HDB_ERR_KVNO_NOT_FOUND);
     171           0 :     CASE(HDB_ERR_NOENTRY);
     172           0 :     CASE(HDB_ERR_NO_MKEY);
     173         185 :     CASE(KRB5KDC_ERR_BADOPTION);
     174           0 :     CASE(KRB5KDC_ERR_CANNOT_POSTDATE);
     175           0 :     CASE(KRB5KDC_ERR_CLIENT_NOTYET);
     176         413 :     CASE(KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);
     177         283 :     CASE(KRB5KDC_ERR_ETYPE_NOSUPP);
     178           4 :     CASE(KRB5KDC_ERR_KEY_EXPIRED);
     179           0 :     CASE(KRB5KDC_ERR_NAME_EXP);
     180           0 :     CASE(KRB5KDC_ERR_NEVER_VALID);
     181           0 :     CASE(KRB5KDC_ERR_NONE);
     182           0 :     CASE(KRB5KDC_ERR_NULL_KEY);
     183           0 :     CASE(KRB5KDC_ERR_PADATA_TYPE_NOSUPP);
     184           0 :     CASE(KRB5KDC_ERR_POLICY);
     185         254 :     CASE(KRB5KDC_ERR_PREAUTH_FAILED);
     186       11298 :     CASE(KRB5KDC_ERR_PREAUTH_REQUIRED);
     187           0 :     CASE(KRB5KDC_ERR_SERVER_NOMATCH);
     188           0 :     CASE(KRB5KDC_ERR_SERVICE_EXP);
     189           0 :     CASE(KRB5KDC_ERR_SERVICE_NOTYET);
     190        1094 :     CASE(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
     191           0 :     CASE(KRB5KDC_ERR_TRTYPE_NOSUPP);
     192        7734 :     CASE(KRB5KRB_ERR_RESPONSE_TOO_BIG);
     193       46604 :     case 0:
     194       46604 :         retname = "SUCCESS";
     195       46604 :         break;
     196         101 :     default:
     197         101 :         retname = NULL;
     198         101 :         break;
     199             :     }
     200             : 
     201             :     /* Let's save a few bytes */
     202             : #define PREFIX "KRB5KDC_"
     203       71023 :     if (retname && strncmp(PREFIX, retname, strlen(PREFIX)) == 0)
     204       13531 :         retname += strlen(PREFIX);
     205             : #undef PREFIX
     206             : 
     207       71023 :     heim_audit_trail((heim_svc_req_desc)r, ret, retname);
     208       71023 : }
     209             : 
     210             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     211       71023 : krb5_kdc_update_time(struct timeval *tv)
     212             : {
     213       71023 :     if (tv == NULL)
     214       71023 :         gettimeofday(&_kdc_now, NULL);
     215             :     else
     216           0 :         _kdc_now = *tv;
     217       71023 : }
     218             : 
     219             : KDC_LIB_FUNCTION struct timeval KDC_LIB_CALL
     220       35916 : krb5_kdc_get_time(void)
     221             : {
     222       35916 :     return _kdc_now;
     223             : }
     224             : 
     225             : 
     226             : #define EXTEND_REQUEST_T(LHS, RHS) do {                 \
     227             :         RHS = realloc(LHS, sizeof(*RHS));               \
     228             :         if (!RHS)                                       \
     229             :             return krb5_enomem((LHS)->context);              \
     230             :         LHS = (void *)RHS;                              \
     231             :         memset(((char *)LHS) + sizeof(*LHS),            \
     232             :                0x0,                                     \
     233             :                sizeof(*RHS) - sizeof(*LHS));            \
     234             :     } while (0)
     235             : 
     236             : static krb5_error_code
     237       71023 : kdc_as_req(kdc_request_t *rptr, int *claim)
     238             : {
     239             :     astgs_request_t r;
     240             :     krb5_error_code ret;
     241             :     size_t len;
     242             : 
     243             :     /* We must free things in the extensions */
     244       71023 :     EXTEND_REQUEST_T(*rptr, r);
     245             : 
     246       71023 :     ret = decode_AS_REQ(r->request.data, r->request.length, &r->req, &len);
     247       71023 :     if (ret)
     248       38595 :         return ret;
     249             : 
     250       32428 :     r->reqtype = "AS-REQ";
     251       32428 :     r->use_request_t = 1;
     252       32428 :     *claim = 1;
     253             : 
     254       32428 :     ret = _kdc_as_rep(r);
     255       32428 :     free_AS_REQ(&r->req);
     256       32428 :     return ret;
     257             : }
     258             : 
     259             : 
     260             : static krb5_error_code
     261       38595 : kdc_tgs_req(kdc_request_t *rptr, int *claim)
     262             : {
     263             :     astgs_request_t r;
     264             :     krb5_error_code ret;
     265             :     size_t len;
     266             : 
     267             :     /* We must free things in the extensions */
     268       38595 :     EXTEND_REQUEST_T(*rptr, r);
     269             : 
     270       38595 :     ret = decode_TGS_REQ(r->request.data, r->request.length, &r->req, &len);
     271       38595 :     if (ret)
     272           0 :         return ret;
     273             : 
     274       38595 :     r->reqtype = "TGS-REQ";
     275       38595 :     r->use_request_t = 1;
     276       38595 :     *claim = 1;
     277             : 
     278       38595 :     ret = _kdc_tgs_rep(r);
     279       38595 :     free_TGS_REQ(&r->req);
     280       38595 :     return ret;
     281             : }
     282             : 
     283             : #ifdef DIGEST
     284             : 
     285             : static krb5_error_code
     286             : kdc_digest(kdc_request_t *rptr, int *claim)
     287             : {
     288             :     kdc_request_t r;
     289             :     DigestREQ digestreq;
     290             :     krb5_error_code ret;
     291             :     size_t len;
     292             : 
     293             :     r = *rptr;
     294             : 
     295             :     ret = decode_DigestREQ(r->request.data, r->request.length,
     296             :                            &digestreq, &len);
     297             :     if (ret)
     298             :         return ret;
     299             : 
     300             :     r->use_request_t = 0;
     301             :     *claim = 1;
     302             : 
     303             :     ret = _kdc_do_digest(r->context, r->config, &digestreq,
     304             :                          r->reply, r->from, r->addr);
     305             :     free_DigestREQ(&digestreq);
     306             :     return ret;
     307             : }
     308             : 
     309             : #endif
     310             : 
     311             : #ifdef KX509
     312             : 
     313             : static krb5_error_code
     314             : kdc_kx509(kdc_request_t *rptr, int *claim)
     315             : {
     316             :     kx509_req_context r;
     317             :     krb5_error_code ret;
     318             : 
     319             :     /* We must free things in the extensions */
     320             :     EXTEND_REQUEST_T(*rptr, r);
     321             : 
     322             :     ret = _kdc_try_kx509_request(r);
     323             :     if (ret)
     324             :         return ret;
     325             : 
     326             :     r->use_request_t = 1;
     327             :     r->reqtype = "KX509";
     328             :     *claim = 1;
     329             : 
     330             :     return _kdc_do_kx509(r); /* Must clean up the req struct extensions */
     331             : }
     332             : 
     333             : #endif
     334             : 
     335             : 
     336             : static struct krb5_kdc_service services[] =  {
     337             :     { KS_KRB5, "AS-REQ",      kdc_as_req },
     338             :     { KS_KRB5, "TGS-REQ",     kdc_tgs_req },
     339             : #ifdef DIGEST
     340             :     { 0,        "DIGEST",     kdc_digest },
     341             : #endif
     342             : #ifdef KX509
     343             :     { 0,        "KX509",      kdc_kx509 },
     344             : #endif
     345             :     { 0, NULL, NULL }
     346             : };
     347             : 
     348             : static int
     349       71023 : process_request(krb5_context context,
     350             :                 krb5_kdc_configuration *config,
     351             :                 unsigned int krb5_only,
     352             :                 unsigned char *buf,
     353             :                 size_t len,
     354             :                 krb5_data *reply,
     355             :                 krb5_boolean *prependlength,
     356             :                 const char *from,
     357             :                 struct sockaddr *addr,
     358             :                 int datagram_reply)
     359             : {
     360             :     kdc_request_t r;
     361             :     krb5_error_code ret;
     362             :     unsigned int i;
     363       71023 :     int claim = 0;
     364             : 
     365       71023 :     r = calloc(sizeof(*r), 1);
     366       71023 :     if (!r)
     367           0 :         return krb5_enomem(context);
     368             : 
     369       71023 :     r->context = context;
     370       71023 :     r->hcontext = context->hcontext;
     371       71023 :     r->config = config;
     372       71023 :     r->logf = config->logf;
     373       71023 :     r->from = from;
     374       71023 :     r->addr = addr;
     375       71023 :     r->request.data = buf;
     376       71023 :     r->request.length = len;
     377       71023 :     r->datagram_reply = datagram_reply;
     378       71023 :     r->reply = reply;
     379       71023 :     r->kv = heim_dict_create(10);
     380       71023 :     r->attributes = heim_dict_create(1);
     381       71023 :     if (r->kv == NULL || r->attributes == NULL) {
     382           0 :         heim_release(r->kv);
     383           0 :         heim_release(r->attributes);
     384           0 :         free(r);
     385           0 :         return krb5_enomem(context);
     386             :     }
     387             : 
     388       71023 :     gettimeofday(&r->tv_start, NULL);
     389             : 
     390      109618 :     for (i = 0; services[i].process != NULL; i++) {
     391      109618 :         if (krb5_only && (services[i].flags & KS_KRB5) == 0)
     392           0 :             continue;
     393      109618 :         kdc_log(context, config, 7, "Probing for %s", services[i].name);
     394      109618 :         ret = (*services[i].process)(&r, &claim);
     395      109618 :         if (claim) {
     396       71023 :             if (prependlength && services[i].flags & KS_NO_LENGTH)
     397           0 :                 *prependlength = 0;
     398             : 
     399       71023 :             if (r->use_request_t) {
     400       71023 :                 gettimeofday(&r->tv_end, NULL);
     401       71023 :                 _kdc_audit_trail(r, ret);
     402       71023 :                 free(r->cname);
     403       71023 :                 free(r->sname);
     404       71023 :                 free(r->e_text_buf);
     405             :             }
     406             : 
     407       71023 :             heim_release(r->reason);
     408       71023 :             heim_release(r->kv);
     409       71023 :             heim_release(r->attributes);
     410       71023 :             free(r);
     411       71023 :             return ret;
     412             :         }
     413             :     }
     414             : 
     415           0 :     heim_release(r->reason);
     416           0 :     heim_release(r->kv);
     417           0 :     heim_release(r->attributes);
     418           0 :     free(r);
     419           0 :     return -1;
     420             : }
     421             : 
     422             : /*
     423             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     424             :  * sending a reply in `reply'.
     425             :  */
     426             : 
     427             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     428           0 : krb5_kdc_process_request(krb5_context context,
     429             :                          krb5_kdc_configuration *config,
     430             :                          unsigned char *buf,
     431             :                          size_t len,
     432             :                          krb5_data *reply,
     433             :                          krb5_boolean *prependlength,
     434             :                          const char *from,
     435             :                          struct sockaddr *addr,
     436             :                          int datagram_reply)
     437             : {
     438           0 :     return process_request(context, config, 0, buf, len, reply, prependlength,
     439             :                            from, addr, datagram_reply);
     440             : }
     441             :  
     442             : /*
     443             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     444             :  * sending a reply in `reply'.
     445             :  *
     446             :  * This only processes krb5 requests
     447             :  */
     448             : 
     449             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     450       71023 : krb5_kdc_process_krb5_request(krb5_context context,
     451             :                               krb5_kdc_configuration *config,
     452             :                               unsigned char *buf,
     453             :                               size_t len,
     454             :                               krb5_data *reply,
     455             :                               const char *from,
     456             :                               struct sockaddr *addr,
     457             :                               int datagram_reply)
     458             : {
     459       71023 :     return process_request(context, config, 1, buf, len, reply, NULL,
     460             :                            from, addr, datagram_reply);
     461             : }
     462             : 
     463             : 
     464             : /*
     465             :  *
     466             :  */
     467             : 
     468             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     469           0 : krb5_kdc_save_request(krb5_context context,
     470             :                       const char *fn,
     471             :                       const unsigned char *buf,
     472             :                       size_t len,
     473             :                       const krb5_data *reply,
     474             :                       const struct sockaddr *sa)
     475             : {
     476             :     krb5_storage *sp;
     477             :     krb5_address a;
     478           0 :     int fd = -1;
     479           0 :     int ret = 0;
     480             :     uint32_t t;
     481             :     krb5_data d;
     482             : 
     483           0 :     memset(&a, 0, sizeof(a));
     484             : 
     485           0 :     d.data = rk_UNCONST(buf); /* do not free here */
     486           0 :     d.length = len;
     487           0 :     t = _kdc_now.tv_sec;
     488             : 
     489           0 :     sp = krb5_storage_emem();
     490           0 :     if (sp == NULL)
     491           0 :         ret = krb5_enomem(context);
     492             : 
     493           0 :     if (ret == 0)
     494           0 :         ret = krb5_sockaddr2address(context, sa, &a);
     495           0 :     if (ret == 0)
     496           0 :         ret = krb5_store_uint32(sp, 1);
     497           0 :     if (ret == 0)
     498           0 :         ret = krb5_store_uint32(sp, t);
     499           0 :     if (ret == 0)
     500           0 :         ret = krb5_store_address(sp, a);
     501           0 :     if (ret == 0)
     502           0 :         ret = krb5_store_data(sp, d);
     503           0 :     d.length = 0;
     504           0 :     d.data = NULL;
     505           0 :     if (ret == 0) {
     506             :         Der_class cl;
     507             :         Der_type ty;
     508             :         unsigned int tag;
     509           0 :         ret = der_get_tag (reply->data, reply->length,
     510             :                            &cl, &ty, &tag, NULL);
     511           0 :         if (ret) {
     512           0 :             ret = krb5_store_uint32(sp, 0xffffffff);
     513           0 :             if (ret == 0)
     514           0 :                 ret = krb5_store_uint32(sp, 0xffffffff);
     515             :         } else {
     516           0 :             ret = krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
     517           0 :             if (ret == 0)
     518           0 :                 ret = krb5_store_uint32(sp, tag);
     519             :         }
     520             :     }
     521             : 
     522           0 :     if (ret == 0)
     523           0 :         ret = krb5_storage_to_data(sp, &d);
     524           0 :     krb5_storage_free(sp);
     525           0 :     sp = NULL;
     526             : 
     527             :     /*
     528             :      * We've got KDC concurrency, so we're going to try to do a single O_APPEND
     529             :      * write(2).  Hopefully we manage to write enough of the header that one
     530             :      * can skip this request if it fails to write completely.
     531             :      */
     532           0 :     if (ret == 0)
     533           0 :         fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
     534           0 :     if (fd < 0)
     535           0 :         krb5_set_error_message(context, ret = errno, "Failed to open: %s", fn);
     536           0 :     if (ret == 0) {
     537           0 :         sp = krb5_storage_from_fd(fd);
     538           0 :         if (sp == NULL)
     539           0 :             krb5_set_error_message(context, ret = ENOMEM,
     540             :                                    "Storage failed to open fd");
     541             :     }
     542           0 :     (void) close(fd);
     543           0 :     if (ret == 0)
     544           0 :         ret = krb5_store_data(sp, d);
     545           0 :     krb5_free_address(context, &a);
     546             :     /*
     547             :      * krb5_storage_free() currently always returns 0, but for FDs it sets
     548             :      * errno to whatever close() set it to if it failed.
     549             :      */
     550           0 :     errno = 0;
     551           0 :     if (ret == 0)
     552           0 :         ret = krb5_storage_free(sp);
     553             :     else
     554           0 :         (void) krb5_storage_free(sp);
     555           0 :     if (ret == 0 && errno)
     556           0 :         ret = errno;
     557             : 
     558           0 :     return ret;
     559             : }
     560             : 
     561             : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
     562           0 : kdc_request_set_attribute(kdc_request_t r, kdc_object_t key, kdc_object_t value)
     563             : {
     564           0 :     return heim_dict_set_value(r->attributes, key, value);
     565             : }
     566             : 
     567             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     568           0 : kdc_request_get_attribute(kdc_request_t r, kdc_object_t key)
     569             : {
     570           0 :     return heim_dict_get_value(r->attributes, key);
     571             : }
     572             : 
     573             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     574           0 : kdc_request_copy_attribute(kdc_request_t r, kdc_object_t key)
     575             : {
     576           0 :     return heim_dict_copy_value(r->attributes, key);
     577             : }
     578             : 
     579             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     580           0 : kdc_request_delete_attribute(kdc_request_t r, kdc_object_t key)
     581             : {
     582           0 :     heim_dict_delete_key(r->attributes, key);
     583           0 : }

Generated by: LCOV version 1.13