LCOV - code coverage report
Current view: top level - third_party/heimdal/kdc - process.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 129 277 46.6 %
Date: 2024-04-21 15:09:00 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        1830 : kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
      54             :         __attribute__ ((__format__ (__printf__, 2, 3)))
      55             : {
      56           0 :     va_list ap;
      57             : 
      58        1830 :     va_start(ap, fmt);
      59        1830 :     heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
      60        1830 :     va_end(ap);
      61        1830 : }
      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      434862 : kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
      79             :                  const char *fmt, ...)
      80             :         __attribute__ ((__format__ (__printf__, 4, 5)))
      81             : {
      82       15895 :     va_list ap;
      83             : 
      84      434862 :     va_start(ap, fmt);
      85      434862 :     heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
      86      434862 :     va_end(ap);
      87      434862 : }
      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      467180 : kdc_audit_setkv_number(kdc_request_t r, const char *k, int64_t v)
     111             : {
     112      467180 :     heim_audit_setkv_number((heim_svc_req_desc)r, k, v);
     113      467180 : }
     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       30739 : kdc_audit_getkv(kdc_request_t r, const char *k)
     129             : {
     130       30739 :     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         417 : kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key)
     139             : {
     140           0 :     size_t i;
     141           0 :     char buf[128];
     142             : 
     143         417 :     if (a->len > 3) {
     144           0 :         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         535 :     for (i = 0; i < 3 && i < a->len; i++) {
     152         118 :         if (krb5_print_address(&a->val[i], buf, sizeof(buf), NULL) == 0)
     153         118 :             kdc_audit_addkv(r, 0, key, "%s", buf);
     154             :     }
     155         417 : }
     156             : 
     157             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     158      104689 : _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
     159             : {
     160      104689 :     const char *retname = NULL;
     161             : 
     162             :     /* Get a symbolic name for some error codes */
     163             : #define CASE(x) case x : retname = #x; break
     164      104689 :     switch (ret ? ret : r->error_code) {
     165           0 :     CASE(ENOMEM);
     166           0 :     CASE(EACCES);
     167        3040 :     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          44 :     CASE(KRB5KDC_ERR_BADOPTION);
     174           0 :     CASE(KRB5KDC_ERR_CANNOT_POSTDATE);
     175           0 :     CASE(KRB5KDC_ERR_CLIENT_NOTYET);
     176         454 :     CASE(KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN);
     177         565 :     CASE(KRB5KDC_ERR_ETYPE_NOSUPP);
     178           5 :     CASE(KRB5KDC_ERR_KEY_EXPIRED);
     179           0 :     CASE(KRB5KDC_ERR_NAME_EXP);
     180           1 :     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         337 :     CASE(KRB5KDC_ERR_POLICY);
     185         382 :     CASE(KRB5KDC_ERR_PREAUTH_FAILED);
     186       18177 :     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        1259 :     CASE(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
     191           0 :     CASE(KRB5KDC_ERR_TRTYPE_NOSUPP);
     192           0 :     CASE(KRB5KRB_AP_ERR_BADADDR);
     193           0 :     CASE(KRB5KRB_AP_ERR_BADDIRECTION);
     194          20 :     CASE(KRB5KRB_AP_ERR_BAD_INTEGRITY);
     195           4 :     CASE(KRB5KRB_AP_ERR_BADKEYVER);
     196           5 :     CASE(KRB5KRB_AP_ERR_BADMATCH);
     197           0 :     CASE(KRB5KRB_AP_ERR_BADORDER);
     198           0 :     CASE(KRB5KRB_AP_ERR_BADSEQ);
     199           0 :     CASE(KRB5KRB_AP_ERR_BADVERSION);
     200           0 :     CASE(KRB5KRB_AP_ERR_ILL_CR_TKT);
     201          28 :     CASE(KRB5KRB_AP_ERR_INAPP_CKSUM);
     202           0 :     CASE(KRB5KRB_AP_ERR_METHOD);
     203           7 :     CASE(KRB5KRB_AP_ERR_MODIFIED);
     204           0 :     CASE(KRB5KRB_AP_ERR_MSG_TYPE);
     205           0 :     CASE(KRB5KRB_AP_ERR_MUT_FAIL);
     206           0 :     CASE(KRB5KRB_AP_ERR_NOKEY);
     207           0 :     CASE(KRB5KRB_AP_ERR_NOT_US);
     208           0 :     CASE(KRB5KRB_AP_ERR_REPEAT);
     209          10 :     CASE(KRB5KRB_AP_ERR_SKEW);
     210           8 :     CASE(KRB5KRB_AP_ERR_TKT_EXPIRED);
     211           0 :     CASE(KRB5KRB_AP_ERR_TKT_INVALID);
     212           4 :     CASE(KRB5KRB_AP_ERR_TKT_NYV);
     213           0 :     CASE(KRB5KRB_AP_ERR_V4_REPLY);
     214           0 :     CASE(KRB5KRB_AP_PATH_NOT_ACCEPTED);
     215           0 :     CASE(KRB5KRB_AP_WRONG_PRINC);
     216           0 :     CASE(KRB5KRB_ERR_FIELD_TOOLONG);
     217          18 :     CASE(KRB5KRB_ERR_GENERIC);
     218       12558 :     CASE(KRB5KRB_ERR_RESPONSE_TOO_BIG);
     219             : 
     220       67040 :     case 0:
     221       67040 :         retname = "SUCCESS";
     222       67040 :         break;
     223         723 :     default:
     224         723 :         retname = NULL;
     225         723 :         break;
     226             :     }
     227             : 
     228             :     /* Let's save a few bytes */
     229             : #define PREFIX "KRB5KDC_"
     230      104689 :     if (retname && strncmp(PREFIX, retname, strlen(PREFIX)) == 0)
     231       21224 :         retname += strlen(PREFIX);
     232             : #undef PREFIX
     233             : 
     234      104689 :     heim_audit_trail((heim_svc_req_desc)r, ret, retname);
     235      104689 : }
     236             : 
     237             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     238      104689 : krb5_kdc_update_time(struct timeval *tv)
     239             : {
     240      104689 :     if (tv == NULL)
     241      104689 :         gettimeofday(&_kdc_now, NULL);
     242             :     else
     243           0 :         _kdc_now = *tv;
     244      104689 : }
     245             : 
     246             : KDC_LIB_FUNCTION struct timeval KDC_LIB_CALL
     247      102844 : krb5_kdc_get_time(void)
     248             : {
     249      102844 :     return _kdc_now;
     250             : }
     251             : 
     252             : 
     253             : #define EXTEND_REQUEST_T(LHS, RHS) do {                 \
     254             :         RHS = realloc(LHS, sizeof(*RHS));               \
     255             :         if (!RHS)                                       \
     256             :             return krb5_enomem((LHS)->context);              \
     257             :         LHS = (void *)RHS;                              \
     258             :         memset(((char *)LHS) + sizeof(*LHS),            \
     259             :                0x0,                                     \
     260             :                sizeof(*RHS) - sizeof(*LHS));            \
     261             :     } while (0)
     262             : 
     263             : static krb5_error_code
     264      104689 : kdc_as_req(kdc_request_t *rptr, int *claim)
     265             : {
     266        3413 :     astgs_request_t r;
     267        3413 :     krb5_error_code ret;
     268        3413 :     size_t len;
     269             : 
     270             :     /* We must free things in the extensions */
     271      104689 :     EXTEND_REQUEST_T(*rptr, r);
     272             : 
     273      104689 :     ret = decode_AS_REQ(r->request.data, r->request.length, &r->req, &len);
     274      104689 :     if (ret)
     275       50871 :         return ret;
     276             : 
     277       52160 :     r->reqtype = "AS-REQ";
     278       52160 :     r->use_request_t = 1;
     279       52160 :     *claim = 1;
     280             : 
     281       52160 :     ret = _kdc_as_rep(r);
     282       52160 :     free_AS_REQ(&r->req);
     283       52160 :     return ret;
     284             : }
     285             : 
     286             : 
     287             : static krb5_error_code
     288       52529 : kdc_tgs_req(kdc_request_t *rptr, int *claim)
     289             : {
     290        1658 :     astgs_request_t r;
     291        1658 :     krb5_error_code ret;
     292        1658 :     size_t len;
     293             : 
     294             :     /* We must free things in the extensions */
     295       52529 :     EXTEND_REQUEST_T(*rptr, r);
     296             : 
     297       52529 :     ret = decode_TGS_REQ(r->request.data, r->request.length, &r->req, &len);
     298       52529 :     if (ret)
     299           0 :         return ret;
     300             : 
     301       52529 :     r->reqtype = "TGS-REQ";
     302       52529 :     r->use_request_t = 1;
     303       52529 :     *claim = 1;
     304             : 
     305       52529 :     ret = _kdc_tgs_rep(r);
     306       52529 :     free_TGS_REQ(&r->req);
     307       52529 :     return ret;
     308             : }
     309             : 
     310             : #ifdef DIGEST
     311             : 
     312             : static krb5_error_code
     313             : kdc_digest(kdc_request_t *rptr, int *claim)
     314             : {
     315             :     kdc_request_t r;
     316             :     DigestREQ digestreq;
     317             :     krb5_error_code ret;
     318             :     size_t len;
     319             : 
     320             :     r = *rptr;
     321             : 
     322             :     ret = decode_DigestREQ(r->request.data, r->request.length,
     323             :                            &digestreq, &len);
     324             :     if (ret)
     325             :         return ret;
     326             : 
     327             :     r->use_request_t = 0;
     328             :     *claim = 1;
     329             : 
     330             :     ret = _kdc_do_digest(r->context, r->config, &digestreq,
     331             :                          r->reply, r->from, r->addr);
     332             :     free_DigestREQ(&digestreq);
     333             :     return ret;
     334             : }
     335             : 
     336             : #endif
     337             : 
     338             : #ifdef KX509
     339             : 
     340             : static krb5_error_code
     341             : kdc_kx509(kdc_request_t *rptr, int *claim)
     342             : {
     343             :     kx509_req_context r;
     344             :     krb5_error_code ret;
     345             : 
     346             :     /* We must free things in the extensions */
     347             :     EXTEND_REQUEST_T(*rptr, r);
     348             : 
     349             :     ret = _kdc_try_kx509_request(r);
     350             :     if (ret)
     351             :         return ret;
     352             : 
     353             :     r->use_request_t = 1;
     354             :     r->reqtype = "KX509";
     355             :     *claim = 1;
     356             : 
     357             :     return _kdc_do_kx509(r); /* Must clean up the req struct extensions */
     358             : }
     359             : 
     360             : #endif
     361             : 
     362             : 
     363             : static struct krb5_kdc_service services[] =  {
     364             :     { KS_KRB5, "AS-REQ",      kdc_as_req },
     365             :     { KS_KRB5, "TGS-REQ",     kdc_tgs_req },
     366             : #ifdef DIGEST
     367             :     { 0,        "DIGEST",     kdc_digest },
     368             : #endif
     369             : #ifdef KX509
     370             :     { 0,        "KX509",      kdc_kx509 },
     371             : #endif
     372             :     { 0, NULL, NULL }
     373             : };
     374             : 
     375             : static int
     376      104689 : process_request(krb5_context context,
     377             :                 krb5_kdc_configuration *config,
     378             :                 unsigned int krb5_only,
     379             :                 unsigned char *buf,
     380             :                 size_t len,
     381             :                 krb5_data *reply,
     382             :                 krb5_boolean *prependlength,
     383             :                 const char *from,
     384             :                 struct sockaddr *addr,
     385             :                 int datagram_reply)
     386             : {
     387        3413 :     kdc_request_t r;
     388        3413 :     krb5_error_code ret;
     389        3413 :     unsigned int i;
     390      104689 :     int claim = 0;
     391             : 
     392      104689 :     r = calloc(sizeof(*r), 1);
     393      104689 :     if (!r)
     394           0 :         return krb5_enomem(context);
     395             : 
     396      104689 :     r->context = context;
     397      104689 :     r->hcontext = context->hcontext;
     398      104689 :     r->config = config;
     399      104689 :     r->logf = config->logf;
     400      104689 :     r->from = from;
     401      104689 :     r->addr = addr;
     402      104689 :     r->request.data = buf;
     403      104689 :     r->request.length = len;
     404      104689 :     r->datagram_reply = datagram_reply;
     405      104689 :     r->reply = reply;
     406      104689 :     r->kv = heim_dict_create(10);
     407      104689 :     r->attributes = heim_dict_create(1);
     408      104689 :     if (r->kv == NULL || r->attributes == NULL) {
     409           0 :         heim_release(r->kv);
     410           0 :         heim_release(r->attributes);
     411           0 :         free(r);
     412           0 :         return krb5_enomem(context);
     413             :     }
     414             : 
     415      104689 :     gettimeofday(&r->tv_start, NULL);
     416             : 
     417      160631 :     for (i = 0; services[i].process != NULL; i++) {
     418      157218 :         if (krb5_only && (services[i].flags & KS_KRB5) == 0)
     419           0 :             continue;
     420      157218 :         kdc_log(context, config, 7, "Probing for %s", services[i].name);
     421      157218 :         ret = (*services[i].process)(&r, &claim);
     422      157218 :         if (claim) {
     423      104689 :             if (prependlength && services[i].flags & KS_NO_LENGTH)
     424           0 :                 *prependlength = 0;
     425             : 
     426      104689 :             if (r->use_request_t) {
     427      104689 :                 gettimeofday(&r->tv_end, NULL);
     428      104689 :                 _kdc_audit_trail(r, ret);
     429      104689 :                 free(r->cname);
     430      104689 :                 free(r->sname);
     431      104689 :                 free(r->e_text_buf);
     432      104689 :                 krb5_data_free(&r->e_data);
     433             :             }
     434             : 
     435      104689 :             heim_release(r->reason);
     436      104689 :             heim_release(r->kv);
     437      104689 :             heim_release(r->attributes);
     438      104689 :             free(r);
     439      104689 :             return ret;
     440             :         }
     441             :     }
     442             : 
     443           0 :     heim_release(r->reason);
     444           0 :     heim_release(r->kv);
     445           0 :     heim_release(r->attributes);
     446           0 :     free(r);
     447           0 :     return -1;
     448             : }
     449             : 
     450             : /*
     451             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     452             :  * sending a reply in `reply'.
     453             :  */
     454             : 
     455             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     456           0 : krb5_kdc_process_request(krb5_context context,
     457             :                          krb5_kdc_configuration *config,
     458             :                          unsigned char *buf,
     459             :                          size_t len,
     460             :                          krb5_data *reply,
     461             :                          krb5_boolean *prependlength,
     462             :                          const char *from,
     463             :                          struct sockaddr *addr,
     464             :                          int datagram_reply)
     465             : {
     466           0 :     return process_request(context, config, 0, buf, len, reply, prependlength,
     467             :                            from, addr, datagram_reply);
     468             : }
     469             :  
     470             : /*
     471             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     472             :  * sending a reply in `reply'.
     473             :  *
     474             :  * This only processes krb5 requests
     475             :  */
     476             : 
     477             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     478      104689 : krb5_kdc_process_krb5_request(krb5_context context,
     479             :                               krb5_kdc_configuration *config,
     480             :                               unsigned char *buf,
     481             :                               size_t len,
     482             :                               krb5_data *reply,
     483             :                               const char *from,
     484             :                               struct sockaddr *addr,
     485             :                               int datagram_reply)
     486             : {
     487      104689 :     return process_request(context, config, 1, buf, len, reply, NULL,
     488             :                            from, addr, datagram_reply);
     489             : }
     490             : 
     491             : 
     492             : /*
     493             :  *
     494             :  */
     495             : 
     496             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     497           0 : krb5_kdc_save_request(krb5_context context,
     498             :                       const char *fn,
     499             :                       const unsigned char *buf,
     500             :                       size_t len,
     501             :                       const krb5_data *reply,
     502             :                       const struct sockaddr *sa)
     503             : {
     504           0 :     krb5_storage *sp;
     505           0 :     krb5_address a;
     506           0 :     int fd = -1;
     507           0 :     int ret = 0;
     508           0 :     uint32_t t;
     509           0 :     krb5_data d;
     510             : 
     511           0 :     memset(&a, 0, sizeof(a));
     512             : 
     513           0 :     d.data = rk_UNCONST(buf); /* do not free here */
     514           0 :     d.length = len;
     515           0 :     t = _kdc_now.tv_sec;
     516             : 
     517           0 :     sp = krb5_storage_emem();
     518           0 :     if (sp == NULL)
     519           0 :         ret = krb5_enomem(context);
     520             : 
     521           0 :     if (ret == 0)
     522           0 :         ret = krb5_sockaddr2address(context, sa, &a);
     523           0 :     if (ret == 0)
     524           0 :         ret = krb5_store_uint32(sp, 1);
     525           0 :     if (ret == 0)
     526           0 :         ret = krb5_store_uint32(sp, t);
     527           0 :     if (ret == 0)
     528           0 :         ret = krb5_store_address(sp, a);
     529           0 :     if (ret == 0)
     530           0 :         ret = krb5_store_data(sp, d);
     531           0 :     d.length = 0;
     532           0 :     d.data = NULL;
     533           0 :     if (ret == 0) {
     534           0 :         Der_class cl;
     535           0 :         Der_type ty;
     536           0 :         unsigned int tag;
     537           0 :         ret = der_get_tag (reply->data, reply->length,
     538             :                            &cl, &ty, &tag, NULL);
     539           0 :         if (ret) {
     540           0 :             ret = krb5_store_uint32(sp, 0xffffffff);
     541           0 :             if (ret == 0)
     542           0 :                 ret = krb5_store_uint32(sp, 0xffffffff);
     543             :         } else {
     544           0 :             ret = krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
     545           0 :             if (ret == 0)
     546           0 :                 ret = krb5_store_uint32(sp, tag);
     547             :         }
     548             :     }
     549             : 
     550           0 :     if (ret == 0)
     551           0 :         ret = krb5_storage_to_data(sp, &d);
     552           0 :     krb5_storage_free(sp);
     553           0 :     sp = NULL;
     554             : 
     555             :     /*
     556             :      * We've got KDC concurrency, so we're going to try to do a single O_APPEND
     557             :      * write(2).  Hopefully we manage to write enough of the header that one
     558             :      * can skip this request if it fails to write completely.
     559             :      */
     560           0 :     if (ret == 0)
     561           0 :         fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
     562           0 :     if (fd < 0)
     563           0 :         krb5_set_error_message(context, ret = errno, "Failed to open: %s", fn);
     564           0 :     if (ret == 0) {
     565           0 :         sp = krb5_storage_from_fd(fd);
     566           0 :         if (sp == NULL)
     567           0 :             krb5_set_error_message(context, ret = ENOMEM,
     568             :                                    "Storage failed to open fd");
     569             :     }
     570           0 :     (void) close(fd);
     571           0 :     if (ret == 0)
     572           0 :         ret = krb5_store_data(sp, d);
     573           0 :     krb5_free_address(context, &a);
     574             :     /*
     575             :      * krb5_storage_free() currently always returns 0, but for FDs it sets
     576             :      * errno to whatever close() set it to if it failed.
     577             :      */
     578           0 :     errno = 0;
     579           0 :     if (ret == 0)
     580           0 :         ret = krb5_storage_free(sp);
     581             :     else
     582           0 :         (void) krb5_storage_free(sp);
     583           0 :     if (ret == 0 && errno)
     584           0 :         ret = errno;
     585             : 
     586           0 :     return ret;
     587             : }
     588             : 
     589             : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
     590           0 : kdc_request_set_attribute(kdc_request_t r, kdc_object_t key, kdc_object_t value)
     591             : {
     592           0 :     return heim_dict_set_value(r->attributes, key, value);
     593             : }
     594             : 
     595             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     596           0 : kdc_request_get_attribute(kdc_request_t r, kdc_object_t key)
     597             : {
     598           0 :     return heim_dict_get_value(r->attributes, key);
     599             : }
     600             : 
     601             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     602           0 : kdc_request_copy_attribute(kdc_request_t r, kdc_object_t key)
     603             : {
     604           0 :     return heim_dict_copy_value(r->attributes, key);
     605             : }
     606             : 
     607             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     608           0 : kdc_request_delete_attribute(kdc_request_t r, kdc_object_t key)
     609             : {
     610           0 :     heim_dict_delete_key(r->attributes, key);
     611           0 : }

Generated by: LCOV version 1.14