Loading plugin/krb5/krb5.cpp +152 −8 Changes for plugin/krb5/krb5.cpp: 152 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <random> #include <algorithm> #include <memory> #include <optional> #include <set> #include <chrono> #include <fstream> Loading @@ -59,6 +60,7 @@ #include "session.h" #include "crypto/krb5keys.h" #include "dsdb/pac.h" #include "crypto/crypto.h" #include "domains.h" #include "types.h" #include "exception.h" Loading Loading @@ -1332,11 +1334,21 @@ bool Asn1Der::parseKdcReq(const uint8_t *data, size_t len, Krb5KdcReq &req) { } break; } case 11: /* additional-tickets */ case 11: /* additional-tickets: SEQUENCE OF Ticket */ { /* For TGS-REQ, this may contain the TGT * Actually in standard Kerberos, additional-tickets is * used for user-to-user. The TGT is in the PA-TGS-REQ. */ const uint8_t *seq; size_t seqLen; size_t so = 0; uint8_t st; if (!parseTLV(bbcontent, bbcontent_len, so, st, seq, seqLen) || st != TAG_SEQUENCE) break; size_t to = 0; while (to < seqLen) { size_t start = to; uint8_t tt; const uint8_t *tc; size_t tl; if (!parseTLV(seq, seqLen, to, tt, tc, tl)) break; Krb5Ticket t; if (parseTicket(seq + start, to - start, t)) req.additional_tickets.push_back(std::move(t)); } break; } } Loading Loading @@ -3587,6 +3599,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l */ Krb5ApReq tgsApReq; bool foundApReq = false; std::vector<uint8_t> paForUser; /* S4U2Self (MS-SFU PA-FOR-USER, type 129) */ if (!req.padata.empty()) { /* Parse SEQUENCE OF PA-DATA to find PA-TGS-REQ */ Loading Loading @@ -3633,6 +3646,8 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l } } if (pdType == 129 && !pdValue.empty()) paForUser = pdValue; if (pdType == KRB5_PADATA_TGS_REQ && !pdValue.empty()) { /* pdValue is an AP-REQ containing the TGT */ size_t apConsumed = 0; Loading Loading @@ -3797,6 +3812,133 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l svcRealm, req.sname.name, req.sname.instance); } /* ---- S4U (MS-SFU): whose ticket this is ---- */ Krb5Principal ticketClient = tgt_enc.cname; bool haveClientUid = false; uuid::uuid s4uClientUid; bool s4uForwardable = true; std::optional<dsdb::Entry> requester; { uuid::uuid ru; std::vector<uint8_t> rk; int32_t re = selectedEtype; std::string rs; if (svcRi->dir && lookupPrincipal(*svcRi, tgt_enc.cname, selectedEtype, ru, rk, re, rs)) requester = svcRi->dir->byGuid(ru); } auto principalOf = [&](const dsdb::Entry &e) { return Krb5Principal(KRB5_NT_PRINCIPAL, svcRi->meta.realm, e.str("sAMAccountName")); }; if (!paForUser.empty()) { /* S4U2Self: PA-FOR-USER ::= SEQUENCE { userName[0] PrincipalName, * userRealm[1] Realm, cksum[2] Checksum, auth-package[3] KerberosString } */ const uint8_t *seq; size_t seqLen; size_t o = 0; uint8_t t; Krb5PrincipalType ut = KRB5_NT_PRINCIPAL; std::vector<std::string> comps; std::string urealm, pkg; std::vector<uint8_t> cksum; if (!Asn1Der::parseTLV(paForUser.data(), paForUser.size(), o, t, seq, seqLen) || t != Asn1Der::TAG_SEQUENCE) return buildStandardError(KRB_ERR_GENERIC, "bad PA-FOR-USER", svcRealm, req.sname.name, req.sname.instance); size_t f = 0; while (f < seqLen) { uint8_t ft; const uint8_t *fc; size_t fl; if (!Asn1Der::parseTLV(seq, seqLen, f, ft, fc, fl)) break; size_t io = 0; uint8_t it; const uint8_t *ic; size_t il; switch (ft & 0x1F) { case 0: Asn1Der::parsePrincipalName(fc, fl, ut, comps); break; case 1: if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) Asn1Der::parseGeneralString(ic, il, urealm); break; case 2: /* Checksum ::= SEQUENCE { cksumtype[0], checksum[1] OCTET STRING } */ if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) { size_t co = 0; uint8_t ct; const uint8_t *cc; size_t cl; while (co < il && Asn1Der::parseTLV(ic, il, co, ct, cc, cl)) if ((ct & 0x1F) == 1) { size_t xo = 0; uint8_t xt; const uint8_t *xc; size_t xl; if (Asn1Der::parseTLV(cc, cl, xo, xt, xc, xl)) cksum.assign(xc, xc + xl); } } break; case 3: if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) Asn1Der::parseGeneralString(ic, il, pkg); break; } } /* KERB_CHECKSUM_HMAC_MD5 (RFC 4757) with the TGT session key, usage 17, * over name-type (LE32) | name strings | realm | auth-package */ crypto::Bytes data; for (int i = 0; i < 4; ++i) data.push_back(uint8_t(uint32_t(ut) >> (8 * i))); for (auto &c : comps) data.insert(data.end(), c.begin(), c.end()); data.insert(data.end(), urealm.begin(), urealm.end()); data.insert(data.end(), pkg.begin(), pkg.end()); const char sk[] = "signaturekey"; crypto::Bytes ksign = crypto::hmacMd5(tgt_enc.session_key.keydata, crypto::Bytes(sk, sk + sizeof sk)); crypto::Bytes tmp = {17, 0, 0, 0}; tmp.insert(tmp.end(), data.begin(), data.end()); crypto::Bytes want = crypto::hmacMd5(ksign, crypto::md5(tmp)); if (!crypto::equal(want, crypto::Bytes(cksum.begin(), cksum.end()))) return buildStandardError(KRB_AP_ERR_MODIFIED, "PA-FOR-USER checksum invalid", svcRealm, req.sname.name, req.sname.instance); /* only for itself: the requested service is the requester */ if (!requester || !(requester->objectGuid == svc_uid)) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Self only to the requesting service", svcRealm, req.sname.name, req.sname.instance); std::string uname; for (auto &c : comps) { if (!uname.empty()) uname += "/"; uname += c; } Krb5Principal up(KRB5_NT_PRINCIPAL, svcRi->meta.realm, uname); uuid::uuid uu; std::vector<uint8_t> uk; int32_t ue = selectedEtype; std::string us; if (!lookupPrincipal(*svcRi, up, selectedEtype, uu, uk, ue, us)) return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "S4U2Self: unknown user " + uname, svcRealm, req.sname.name, req.sname.instance); auto ue2 = svcRi->dir->byGuid(uu); if (!ue2) return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "S4U2Self: unknown user", svcRealm, req.sname.name, req.sname.instance); ticketClient = principalOf(*ue2); s4uClientUid = uu; haveClientUid = true; /* forwardable (usable for S4U2Proxy) only with protocol transition * (TRUSTED_TO_AUTH_FOR_DELEGATION) and a delegable user */ uint32_t ruac = uint32_t(dsdb::intValue(requester->attrs, "userAccountControl", 0)); uint32_t uuac = uint32_t(dsdb::intValue(ue2->attrs, "userAccountControl", 0)); s4uForwardable = (ruac & 0x1000000) && !(uuac & 0x100000); std::cerr << "[KDC] S4U2Self " << tgt_enc.cname.name << " for '" << uname << "' forwardable=" << s4uForwardable << std::endl; } if (req.kdc_options & 0x00020000) { /* S4U2Proxy (cname-in-addl-tkt): the evidence ticket is the user's * ticket to the requester; the target must be in the requester's * msDS-AllowedToDelegateTo */ if (req.additional_tickets.empty() || !requester) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: no evidence ticket", svcRealm, req.sname.name, req.sname.instance); Krb5Ticket &ev = req.additional_tickets.front(); uuid::uuid eu; std::vector<uint8_t> ek; int32_t ee = ev.enc_etype; std::string es; Krb5EncTicketPart evEnc; bool ok = false; if (lookupPrincipal(*svcRi, tgt_enc.cname, ev.enc_etype, eu, ek, ee, es)) { try { auto pl = Krb5Crypto::decrypt(ek, ev.enc_part, KRB5_KU_TICKET); size_t cc = 0; ok = evEnc.deserialize(pl.data(), pl.size(), cc); } catch (const std::exception &) { ok = false; } } if (!ok) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: evidence ticket is not for the requester", svcRealm, req.sname.name, req.sname.instance); if (!(evEnc.flags & KRB5_TF_FORWARDABLE)) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: evidence ticket not forwardable", svcRealm, req.sname.name, req.sname.instance); std::string target = req.sname.name + (req.sname.instance.empty() ? "" : "/" + req.sname.instance); bool allowed = false; if (auto *atd = requester->get("msDS-AllowedToDelegateTo")) for (auto &v : *atd) { std::string a = v.substr(0, v.find('@')); if (dsdb::iequals(a, target)) allowed = true; } std::cerr << "[KDC] S4U2Proxy " << tgt_enc.cname.name << " for '" << evEnc.cname.name << "' -> " << target << (allowed ? " allowed" : " NOT allowed") << std::endl; if (!allowed) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: target not in msDS-AllowedToDelegateTo", svcRealm, req.sname.name, req.sname.instance); ticketClient = evEnc.cname; uuid::uuid cu; std::vector<uint8_t> ck; int32_t ce = selectedEtype; std::string cs; if (lookupPrincipal(*svcRi, evEnc.cname, selectedEtype, cu, ck, ce, cs)) { s4uClientUid = cu; haveClientUid = true; } } /* Generate service session key */ Krb5SessionKey svc_session_key = Krb5Crypto::generateSessionKey(selectedEtype); Loading @@ -3807,7 +3949,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l endtime = tgt_enc.endtime; uint32_t svcFlags = KRB5_TF_PRE_AUTHENT; if (tgt_enc.flags & KRB5_TF_FORWARDABLE) if ((tgt_enc.flags & KRB5_TF_FORWARDABLE) && s4uForwardable) svcFlags |= KRB5_TF_FORWARDABLE; if (tgt_enc.flags & KRB5_TF_RENEWABLE) svcFlags |= KRB5_TF_RENEWABLE; Loading @@ -3816,7 +3958,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l Krb5EncTicketPart svc_enc_tkt; svc_enc_tkt.flags = svcFlags; svc_enc_tkt.session_key = svc_session_key; svc_enc_tkt.cname = tgt_enc.cname; svc_enc_tkt.cname = ticketClient; svc_enc_tkt.transited = tgt_enc.transited; svc_enc_tkt.authtime = tgt_enc.authtime; svc_enc_tkt.starttime = now; Loading @@ -3827,7 +3969,9 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l * from the TGT's cname (a standard, serialized field) so the service ticket * gets a valid PAC; without it Windows rejects the logon ("bad password"). */ uuid::uuid pacUid = tgt_enc.uid; { if (haveClientUid) { pacUid = s4uClientUid; } else { std::vector<uint8_t> _k; int32_t _ke = selectedEtype; std::string _s; uuid::uuid cu; if (lookupPrincipal(*svcRi, tgt_enc.cname, selectedEtype, cu, _k, _ke, _s)) pacUid = cu; Loading Loading @@ -3878,7 +4022,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l Krb5KdcRep tgs_rep; tgs_rep.pvno = 5; tgs_rep.msg_type = KRB_TGS_REP; tgs_rep.cname = tgt_enc.cname; tgs_rep.cname = ticketClient; tgs_rep.ticket = svc_ticket; tgs_rep.enc_etype = selectedEtype; tgs_rep.enc_kvno = 1; Loading plugin/krb5/krb5.h +1 −0 Changes for plugin/krb5/krb5.h: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -504,6 +504,7 @@ namespace fenrirds { std::vector<Krb5EncType> etypes; /* requested enc types */ std::vector<uint8_t> padata; /* pre-auth data (PA-DATA) */ Krb5Ticket tgt; /* TGT (only for TGS-REQ) */ std::vector<Krb5Ticket> additional_tickets; /* [11]: S4U2Proxy evidence, user-to-user */ std::vector<uint8_t> authenticator; /* AP-REQ in padata (TGS-REQ)*/ Krb5KdcReq(); Loading Loading
plugin/krb5/krb5.cpp +152 −8 Changes for plugin/krb5/krb5.cpp: 152 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <random> #include <algorithm> #include <memory> #include <optional> #include <set> #include <chrono> #include <fstream> Loading @@ -59,6 +60,7 @@ #include "session.h" #include "crypto/krb5keys.h" #include "dsdb/pac.h" #include "crypto/crypto.h" #include "domains.h" #include "types.h" #include "exception.h" Loading Loading @@ -1332,11 +1334,21 @@ bool Asn1Der::parseKdcReq(const uint8_t *data, size_t len, Krb5KdcReq &req) { } break; } case 11: /* additional-tickets */ case 11: /* additional-tickets: SEQUENCE OF Ticket */ { /* For TGS-REQ, this may contain the TGT * Actually in standard Kerberos, additional-tickets is * used for user-to-user. The TGT is in the PA-TGS-REQ. */ const uint8_t *seq; size_t seqLen; size_t so = 0; uint8_t st; if (!parseTLV(bbcontent, bbcontent_len, so, st, seq, seqLen) || st != TAG_SEQUENCE) break; size_t to = 0; while (to < seqLen) { size_t start = to; uint8_t tt; const uint8_t *tc; size_t tl; if (!parseTLV(seq, seqLen, to, tt, tc, tl)) break; Krb5Ticket t; if (parseTicket(seq + start, to - start, t)) req.additional_tickets.push_back(std::move(t)); } break; } } Loading Loading @@ -3587,6 +3599,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l */ Krb5ApReq tgsApReq; bool foundApReq = false; std::vector<uint8_t> paForUser; /* S4U2Self (MS-SFU PA-FOR-USER, type 129) */ if (!req.padata.empty()) { /* Parse SEQUENCE OF PA-DATA to find PA-TGS-REQ */ Loading Loading @@ -3633,6 +3646,8 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l } } if (pdType == 129 && !pdValue.empty()) paForUser = pdValue; if (pdType == KRB5_PADATA_TGS_REQ && !pdValue.empty()) { /* pdValue is an AP-REQ containing the TGT */ size_t apConsumed = 0; Loading Loading @@ -3797,6 +3812,133 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l svcRealm, req.sname.name, req.sname.instance); } /* ---- S4U (MS-SFU): whose ticket this is ---- */ Krb5Principal ticketClient = tgt_enc.cname; bool haveClientUid = false; uuid::uuid s4uClientUid; bool s4uForwardable = true; std::optional<dsdb::Entry> requester; { uuid::uuid ru; std::vector<uint8_t> rk; int32_t re = selectedEtype; std::string rs; if (svcRi->dir && lookupPrincipal(*svcRi, tgt_enc.cname, selectedEtype, ru, rk, re, rs)) requester = svcRi->dir->byGuid(ru); } auto principalOf = [&](const dsdb::Entry &e) { return Krb5Principal(KRB5_NT_PRINCIPAL, svcRi->meta.realm, e.str("sAMAccountName")); }; if (!paForUser.empty()) { /* S4U2Self: PA-FOR-USER ::= SEQUENCE { userName[0] PrincipalName, * userRealm[1] Realm, cksum[2] Checksum, auth-package[3] KerberosString } */ const uint8_t *seq; size_t seqLen; size_t o = 0; uint8_t t; Krb5PrincipalType ut = KRB5_NT_PRINCIPAL; std::vector<std::string> comps; std::string urealm, pkg; std::vector<uint8_t> cksum; if (!Asn1Der::parseTLV(paForUser.data(), paForUser.size(), o, t, seq, seqLen) || t != Asn1Der::TAG_SEQUENCE) return buildStandardError(KRB_ERR_GENERIC, "bad PA-FOR-USER", svcRealm, req.sname.name, req.sname.instance); size_t f = 0; while (f < seqLen) { uint8_t ft; const uint8_t *fc; size_t fl; if (!Asn1Der::parseTLV(seq, seqLen, f, ft, fc, fl)) break; size_t io = 0; uint8_t it; const uint8_t *ic; size_t il; switch (ft & 0x1F) { case 0: Asn1Der::parsePrincipalName(fc, fl, ut, comps); break; case 1: if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) Asn1Der::parseGeneralString(ic, il, urealm); break; case 2: /* Checksum ::= SEQUENCE { cksumtype[0], checksum[1] OCTET STRING } */ if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) { size_t co = 0; uint8_t ct; const uint8_t *cc; size_t cl; while (co < il && Asn1Der::parseTLV(ic, il, co, ct, cc, cl)) if ((ct & 0x1F) == 1) { size_t xo = 0; uint8_t xt; const uint8_t *xc; size_t xl; if (Asn1Der::parseTLV(cc, cl, xo, xt, xc, xl)) cksum.assign(xc, xc + xl); } } break; case 3: if (Asn1Der::parseTLV(fc, fl, io, it, ic, il)) Asn1Der::parseGeneralString(ic, il, pkg); break; } } /* KERB_CHECKSUM_HMAC_MD5 (RFC 4757) with the TGT session key, usage 17, * over name-type (LE32) | name strings | realm | auth-package */ crypto::Bytes data; for (int i = 0; i < 4; ++i) data.push_back(uint8_t(uint32_t(ut) >> (8 * i))); for (auto &c : comps) data.insert(data.end(), c.begin(), c.end()); data.insert(data.end(), urealm.begin(), urealm.end()); data.insert(data.end(), pkg.begin(), pkg.end()); const char sk[] = "signaturekey"; crypto::Bytes ksign = crypto::hmacMd5(tgt_enc.session_key.keydata, crypto::Bytes(sk, sk + sizeof sk)); crypto::Bytes tmp = {17, 0, 0, 0}; tmp.insert(tmp.end(), data.begin(), data.end()); crypto::Bytes want = crypto::hmacMd5(ksign, crypto::md5(tmp)); if (!crypto::equal(want, crypto::Bytes(cksum.begin(), cksum.end()))) return buildStandardError(KRB_AP_ERR_MODIFIED, "PA-FOR-USER checksum invalid", svcRealm, req.sname.name, req.sname.instance); /* only for itself: the requested service is the requester */ if (!requester || !(requester->objectGuid == svc_uid)) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Self only to the requesting service", svcRealm, req.sname.name, req.sname.instance); std::string uname; for (auto &c : comps) { if (!uname.empty()) uname += "/"; uname += c; } Krb5Principal up(KRB5_NT_PRINCIPAL, svcRi->meta.realm, uname); uuid::uuid uu; std::vector<uint8_t> uk; int32_t ue = selectedEtype; std::string us; if (!lookupPrincipal(*svcRi, up, selectedEtype, uu, uk, ue, us)) return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "S4U2Self: unknown user " + uname, svcRealm, req.sname.name, req.sname.instance); auto ue2 = svcRi->dir->byGuid(uu); if (!ue2) return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "S4U2Self: unknown user", svcRealm, req.sname.name, req.sname.instance); ticketClient = principalOf(*ue2); s4uClientUid = uu; haveClientUid = true; /* forwardable (usable for S4U2Proxy) only with protocol transition * (TRUSTED_TO_AUTH_FOR_DELEGATION) and a delegable user */ uint32_t ruac = uint32_t(dsdb::intValue(requester->attrs, "userAccountControl", 0)); uint32_t uuac = uint32_t(dsdb::intValue(ue2->attrs, "userAccountControl", 0)); s4uForwardable = (ruac & 0x1000000) && !(uuac & 0x100000); std::cerr << "[KDC] S4U2Self " << tgt_enc.cname.name << " for '" << uname << "' forwardable=" << s4uForwardable << std::endl; } if (req.kdc_options & 0x00020000) { /* S4U2Proxy (cname-in-addl-tkt): the evidence ticket is the user's * ticket to the requester; the target must be in the requester's * msDS-AllowedToDelegateTo */ if (req.additional_tickets.empty() || !requester) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: no evidence ticket", svcRealm, req.sname.name, req.sname.instance); Krb5Ticket &ev = req.additional_tickets.front(); uuid::uuid eu; std::vector<uint8_t> ek; int32_t ee = ev.enc_etype; std::string es; Krb5EncTicketPart evEnc; bool ok = false; if (lookupPrincipal(*svcRi, tgt_enc.cname, ev.enc_etype, eu, ek, ee, es)) { try { auto pl = Krb5Crypto::decrypt(ek, ev.enc_part, KRB5_KU_TICKET); size_t cc = 0; ok = evEnc.deserialize(pl.data(), pl.size(), cc); } catch (const std::exception &) { ok = false; } } if (!ok) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: evidence ticket is not for the requester", svcRealm, req.sname.name, req.sname.instance); if (!(evEnc.flags & KRB5_TF_FORWARDABLE)) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: evidence ticket not forwardable", svcRealm, req.sname.name, req.sname.instance); std::string target = req.sname.name + (req.sname.instance.empty() ? "" : "/" + req.sname.instance); bool allowed = false; if (auto *atd = requester->get("msDS-AllowedToDelegateTo")) for (auto &v : *atd) { std::string a = v.substr(0, v.find('@')); if (dsdb::iequals(a, target)) allowed = true; } std::cerr << "[KDC] S4U2Proxy " << tgt_enc.cname.name << " for '" << evEnc.cname.name << "' -> " << target << (allowed ? " allowed" : " NOT allowed") << std::endl; if (!allowed) return buildStandardError(KDC_ERR_BADOPTION, "S4U2Proxy: target not in msDS-AllowedToDelegateTo", svcRealm, req.sname.name, req.sname.instance); ticketClient = evEnc.cname; uuid::uuid cu; std::vector<uint8_t> ck; int32_t ce = selectedEtype; std::string cs; if (lookupPrincipal(*svcRi, evEnc.cname, selectedEtype, cu, ck, ce, cs)) { s4uClientUid = cu; haveClientUid = true; } } /* Generate service session key */ Krb5SessionKey svc_session_key = Krb5Crypto::generateSessionKey(selectedEtype); Loading @@ -3807,7 +3949,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l endtime = tgt_enc.endtime; uint32_t svcFlags = KRB5_TF_PRE_AUTHENT; if (tgt_enc.flags & KRB5_TF_FORWARDABLE) if ((tgt_enc.flags & KRB5_TF_FORWARDABLE) && s4uForwardable) svcFlags |= KRB5_TF_FORWARDABLE; if (tgt_enc.flags & KRB5_TF_RENEWABLE) svcFlags |= KRB5_TF_RENEWABLE; Loading @@ -3816,7 +3958,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l Krb5EncTicketPart svc_enc_tkt; svc_enc_tkt.flags = svcFlags; svc_enc_tkt.session_key = svc_session_key; svc_enc_tkt.cname = tgt_enc.cname; svc_enc_tkt.cname = ticketClient; svc_enc_tkt.transited = tgt_enc.transited; svc_enc_tkt.authtime = tgt_enc.authtime; svc_enc_tkt.starttime = now; Loading @@ -3827,7 +3969,9 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l * from the TGT's cname (a standard, serialized field) so the service ticket * gets a valid PAC; without it Windows rejects the logon ("bad password"). */ uuid::uuid pacUid = tgt_enc.uid; { if (haveClientUid) { pacUid = s4uClientUid; } else { std::vector<uint8_t> _k; int32_t _ke = selectedEtype; std::string _s; uuid::uuid cu; if (lookupPrincipal(*svcRi, tgt_enc.cname, selectedEtype, cu, _k, _ke, _s)) pacUid = cu; Loading Loading @@ -3878,7 +4022,7 @@ std::vector<uint8_t> Krb5KDC::handleStandardTgsReq(const uint8_t *data, size_t l Krb5KdcRep tgs_rep; tgs_rep.pvno = 5; tgs_rep.msg_type = KRB_TGS_REP; tgs_rep.cname = tgt_enc.cname; tgs_rep.cname = ticketClient; tgs_rep.ticket = svc_ticket; tgs_rep.enc_etype = selectedEtype; tgs_rep.enc_kvno = 1; Loading
plugin/krb5/krb5.h +1 −0 Changes for plugin/krb5/krb5.h: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -504,6 +504,7 @@ namespace fenrirds { std::vector<Krb5EncType> etypes; /* requested enc types */ std::vector<uint8_t> padata; /* pre-auth data (PA-DATA) */ Krb5Ticket tgt; /* TGT (only for TGS-REQ) */ std::vector<Krb5Ticket> additional_tickets; /* [11]: S4U2Proxy evidence, user-to-user */ std::vector<uint8_t> authenticator; /* AP-REQ in padata (TGS-REQ)*/ Krb5KdcReq(); Loading