Changeset 745 for trunk/server/source4/heimdal/kdc/kerberos5.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/heimdal/kdc/kerberos5.c
r414 r745 34 34 #include "kdc_locl.h" 35 35 36 RCSID("$Id$");37 38 36 #define MAX_TIME ((time_t)((1U << 31) - 1)) 39 37 … … 61 59 62 60 static void 63 set_salt_padata 61 set_salt_padata(METHOD_DATA *md, Salt *salt) 64 62 { 65 63 if (salt) { 66 67 68 69 64 realloc_method_data(md); 65 md->val[md->len - 1].padata_type = salt->type; 66 der_copy_octet_string(&salt->salt, 67 &md->val[md->len - 1].padata_value); 70 68 } 71 69 } … … 128 126 _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, 129 127 krb5_enctype *etypes, unsigned len, 130 Key **ret_key , krb5_enctype *ret_etype)128 Key **ret_key) 131 129 { 132 130 int i; … … 149 147 } 150 148 *ret_key = key; 151 *ret_etype = etypes[i];152 149 ret = 0; 153 150 if (is_default_salt_p(&def_salt, key)) { … … 262 259 int skvno, const EncryptionKey *skey, 263 260 int ckvno, const EncryptionKey *reply_key, 261 int rk_is_subkey, 264 262 const char **e_text, 265 263 krb5_data *reply) … … 273 271 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); 274 272 if(ret) { 275 kdc_log(context, config, 0, "Failed to encode ticket: %s", 276 krb5_get_err_text(context, ret)); 273 const char *msg = krb5_get_error_message(context, ret); 274 kdc_log(context, config, 0, "Failed to encode ticket: %s", msg); 275 krb5_free_error_message(context, msg); 277 276 return ret; 278 277 } … … 286 285 ret = krb5_crypto_init(context, skey, etype, &crypto); 287 286 if (ret) { 287 const char *msg; 288 288 free(buf); 289 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", 290 krb5_get_err_text(context, ret)); 289 msg = krb5_get_error_message(context, ret); 290 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 291 krb5_free_error_message(context, msg); 291 292 return ret; 292 293 } … … 302 303 krb5_crypto_destroy(context, crypto); 303 304 if(ret) { 304 kdc_log(context, config, 0, "Failed to encrypt data: %s", 305 krb5_get_err_text(context, ret)); 305 const char *msg = krb5_get_error_message(context, ret); 306 kdc_log(context, config, 0, "Failed to encrypt data: %s", msg); 307 krb5_free_error_message(context, msg); 306 308 return ret; 307 309 } … … 312 314 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret); 313 315 if(ret) { 314 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 315 krb5_get_err_text(context, ret)); 316 const char *msg = krb5_get_error_message(context, ret); 317 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 318 krb5_free_error_message(context, msg); 316 319 return ret; 317 320 } … … 324 327 ret = krb5_crypto_init(context, reply_key, 0, &crypto); 325 328 if (ret) { 329 const char *msg = krb5_get_error_message(context, ret); 326 330 free(buf); 327 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", 328 krb5_get_err_text(context, ret));331 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 332 krb5_free_error_message(context, msg); 329 333 return ret; 330 334 } … … 342 346 krb5_encrypt_EncryptedData(context, 343 347 crypto, 344 KRB5_KU_TGS_REP_ENC_PART_SESSION,348 rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION, 345 349 buf, 346 350 len, … … 352 356 krb5_crypto_destroy(context, crypto); 353 357 if(ret) { 354 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", 355 krb5_get_err_text(context, ret)); 358 const char *msg = krb5_get_error_message(context, ret); 359 kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg); 360 krb5_free_error_message(context, msg); 356 361 return ret; 357 362 } … … 896 901 hdb_entry_ex *client = NULL, *server = NULL; 897 902 HDB *clientdb; 898 krb5_enctype cetype,setype, sessionetype;903 krb5_enctype setype, sessionetype; 899 904 krb5_data e_data; 900 905 EncTicketPart et; … … 906 911 krb5_crypto crypto; 907 912 Key *ckey, *skey; 908 EncryptionKey *reply_key ;913 EncryptionKey *reply_key = NULL, session_key; 909 914 int flags = 0; 910 915 #ifdef PKINIT … … 913 918 914 919 memset(&rep, 0, sizeof(rep)); 920 memset(&session_key, 0, sizeof(session_key)); 915 921 krb5_data_zero(&e_data); 922 923 ALLOC(rep.padata); 924 rep.padata->len = 0; 925 rep.padata->val = NULL; 916 926 917 927 if (f.canonicalize) … … 979 989 980 990 ret = _kdc_db_fetch(context, config, client_princ, 981 HDB_F_GET_CLIENT | flags, &clientdb, &client); 982 if(ret){ 983 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, 984 krb5_get_err_text(context, ret)); 991 HDB_F_GET_CLIENT | flags, NULL, 992 &clientdb, &client); 993 if(ret == HDB_ERR_NOT_FOUND_HERE) { 994 kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name); 995 goto out; 996 } else if(ret){ 997 const char *msg = krb5_get_error_message(context, ret); 998 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg); 999 krb5_free_error_message(context, msg); 985 1000 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 986 1001 goto out; 987 1002 } 988 989 1003 ret = _kdc_db_fetch(context, config, server_princ, 990 HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, 991 NULL, &server); 992 if(ret){ 993 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, 994 krb5_get_err_text(context, ret)); 1004 HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags, 1005 NULL, NULL, &server); 1006 if(ret == HDB_ERR_NOT_FOUND_HERE) { 1007 kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name); 1008 goto out; 1009 } else if(ret){ 1010 const char *msg = krb5_get_error_message(context, ret); 1011 kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg); 1012 krb5_free_error_message(context, msg); 995 1013 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; 996 1014 goto out; … … 1001 1019 1002 1020 /* 1003 * Find the client key for reply encryption and pa-type salt, Pick 1004 * the client key upfront before the other keys because that is 1005 * going to affect what enctypes we are going to use in 1006 * ETYPE-INFO{,2}. 1021 * Select a session enctype from the list of the crypto systems 1022 * supported enctype, is supported by the client and is one of the 1023 * enctype of the enctype of the krbtgt. 1024 * 1025 * The later is used as a hint what enctype all KDC are supporting 1026 * to make sure a newer version of KDC wont generate a session 1027 * enctype that and older version of a KDC in the same realm can't 1028 * decrypt. 1029 * 1030 * But if the KDC admin is paranoid and doesn't want to have "no 1031 * the best" enctypes on the krbtgt, lets save the best pick from 1032 * the client list and hope that that will work for any other 1033 * KDCs. 1007 1034 */ 1008 1009 ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, 1010 &ckey, &cetype); 1011 if (ret) { 1012 kdc_log(context, config, 0, 1013 "Client (%s) has no support for etypes", client_name); 1014 goto out; 1035 { 1036 const krb5_enctype *p; 1037 krb5_enctype clientbest = ETYPE_NULL; 1038 int i, j; 1039 1040 p = krb5_kerberos_enctypes(context); 1041 1042 sessionetype = ETYPE_NULL; 1043 1044 for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) { 1045 if (krb5_enctype_valid(context, p[i]) != 0) 1046 continue; 1047 1048 for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) { 1049 Key *dummy; 1050 /* check with client */ 1051 if (p[i] != b->etype.val[j]) 1052 continue; 1053 /* save best of union of { client, crypto system } */ 1054 if (clientbest == ETYPE_NULL) 1055 clientbest = p[i]; 1056 /* check with krbtgt */ 1057 ret = hdb_enctype2key(context, &server->entry, p[i], &dummy); 1058 if (ret) 1059 continue; 1060 sessionetype = p[i]; 1061 } 1062 } 1063 /* if krbtgt had no shared keys with client, pick clients best */ 1064 if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) { 1065 sessionetype = clientbest; 1066 } else if (sessionetype == ETYPE_NULL) { 1067 kdc_log(context, config, 0, 1068 "Client (%s) from %s has no common enctypes with KDC" 1069 "to use for the session key", 1070 client_name, from); 1071 goto out; 1072 } 1015 1073 } 1016 1074 … … 1136 1194 ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto); 1137 1195 if (ret) { 1138 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", 1139 krb5_get_err_text(context, ret)); 1196 const char *msg = krb5_get_error_message(context, ret); 1197 kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); 1198 krb5_free_error_message(context, msg); 1140 1199 free_EncryptedData(&enc_data); 1141 1200 continue; … … 1155 1214 if(ret){ 1156 1215 krb5_error_code ret2; 1216 const char *msg = krb5_get_error_message(context, ret); 1217 1157 1218 ret2 = krb5_enctype_to_string(context, 1158 1219 pa_key->key.keytype, &str); … … 1162 1223 "Failed to decrypt PA-DATA -- %s " 1163 1224 "(enctype %s) error %s", 1164 client_name, 1165 str ? str : "unknown enctype", 1166 krb5_get_err_text(context, ret)); 1225 client_name, str ? str : "unknown enctype", msg); 1226 krb5_free_error_message(context, msg); 1167 1227 free(str); 1168 1228 … … 1220 1280 et.flags.pre_authent = 1; 1221 1281 1222 ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str); 1282 set_salt_padata(rep.padata, pa_key->salt); 1283 1284 reply_key = &pa_key->key; 1285 1286 ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str); 1223 1287 if (ret) 1224 1288 str = NULL; … … 1290 1354 * If there is a client key, send ETYPE_INFO{,2} 1291 1355 */ 1292 if (ckey) { 1356 ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, 1357 &ckey); 1358 if (ret == 0) { 1293 1359 1294 1360 /* … … 1361 1427 goto out; 1362 1428 1363 /*1364 * Select a session enctype from the list of the crypto systems1365 * supported enctype, is supported by the client and is one of the1366 * enctype of the enctype of the krbtgt.1367 *1368 * The later is used as a hint what enctype all KDC are supporting1369 * to make sure a newer version of KDC wont generate a session1370 * enctype that and older version of a KDC in the same realm can't1371 * decrypt.1372 *1373 * But if the KDC admin is paranoid and doesn't want to have "no1374 * the best" enctypes on the krbtgt, lets save the best pick from1375 * the client list and hope that that will work for any other1376 * KDCs.1377 */1378 {1379 const krb5_enctype *p;1380 krb5_enctype clientbest = ETYPE_NULL;1381 int i, j;1382 1383 p = krb5_kerberos_enctypes(context);1384 1385 sessionetype = ETYPE_NULL;1386 1387 for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {1388 if (krb5_enctype_valid(context, p[i]) != 0)1389 continue;1390 1391 for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {1392 Key *dummy;1393 /* check with client */1394 if (p[i] != b->etype.val[j])1395 continue;1396 /* save best of union of { client, crypto system } */1397 if (clientbest == ETYPE_NULL)1398 clientbest = p[i];1399 /* check with krbtgt */1400 ret = hdb_enctype2key(context, &server->entry, p[i], &dummy);1401 if (ret)1402 continue;1403 sessionetype = p[i];1404 }1405 }1406 /* if krbtgt had no shared keys with client, pick clients best */1407 if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) {1408 sessionetype = clientbest;1409 } else if (sessionetype == ETYPE_NULL) {1410 kdc_log(context, config, 0,1411 "Client (%s) from %s has no common enctypes with KDC"1412 "to use for the session key",1413 client_name, from);1414 goto out;1415 }1416 }1417 1418 log_as_req(context, config, cetype, setype, b);1419 1420 1429 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey 1421 1430 || (f.request_anonymous && !config->allow_anonymous)) { 1422 1431 ret = KRB5KDC_ERR_BADOPTION; 1432 e_text = "Bad KDC options"; 1423 1433 kdc_log(context, config, 0, "Bad KDC options -- %s", client_name); 1424 1434 goto out; … … 1450 1460 et.flags.forwardable = f.forwardable; 1451 1461 else if (f.forwardable) { 1462 e_text = "Ticket may not be forwardable"; 1452 1463 ret = KRB5KDC_ERR_POLICY; 1453 1464 kdc_log(context, config, 0, … … 1458 1469 et.flags.proxiable = f.proxiable; 1459 1470 else if (f.proxiable) { 1471 e_text = "Ticket may not be proxiable"; 1460 1472 ret = KRB5KDC_ERR_POLICY; 1461 1473 kdc_log(context, config, 0, … … 1466 1478 et.flags.may_postdate = f.allow_postdate; 1467 1479 else if (f.allow_postdate){ 1480 e_text = "Ticket may not be postdate"; 1468 1481 ret = KRB5KDC_ERR_POLICY; 1469 1482 kdc_log(context, config, 0, … … 1474 1487 /* check for valid set of addresses */ 1475 1488 if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) { 1489 e_text = "Bad address list in requested"; 1476 1490 ret = KRB5KRB_AP_ERR_BADADDR; 1477 1491 kdc_log(context, config, 0, … … 1612 1626 } 1613 1627 1614 ALLOC(rep.padata);1615 rep.padata->len = 0;1616 rep.padata->val = NULL;1617 1618 1628 #if PKINIT 1619 1629 if (pkp) { … … 1630 1640 if (ret) 1631 1641 goto out; 1642 1632 1643 } else 1633 1644 #endif 1634 if (ckey) { 1635 reply_key = &ckey->key; 1645 { 1636 1646 ret = krb5_generate_random_keyblock(context, sessionetype, &et.key); 1637 1647 if (ret) 1638 1648 goto out; 1639 } else { 1649 } 1650 1651 if (reply_key == NULL) { 1640 1652 e_text = "Client have no reply key"; 1641 1653 ret = KRB5KDC_ERR_CLIENT_NOTYET; … … 1646 1658 if (ret) 1647 1659 goto out; 1648 1649 if (ckey)1650 set_salt_padata (rep.padata, ckey->salt);1651 1660 1652 1661 /* Add signing of alias referral */ … … 1748 1757 server, 1749 1758 setype, 1759 client->entry.principal, 1750 1760 NULL, 1751 1761 NULL, … … 1754 1764 goto out; 1755 1765 1766 log_as_req(context, config, reply_key->keytype, setype, b); 1767 1756 1768 ret = _kdc_encode_reply(context, config, 1757 1769 &rep, &et, &ek, setype, server->entry.kvno, 1758 1770 &skey->key, client->entry.kvno, 1759 reply_key, &e_text, reply);1771 reply_key, 0, &e_text, reply); 1760 1772 free_EncTicketPart(&et); 1761 1773 free_EncKDCRepPart(&ek); … … 1772 1784 out: 1773 1785 free_AS_REP(&rep); 1774 if(ret ){1786 if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){ 1775 1787 krb5_mk_error(context, 1776 1788 ret,
Note:
See TracChangeset
for help on using the changeset viewer.