root/source4/heimdal/kdc/kerberos5.c

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

DEFINITIONS

This source file includes following definitions.
  1. _kdc_fix_time
  2. realloc_method_data
  3. set_salt_padata
  4. _kdc_find_padata
  5. _kdc_is_weak_expection
  6. is_default_salt_p
  7. _kdc_find_etype
  8. _kdc_make_anonymous_principalname
  9. _kdc_log_timestamp
  10. log_patypes
  11. _kdc_encode_reply
  12. older_enctype
  13. only_older_enctype_p
  14. make_etype_info_entry
  15. get_pa_etype_info
  16. make_etype_info2_entry
  17. get_pa_etype_info2
  18. log_as_req
  19. _kdc_check_flags
  20. _kdc_check_addresses
  21. send_pac_p
  22. _kdc_as_rep
  23. _kdc_tkt_add_if_relevant_ad

   1 /*
   2  * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "kdc_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 #define MAX_TIME ((time_t)((1U << 31) - 1))
  39 
  40 void
  41 _kdc_fix_time(time_t **t)
     /* [<][>][^][v][top][bottom][index][help] */
  42 {
  43     if(*t == NULL){
  44         ALLOC(*t);
  45         **t = MAX_TIME;
  46     }
  47     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
  48 }
  49 
  50 static int
  51 realloc_method_data(METHOD_DATA *md)
     /* [<][>][^][v][top][bottom][index][help] */
  52 {
  53     PA_DATA *pa;
  54     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
  55     if(pa == NULL)
  56         return ENOMEM;
  57     md->val = pa;
  58     md->len++;
  59     return 0;
  60 }
  61 
  62 static void
  63 set_salt_padata (METHOD_DATA *md, Salt *salt)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65     if (salt) {
  66         realloc_method_data(md);
  67         md->val[md->len - 1].padata_type = salt->type;
  68         der_copy_octet_string(&salt->salt,
  69                               &md->val[md->len - 1].padata_value);
  70     }
  71 }
  72 
  73 const PA_DATA*
  74 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76     if (req->padata == NULL)
  77         return NULL;
  78 
  79     while(*start < req->padata->len){
  80         (*start)++;
  81         if(req->padata->val[*start - 1].padata_type == type)
  82             return &req->padata->val[*start - 1];
  83     }
  84     return NULL;
  85 }
  86 
  87 /*
  88  * This is a hack to allow predefined weak services, like afs to
  89  * still use weak types
  90  */
  91 
  92 krb5_boolean
  93 _kdc_is_weak_expection(krb5_principal principal, krb5_enctype etype)
     /* [<][>][^][v][top][bottom][index][help] */
  94 {
  95     if (principal->name.name_string.len > 0 &&
  96         strcmp(principal->name.name_string.val[0], "afs") == 0 &&
  97         (etype == ETYPE_DES_CBC_CRC
  98          || etype == ETYPE_DES_CBC_MD4
  99          || etype == ETYPE_DES_CBC_MD5))
 100         return TRUE;
 101     return FALSE;
 102 }
 103 
 104 
 105 /*
 106  * Detect if `key' is the using the the precomputed `default_salt'.
 107  */
 108 
 109 static krb5_boolean
 110 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
     /* [<][>][^][v][top][bottom][index][help] */
 111 {
 112     if (key->salt == NULL)
 113         return TRUE;
 114     if (default_salt->salttype != key->salt->type)
 115         return FALSE;
 116     if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
 117         return FALSE;
 118     return TRUE;
 119 }
 120 
 121 /*
 122  * return the first appropriate key of `princ' in `ret_key'.  Look for
 123  * all the etypes in (`etypes', `len'), stopping as soon as we find
 124  * one, but preferring one that has default salt
 125  */
 126 
 127 krb5_error_code
 128 _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ,
     /* [<][>][^][v][top][bottom][index][help] */
 129                 krb5_enctype *etypes, unsigned len,
 130                 Key **ret_key, krb5_enctype *ret_etype)
 131 {
 132     int i;
 133     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
 134     krb5_salt def_salt;
 135 
 136     krb5_get_pw_salt (context, princ->entry.principal, &def_salt);
 137 
 138     for(i = 0; ret != 0 && i < len ; i++) {
 139         Key *key = NULL;
 140 
 141         if (krb5_enctype_valid(context, etypes[i]) != 0 &&
 142             !_kdc_is_weak_expection(princ->entry.principal, etypes[i]))
 143             continue;
 144 
 145         while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
 146             if (key->key.keyvalue.length == 0) {
 147                 ret = KRB5KDC_ERR_NULL_KEY;
 148                 continue;
 149             }
 150             *ret_key   = key;
 151             *ret_etype = etypes[i];
 152             ret = 0;
 153             if (is_default_salt_p(&def_salt, key)) {
 154                 krb5_free_salt (context, def_salt);
 155                 return ret;
 156             }
 157         }
 158     }
 159     krb5_free_salt (context, def_salt);
 160     return ret;
 161 }
 162 
 163 krb5_error_code
 164 _kdc_make_anonymous_principalname (PrincipalName *pn)
     /* [<][>][^][v][top][bottom][index][help] */
 165 {
 166     pn->name_type = KRB5_NT_PRINCIPAL;
 167     pn->name_string.len = 1;
 168     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
 169     if (pn->name_string.val == NULL)
 170         return ENOMEM;
 171     pn->name_string.val[0] = strdup("anonymous");
 172     if (pn->name_string.val[0] == NULL) {
 173         free(pn->name_string.val);
 174         pn->name_string.val = NULL;
 175         return ENOMEM;
 176     }
 177     return 0;
 178 }
 179 
 180 void
 181 _kdc_log_timestamp(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 182                    krb5_kdc_configuration *config,
 183                    const char *type,
 184                    KerberosTime authtime, KerberosTime *starttime,
 185                    KerberosTime endtime, KerberosTime *renew_till)
 186 {
 187     char authtime_str[100], starttime_str[100],
 188         endtime_str[100], renewtime_str[100];
 189 
 190     krb5_format_time(context, authtime,
 191                      authtime_str, sizeof(authtime_str), TRUE);
 192     if (starttime)
 193         krb5_format_time(context, *starttime,
 194                          starttime_str, sizeof(starttime_str), TRUE);
 195     else
 196         strlcpy(starttime_str, "unset", sizeof(starttime_str));
 197     krb5_format_time(context, endtime,
 198                      endtime_str, sizeof(endtime_str), TRUE);
 199     if (renew_till)
 200         krb5_format_time(context, *renew_till,
 201                          renewtime_str, sizeof(renewtime_str), TRUE);
 202     else
 203         strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
 204 
 205     kdc_log(context, config, 5,
 206             "%s authtime: %s starttime: %s endtime: %s renew till: %s",
 207             type, authtime_str, starttime_str, endtime_str, renewtime_str);
 208 }
 209 
 210 static void
 211 log_patypes(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 212             krb5_kdc_configuration *config,
 213             METHOD_DATA *padata)
 214 {
 215     struct rk_strpool *p = NULL;
 216     char *str;
 217     int i;
 218         
 219     for (i = 0; i < padata->len; i++) {
 220         switch(padata->val[i].padata_type) {
 221         case KRB5_PADATA_PK_AS_REQ:
 222             p = rk_strpoolprintf(p, "PK-INIT(ietf)");
 223             break;
 224         case KRB5_PADATA_PK_AS_REQ_WIN:
 225             p = rk_strpoolprintf(p, "PK-INIT(win2k)");
 226             break;
 227         case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
 228             p = rk_strpoolprintf(p, "OCSP");
 229             break;
 230         case KRB5_PADATA_ENC_TIMESTAMP:
 231             p = rk_strpoolprintf(p, "encrypted-timestamp");
 232             break;
 233         default:
 234             p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
 235             break;
 236         }
 237         if (p && i + 1 < padata->len)
 238             p = rk_strpoolprintf(p, ", ");
 239         if (p == NULL) {
 240             kdc_log(context, config, 0, "out of memory");
 241             return;
 242         }
 243     }
 244     if (p == NULL)
 245         p = rk_strpoolprintf(p, "none");
 246         
 247     str = rk_strpoolcollect(p);
 248     kdc_log(context, config, 0, "Client sent patypes: %s", str);
 249     free(str);
 250 }
 251 
 252 /*
 253  *
 254  */
 255 
 256 
 257 krb5_error_code
 258 _kdc_encode_reply(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 259                   krb5_kdc_configuration *config,
 260                   KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
 261                   krb5_enctype etype,
 262                   int skvno, const EncryptionKey *skey,
 263                   int ckvno, const EncryptionKey *ckey,
 264                   const char **e_text,
 265                   krb5_data *reply)
 266 {
 267     unsigned char *buf;
 268     size_t buf_size;
 269     size_t len;
 270     krb5_error_code ret;
 271     krb5_crypto crypto;
 272 
 273     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
 274     if(ret) {
 275         kdc_log(context, config, 0, "Failed to encode ticket: %s",
 276                 krb5_get_err_text(context, ret));
 277         return ret;
 278     }
 279     if(buf_size != len) {
 280         free(buf);
 281         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
 282         *e_text = "KDC internal error";
 283         return KRB5KRB_ERR_GENERIC;
 284     }
 285 
 286     ret = krb5_crypto_init(context, skey, etype, &crypto);
 287     if (ret) {
 288         free(buf);
 289         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
 290                 krb5_get_err_text(context, ret));
 291         return ret;
 292     }
 293 
 294     ret = krb5_encrypt_EncryptedData(context,
 295                                      crypto,
 296                                      KRB5_KU_TICKET,
 297                                      buf,
 298                                      len,
 299                                      skvno,
 300                                      &rep->ticket.enc_part);
 301     free(buf);
 302     krb5_crypto_destroy(context, crypto);
 303     if(ret) {
 304         kdc_log(context, config, 0, "Failed to encrypt data: %s",
 305                 krb5_get_err_text(context, ret));
 306         return ret;
 307     }
 308 
 309     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
 310         ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
 311     else
 312         ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
 313     if(ret) {
 314         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
 315                 krb5_get_err_text(context, ret));
 316         return ret;
 317     }
 318     if(buf_size != len) {
 319         free(buf);
 320         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
 321         *e_text = "KDC internal error";
 322         return KRB5KRB_ERR_GENERIC;
 323     }
 324     ret = krb5_crypto_init(context, ckey, 0, &crypto);
 325     if (ret) {
 326         free(buf);
 327         kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
 328                 krb5_get_err_text(context, ret));
 329         return ret;
 330     }
 331     if(rep->msg_type == krb_as_rep) {
 332         krb5_encrypt_EncryptedData(context,
 333                                    crypto,
 334                                    KRB5_KU_AS_REP_ENC_PART,
 335                                    buf,
 336                                    len,
 337                                    ckvno,
 338                                    &rep->enc_part);
 339         free(buf);
 340         ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
 341     } else {
 342         krb5_encrypt_EncryptedData(context,
 343                                    crypto,
 344                                    KRB5_KU_TGS_REP_ENC_PART_SESSION,
 345                                    buf,
 346                                    len,
 347                                    ckvno,
 348                                    &rep->enc_part);
 349         free(buf);
 350         ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
 351     }
 352     krb5_crypto_destroy(context, crypto);
 353     if(ret) {
 354         kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
 355                 krb5_get_err_text(context, ret));
 356         return ret;
 357     }
 358     if(buf_size != len) {
 359         free(buf);
 360         kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
 361         *e_text = "KDC internal error";
 362         return KRB5KRB_ERR_GENERIC;
 363     }
 364     reply->data = buf;
 365     reply->length = buf_size;
 366     return 0;
 367 }
 368 
 369 /*
 370  * Return 1 if the client have only older enctypes, this is for
 371  * determining if the server should send ETYPE_INFO2 or not.
 372  */
 373 
 374 static int
 375 older_enctype(krb5_enctype enctype)
     /* [<][>][^][v][top][bottom][index][help] */
 376 {
 377     switch (enctype) {
 378     case ETYPE_DES_CBC_CRC:
 379     case ETYPE_DES_CBC_MD4:
 380     case ETYPE_DES_CBC_MD5:
 381     case ETYPE_DES3_CBC_SHA1:
 382     case ETYPE_ARCFOUR_HMAC_MD5:
 383     case ETYPE_ARCFOUR_HMAC_MD5_56:
 384     /*
 385      * The following three is "old" windows enctypes and is needed for
 386      * windows 2000 hosts.
 387      */
 388     case ETYPE_ARCFOUR_MD4:
 389     case ETYPE_ARCFOUR_HMAC_OLD:
 390     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
 391         return 1;
 392     default:
 393         return 0;
 394     }
 395 }
 396 
 397 static int
 398 only_older_enctype_p(const KDC_REQ *req)
     /* [<][>][^][v][top][bottom][index][help] */
 399 {
 400     int i;
 401 
 402     for(i = 0; i < req->req_body.etype.len; i++) {
 403         if (!older_enctype(req->req_body.etype.val[i]))
 404             return 0;
 405     }
 406     return 1;
 407 }
 408 
 409 /*
 410  *
 411  */
 412 
 413 static krb5_error_code
 414 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
     /* [<][>][^][v][top][bottom][index][help] */
 415 {
 416     ent->etype = key->key.keytype;
 417     if(key->salt){
 418 #if 0
 419         ALLOC(ent->salttype);
 420 
 421         if(key->salt->type == hdb_pw_salt)
 422             *ent->salttype = 0; /* or 1? or NULL? */
 423         else if(key->salt->type == hdb_afs3_salt)
 424             *ent->salttype = 2;
 425         else {
 426             kdc_log(context, config, 0, "unknown salt-type: %d",
 427                     key->salt->type);
 428             return KRB5KRB_ERR_GENERIC;
 429         }
 430         /* according to `the specs', we can't send a salt if
 431            we have AFS3 salted key, but that requires that you
 432            *know* what cell you are using (e.g by assuming
 433            that the cell is the same as the realm in lower
 434            case) */
 435 #elif 0
 436         ALLOC(ent->salttype);
 437         *ent->salttype = key->salt->type;
 438 #else
 439         /*
 440          * We shouldn't sent salttype since it is incompatible with the
 441          * specification and it breaks windows clients.  The afs
 442          * salting problem is solved by using KRB5-PADATA-AFS3-SALT
 443          * implemented in Heimdal 0.7 and later.
 444          */
 445         ent->salttype = NULL;
 446 #endif
 447         krb5_copy_data(context, &key->salt->salt,
 448                        &ent->salt);
 449     } else {
 450         /* we return no salt type at all, as that should indicate
 451          * the default salt type and make everybody happy.  some
 452          * systems (like w2k) dislike being told the salt type
 453          * here. */
 454 
 455         ent->salttype = NULL;
 456         ent->salt = NULL;
 457     }
 458     return 0;
 459 }
 460 
 461 static krb5_error_code
 462 get_pa_etype_info(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 463                   krb5_kdc_configuration *config,
 464                   METHOD_DATA *md, hdb_entry *client,
 465                   ENCTYPE *etypes, unsigned int etypes_len)
 466 {
 467     krb5_error_code ret = 0;
 468     int i, j;
 469     unsigned int n = 0;
 470     ETYPE_INFO pa;
 471     unsigned char *buf;
 472     size_t len;
 473 
 474 
 475     pa.len = client->keys.len;
 476     if(pa.len > UINT_MAX/sizeof(*pa.val))
 477         return ERANGE;
 478     pa.val = malloc(pa.len * sizeof(*pa.val));
 479     if(pa.val == NULL)
 480         return ENOMEM;
 481     memset(pa.val, 0, pa.len * sizeof(*pa.val));
 482 
 483     for(i = 0; i < client->keys.len; i++) {
 484         for (j = 0; j < n; j++)
 485             if (pa.val[j].etype == client->keys.val[i].key.keytype)
 486                 goto skip1;
 487         for(j = 0; j < etypes_len; j++) {
 488             if(client->keys.val[i].key.keytype == etypes[j]) {
 489                 if (krb5_enctype_valid(context, etypes[j]) != 0)
 490                     continue;
 491                 if (!older_enctype(etypes[j]))
 492                     continue;
 493                 if (n >= pa.len)
 494                     krb5_abortx(context, "internal error: n >= p.len");
 495                 if((ret = make_etype_info_entry(context,
 496                                                 &pa.val[n++],
 497                                                 &client->keys.val[i])) != 0) {
 498                     free_ETYPE_INFO(&pa);
 499                     return ret;
 500                 }
 501                 break;
 502             }
 503         }
 504     skip1:;
 505     }
 506     for(i = 0; i < client->keys.len; i++) {
 507         /* already added? */
 508         for(j = 0; j < etypes_len; j++) {
 509             if(client->keys.val[i].key.keytype == etypes[j])
 510                 goto skip2;
 511         }
 512         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
 513             continue;
 514         if (!older_enctype(etypes[j]))
 515             continue;
 516         if (n >= pa.len)
 517             krb5_abortx(context, "internal error: n >= p.len");
 518         if((ret = make_etype_info_entry(context,
 519                                         &pa.val[n++],
 520                                         &client->keys.val[i])) != 0) {
 521             free_ETYPE_INFO(&pa);
 522             return ret;
 523         }
 524     skip2:;
 525     }
 526 
 527     if(n < pa.len) {
 528         /* stripped out dups, newer enctypes, and not valid enctypes */
 529         pa.len = n;
 530     }
 531 
 532     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
 533     free_ETYPE_INFO(&pa);
 534     if(ret)
 535         return ret;
 536     ret = realloc_method_data(md);
 537     if(ret) {
 538         free(buf);
 539         return ret;
 540     }
 541     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
 542     md->val[md->len - 1].padata_value.length = len;
 543     md->val[md->len - 1].padata_value.data = buf;
 544     return 0;
 545 }
 546 
 547 /*
 548  *
 549  */
 550 
 551 extern int _krb5_AES_string_to_default_iterator;
 552 
 553 static krb5_error_code
 554 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
     /* [<][>][^][v][top][bottom][index][help] */
 555 {
 556     ent->etype = key->key.keytype;
 557     if(key->salt) {
 558         ALLOC(ent->salt);
 559         if (ent->salt == NULL)
 560             return ENOMEM;
 561         *ent->salt = malloc(key->salt->salt.length + 1);
 562         if (*ent->salt == NULL) {
 563             free(ent->salt);
 564             ent->salt = NULL;
 565             return ENOMEM;
 566         }
 567         memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
 568         (*ent->salt)[key->salt->salt.length] = '\0';
 569     } else
 570         ent->salt = NULL;
 571 
 572     ent->s2kparams = NULL;
 573 
 574     switch (key->key.keytype) {
 575     case ETYPE_AES128_CTS_HMAC_SHA1_96:
 576     case ETYPE_AES256_CTS_HMAC_SHA1_96:
 577         ALLOC(ent->s2kparams);
 578         if (ent->s2kparams == NULL)
 579             return ENOMEM;
 580         ent->s2kparams->length = 4;
 581         ent->s2kparams->data = malloc(ent->s2kparams->length);
 582         if (ent->s2kparams->data == NULL) {
 583             free(ent->s2kparams);
 584             ent->s2kparams = NULL;
 585             return ENOMEM;
 586         }
 587         _krb5_put_int(ent->s2kparams->data,
 588                       _krb5_AES_string_to_default_iterator,
 589                       ent->s2kparams->length);
 590         break;
 591     case ETYPE_DES_CBC_CRC:
 592     case ETYPE_DES_CBC_MD4:
 593     case ETYPE_DES_CBC_MD5:
 594         /* Check if this was a AFS3 salted key */
 595         if(key->salt && key->salt->type == hdb_afs3_salt){
 596             ALLOC(ent->s2kparams);
 597             if (ent->s2kparams == NULL)
 598                 return ENOMEM;
 599             ent->s2kparams->length = 1;
 600             ent->s2kparams->data = malloc(ent->s2kparams->length);
 601             if (ent->s2kparams->data == NULL) {
 602                 free(ent->s2kparams);
 603                 ent->s2kparams = NULL;
 604                 return ENOMEM;
 605             }
 606             _krb5_put_int(ent->s2kparams->data,
 607                           1,
 608                           ent->s2kparams->length);
 609         }
 610         break;
 611     default:
 612         break;
 613     }
 614     return 0;
 615 }
 616 
 617 /*
 618  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
 619  * database (client supported enctypes first, then the unsupported
 620  * enctypes).
 621  */
 622 
 623 static krb5_error_code
 624 get_pa_etype_info2(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 625                    krb5_kdc_configuration *config,
 626                    METHOD_DATA *md, hdb_entry *client,
 627                    ENCTYPE *etypes, unsigned int etypes_len)
 628 {
 629     krb5_error_code ret = 0;
 630     int i, j;
 631     unsigned int n = 0;
 632     ETYPE_INFO2 pa;
 633     unsigned char *buf;
 634     size_t len;
 635 
 636     pa.len = client->keys.len;
 637     if(pa.len > UINT_MAX/sizeof(*pa.val))
 638         return ERANGE;
 639     pa.val = malloc(pa.len * sizeof(*pa.val));
 640     if(pa.val == NULL)
 641         return ENOMEM;
 642     memset(pa.val, 0, pa.len * sizeof(*pa.val));
 643 
 644     for(i = 0; i < client->keys.len; i++) {
 645         for (j = 0; j < n; j++)
 646             if (pa.val[j].etype == client->keys.val[i].key.keytype)
 647                 goto skip1;
 648         for(j = 0; j < etypes_len; j++) {
 649             if(client->keys.val[i].key.keytype == etypes[j]) {
 650                 if (krb5_enctype_valid(context, etypes[j]) != 0)
 651                     continue;
 652                 if (n >= pa.len)
 653                     krb5_abortx(context, "internal error: n >= p.len");
 654                 if((ret = make_etype_info2_entry(&pa.val[n++],
 655                                                  &client->keys.val[i])) != 0) {
 656                     free_ETYPE_INFO2(&pa);
 657                     return ret;
 658                 }
 659                 break;
 660             }
 661         }
 662     skip1:;
 663     }
 664     /* send enctypes that the client doesn't know about too */
 665     for(i = 0; i < client->keys.len; i++) {
 666         /* already added? */
 667         for(j = 0; j < etypes_len; j++) {
 668             if(client->keys.val[i].key.keytype == etypes[j])
 669                 goto skip2;
 670         }
 671         if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
 672             continue;
 673         if (n >= pa.len)
 674             krb5_abortx(context, "internal error: n >= p.len");
 675         if((ret = make_etype_info2_entry(&pa.val[n++],
 676                                          &client->keys.val[i])) != 0) {
 677             free_ETYPE_INFO2(&pa);
 678             return ret;
 679         }
 680       skip2:;
 681     }
 682 
 683     if(n < pa.len) {
 684         /* stripped out dups, and not valid enctypes */
 685         pa.len = n;
 686     }
 687 
 688     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
 689     free_ETYPE_INFO2(&pa);
 690     if(ret)
 691         return ret;
 692     ret = realloc_method_data(md);
 693     if(ret) {
 694         free(buf);
 695         return ret;
 696     }
 697     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
 698     md->val[md->len - 1].padata_value.length = len;
 699     md->val[md->len - 1].padata_value.data = buf;
 700     return 0;
 701 }
 702 
 703 /*
 704  *
 705  */
 706 
 707 static void
 708 log_as_req(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 709            krb5_kdc_configuration *config,
 710            krb5_enctype cetype,
 711            krb5_enctype setype,
 712            const KDC_REQ_BODY *b)
 713 {
 714     krb5_error_code ret;
 715     struct rk_strpool *p = NULL;
 716     char *str;
 717     int i;
 718 
 719     for (i = 0; i < b->etype.len; i++) {
 720         ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
 721         if (ret == 0) {
 722             p = rk_strpoolprintf(p, "%s", str);
 723             free(str);
 724         } else
 725             p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
 726         if (p && i + 1 < b->etype.len)
 727             p = rk_strpoolprintf(p, ", ");
 728         if (p == NULL) {
 729             kdc_log(context, config, 0, "out of memory");
 730             return;
 731         }
 732     }
 733     if (p == NULL)
 734         p = rk_strpoolprintf(p, "no encryption types");
 735 
 736     str = rk_strpoolcollect(p);
 737     kdc_log(context, config, 0, "Client supported enctypes: %s", str);
 738     free(str);
 739 
 740     {
 741         char *cet;
 742         char *set;
 743 
 744         ret = krb5_enctype_to_string(context, cetype, &cet);
 745         if(ret == 0) {
 746             ret = krb5_enctype_to_string(context, setype, &set);
 747             if (ret == 0) {
 748                 kdc_log(context, config, 5, "Using %s/%s", cet, set);
 749                 free(set);
 750             }
 751             free(cet);
 752         }
 753         if (ret != 0)
 754             kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
 755     }
 756 
 757     {
 758         char fixedstr[128];
 759         unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
 760                       fixedstr, sizeof(fixedstr));
 761         if(*fixedstr)
 762             kdc_log(context, config, 2, "Requested flags: %s", fixedstr);
 763     }
 764 }
 765 
 766 /*
 767  * verify the flags on `client' and `server', returning 0
 768  * if they are OK and generating an error messages and returning
 769  * and error code otherwise.
 770  */
 771 
 772 krb5_error_code
 773 _kdc_check_flags(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 774                  krb5_kdc_configuration *config,
 775                  hdb_entry_ex *client_ex, const char *client_name,
 776                  hdb_entry_ex *server_ex, const char *server_name,
 777                  krb5_boolean is_as_req)
 778 {
 779     if(client_ex != NULL) {
 780         hdb_entry *client = &client_ex->entry;
 781 
 782         /* check client */
 783         if (client->flags.invalid) {
 784             kdc_log(context, config, 0,
 785                     "Client (%s) has invalid bit set", client_name);
 786             return KRB5KDC_ERR_POLICY;
 787         }
 788         
 789         if(!client->flags.client){
 790             kdc_log(context, config, 0,
 791                     "Principal may not act as client -- %s", client_name);
 792             return KRB5KDC_ERR_POLICY;
 793         }
 794         
 795         if (client->valid_start && *client->valid_start > kdc_time) {
 796             char starttime_str[100];
 797             krb5_format_time(context, *client->valid_start,
 798                              starttime_str, sizeof(starttime_str), TRUE);
 799             kdc_log(context, config, 0,
 800                     "Client not yet valid until %s -- %s",
 801                     starttime_str, client_name);
 802             return KRB5KDC_ERR_CLIENT_NOTYET;
 803         }
 804         
 805         if (client->valid_end && *client->valid_end < kdc_time) {
 806             char endtime_str[100];
 807             krb5_format_time(context, *client->valid_end,
 808                              endtime_str, sizeof(endtime_str), TRUE);
 809             kdc_log(context, config, 0,
 810                     "Client expired at %s -- %s",
 811                     endtime_str, client_name);
 812             return KRB5KDC_ERR_NAME_EXP;
 813         }
 814         
 815         if (client->pw_end && *client->pw_end < kdc_time
 816             && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
 817             char pwend_str[100];
 818             krb5_format_time(context, *client->pw_end,
 819                              pwend_str, sizeof(pwend_str), TRUE);
 820             kdc_log(context, config, 0,
 821                     "Client's key has expired at %s -- %s",
 822                     pwend_str, client_name);
 823             return KRB5KDC_ERR_KEY_EXPIRED;
 824         }
 825     }
 826 
 827     /* check server */
 828 
 829     if (server_ex != NULL) {
 830         hdb_entry *server = &server_ex->entry;
 831 
 832         if (server->flags.invalid) {
 833             kdc_log(context, config, 0,
 834                     "Server has invalid flag set -- %s", server_name);
 835             return KRB5KDC_ERR_POLICY;
 836         }
 837 
 838         if(!server->flags.server){
 839             kdc_log(context, config, 0,
 840                     "Principal may not act as server -- %s", server_name);
 841             return KRB5KDC_ERR_POLICY;
 842         }
 843 
 844         if(!is_as_req && server->flags.initial) {
 845             kdc_log(context, config, 0,
 846                     "AS-REQ is required for server -- %s", server_name);
 847             return KRB5KDC_ERR_POLICY;
 848         }
 849 
 850         if (server->valid_start && *server->valid_start > kdc_time) {
 851             char starttime_str[100];
 852             krb5_format_time(context, *server->valid_start,
 853                              starttime_str, sizeof(starttime_str), TRUE);
 854             kdc_log(context, config, 0,
 855                     "Server not yet valid until %s -- %s",
 856                     starttime_str, server_name);
 857             return KRB5KDC_ERR_SERVICE_NOTYET;
 858         }
 859 
 860         if (server->valid_end && *server->valid_end < kdc_time) {
 861             char endtime_str[100];
 862             krb5_format_time(context, *server->valid_end,
 863                              endtime_str, sizeof(endtime_str), TRUE);
 864             kdc_log(context, config, 0,
 865                     "Server expired at %s -- %s",
 866                     endtime_str, server_name);
 867             return KRB5KDC_ERR_SERVICE_EXP;
 868         }
 869 
 870         if (server->pw_end && *server->pw_end < kdc_time) {
 871             char pwend_str[100];
 872             krb5_format_time(context, *server->pw_end,
 873                              pwend_str, sizeof(pwend_str), TRUE);
 874             kdc_log(context, config, 0,
 875                     "Server's key has expired at -- %s",
 876                     pwend_str, server_name);
 877             return KRB5KDC_ERR_KEY_EXPIRED;
 878         }
 879     }
 880     return 0;
 881 }
 882 
 883 /*
 884  * Return TRUE if `from' is part of `addresses' taking into consideration
 885  * the configuration variables that tells us how strict we should be about
 886  * these checks
 887  */
 888 
 889 krb5_boolean
 890 _kdc_check_addresses(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 891                      krb5_kdc_configuration *config,
 892                      HostAddresses *addresses, const struct sockaddr *from)
 893 {
 894     krb5_error_code ret;
 895     krb5_address addr;
 896     krb5_boolean result;
 897     krb5_boolean only_netbios = TRUE;
 898     int i;
 899 
 900     if(config->check_ticket_addresses == 0)
 901         return TRUE;
 902 
 903     if(addresses == NULL)
 904         return config->allow_null_ticket_addresses;
 905 
 906     for (i = 0; i < addresses->len; ++i) {
 907         if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
 908             only_netbios = FALSE;
 909         }
 910     }
 911 
 912     /* Windows sends it's netbios name, which I can only assume is
 913      * used for the 'allowed workstations' check.  This is painful,
 914      * but we still want to check IP addresses if they happen to be
 915      * present.
 916      */
 917 
 918     if(only_netbios)
 919         return config->allow_null_ticket_addresses;
 920 
 921     ret = krb5_sockaddr2address (context, from, &addr);
 922     if(ret)
 923         return FALSE;
 924 
 925     result = krb5_address_search(context, &addr, addresses);
 926     krb5_free_address (context, &addr);
 927     return result;
 928 }
 929 
 930 /*
 931  *
 932  */
 933 
 934 static krb5_boolean
 935 send_pac_p(krb5_context context, KDC_REQ *req)
     /* [<][>][^][v][top][bottom][index][help] */
 936 {
 937     krb5_error_code ret;
 938     PA_PAC_REQUEST pacreq;
 939     const PA_DATA *pa;
 940     int i = 0;
 941 
 942     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
 943     if (pa == NULL)
 944         return TRUE;
 945 
 946     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
 947                                 pa->padata_value.length,
 948                                 &pacreq,
 949                                 NULL);
 950     if (ret)
 951         return TRUE;
 952     i = pacreq.include_pac;
 953     free_PA_PAC_REQUEST(&pacreq);
 954     if (i == 0)
 955         return FALSE;
 956     return TRUE;
 957 }
 958 
 959 /*
 960  *
 961  */
 962 
 963 krb5_error_code
 964 _kdc_as_rep(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 965             krb5_kdc_configuration *config,
 966             KDC_REQ *req,
 967             const krb5_data *req_buffer,
 968             krb5_data *reply,
 969             const char *from,
 970             struct sockaddr *from_addr,
 971             int datagram_reply)
 972 {
 973     KDC_REQ_BODY *b = &req->req_body;
 974     AS_REP rep;
 975     KDCOptions f = b->kdc_options;
 976     hdb_entry_ex *client = NULL, *server = NULL;
 977     krb5_enctype cetype, setype, sessionetype;
 978     krb5_data e_data;
 979     EncTicketPart et;
 980     EncKDCRepPart ek;
 981     krb5_principal client_princ = NULL, server_princ = NULL;
 982     char *client_name = NULL, *server_name = NULL;
 983     krb5_error_code ret = 0;
 984     const char *e_text = NULL;
 985     krb5_crypto crypto;
 986     Key *ckey, *skey;
 987     EncryptionKey *reply_key;
 988     int flags = 0;
 989 #ifdef PKINIT
 990     pk_client_params *pkp = NULL;
 991 #endif
 992 
 993     memset(&rep, 0, sizeof(rep));
 994     krb5_data_zero(&e_data);
 995 
 996     if (f.canonicalize)
 997         flags |= HDB_F_CANON;
 998 
 999     if(b->sname == NULL){
1000         ret = KRB5KRB_ERR_GENERIC;
1001         e_text = "No server in request";
1002     } else{
1003         ret = _krb5_principalname2krb5_principal (context,
1004                                                   &server_princ,
1005                                                   *(b->sname),
1006                                                   b->realm);
1007         if (ret == 0)
1008             ret = krb5_unparse_name(context, server_princ, &server_name);
1009     }
1010     if (ret) {
1011         kdc_log(context, config, 0,
1012                 "AS-REQ malformed server name from %s", from);
1013         goto out;
1014     }
1015 
1016     if(b->cname == NULL){
1017         ret = KRB5KRB_ERR_GENERIC;
1018         e_text = "No client in request";
1019     } else {
1020 
1021         if (b->cname->name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
1022             if (b->cname->name_string.len != 1) {
1023                 kdc_log(context, config, 0,
1024                         "AS-REQ malformed canon request from %s, "
1025                         "enterprise name with %d name components",
1026                         from, b->cname->name_string.len);
1027                 ret = KRB5_PARSE_MALFORMED;
1028                 goto out;
1029             }
1030             ret = krb5_parse_name(context, b->cname->name_string.val[0],
1031                                   &client_princ);
1032             if (ret)
1033                 goto out;
1034         } else {
1035             ret = _krb5_principalname2krb5_principal (context,
1036                                                       &client_princ,
1037                                                       *(b->cname),
1038                                                       b->realm);
1039             if (ret)
1040                 goto out;
1041         }
1042         ret = krb5_unparse_name(context, client_princ, &client_name);
1043     }
1044     if (ret) {
1045         kdc_log(context, config, 0,
1046                 "AS-REQ malformed client name from %s", from);
1047         goto out;
1048     }
1049 
1050     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1051             client_name, from, server_name);
1052 
1053     ret = _kdc_db_fetch(context, config, client_princ,
1054                         HDB_F_GET_CLIENT | flags, NULL, &client);
1055     if(ret){
1056         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
1057                 krb5_get_err_text(context, ret));
1058         ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1059         goto out;
1060     }
1061 
1062     ret = _kdc_db_fetch(context, config, server_princ,
1063                         HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
1064                         NULL, &server);
1065     if(ret){
1066         kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
1067                 krb5_get_err_text(context, ret));
1068         ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1069         goto out;
1070     }
1071 
1072     ret = _kdc_windc_client_access(context, client, req, &e_data);
1073     if(ret)
1074         goto out;
1075 
1076     ret = _kdc_check_flags(context, config,
1077                            client, client_name,
1078                            server, server_name,
1079                            TRUE);
1080     if(ret)
1081         goto out;
1082 
1083     memset(&et, 0, sizeof(et));
1084     memset(&ek, 0, sizeof(ek));
1085 
1086     if(req->padata){
1087         int i;
1088         const PA_DATA *pa;
1089         int found_pa = 0;
1090 
1091         log_patypes(context, config, req->padata);
1092 
1093 #ifdef PKINIT
1094         kdc_log(context, config, 5,
1095                 "Looking for PKINIT pa-data -- %s", client_name);
1096 
1097         e_text = "No PKINIT PA found";
1098 
1099         i = 0;
1100         if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
1101             ;
1102         if (pa == NULL) {
1103             i = 0;
1104             if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
1105                 ;
1106         }
1107         if (pa) {
1108             char *client_cert = NULL;
1109 
1110             ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
1111             if (ret) {
1112                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1113                 kdc_log(context, config, 5,
1114                         "Failed to decode PKINIT PA-DATA -- %s",
1115                         client_name);
1116                 goto ts_enc;
1117             }
1118             if (ret == 0 && pkp == NULL)
1119                 goto ts_enc;
1120 
1121             ret = _kdc_pk_check_client(context,
1122                                        config,
1123                                        client,
1124                                        pkp,
1125                                        &client_cert);
1126             if (ret) {
1127                 e_text = "PKINIT certificate not allowed to "
1128                     "impersonate principal";
1129                 _kdc_pk_free_client_param(context, pkp);
1130 
1131                 kdc_log(context, config, 0, "%s", e_text);
1132                 pkp = NULL;
1133                 goto out;
1134             }
1135             found_pa = 1;
1136             et.flags.pre_authent = 1;
1137             kdc_log(context, config, 0,
1138                     "PKINIT pre-authentication succeeded -- %s using %s",
1139                     client_name, client_cert);
1140             free(client_cert);
1141             if (pkp)
1142                 goto preauth_done;
1143         }
1144     ts_enc:
1145 #endif
1146         kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
1147                 client_name);
1148 
1149         i = 0;
1150         e_text = "No ENC-TS found";
1151         while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1152             krb5_data ts_data;
1153             PA_ENC_TS_ENC p;
1154             size_t len;
1155             EncryptedData enc_data;
1156             Key *pa_key;
1157             char *str;
1158         
1159             found_pa = 1;
1160         
1161             ret = decode_EncryptedData(pa->padata_value.data,
1162                                        pa->padata_value.length,
1163                                        &enc_data,
1164                                        &len);
1165             if (ret) {
1166                 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1167                 kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
1168                         client_name);
1169                 goto out;
1170             }
1171         
1172             ret = hdb_enctype2key(context, &client->entry,
1173                                   enc_data.etype, &pa_key);
1174             if(ret){
1175                 char *estr;
1176                 e_text = "No key matches pa-data";
1177                 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1178                 if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1179                     estr = NULL;
1180                 if(estr == NULL)
1181                     kdc_log(context, config, 5,
1182                             "No client key matching pa-data (%d) -- %s",
1183                             enc_data.etype, client_name);
1184                 else
1185                     kdc_log(context, config, 5,
1186                             "No client key matching pa-data (%s) -- %s",
1187                             estr, client_name);
1188                 free(estr);
1189                 
1190                 free_EncryptedData(&enc_data);
1191                 continue;
1192             }
1193 
1194         try_next_key:
1195             ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1196             if (ret) {
1197                 kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1198                         krb5_get_err_text(context, ret));
1199                 free_EncryptedData(&enc_data);
1200                 continue;
1201             }
1202 
1203             ret = krb5_decrypt_EncryptedData (context,
1204                                               crypto,
1205                                               KRB5_KU_PA_ENC_TIMESTAMP,
1206                                               &enc_data,
1207                                               &ts_data);
1208             krb5_crypto_destroy(context, crypto);
1209             if(ret){
1210                 krb5_error_code ret2;
1211                 ret2 = krb5_enctype_to_string(context,
1212                                               pa_key->key.keytype, &str);
1213                 if (ret2)
1214                     str = NULL;
1215                 kdc_log(context, config, 5,
1216                         "Failed to decrypt PA-DATA -- %s "
1217                         "(enctype %s) error %s",
1218                         client_name,
1219                         str ? str : "unknown enctype",
1220                         krb5_get_err_text(context, ret));
1221                 free(str);
1222 
1223                 if(hdb_next_enctype2key(context, &client->entry,
1224                                         enc_data.etype, &pa_key) == 0)
1225                     goto try_next_key;
1226                 e_text = "Failed to decrypt PA-DATA";
1227 
1228                 free_EncryptedData(&enc_data);
1229                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1230                 continue;
1231             }
1232             free_EncryptedData(&enc_data);
1233             ret = decode_PA_ENC_TS_ENC(ts_data.data,
1234                                        ts_data.length,
1235                                        &p,
1236                                        &len);
1237             krb5_data_free(&ts_data);
1238             if(ret){
1239                 e_text = "Failed to decode PA-ENC-TS-ENC";
1240                 ret = KRB5KDC_ERR_PREAUTH_FAILED;
1241                 kdc_log(context, config,
1242                         5, "Failed to decode PA-ENC-TS_ENC -- %s",
1243                         client_name);
1244                 continue;
1245             }
1246             free_PA_ENC_TS_ENC(&p);
1247             if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1248                 char client_time[100];
1249                 
1250                 krb5_format_time(context, p.patimestamp,
1251                                  client_time, sizeof(client_time), TRUE);
1252 
1253                 ret = KRB5KRB_AP_ERR_SKEW;
1254                 kdc_log(context, config, 0,
1255                         "Too large time skew, "
1256                         "client time %s is out by %u > %u seconds -- %s",
1257                         client_time,
1258                         (unsigned)abs(kdc_time - p.patimestamp),
1259                         context->max_skew,
1260                         client_name);
1261 #if 1
1262                 /* This code is from samba, needs testing */
1263                 /*
1264                  * the following is needed to make windows clients
1265                  * to retry using the timestamp in the error message
1266                  *
1267                  * this is maybe a bug in windows to not trying when e_text
1268                  * is present...
1269                  */
1270                 e_text = NULL;
1271 #else
1272                 e_text = "Too large time skew";
1273 #endif
1274                 goto out;
1275             }
1276             et.flags.pre_authent = 1;
1277 
1278             ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1279             if (ret)
1280                 str = NULL;
1281 
1282             kdc_log(context, config, 2,
1283                     "ENC-TS Pre-authentication succeeded -- %s using %s",
1284                     client_name, str ? str : "unknown enctype");
1285             free(str);
1286             break;
1287         }
1288 #ifdef PKINIT
1289     preauth_done:
1290 #endif
1291         if(found_pa == 0 && config->require_preauth)
1292             goto use_pa;
1293         /* We come here if we found a pa-enc-timestamp, but if there
1294            was some problem with it, other than too large skew */
1295         if(found_pa && et.flags.pre_authent == 0){
1296             kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1297             e_text = NULL;
1298             goto out;
1299         }
1300     }else if (config->require_preauth
1301               || client->entry.flags.require_preauth
1302               || server->entry.flags.require_preauth) {
1303         METHOD_DATA method_data;
1304         PA_DATA *pa;
1305         unsigned char *buf;
1306         size_t len;
1307 
1308     use_pa:
1309         method_data.len = 0;
1310         method_data.val = NULL;
1311 
1312         ret = realloc_method_data(&method_data);
1313         pa = &method_data.val[method_data.len-1];
1314         pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
1315         pa->padata_value.length = 0;
1316         pa->padata_value.data   = NULL;
1317 
1318 #ifdef PKINIT
1319         ret = realloc_method_data(&method_data);
1320         pa = &method_data.val[method_data.len-1];
1321         pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
1322         pa->padata_value.length = 0;
1323         pa->padata_value.data   = NULL;
1324 
1325         ret = realloc_method_data(&method_data);
1326         pa = &method_data.val[method_data.len-1];
1327         pa->padata_type         = KRB5_PADATA_PK_AS_REQ_WIN;
1328         pa->padata_value.length = 0;
1329         pa->padata_value.data   = NULL;
1330 #endif
1331 
1332         /*
1333          * RFC4120 requires:
1334          * - If the client only knows about old enctypes, then send
1335          *   both info replies (we send 'info' first in the list).
1336          * - If the client is 'modern', because it knows about 'new'
1337          *   enctype types, then only send the 'info2' reply.
1338          */
1339 
1340         /* XXX check ret */
1341         if (only_older_enctype_p(req))
1342             ret = get_pa_etype_info(context, config,
1343                                     &method_data, &client->entry,
1344                                     b->etype.val, b->etype.len);
1345         /* XXX check ret */
1346         ret = get_pa_etype_info2(context, config, &method_data,
1347                                  &client->entry, b->etype.val, b->etype.len);
1348 
1349         
1350         ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1351         free_METHOD_DATA(&method_data);
1352 
1353         e_data.data   = buf;
1354         e_data.length = len;
1355         e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1356 
1357         ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1358 
1359         kdc_log(context, config, 0,
1360                 "No preauth found, returning PREAUTH-REQUIRED -- %s",
1361                 client_name);
1362         goto out;
1363     }
1364 
1365     /*
1366      * Find the client key (for preauth ENC-TS verification and reply
1367      * encryption).  Then the best encryption type for the KDC and
1368      * last the best session key that shared between the client and
1369      * KDC runtime enctypes.
1370      */
1371 
1372     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1373                           &ckey, &cetype);
1374     if (ret) {
1375         kdc_log(context, config, 0,
1376                 "Client (%s) has no support for etypes", client_name);
1377         goto out;
1378     }
1379         
1380     ret = _kdc_get_preferred_key(context, config,
1381                                  server, server_name,
1382                                  &setype, &skey);
1383     if(ret)
1384         goto out;
1385 
1386     /*
1387      * Select a session enctype from the list of the crypto systems
1388      * supported enctype, is supported by the client and is one of the
1389      * enctype of the enctype of the krbtgt.
1390      *
1391      * The later is used as a hint what enctype all KDC are supporting
1392      * to make sure a newer version of KDC wont generate a session
1393      * enctype that and older version of a KDC in the same realm can't
1394      * decrypt.
1395      *
1396      * But if the KDC admin is paranoid and doesn't want to have "no
1397      * the best" enctypes on the krbtgt, lets save the best pick from
1398      * the client list and hope that that will work for any other
1399      * KDCs.
1400      */
1401     {
1402         const krb5_enctype *p;
1403         krb5_enctype clientbest = ETYPE_NULL;
1404         int i, j;
1405 
1406         p = krb5_kerberos_enctypes(context);
1407 
1408         sessionetype = ETYPE_NULL;
1409 
1410         for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1411             if (krb5_enctype_valid(context, p[i]) != 0)
1412                 continue;
1413 
1414             for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {
1415                 Key *dummy;
1416                 /* check with client */
1417                 if (p[i] != b->etype.val[j])
1418                     continue;
1419                 /* save best of union of { client, crypto system } */
1420                 if (clientbest == ETYPE_NULL)
1421                     clientbest = p[i];
1422                 /* check with krbtgt */
1423                 ret = hdb_enctype2key(context, &server->entry, p[i], &dummy);
1424                 if (ret)
1425                     continue;
1426                 sessionetype = p[i];
1427             }
1428         }
1429         /* if krbtgt had no shared keys with client, pick clients best */
1430         if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) {
1431             sessionetype = clientbest;
1432         } else if (sessionetype == ETYPE_NULL) {
1433             kdc_log(context, config, 0,
1434                     "Client (%s) from %s has no common enctypes with KDC"
1435                     "to use for the session key",
1436                     client_name, from);
1437             goto out;
1438         }
1439     }
1440 
1441     log_as_req(context, config, cetype, setype, b);
1442 
1443     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1444        || (f.request_anonymous && !config->allow_anonymous)) {
1445         ret = KRB5KDC_ERR_BADOPTION;
1446         kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1447         goto out;
1448     }
1449 
1450     rep.pvno = 5;
1451     rep.msg_type = krb_as_rep;
1452     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1453     if (f.request_anonymous)
1454         _kdc_make_anonymous_principalname (&rep.cname);
1455     else
1456         _krb5_principal2principalname(&rep.cname,
1457                                       client->entry.principal);
1458     rep.ticket.tkt_vno = 5;
1459     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1460     _krb5_principal2principalname(&rep.ticket.sname,
1461                                   server->entry.principal);
1462     /* java 1.6 expects the name to be the same type, lets allow that
1463      * uncomplicated name-types. */
1464 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
1465     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
1466         rep.ticket.sname.name_type = b->sname->name_type;
1467 #undef CNT
1468 
1469     et.flags.initial = 1;
1470     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1471         et.flags.forwardable = f.forwardable;
1472     else if (f.forwardable) {
1473         ret = KRB5KDC_ERR_POLICY;
1474         kdc_log(context, config, 0,
1475                 "Ticket may not be forwardable -- %s", client_name);
1476         goto out;
1477     }
1478     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1479         et.flags.proxiable = f.proxiable;
1480     else if (f.proxiable) {
1481         ret = KRB5KDC_ERR_POLICY;
1482         kdc_log(context, config, 0,
1483                 "Ticket may not be proxiable -- %s", client_name);
1484         goto out;
1485     }
1486     if(client->entry.flags.postdate && server->entry.flags.postdate)
1487         et.flags.may_postdate = f.allow_postdate;
1488     else if (f.allow_postdate){
1489         ret = KRB5KDC_ERR_POLICY;
1490         kdc_log(context, config, 0,
1491                 "Ticket may not be postdatable -- %s", client_name);
1492         goto out;
1493     }
1494 
1495     /* check for valid set of addresses */
1496     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1497         ret = KRB5KRB_AP_ERR_BADADDR;
1498         kdc_log(context, config, 0,
1499                 "Bad address list requested -- %s", client_name);
1500         goto out;
1501     }
1502 
1503     ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1504     if (ret)
1505         goto out;
1506     copy_PrincipalName(&rep.cname, &et.cname);
1507     copy_Realm(&rep.crealm, &et.crealm);
1508 
1509     {
1510         time_t start;
1511         time_t t;
1512         
1513         start = et.authtime = kdc_time;
1514 
1515         if(f.postdated && req->req_body.from){
1516             ALLOC(et.starttime);
1517             start = *et.starttime = *req->req_body.from;
1518             et.flags.invalid = 1;
1519             et.flags.postdated = 1; /* XXX ??? */
1520         }
1521         _kdc_fix_time(&b->till);
1522         t = *b->till;
1523 
1524         /* be careful not overflowing */
1525 
1526         if(client->entry.max_life)
1527             t = start + min(t - start, *client->entry.max_life);
1528         if(server->entry.max_life)
1529             t = start + min(t - start, *server->entry.max_life);
1530 #if 0
1531         t = min(t, start + realm->max_life);
1532 #endif
1533         et.endtime = t;
1534         if(f.renewable_ok && et.endtime < *b->till){
1535             f.renewable = 1;
1536             if(b->rtime == NULL){
1537                 ALLOC(b->rtime);
1538                 *b->rtime = 0;
1539             }
1540             if(*b->rtime < *b->till)
1541                 *b->rtime = *b->till;
1542         }
1543         if(f.renewable && b->rtime){
1544             t = *b->rtime;
1545             if(t == 0)
1546                 t = MAX_TIME;
1547             if(client->entry.max_renew)
1548                 t = start + min(t - start, *client->entry.max_renew);
1549             if(server->entry.max_renew)
1550                 t = start + min(t - start, *server->entry.max_renew);
1551 #if 0
1552             t = min(t, start + realm->max_renew);
1553 #endif
1554             ALLOC(et.renew_till);
1555             *et.renew_till = t;
1556             et.flags.renewable = 1;
1557         }
1558     }
1559 
1560     if (f.request_anonymous)
1561         et.flags.anonymous = 1;
1562 
1563     if(b->addresses){
1564         ALLOC(et.caddr);
1565         copy_HostAddresses(b->addresses, et.caddr);
1566     }
1567 
1568     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1569     krb5_data_zero(&et.transited.contents);
1570 
1571     copy_EncryptionKey(&et.key, &ek.key);
1572 
1573     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1574      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1575      * incapable of correctly decoding SEQUENCE OF's of zero length.
1576      *
1577      * To fix this, always send at least one no-op last_req
1578      *
1579      * If there's a pw_end or valid_end we will use that,
1580      * otherwise just a dummy lr.
1581      */
1582     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1583     if (ek.last_req.val == NULL) {
1584         ret = ENOMEM;
1585         goto out;
1586     }
1587     ek.last_req.len = 0;
1588     if (client->entry.pw_end
1589         && (config->kdc_warn_pwexpire == 0
1590             || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1591         ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1592         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1593         ++ek.last_req.len;
1594     }
1595     if (client->entry.valid_end) {
1596         ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1597         ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1598         ++ek.last_req.len;
1599     }
1600     if (ek.last_req.len == 0) {
1601         ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1602         ek.last_req.val[ek.last_req.len].lr_value = 0;
1603         ++ek.last_req.len;
1604     }
1605     ek.nonce = b->nonce;
1606     if (client->entry.valid_end || client->entry.pw_end) {
1607         ALLOC(ek.key_expiration);
1608         if (client->entry.valid_end) {
1609             if (client->entry.pw_end)
1610                 *ek.key_expiration = min(*client->entry.valid_end,
1611                                          *client->entry.pw_end);
1612             else
1613                 *ek.key_expiration = *client->entry.valid_end;
1614         } else
1615             *ek.key_expiration = *client->entry.pw_end;
1616     } else
1617         ek.key_expiration = NULL;
1618     ek.flags = et.flags;
1619     ek.authtime = et.authtime;
1620     if (et.starttime) {
1621         ALLOC(ek.starttime);
1622         *ek.starttime = *et.starttime;
1623     }
1624     ek.endtime = et.endtime;
1625     if (et.renew_till) {
1626         ALLOC(ek.renew_till);
1627         *ek.renew_till = *et.renew_till;
1628     }
1629     copy_Realm(&rep.ticket.realm, &ek.srealm);
1630     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1631     if(et.caddr){
1632         ALLOC(ek.caddr);
1633         copy_HostAddresses(et.caddr, ek.caddr);
1634     }
1635 
1636     ALLOC(rep.padata);
1637     rep.padata->len = 0;
1638     rep.padata->val = NULL;
1639 
1640     reply_key = &ckey->key;
1641 #if PKINIT
1642     if (pkp) {
1643         ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1644                                   req, req_buffer,
1645                                   &reply_key, rep.padata);
1646         if (ret)
1647             goto out;
1648         ret = _kdc_add_inital_verified_cas(context,
1649                                            config,
1650                                            pkp,
1651                                            &et);
1652         if (ret)
1653             goto out;
1654     }
1655 #endif
1656 
1657     set_salt_padata (rep.padata, ckey->salt);
1658 
1659     /* Add signing of alias referral */
1660     if (f.canonicalize) {
1661         PA_ClientCanonicalized canon;
1662         krb5_data data;
1663         PA_DATA pa;
1664         krb5_crypto crypto;
1665         size_t len;
1666 
1667         memset(&canon, 0, sizeof(canon));
1668 
1669         canon.names.requested_name = *b->cname;
1670         canon.names.mapped_name = client->entry.principal->name;
1671 
1672         ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
1673                            &canon.names, &len, ret);
1674         if (ret)
1675             goto out;
1676         if (data.length != len)
1677             krb5_abortx(context, "internal asn.1 error");
1678 
1679         /* sign using "returned session key" */
1680         ret = krb5_crypto_init(context, &et.key, 0, &crypto);
1681         if (ret) {
1682             free(data.data);
1683             goto out;
1684         }
1685 
1686         ret = krb5_create_checksum(context, crypto,
1687                                    KRB5_KU_CANONICALIZED_NAMES, 0,
1688                                    data.data, data.length,
1689                                    &canon.canon_checksum);
1690         free(data.data);
1691         krb5_crypto_destroy(context, crypto);
1692         if (ret)
1693             goto out;
1694         
1695         ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
1696                            &canon, &len, ret);
1697         free_Checksum(&canon.canon_checksum);
1698         if (ret)
1699             goto out;
1700         if (data.length != len)
1701             krb5_abortx(context, "internal asn.1 error");
1702 
1703         pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
1704         pa.padata_value = data;
1705         ret = add_METHOD_DATA(rep.padata, &pa);
1706         free(data.data);
1707         if (ret)
1708             goto out;
1709     }
1710 
1711     if (rep.padata->len == 0) {
1712         free(rep.padata);
1713         rep.padata = NULL;
1714     }
1715 
1716     /* Add the PAC */
1717     if (send_pac_p(context, req)) {
1718         krb5_pac p = NULL;
1719         krb5_data data;
1720 
1721         ret = _kdc_pac_generate(context, client, &p);
1722         if (ret) {
1723             kdc_log(context, config, 0, "PAC generation failed for -- %s",
1724                     client_name);
1725             goto out;
1726         }
1727         if (p != NULL) {
1728             ret = _krb5_pac_sign(context, p, et.authtime,
1729                                  client->entry.principal,
1730                                  &skey->key, /* Server key */
1731                                  &skey->key, /* FIXME: should be krbtgt key */
1732                                  &data);
1733             krb5_pac_free(context, p);
1734             if (ret) {
1735                 kdc_log(context, config, 0, "PAC signing failed for -- %s",
1736                         client_name);
1737                 goto out;
1738             }
1739 
1740             ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1741                                               KRB5_AUTHDATA_WIN2K_PAC,
1742                                               &data);
1743             krb5_data_free(&data);
1744             if (ret)
1745                 goto out;
1746         }
1747     }
1748 
1749     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1750                        et.endtime, et.renew_till);
1751 
1752     /* do this as the last thing since this signs the EncTicketPart */
1753     ret = _kdc_add_KRB5SignedPath(context,
1754                                   config,
1755                                   server,
1756                                   setype,
1757                                   NULL,
1758                                   NULL,
1759                                   &et);
1760     if (ret)
1761         goto out;
1762 
1763     ret = _kdc_encode_reply(context, config,
1764                             &rep, &et, &ek, setype, server->entry.kvno,
1765                             &skey->key, client->entry.kvno,
1766                             reply_key, &e_text, reply);
1767     free_EncTicketPart(&et);
1768     free_EncKDCRepPart(&ek);
1769     if (ret)
1770         goto out;
1771 
1772     /* */
1773     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1774         krb5_data_free(reply);
1775         ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1776         e_text = "Reply packet too large";
1777     }
1778 
1779 out:
1780     free_AS_REP(&rep);
1781     if(ret){
1782         krb5_mk_error(context,
1783                       ret,
1784                       e_text,
1785                       (e_data.data ? &e_data : NULL),
1786                       client_princ,
1787                       server_princ,
1788                       NULL,
1789                       NULL,
1790                       reply);
1791         ret = 0;
1792     }
1793 #ifdef PKINIT
1794     if (pkp)
1795         _kdc_pk_free_client_param(context, pkp);
1796 #endif
1797     if (e_data.data)
1798         free(e_data.data);
1799     if (client_princ)
1800         krb5_free_principal(context, client_princ);
1801     free(client_name);
1802     if (server_princ)
1803         krb5_free_principal(context, server_princ);
1804     free(server_name);
1805     if(client)
1806         _kdc_free_ent(context, client);
1807     if(server)
1808         _kdc_free_ent(context, server);
1809     return ret;
1810 }
1811 
1812 /*
1813  * Add the AuthorizationData `data´ of `type´ to the last element in
1814  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1815  */
1816 
1817 krb5_error_code
1818 _kdc_tkt_add_if_relevant_ad(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1819                             EncTicketPart *tkt,
1820                             int type,
1821                             const krb5_data *data)
1822 {
1823     krb5_error_code ret;
1824     size_t size;
1825 
1826     if (tkt->authorization_data == NULL) {
1827         tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1828         if (tkt->authorization_data == NULL) {
1829             krb5_set_error_message(context, ENOMEM, "out of memory");
1830             return ENOMEM;
1831         }
1832     }
1833         
1834     /* add the entry to the last element */
1835     {
1836         AuthorizationData ad = { 0, NULL };
1837         AuthorizationDataElement ade;
1838 
1839         ade.ad_type = type;
1840         ade.ad_data = *data;
1841 
1842         ret = add_AuthorizationData(&ad, &ade);
1843         if (ret) {
1844             krb5_set_error_message(context, ret, "add AuthorizationData failed");
1845             return ret;
1846         }
1847 
1848         ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1849 
1850         ASN1_MALLOC_ENCODE(AuthorizationData,
1851                            ade.ad_data.data, ade.ad_data.length,
1852                            &ad, &size, ret);
1853         free_AuthorizationData(&ad);
1854         if (ret) {
1855             krb5_set_error_message(context, ret, "ASN.1 encode of "
1856                                    "AuthorizationData failed");
1857             return ret;
1858         }
1859         if (ade.ad_data.length != size)
1860             krb5_abortx(context, "internal asn.1 encoder error");
1861         
1862         ret = add_AuthorizationData(tkt->authorization_data, &ade);
1863         der_free_octet_string(&ade.ad_data);
1864         if (ret) {
1865             krb5_set_error_message(context, ret, "add AuthorizationData failed");
1866             return ret;
1867         }
1868     }
1869 
1870     return 0;
1871 }

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