LCOV - code coverage report
Current view: top level - third_party/heimdal/kdc - process.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 111 255 43.5 %
Date: 2024-02-14 10:14:15 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        1356 : kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
      54             :         __attribute__ ((__format__ (__printf__, 2, 3)))
      55             : {
      56             :     va_list ap;
      57             : 
      58        1356 :     va_start(ap, fmt);
      59        1356 :     heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
      60        1356 :     va_end(ap);
      61        1356 : }
      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      292715 : 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      292715 :     va_start(ap, fmt);
      85      292715 :     heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
      86      292715 :     va_end(ap);
      87      292715 : }
      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      259472 : kdc_audit_setkv_number(kdc_request_t r, const char *k, int64_t v)
     111             : {
     112      259472 :     heim_audit_setkv_number((heim_svc_req_desc)r, k, v);
     113      259472 : }
     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       18737 : kdc_audit_getkv(kdc_request_t r, const char *k)
     129             : {
     130       18737 :     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       71211 : _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
     159             : {
     160       71211 :     const char *retname = NULL;
     161             : 
     162             :     /* Get a symbolic name for some error codes */
     163             : #define CASE(x) case x : retname = #x; break
     164       71211 :     switch (ret ? ret : r->error_code) {
     165           0 :     CASE(ENOMEM);
     166           0 :     CASE(EACCES);
     167        3048 :     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          32 :     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       11306 :     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        1096 :     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          12 :     CASE(KRB5KRB_AP_ERR_BAD_INTEGRITY);
     195           0 :     CASE(KRB5KRB_AP_ERR_BADKEYVER);
     196           2 :     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          20 :     CASE(KRB5KRB_AP_ERR_INAPP_CKSUM);
     202           0 :     CASE(KRB5KRB_AP_ERR_METHOD);
     203           0 :     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           8 :     CASE(KRB5KRB_AP_ERR_SKEW);
     210           0 :     CASE(KRB5KRB_AP_ERR_TKT_EXPIRED);
     211           0 :     CASE(KRB5KRB_AP_ERR_TKT_INVALID);
     212           0 :     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           0 :     CASE(KRB5KRB_ERR_GENERIC);
     218        7742 :     CASE(KRB5KRB_ERR_RESPONSE_TOO_BIG);
     219             : 
     220       46932 :     case 0:
     221       46932 :         retname = "SUCCESS";
     222       46932 :         break;
     223          59 :     default:
     224          59 :         retname = NULL;
     225          59 :         break;
     226             :     }
     227             : 
     228             :     /* Let's save a few bytes */
     229             : #define PREFIX "KRB5KDC_"
     230       71211 :     if (retname && strncmp(PREFIX, retname, strlen(PREFIX)) == 0)
     231       13388 :         retname += strlen(PREFIX);
     232             : #undef PREFIX
     233             : 
     234       71211 :     heim_audit_trail((heim_svc_req_desc)r, ret, retname);
     235       71211 : }
     236             : 
     237             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     238       71211 : krb5_kdc_update_time(struct timeval *tv)
     239             : {
     240       71211 :     if (tv == NULL)
     241       71211 :         gettimeofday(&_kdc_now, NULL);
     242             :     else
     243           0 :         _kdc_now = *tv;
     244       71211 : }
     245             : 
     246             : KDC_LIB_FUNCTION struct timeval KDC_LIB_CALL
     247       36083 : krb5_kdc_get_time(void)
     248             : {
     249       36083 :     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       71211 : kdc_as_req(kdc_request_t *rptr, int *claim)
     265             : {
     266             :     astgs_request_t r;
     267             :     krb5_error_code ret;
     268             :     size_t len;
     269             : 
     270             :     /* We must free things in the extensions */
     271       71211 :     EXTEND_REQUEST_T(*rptr, r);
     272             : 
     273       71211 :     ret = decode_AS_REQ(r->request.data, r->request.length, &r->req, &len);
     274       71211 :     if (ret)
     275       38759 :         return ret;
     276             : 
     277       32452 :     r->reqtype = "AS-REQ";
     278       32452 :     r->use_request_t = 1;
     279       32452 :     *claim = 1;
     280             : 
     281       32452 :     ret = _kdc_as_rep(r);
     282       32452 :     free_AS_REQ(&r->req);
     283       32452 :     return ret;
     284             : }
     285             : 
     286             : 
     287             : static krb5_error_code
     288       38759 : kdc_tgs_req(kdc_request_t *rptr, int *claim)
     289             : {
     290             :     astgs_request_t r;
     291             :     krb5_error_code ret;
     292             :     size_t len;
     293             : 
     294             :     /* We must free things in the extensions */
     295       38759 :     EXTEND_REQUEST_T(*rptr, r);
     296             : 
     297       38759 :     ret = decode_TGS_REQ(r->request.data, r->request.length, &r->req, &len);
     298       38759 :     if (ret)
     299           0 :         return ret;
     300             : 
     301       38759 :     r->reqtype = "TGS-REQ";
     302       38759 :     r->use_request_t = 1;
     303       38759 :     *claim = 1;
     304             : 
     305       38759 :     ret = _kdc_tgs_rep(r);
     306       38759 :     free_TGS_REQ(&r->req);
     307       38759 :     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       71211 : 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             :     kdc_request_t r;
     388             :     krb5_error_code ret;
     389             :     unsigned int i;
     390       71211 :     int claim = 0;
     391             : 
     392       71211 :     r = calloc(sizeof(*r), 1);
     393       71211 :     if (!r)
     394           0 :         return krb5_enomem(context);
     395             : 
     396       71211 :     r->context = context;
     397       71211 :     r->hcontext = context->hcontext;
     398       71211 :     r->config = config;
     399       71211 :     r->logf = config->logf;
     400       71211 :     r->from = from;
     401       71211 :     r->addr = addr;
     402       71211 :     r->request.data = buf;
     403       71211 :     r->request.length = len;
     404       71211 :     r->datagram_reply = datagram_reply;
     405       71211 :     r->reply = reply;
     406       71211 :     r->kv = heim_dict_create(10);
     407       71211 :     r->attributes = heim_dict_create(1);
     408       71211 :     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       71211 :     gettimeofday(&r->tv_start, NULL);
     416             : 
     417      109970 :     for (i = 0; services[i].process != NULL; i++) {
     418      109970 :         if (krb5_only && (services[i].flags & KS_KRB5) == 0)
     419           0 :             continue;
     420      109970 :         kdc_log(context, config, 7, "Probing for %s", services[i].name);
     421      109970 :         ret = (*services[i].process)(&r, &claim);
     422      109970 :         if (claim) {
     423       71211 :             if (prependlength && services[i].flags & KS_NO_LENGTH)
     424           0 :                 *prependlength = 0;
     425             : 
     426       71211 :             if (r->use_request_t) {
     427       71211 :                 gettimeofday(&r->tv_end, NULL);
     428       71211 :                 _kdc_audit_trail(r, ret);
     429       71211 :                 free(r->cname);
     430       71211 :                 free(r->sname);
     431       71211 :                 free(r->e_text_buf);
     432             :             }
     433             : 
     434       71211 :             heim_release(r->reason);
     435       71211 :             heim_release(r->kv);
     436       71211 :             heim_release(r->attributes);
     437       71211 :             free(r);
     438       71211 :             return ret;
     439             :         }
     440             :     }
     441             : 
     442           0 :     heim_release(r->reason);
     443           0 :     heim_release(r->kv);
     444           0 :     heim_release(r->attributes);
     445           0 :     free(r);
     446           0 :     return -1;
     447             : }
     448             : 
     449             : /*
     450             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     451             :  * sending a reply in `reply'.
     452             :  */
     453             : 
     454             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     455           0 : krb5_kdc_process_request(krb5_context context,
     456             :                          krb5_kdc_configuration *config,
     457             :                          unsigned char *buf,
     458             :                          size_t len,
     459             :                          krb5_data *reply,
     460             :                          krb5_boolean *prependlength,
     461             :                          const char *from,
     462             :                          struct sockaddr *addr,
     463             :                          int datagram_reply)
     464             : {
     465           0 :     return process_request(context, config, 0, buf, len, reply, prependlength,
     466             :                            from, addr, datagram_reply);
     467             : }
     468             :  
     469             : /*
     470             :  * handle the request in `buf, len', from `addr' (or `from' as a string),
     471             :  * sending a reply in `reply'.
     472             :  *
     473             :  * This only processes krb5 requests
     474             :  */
     475             : 
     476             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     477       71211 : krb5_kdc_process_krb5_request(krb5_context context,
     478             :                               krb5_kdc_configuration *config,
     479             :                               unsigned char *buf,
     480             :                               size_t len,
     481             :                               krb5_data *reply,
     482             :                               const char *from,
     483             :                               struct sockaddr *addr,
     484             :                               int datagram_reply)
     485             : {
     486       71211 :     return process_request(context, config, 1, buf, len, reply, NULL,
     487             :                            from, addr, datagram_reply);
     488             : }
     489             : 
     490             : 
     491             : /*
     492             :  *
     493             :  */
     494             : 
     495             : KDC_LIB_FUNCTION int KDC_LIB_CALL
     496           0 : krb5_kdc_save_request(krb5_context context,
     497             :                       const char *fn,
     498             :                       const unsigned char *buf,
     499             :                       size_t len,
     500             :                       const krb5_data *reply,
     501             :                       const struct sockaddr *sa)
     502             : {
     503             :     krb5_storage *sp;
     504             :     krb5_address a;
     505           0 :     int fd = -1;
     506           0 :     int ret = 0;
     507             :     uint32_t t;
     508             :     krb5_data d;
     509             : 
     510           0 :     memset(&a, 0, sizeof(a));
     511             : 
     512           0 :     d.data = rk_UNCONST(buf); /* do not free here */
     513           0 :     d.length = len;
     514           0 :     t = _kdc_now.tv_sec;
     515             : 
     516           0 :     sp = krb5_storage_emem();
     517           0 :     if (sp == NULL)
     518           0 :         ret = krb5_enomem(context);
     519             : 
     520           0 :     if (ret == 0)
     521           0 :         ret = krb5_sockaddr2address(context, sa, &a);
     522           0 :     if (ret == 0)
     523           0 :         ret = krb5_store_uint32(sp, 1);
     524           0 :     if (ret == 0)
     525           0 :         ret = krb5_store_uint32(sp, t);
     526           0 :     if (ret == 0)
     527           0 :         ret = krb5_store_address(sp, a);
     528           0 :     if (ret == 0)
     529           0 :         ret = krb5_store_data(sp, d);
     530           0 :     d.length = 0;
     531           0 :     d.data = NULL;
     532           0 :     if (ret == 0) {
     533             :         Der_class cl;
     534             :         Der_type ty;
     535             :         unsigned int tag;
     536           0 :         ret = der_get_tag (reply->data, reply->length,
     537             :                            &cl, &ty, &tag, NULL);
     538           0 :         if (ret) {
     539           0 :             ret = krb5_store_uint32(sp, 0xffffffff);
     540           0 :             if (ret == 0)
     541           0 :                 ret = krb5_store_uint32(sp, 0xffffffff);
     542             :         } else {
     543           0 :             ret = krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
     544           0 :             if (ret == 0)
     545           0 :                 ret = krb5_store_uint32(sp, tag);
     546             :         }
     547             :     }
     548             : 
     549           0 :     if (ret == 0)
     550           0 :         ret = krb5_storage_to_data(sp, &d);
     551           0 :     krb5_storage_free(sp);
     552           0 :     sp = NULL;
     553             : 
     554             :     /*
     555             :      * We've got KDC concurrency, so we're going to try to do a single O_APPEND
     556             :      * write(2).  Hopefully we manage to write enough of the header that one
     557             :      * can skip this request if it fails to write completely.
     558             :      */
     559           0 :     if (ret == 0)
     560           0 :         fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
     561           0 :     if (fd < 0)
     562           0 :         krb5_set_error_message(context, ret = errno, "Failed to open: %s", fn);
     563           0 :     if (ret == 0) {
     564           0 :         sp = krb5_storage_from_fd(fd);
     565           0 :         if (sp == NULL)
     566           0 :             krb5_set_error_message(context, ret = ENOMEM,
     567             :                                    "Storage failed to open fd");
     568             :     }
     569           0 :     (void) close(fd);
     570           0 :     if (ret == 0)
     571           0 :         ret = krb5_store_data(sp, d);
     572           0 :     krb5_free_address(context, &a);
     573             :     /*
     574             :      * krb5_storage_free() currently always returns 0, but for FDs it sets
     575             :      * errno to whatever close() set it to if it failed.
     576             :      */
     577           0 :     errno = 0;
     578           0 :     if (ret == 0)
     579           0 :         ret = krb5_storage_free(sp);
     580             :     else
     581           0 :         (void) krb5_storage_free(sp);
     582           0 :     if (ret == 0 && errno)
     583           0 :         ret = errno;
     584             : 
     585           0 :     return ret;
     586             : }
     587             : 
     588             : KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
     589           0 : kdc_request_set_attribute(kdc_request_t r, kdc_object_t key, kdc_object_t value)
     590             : {
     591           0 :     return heim_dict_set_value(r->attributes, key, value);
     592             : }
     593             : 
     594             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     595           0 : kdc_request_get_attribute(kdc_request_t r, kdc_object_t key)
     596             : {
     597           0 :     return heim_dict_get_value(r->attributes, key);
     598             : }
     599             : 
     600             : KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
     601           0 : kdc_request_copy_attribute(kdc_request_t r, kdc_object_t key)
     602             : {
     603           0 :     return heim_dict_copy_value(r->attributes, key);
     604             : }
     605             : 
     606             : KDC_LIB_FUNCTION void KDC_LIB_CALL
     607           0 : kdc_request_delete_attribute(kdc_request_t r, kdc_object_t key)
     608             : {
     609           0 :     heim_dict_delete_key(r->attributes, key);
     610           0 : }

Generated by: LCOV version 1.14