~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source4/heimdal/kdc/krb5tgs.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 
34
34
#include "kdc_locl.h"
35
35
 
36
 
RCSID("$Id$");
37
 
 
38
36
/*
39
37
 * return the realm of a krbtgt-ticket or NULL
40
38
 */
106
104
                        krb5_kdc_configuration *config,
107
105
                        hdb_entry_ex *krbtgt,
108
106
                        krb5_enctype enctype,
 
107
                        krb5_principal client,
109
108
                        krb5_const_principal server,
110
109
                        krb5_principals principals,
111
110
                        EncTicketPart *tkt)
125
124
    {
126
125
        KRB5SignedPathData spd;
127
126
        
128
 
        spd.encticket = *tkt;
 
127
        spd.client = client;
 
128
        spd.authtime = tkt->authtime;
129
129
        spd.delegated = principals;
 
130
        spd.method_data = NULL;
130
131
        
131
132
        ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
132
133
                           &spd, &size, ret);
153
154
 
154
155
    sp.etype = enctype;
155
156
    sp.delegated = principals;
 
157
    sp.method_data = NULL;
156
158
 
157
159
    ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
158
160
                               data.data, data.length, &sp.cksum);
185
187
check_KRB5SignedPath(krb5_context context,
186
188
                     krb5_kdc_configuration *config,
187
189
                     hdb_entry_ex *krbtgt,
 
190
                     krb5_principal cp,
188
191
                     EncTicketPart *tkt,
189
192
                     krb5_principals *delegated,
190
193
                     int *signedpath)
200
203
    if (ret == 0) {
201
204
        KRB5SignedPathData spd;
202
205
        KRB5SignedPath sp;
203
 
        AuthorizationData *ad;
204
206
        size_t size;
205
207
 
206
208
        ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
208
210
        if (ret)
209
211
            return ret;
210
212
 
211
 
        spd.encticket = *tkt;
212
 
        /* the KRB5SignedPath is the last entry */
213
 
        ad = spd.encticket.authorization_data;
214
 
        if (--ad->len == 0)
215
 
            spd.encticket.authorization_data = NULL;
 
213
        spd.client = cp;
 
214
        spd.authtime = tkt->authtime;
216
215
        spd.delegated = sp.delegated;
 
216
        spd.method_data = sp.method_data;
217
217
 
218
218
        ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
219
219
                           &spd, &size, ret);
220
 
        ad->len++;
221
 
        spd.encticket.authorization_data = ad;
222
220
        if (ret) {
223
221
            free_KRB5SignedPath(&sp);
224
222
            return ret;
244
242
        free(data.data);
245
243
        if (ret) {
246
244
            free_KRB5SignedPath(&sp);
247
 
            return ret;
 
245
            kdc_log(context, config, 5,
 
246
                    "KRB5SignedPath not signed correctly, not marking as signed");
 
247
            return 0;
248
248
        }
249
249
 
250
250
        if (delegated && sp.delegated) {
281
281
          const krb5_principal client_principal,
282
282
          hdb_entry_ex *client,
283
283
          hdb_entry_ex *server,
 
284
          hdb_entry_ex *krbtgt,
284
285
          const EncryptionKey *server_key,
285
 
          const EncryptionKey *krbtgt_key,
 
286
          const EncryptionKey *krbtgt_check_key,
 
287
          const EncryptionKey *krbtgt_sign_key,
286
288
          EncTicketPart *tkt,
287
289
          krb5_data *rspac,
288
290
          int *signedpath)
312
314
        for (j = 0; j < child.len; j++) {
313
315
 
314
316
            if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
 
317
                int signed_pac = 0;
315
318
                krb5_pac pac;
316
319
 
317
320
                /* Found PAC */
325
328
 
326
329
                ret = krb5_pac_verify(context, pac, tkt->authtime,
327
330
                                      client_principal,
328
 
                                      krbtgt_key, NULL);
 
331
                                      krbtgt_check_key, NULL);
329
332
                if (ret) {
330
333
                    krb5_pac_free(context, pac);
331
334
                    return ret;
332
335
                }
333
336
 
334
337
                ret = _kdc_pac_verify(context, client_principal,
335
 
                                      client, server, &pac);
 
338
                                      client, server, krbtgt, &pac, &signed_pac);
336
339
                if (ret) {
337
340
                    krb5_pac_free(context, pac);
338
341
                    return ret;
339
342
                }
340
 
                *signedpath = 1;
341
 
 
342
 
                ret = _krb5_pac_sign(context, pac, tkt->authtime,
343
 
                                     client_principal,
344
 
                                     server_key, krbtgt_key, rspac);
345
 
 
 
343
 
 
344
                /*
 
345
                 * Only re-sign PAC if we could verify it with the PAC
 
346
                 * function. The no-verify case happens when we get in
 
347
                 * a PAC from cross realm from a Windows domain and
 
348
                 * that there is no PAC verification function.
 
349
                 */
 
350
                if (signed_pac) {
 
351
                    *signedpath = 1;
 
352
                    ret = _krb5_pac_sign(context, pac, tkt->authtime,
 
353
                                         client_principal,
 
354
                                         server_key, krbtgt_sign_key, rspac);
 
355
                }
346
356
                krb5_pac_free(context, pac);
347
 
 
 
357
                
348
358
                return ret;
349
359
            }
350
360
        }
447
457
    }
448
458
 
449
459
    if(f.renewable){
450
 
        if(!tgt->flags.renewable){
 
460
        if(!tgt->flags.renewable || tgt->renew_till == NULL){
451
461
            kdc_log(context, config, 0,
452
462
                    "Bad request for renewable ticket");
453
463
            return KRB5KDC_ERR_BADOPTION;
486
496
}
487
497
 
488
498
/*
489
 
 *
 
499
 * Determine if constrained delegation is allowed from this client to this server
490
500
 */
491
501
 
492
502
static krb5_error_code
529
539
}
530
540
 
531
541
/*
 
542
 * Determine if s4u2self is allowed from this client to this server
 
543
 *
 
544
 * For example, regardless of the principal being impersonated, if the
 
545
 * 'client' and 'server' are the same, then it's safe.
 
546
 */
 
547
 
 
548
static krb5_error_code
 
549
check_s4u2self(krb5_context context,
 
550
               krb5_kdc_configuration *config,
 
551
               HDB *clientdb,
 
552
               hdb_entry_ex *client,
 
553
               krb5_const_principal server)
 
554
{
 
555
    krb5_error_code ret;
 
556
 
 
557
    /* if client does a s4u2self to itself, that ok */
 
558
    if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
 
559
        return 0;
 
560
 
 
561
    if (clientdb->hdb_check_s4u2self) {
 
562
        ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server);
 
563
        if (ret == 0)
 
564
            return 0;
 
565
    } else {
 
566
        ret = KRB5KDC_ERR_BADOPTION;
 
567
    }
 
568
    return ret;
 
569
}
 
570
 
 
571
/*
532
572
 *
533
573
 */
534
574
 
669
709
               KDC_REQ_BODY *b,
670
710
               krb5_const_principal tgt_name,
671
711
               const EncTicketPart *tgt,
 
712
               const krb5_keyblock *replykey,
 
713
               int rk_is_subkey,
672
714
               const EncryptionKey *serverkey,
673
715
               const krb5_keyblock *sessionkey,
674
716
               krb5_kvno kvno,
768
810
        et.endtime = *et.starttime + life;
769
811
    }
770
812
    if(f.renewable_ok && tgt->flags.renewable &&
771
 
       et.renew_till == NULL && et.endtime < *b->till){
 
813
       et.renew_till == NULL && et.endtime < *b->till &&
 
814
       tgt->renew_till != NULL)
 
815
    {
772
816
        et.flags.renewable = 1;
773
817
        ALLOC(et.renew_till);
774
818
        *et.renew_till = *b->till;
821
865
        unsigned int i = 0;
822
866
 
823
867
        /* XXX check authdata */
 
868
 
824
869
        if (et.authorization_data == NULL) {
825
 
            ret = ENOMEM;
826
 
            krb5_set_error_message(context, ret, "malloc: out of memory");
827
 
            goto out;
 
870
            et.authorization_data = calloc(1, sizeof(*et.authorization_data));
 
871
            if (et.authorization_data == NULL) {
 
872
                ret = ENOMEM;
 
873
                krb5_set_error_message(context, ret, "malloc: out of memory");
 
874
                goto out;
 
875
            }
828
876
        }
829
877
        for(i = 0; i < auth_data->len ; i++) {
830
878
            ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
884
932
                                          config,
885
933
                                          krbtgt,
886
934
                                          krbtgt_etype,
 
935
                                          client_principal,
887
936
                                          NULL,
888
937
                                          spp,
889
938
                                          &et);
924
973
    ret = _kdc_encode_reply(context, config,
925
974
                            &rep, &et, &ek, et.key.keytype,
926
975
                            kvno,
927
 
                            serverkey, 0, &tgt->key, e_text, reply);
 
976
                            serverkey, 0, replykey, rk_is_subkey,
 
977
                            e_text, reply);
928
978
    if (is_weak)
929
979
        krb5_enctype_disable(context, et.key.keytype);
930
980
 
985
1035
    /* XXX should not re-encode this */
986
1036
    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
987
1037
    if(ret){
988
 
        kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
989
 
                krb5_get_err_text(context, ret));
 
1038
        const char *msg = krb5_get_error_message(context, ret);
 
1039
        kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
 
1040
        krb5_free_error_message(context, msg);
990
1041
        goto out;
991
1042
    }
992
1043
    if(buf_size != len) {
998
1049
    }
999
1050
    ret = krb5_crypto_init(context, key, 0, &crypto);
1000
1051
    if (ret) {
 
1052
        const char *msg = krb5_get_error_message(context, ret);
1001
1053
        free(buf);
1002
 
        kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1003
 
                krb5_get_err_text(context, ret));
 
1054
        kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
 
1055
        krb5_free_error_message(context, msg);
1004
1056
        goto out;
1005
1057
    }
1006
1058
    ret = krb5_verify_checksum(context,
1012
1064
    free(buf);
1013
1065
    krb5_crypto_destroy(context, crypto);
1014
1066
    if(ret){
 
1067
        const char *msg = krb5_get_error_message(context, ret);
1015
1068
        kdc_log(context, config, 0,
1016
 
                "Failed to verify authenticator checksum: %s",
1017
 
                krb5_get_err_text(context, ret));
 
1069
                "Failed to verify authenticator checksum: %s", msg);
 
1070
        krb5_free_error_message(context, msg);
1018
1071
    }
1019
1072
out:
1020
1073
    free_Authenticator(auth);
1074
1127
                  const struct sockaddr *from_addr,
1075
1128
                  time_t **csec,
1076
1129
                  int **cusec,
1077
 
                  AuthorizationData **auth_data)
 
1130
                  AuthorizationData **auth_data,
 
1131
                  krb5_keyblock **replykey,
 
1132
                  int *rk_is_subkey)
1078
1133
{
1079
1134
    krb5_ap_req ap_req;
1080
1135
    krb5_error_code ret;
1084
1139
    krb5_flags verify_ap_req_flags;
1085
1140
    krb5_crypto crypto;
1086
1141
    Key *tkey;
 
1142
    krb5_keyblock *subkey = NULL;
 
1143
    unsigned usage;
1087
1144
 
1088
1145
    *auth_data = NULL;
1089
1146
    *csec  = NULL;
1090
1147
    *cusec = NULL;
 
1148
    *replykey = NULL;
1091
1149
 
1092
1150
    memset(&ap_req, 0, sizeof(ap_req));
1093
1151
    ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1094
1152
    if(ret){
1095
 
        kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
1096
 
                krb5_get_err_text(context, ret));
 
1153
        const char *msg = krb5_get_error_message(context, ret);
 
1154
        kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
 
1155
        krb5_free_error_message(context, msg);
1097
1156
        goto out;
1098
1157
    }
1099
1158
 
1109
1168
                                       ap_req.ticket.sname,
1110
1169
                                       ap_req.ticket.realm);
1111
1170
 
1112
 
    ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
 
1171
    ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, ap_req.ticket.enc_part.kvno, NULL, krbtgt);
1113
1172
 
1114
 
    if(ret) {
 
1173
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
 
1174
        char *p;
 
1175
        ret = krb5_unparse_name(context, princ, &p);
 
1176
        if (ret != 0)
 
1177
            p = "<unparse_name failed>";
 
1178
        krb5_free_principal(context, princ);
 
1179
        kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p);
 
1180
        if (ret == 0)
 
1181
            free(p);
 
1182
        ret = HDB_ERR_NOT_FOUND_HERE;
 
1183
        goto out;
 
1184
    } else if(ret){
 
1185
        const char *msg = krb5_get_error_message(context, ret);
1115
1186
        char *p;
1116
1187
        ret = krb5_unparse_name(context, princ, &p);
1117
1188
        if (ret != 0)
1118
1189
            p = "<unparse_name failed>";
1119
1190
        krb5_free_principal(context, princ);
1120
1191
        kdc_log(context, config, 0,
1121
 
                "Ticket-granting ticket not found in database: %s: %s",
1122
 
                p, krb5_get_err_text(context, ret));
 
1192
                "Ticket-granting ticket not found in database: %s", msg);
 
1193
        krb5_free_error_message(context, msg);
1123
1194
        if (ret == 0)
1124
1195
            free(p);
1125
1196
        ret = KRB5KRB_AP_ERR_NOT_US;
1181
1252
                        
1182
1253
    krb5_free_principal(context, princ);
1183
1254
    if(ret) {
1184
 
        kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
1185
 
                krb5_get_err_text(context, ret));
 
1255
        const char *msg = krb5_get_error_message(context, ret);
 
1256
        kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
 
1257
        krb5_free_error_message(context, msg);
1186
1258
        goto out;
1187
1259
    }
1188
1260
 
1216
1288
        goto out;
1217
1289
    }
1218
1290
 
 
1291
    usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
 
1292
    *rk_is_subkey = 1;
 
1293
 
 
1294
    ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
 
1295
    if(ret){
 
1296
        const char *msg = krb5_get_error_message(context, ret);
 
1297
        krb5_auth_con_free(context, ac);
 
1298
        kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
 
1299
        krb5_free_error_message(context, msg);
 
1300
        goto out;
 
1301
    }
 
1302
    if(subkey == NULL){
 
1303
        usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
 
1304
        *rk_is_subkey = 0;
 
1305
 
 
1306
        ret = krb5_auth_con_getkey(context, ac, &subkey);
 
1307
        if(ret) {
 
1308
            const char *msg = krb5_get_error_message(context, ret);
 
1309
            krb5_auth_con_free(context, ac);
 
1310
            kdc_log(context, config, 0, "Failed to get session key: %s", msg);
 
1311
            krb5_free_error_message(context, msg);
 
1312
            goto out;
 
1313
        }
 
1314
    }
 
1315
    if(subkey == NULL){
 
1316
        krb5_auth_con_free(context, ac);
 
1317
        kdc_log(context, config, 0,
 
1318
                "Failed to get key for enc-authorization-data");
 
1319
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
 
1320
        goto out;
 
1321
    }
 
1322
 
 
1323
    *replykey = subkey;
 
1324
 
1219
1325
    if (b->enc_authorization_data) {
1220
 
        unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1221
 
        krb5_keyblock *subkey;
1222
1326
        krb5_data ad;
1223
1327
 
1224
 
        ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
1225
 
        if(ret){
1226
 
            krb5_auth_con_free(context, ac);
1227
 
            kdc_log(context, config, 0, "Failed to get remote subkey: %s",
1228
 
                    krb5_get_err_text(context, ret));
1229
 
            goto out;
1230
 
        }
1231
 
        if(subkey == NULL){
1232
 
            usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1233
 
            ret = krb5_auth_con_getkey(context, ac, &subkey);
1234
 
            if(ret) {
1235
 
                krb5_auth_con_free(context, ac);
1236
 
                kdc_log(context, config, 0, "Failed to get session key: %s",
1237
 
                        krb5_get_err_text(context, ret));
1238
 
                goto out;
1239
 
            }
1240
 
        }
1241
 
        if(subkey == NULL){
1242
 
            krb5_auth_con_free(context, ac);
1243
 
            kdc_log(context, config, 0,
1244
 
                    "Failed to get key for enc-authorization-data");
1245
 
            ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1246
 
            goto out;
1247
 
        }
1248
1328
        ret = krb5_crypto_init(context, subkey, 0, &crypto);
1249
 
        krb5_free_keyblock(context, subkey);
1250
1329
        if (ret) {
 
1330
            const char *msg = krb5_get_error_message(context, ret);
1251
1331
            krb5_auth_con_free(context, ac);
1252
 
            kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1253
 
                    krb5_get_err_text(context, ret));
 
1332
            kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
 
1333
            krb5_free_error_message(context, msg);
1254
1334
            goto out;
1255
1335
        }
1256
1336
        ret = krb5_decrypt_EncryptedData (context,
1374
1454
                KDC_REQ_BODY *b,
1375
1455
                hdb_entry_ex *krbtgt,
1376
1456
                krb5_enctype krbtgt_etype,
 
1457
                const krb5_keyblock *replykey,
 
1458
                int rk_is_subkey,
1377
1459
                krb5_ticket *ticket,
1378
1460
                krb5_data *reply,
1379
1461
                const char *from,
1384
1466
    krb5_error_code ret;
1385
1467
    krb5_principal cp = NULL, sp = NULL;
1386
1468
    krb5_principal client_principal = NULL;
 
1469
    krb5_principal krbtgt_principal = NULL;
1387
1470
    char *spn = NULL, *cpn = NULL;
1388
 
    hdb_entry_ex *server = NULL, *client = NULL;
1389
 
    HDB *clientdb;
 
1471
    hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
 
1472
    HDB *clientdb, *s4u2self_impersonated_clientdb;
1390
1473
    krb5_realm ref_realm = NULL;
1391
1474
    EncTicketPart *tgt = &ticket->ticket;
1392
1475
    krb5_principals spp = NULL;
1395
1478
    krb5_kvno kvno;
1396
1479
    krb5_data rspac;
1397
1480
 
 
1481
    hdb_entry_ex *krbtgt_out = NULL;
 
1482
 
1398
1483
    METHOD_DATA enc_pa_data;
1399
1484
 
1400
1485
    PrincipalName *s;
1404
1489
    char opt_str[128];
1405
1490
    int signedpath = 0;
1406
1491
 
1407
 
    Key *tkey;
 
1492
    Key *tkey_check;
 
1493
    Key *tkey_sign;
1408
1494
 
1409
1495
    memset(&sessionkey, 0, sizeof(sessionkey));
1410
1496
    memset(&adtkt, 0, sizeof(adtkt));
1436
1522
        }
1437
1523
        _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1438
1524
        ret = _kdc_db_fetch(context, config, p,
1439
 
                            HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
 
1525
                            HDB_F_GET_KRBTGT, t->enc_part.kvno,
1440
1526
                            NULL, &uu);
1441
1527
        krb5_free_principal(context, p);
1442
1528
        if(ret){
1489
1575
 
1490
1576
server_lookup:
1491
1577
    ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
1492
 
                        NULL, &server);
 
1578
                        NULL, NULL, &server);
1493
1579
 
1494
 
    if(ret){
1495
 
        const char *new_rlm;
 
1580
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
 
1581
        kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
 
1582
        goto out;
 
1583
    } else if(ret){
 
1584
        const char *new_rlm, *msg;
1496
1585
        Realm req_rlm;
1497
1586
        krb5_realm *realms;
1498
1587
 
1540
1629
            }
1541
1630
            krb5_free_host_realm(context, realms);
1542
1631
        }
 
1632
        msg = krb5_get_error_message(context, ret);
1543
1633
        kdc_log(context, config, 0,
1544
 
                "Server not found in database: %s: %s", spn,
1545
 
                krb5_get_err_text(context, ret));
 
1634
                "Server not found in database: %s: %s", spn, msg);
 
1635
        krb5_free_error_message(context, msg);
1546
1636
        if (ret == HDB_ERR_NOENTRY)
1547
1637
            ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1548
1638
        goto out;
1549
1639
    }
1550
1640
 
1551
 
    ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
1552
 
                        &clientdb, &client);
1553
 
    if(ret) {
1554
 
        const char *krbtgt_realm;
1555
 
 
1556
 
        /*
1557
 
         * If the client belongs to the same realm as our krbtgt, it
1558
 
         * should exist in the local database.
1559
 
         *
1560
 
         */
1561
 
 
1562
 
        krbtgt_realm =
1563
 
            krb5_principal_get_comp_string(context,
1564
 
                                           krbtgt->entry.principal, 1);
1565
 
 
1566
 
        if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1567
 
            if (ret == HDB_ERR_NOENTRY)
1568
 
                ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1569
 
            kdc_log(context, config, 1, "Client no longer in database: %s",
1570
 
                    cpn);
1571
 
            goto out;
1572
 
        }
1573
 
        
1574
 
        kdc_log(context, config, 1, "Client not found in database: %s: %s",
1575
 
                cpn, krb5_get_err_text(context, ret));
1576
 
    }
1577
 
 
1578
1641
    /*
1579
1642
     * Select enctype, return key and kvno.
1580
1643
     */
1600
1663
        } else {
1601
1664
            Key *skey;
1602
1665
        
1603
 
            ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len,
1604
 
                                  &skey, &etype);
 
1666
            ret = _kdc_find_etype(context, server,
 
1667
                                  b->etype.val, b->etype.len, &skey);
1605
1668
            if(ret) {
1606
1669
                kdc_log(context, config, 0,
1607
1670
                        "Server (%s) has no support for etypes", spn);
1608
1671
                goto out;
1609
1672
            }
1610
1673
            ekey = &skey->key;
 
1674
            etype = skey->key.keytype;
1611
1675
            kvno = server->entry.kvno;
1612
1676
        }
1613
1677
        
1622
1686
     * backward.
1623
1687
     */
1624
1688
 
1625
 
    if (strcmp(krb5_principal_get_realm(context, sp),
1626
 
               krb5_principal_get_comp_string(context,
1627
 
                                              krbtgt->entry.principal,
1628
 
                                              1)) != 0) {
 
1689
    /*
 
1690
     * Validate authoriation data
 
1691
     */
 
1692
 
 
1693
    ret = hdb_enctype2key(context, &krbtgt->entry,
 
1694
                          krbtgt_etype, &tkey_check);
 
1695
    if(ret) {
 
1696
        kdc_log(context, config, 0,
 
1697
                    "Failed to find key for krbtgt PAC check");
 
1698
        goto out;
 
1699
    }
 
1700
 
 
1701
    /* Now refetch the primary krbtgt, and get the current kvno (the
 
1702
     * sign check may have been on an old kvno, and the server may
 
1703
     * have been an incoming trust) */
 
1704
    ret = krb5_make_principal(context, &krbtgt_principal, 
 
1705
                              krb5_principal_get_comp_string(context,
 
1706
                                                             krbtgt->entry.principal,
 
1707
                                                             1),
 
1708
                              KRB5_TGS_NAME, 
 
1709
                              krb5_principal_get_comp_string(context,
 
1710
                                                             krbtgt->entry.principal,
 
1711
                                                             1), NULL);
 
1712
    if(ret) {
 
1713
        kdc_log(context, config, 0,
 
1714
                    "Failed to generate krbtgt principal");
 
1715
        goto out;
 
1716
    }
 
1717
 
 
1718
    ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
 
1719
    krb5_free_principal(context, krbtgt_principal);
 
1720
    if (ret) {
 
1721
        krb5_error_code ret2;
 
1722
        char *tpn, *tpn2;
 
1723
        ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
 
1724
        ret2 = krb5_unparse_name(context, krbtgt->entry.principal, &tpn2);
 
1725
        kdc_log(context, config, 0,
 
1726
                "Request with wrong krbtgt: %s, %s not found in our database",
 
1727
                (ret == 0) ? tpn : "<unknown>", (ret2 == 0) ? tpn2 : "<unknown>");
 
1728
        if(ret == 0)
 
1729
            free(tpn);
 
1730
        if(ret2 == 0)
 
1731
            free(tpn2);
 
1732
        ret = KRB5KRB_AP_ERR_NOT_US;
 
1733
        goto out;
 
1734
    }
 
1735
 
 
1736
    /* The first realm is the realm of the service, the second is
 
1737
     * krbtgt/<this>/@REALM component of the krbtgt DN the request was
 
1738
     * encrypted to.  The redirection via the krbtgt_out entry allows
 
1739
     * the DB to possibly correct the case of the realm (Samba4 does
 
1740
     * this) before the strcmp() */
 
1741
    if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
 
1742
               krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
1629
1743
        char *tpn;
1630
 
        ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
 
1744
        ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &tpn);
1631
1745
        kdc_log(context, config, 0,
1632
1746
                "Request with wrong krbtgt: %s",
1633
1747
                (ret == 0) ? tpn : "<unknown>");
1634
1748
        if(ret == 0)
1635
1749
            free(tpn);
1636
1750
        ret = KRB5KRB_AP_ERR_NOT_US;
1637
 
        goto out;
1638
1751
    }
1639
1752
 
1640
 
    /*
1641
 
     * Validate authoriation data
1642
 
     */
1643
 
 
1644
 
    ret = hdb_enctype2key(context, &krbtgt->entry,
1645
 
                          krbtgt_etype, &tkey);
 
1753
    ret = hdb_enctype2key(context, &krbtgt_out->entry,
 
1754
                          krbtgt_etype, &tkey_sign);
1646
1755
    if(ret) {
1647
1756
        kdc_log(context, config, 0,
1648
 
                    "Failed to find key for krbtgt PAC check");
 
1757
                    "Failed to find key for krbtgt PAC signature");
1649
1758
        goto out;
1650
1759
    }
1651
1760
 
 
1761
    ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
 
1762
                        NULL, &clientdb, &client);
 
1763
    if(ret == HDB_ERR_NOT_FOUND_HERE) {
 
1764
        /* This is OK, we are just trying to find out if they have
 
1765
         * been disabled or deleted in the meantime, missing secrets
 
1766
         * is OK */
 
1767
    } else if(ret){
 
1768
        const char *krbtgt_realm, *msg;
 
1769
 
 
1770
        /*
 
1771
         * If the client belongs to the same realm as our krbtgt, it
 
1772
         * should exist in the local database.
 
1773
         *
 
1774
         */
 
1775
 
 
1776
        krbtgt_realm = krb5_principal_get_realm(context, krbtgt_out->entry.principal);
 
1777
 
 
1778
        if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
 
1779
            if (ret == HDB_ERR_NOENTRY)
 
1780
                ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
 
1781
            kdc_log(context, config, 1, "Client no longer in database: %s",
 
1782
                    cpn);
 
1783
            goto out;
 
1784
        }
 
1785
 
 
1786
        msg = krb5_get_error_message(context, ret);
 
1787
        kdc_log(context, config, 1, "Client not found in database: %s", msg);
 
1788
        krb5_free_error_message(context, msg);
 
1789
    }
 
1790
 
1652
1791
    ret = check_PAC(context, config, cp,
1653
 
                    client, server, ekey, &tkey->key,
 
1792
                    client, server, krbtgt, ekey, &tkey_check->key, &tkey_sign->key,
1654
1793
                    tgt, &rspac, &signedpath);
1655
1794
    if (ret) {
 
1795
        const char *msg = krb5_get_error_message(context, ret);
1656
1796
        kdc_log(context, config, 0,
1657
1797
                "Verify PAC failed for %s (%s) from %s with %s",
1658
 
                spn, cpn, from, krb5_get_err_text(context, ret));
 
1798
                spn, cpn, from, msg);
 
1799
        krb5_free_error_message(context, msg);
1659
1800
        goto out;
1660
1801
    }
1661
1802
 
1663
1804
    ret = check_KRB5SignedPath(context,
1664
1805
                               config,
1665
1806
                               krbtgt,
 
1807
                               cp,
1666
1808
                               tgt,
1667
1809
                               &spp,
1668
1810
                               &signedpath);
1669
1811
    if (ret) {
 
1812
        const char *msg = krb5_get_error_message(context, ret);
1670
1813
        kdc_log(context, config, 0,
1671
1814
                "KRB5SignedPath check failed for %s (%s) from %s with %s",
1672
 
                spn, cpn, from, krb5_get_err_text(context, ret));
 
1815
                spn, cpn, from, msg);
 
1816
        krb5_free_error_message(context, msg);
1673
1817
        goto out;
1674
1818
    }
1675
1819
 
1705
1849
 
1706
1850
            ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1707
1851
            if (ret) {
 
1852
                const char *msg = krb5_get_error_message(context, ret);
1708
1853
                free_PA_S4U2Self(&self);
1709
1854
                krb5_data_free(&datack);
1710
 
                kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1711
 
                        krb5_get_err_text(context, ret));
 
1855
                kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
 
1856
                krb5_free_error_message(context, msg);
1712
1857
                goto out;
1713
1858
            }
1714
1859
 
1721
1866
            krb5_data_free(&datack);
1722
1867
            krb5_crypto_destroy(context, crypto);
1723
1868
            if (ret) {
 
1869
                const char *msg = krb5_get_error_message(context, ret);
1724
1870
                free_PA_S4U2Self(&self);
1725
1871
                kdc_log(context, config, 0,
1726
 
                        "krb5_verify_checksum failed for S4U2Self: %s",
1727
 
                        krb5_get_err_text(context, ret));
 
1872
                        "krb5_verify_checksum failed for S4U2Self: %s", msg);
 
1873
                krb5_free_error_message(context, msg);
1728
1874
                goto out;
1729
1875
            }
1730
1876
 
1740
1886
            if (ret)
1741
1887
                goto out;
1742
1888
 
 
1889
            /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
 
1890
            if(rspac.data) {
 
1891
                krb5_pac p = NULL;
 
1892
                krb5_data_free(&rspac);
 
1893
                ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON,
 
1894
                                    NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client);
 
1895
                if (ret) {
 
1896
                    const char *msg;
 
1897
 
 
1898
                    /*
 
1899
                     * If the client belongs to the same realm as our krbtgt, it
 
1900
                     * should exist in the local database.
 
1901
                     *
 
1902
                     */
 
1903
 
 
1904
                    if (ret == HDB_ERR_NOENTRY)
 
1905
                        ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
 
1906
                    msg = krb5_get_error_message(context, ret);
 
1907
                    kdc_log(context, config, 1, "S2U4Self principal to impersonate %s not found in database: %s", cpn, msg);
 
1908
                    krb5_free_error_message(context, msg);
 
1909
                    goto out;
 
1910
                }
 
1911
                ret = _kdc_pac_generate(context, s4u2self_impersonated_client, &p);
 
1912
                if (ret) {
 
1913
                    kdc_log(context, config, 0, "PAC generation failed for -- %s",
 
1914
                            selfcpn);
 
1915
                    goto out;
 
1916
                }
 
1917
                if (p != NULL) {
 
1918
                    ret = _krb5_pac_sign(context, p, ticket->ticket.authtime,
 
1919
                                         s4u2self_impersonated_client->entry.principal,
 
1920
                                         ekey, &tkey_sign->key,
 
1921
                                         &rspac);
 
1922
                    krb5_pac_free(context, p);
 
1923
                    if (ret) {
 
1924
                        kdc_log(context, config, 0, "PAC signing failed for -- %s",
 
1925
                                selfcpn);
 
1926
                        goto out;
 
1927
                    }
 
1928
                }
 
1929
            }
 
1930
 
1743
1931
            /*
1744
1932
             * Check that service doing the impersonating is
1745
1933
             * requesting a ticket to it-self.
1746
1934
             */
1747
 
            if (krb5_principal_compare(context, cp, sp) != TRUE) {
 
1935
            ret = check_s4u2self(context, config, clientdb, client, sp);
 
1936
            if (ret) {
1748
1937
                kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
1749
 
                        "to impersonate some other user "
 
1938
                        "to impersonate to service "
1750
1939
                        "(tried for user %s to service %s)",
1751
1940
                        cpn, selfcpn, spn);
1752
1941
                free(selfcpn);
1753
 
                ret = KRB5KDC_ERR_BADOPTION; /* ? */
1754
1942
                goto out;
1755
1943
            }
1756
1944
 
1855
2043
        ret = check_KRB5SignedPath(context,
1856
2044
                                   config,
1857
2045
                                   krbtgt,
 
2046
                                   cp,
1858
2047
                                   &adtkt,
1859
2048
                                   NULL,
1860
2049
                                   &ad_signedpath);
1861
2050
        if (ret == 0 && !ad_signedpath)
1862
2051
            ret = KRB5KDC_ERR_BADOPTION;
1863
2052
        if (ret) {
 
2053
            const char *msg = krb5_get_error_message(context, ret);
1864
2054
            kdc_log(context, config, 0,
1865
2055
                    "KRB5SignedPath check from service %s failed "
1866
2056
                    "for delegation to %s for client %s "
1867
2057
                    "from %s failed with %s",
1868
 
                    spn, str, cpn, from, krb5_get_err_text(context, ret));
 
2058
                    spn, str, cpn, from, msg);
 
2059
            krb5_free_error_message(context, msg);
1869
2060
            free(str);
1870
2061
            goto out;
1871
2062
        }
1945
2136
                         b,
1946
2137
                         client_principal,
1947
2138
                         tgt,
 
2139
                         replykey,
 
2140
                         rk_is_subkey,
1948
2141
                         ekey,
1949
2142
                         &sessionkey,
1950
2143
                         kvno,
1951
2144
                         *auth_data,
1952
2145
                         server,
1953
 
                         sp,
 
2146
                         server->entry.principal,
1954
2147
                         spn,
1955
2148
                         client,
1956
2149
                         cp,
1957
 
                         krbtgt,
 
2150
                         krbtgt_out,
1958
2151
                         krbtgt_etype,
1959
2152
                         spp,
1960
2153
                         &rspac,
1968
2161
        
1969
2162
    krb5_data_free(&rspac);
1970
2163
    krb5_free_keyblock_contents(context, &sessionkey);
 
2164
    if(krbtgt_out)
 
2165
        _kdc_free_ent(context, krbtgt_out);
1971
2166
    if(server)
1972
2167
        _kdc_free_ent(context, server);
1973
2168
    if(client)
1974
2169
        _kdc_free_ent(context, client);
 
2170
    if(s4u2self_impersonated_client)
 
2171
        _kdc_free_ent(context, s4u2self_impersonated_client);
1975
2172
 
1976
2173
    if (client_principal && client_principal != cp)
1977
2174
        krb5_free_principal(context, client_principal);
2011
2208
    const char *e_text = NULL;
2012
2209
    krb5_enctype krbtgt_etype = ETYPE_NULL;
2013
2210
 
 
2211
    krb5_keyblock *replykey = NULL;
 
2212
    int rk_is_subkey = 0;
2014
2213
    time_t *csec = NULL;
2015
2214
    int *cusec = NULL;
2016
2215
 
2038
2237
                            &e_text,
2039
2238
                            from, from_addr,
2040
2239
                            &csec, &cusec,
2041
 
                            &auth_data);
 
2240
                            &auth_data,
 
2241
                            &replykey,
 
2242
                            &rk_is_subkey);
 
2243
    if (ret == HDB_ERR_NOT_FOUND_HERE) {
 
2244
        /* kdc_log() is called in tgs_parse_request() */
 
2245
        goto out;
 
2246
    }
2042
2247
    if (ret) {
2043
2248
        kdc_log(context, config, 0,
2044
2249
                "Failed parsing TGS-REQ from %s", from);
2051
2256
                          &req->req_body,
2052
2257
                          krbtgt,
2053
2258
                          krbtgt_etype,
 
2259
                          replykey,
 
2260
                          rk_is_subkey,
2054
2261
                          ticket,
2055
2262
                          data,
2056
2263
                          from,
2071
2278
    }
2072
2279
 
2073
2280
out:
2074
 
    if(ret && data->data == NULL){
 
2281
    if (replykey)
 
2282
        krb5_free_keyblock(context, replykey);
 
2283
    if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
2075
2284
        krb5_mk_error(context,
2076
2285
                      ret,
2077
2286
                      NULL,
2081
2290
                      csec,
2082
2291
                      cusec,
2083
2292
                      data);
 
2293
        ret = 0;
2084
2294
    }
2085
2295
    free(csec);
2086
2296
    free(cusec);
2094
2304
        free(auth_data);
2095
2305
    }
2096
2306
 
2097
 
    return 0;
 
2307
    return ret;
2098
2308
}