Loading plugin/krb5/krb5.cpp +16 −2 Changes for plugin/krb5/krb5.cpp: 16 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -2939,10 +2939,13 @@ std::vector<uint8_t> Krb5KDC::handleStandardAsReq(const uint8_t *data, size_t le selectedEtype = static_cast<Krb5EncType>(clientEtype); if (!found) { std::cerr << "[KDC] AS-REQ lookup -> PRINCIPAL NOT FOUND" << std::endl; return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "Principal not found: " + req.cname.toString(), req.cname.realm, "krbtgt"); } std::cerr << "[KDC] AS-REQ found uid etype=" << clientEtype << " salt='" << clientSalt << "' keylen=" << client_key.size() << std::endl; /* Check pre-authentication */ if (req.padata.empty()) { Loading Loading @@ -3041,11 +3044,16 @@ std::vector<uint8_t> Krb5KDC::handleStandardAsReq(const uint8_t *data, size_t le uint32_t pa_usec = 0; if (Asn1Der::parsePaEncTimestamp(pa_plain.data(), pa_plain.size(), pa_time, pa_usec)) { time_t now = time(nullptr); std::cerr << "[KDC] preauth decrypt OK (paEtype=" << int(paEtype) << " skew=" << long(now - pa_time) << ")" << std::endl; if (std::abs(static_cast<long>(now - pa_time)) <= _MaxClockSkew) paVerified = true; } else { std::cerr << "[KDC] preauth decrypt OK but timestamp parse FAILED" << std::endl; } } catch (const AuthBackendError &) { /* Decryption failed = wrong key */ std::cerr << "[KDC] preauth decrypt FAILED (wrong key, paEtype=" << int(paEtype) << " cipher=" << paCipher.size() << "B)" << std::endl; } } } Loading Loading @@ -3675,10 +3683,16 @@ bool Krb5KDC::ntlmNtHash(const std::string &user, const std::string &domain, e = ri->dir->byUpn(user); if (!e && !user.empty() && user.back() != '$') e = ri->dir->bySamAccountName(user + "$"); if (!e) if (!e) { std::cerr << "[KDC] ntlmNtHash user='" << user << "' domain='" << domain << "' realm='" << ri->meta.realm << "' -> ACCOUNT NOT FOUND" << std::endl; return false; } dsdb::Secrets sec = ri->dir->secretsOf(e->objectGuid); std::cerr << "[KDC] ntlmNtHash user='" << user << "' domain='" << domain << "' -> found dn='" << e->dn.str() << "' ntHash=" << sec.ntHash.size() << "B keys=" << sec.keys.size() << std::endl; if (sec.ntHash.size() != 16) return false; ntHash.assign(sec.ntHash.begin(), sec.ntHash.end()); Loading plugin/smb/smb.cpp +5 −1 Changes for plugin/smb/smb.cpp: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -492,7 +492,11 @@ std::vector<uint8_t> SmbServer::handleMessage(Conn &c, const std::vector<uint8_t return errorResponse(req, smb::STATUS_OBJECT_NAME_NOT_FOUND); uint64_t fid = c.nextFid++; c.pipes[fid] = new RpcPipe(pname); c.pipes[fid]->setSessionKey(c.sessionKey); /* RPC-over-SMB session key (used e.g. to decrypt SAMR passwords): for * SMB 3.x it is the derived application key (SMBAppKey), not the raw * authentication session key. */ c.pipes[fid]->setSessionKey((c.dialect >= smb::SMB_3_0 && c.haveKeys) ? c.keys.application : c.sessionKey); smb::Smb2Header h; h.command=req.command; h.messageId=req.messageId; h.sessionId=c.sessionId; h.treeId=req.treeId; h.status=smb::STATUS_SUCCESS; h.creditReqResp=1; auto resp = smb::buildHeader(h); Loading src/rpc/netlogon.cpp +2 −2 Changes for src/rpc/netlogon.cpp: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ DispatchResult netlogonDispatch(uint16_t opnum, const std::vector<uint8_t> &stub switch (opnum) { case NETR_SERVERREQCHALLENGE: { NdrPull in(stub); in.u32(); /* PrimaryName unique referent (NULL) */ if (in.u32() != 0) in.unistrBuffer(); /* PrimaryName [unique,string]: skip if present */ std::string computer = in.unistrBuffer(); uint8_t cc[8]; in.take(cc, 8); Chan ch; Loading @@ -100,7 +100,7 @@ DispatchResult netlogonDispatch(uint16_t opnum, const std::vector<uint8_t> &stub case NETR_SERVERAUTHENTICATE2: case NETR_SERVERAUTHENTICATE3: { NdrPull in(stub); in.u32(); /* PrimaryName unique (NULL) */ if (in.u32() != 0) in.unistrBuffer(); /* PrimaryName [unique,string]: skip if present */ std::string account = in.unistrBuffer(); in.u16(); /* secure_channel_type */ std::string computer = in.unistrBuffer(); Loading src/rpc/samr.cpp +4 −0 Changes for src/rpc/samr.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -314,12 +314,16 @@ DispatchResult samrDispatch(uint16_t opnum, const std::vector<uint8_t> &stub, auto key16 = std::vector<uint8_t>(sessionKey.begin(), sessionKey.begin() + 16); auto dec = crypto::rc4(key16, enc); uint32_t pwLen = dec[512] | dec[513] << 8 | dec[514] << 16 | uint32_t(dec[515]) << 24; std::cerr << "[SAMR] SetUserInfo2 level=" << level << " sessKey=" << sessionKey.size() << "B rest=" << rest.size() << "B pwLen=" << pwLen << std::endl; if (pwLen <= 512) { std::string pw = crypto::fromUtf16le(dec.data() + (512 - pwLen), pwLen); std::string sam = dsdb::value(attrs, "sAMAccountName"); bool comp = dsdb::hasValue(attrs, "objectClass", "computer"); auto kind = comp ? dsdb::PrincipalKind::Computer : dsdb::PrincipalKind::User; std::string salt = dsdb::kerberosSalt(kind, d.meta.realm, sam, d.meta.dnsName); std::cerr << "[SAMR] SetUserInfo2 sam='" << sam << "' computer=" << comp << " salt='" << salt << "' pwBytes=" << pw.size() << std::endl; dsdb::Secrets old = dir.secretsOf(obj.guid); newSec = std::make_unique<dsdb::Secrets>(dsdb::deriveSecrets(pw, salt, old.kvno)); /* enable the account once it has a password */ Loading Loading
plugin/krb5/krb5.cpp +16 −2 Changes for plugin/krb5/krb5.cpp: 16 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -2939,10 +2939,13 @@ std::vector<uint8_t> Krb5KDC::handleStandardAsReq(const uint8_t *data, size_t le selectedEtype = static_cast<Krb5EncType>(clientEtype); if (!found) { std::cerr << "[KDC] AS-REQ lookup -> PRINCIPAL NOT FOUND" << std::endl; return buildStandardError(KDC_ERR_C_PRINCIPAL_UNKNOWN, "Principal not found: " + req.cname.toString(), req.cname.realm, "krbtgt"); } std::cerr << "[KDC] AS-REQ found uid etype=" << clientEtype << " salt='" << clientSalt << "' keylen=" << client_key.size() << std::endl; /* Check pre-authentication */ if (req.padata.empty()) { Loading Loading @@ -3041,11 +3044,16 @@ std::vector<uint8_t> Krb5KDC::handleStandardAsReq(const uint8_t *data, size_t le uint32_t pa_usec = 0; if (Asn1Der::parsePaEncTimestamp(pa_plain.data(), pa_plain.size(), pa_time, pa_usec)) { time_t now = time(nullptr); std::cerr << "[KDC] preauth decrypt OK (paEtype=" << int(paEtype) << " skew=" << long(now - pa_time) << ")" << std::endl; if (std::abs(static_cast<long>(now - pa_time)) <= _MaxClockSkew) paVerified = true; } else { std::cerr << "[KDC] preauth decrypt OK but timestamp parse FAILED" << std::endl; } } catch (const AuthBackendError &) { /* Decryption failed = wrong key */ std::cerr << "[KDC] preauth decrypt FAILED (wrong key, paEtype=" << int(paEtype) << " cipher=" << paCipher.size() << "B)" << std::endl; } } } Loading Loading @@ -3675,10 +3683,16 @@ bool Krb5KDC::ntlmNtHash(const std::string &user, const std::string &domain, e = ri->dir->byUpn(user); if (!e && !user.empty() && user.back() != '$') e = ri->dir->bySamAccountName(user + "$"); if (!e) if (!e) { std::cerr << "[KDC] ntlmNtHash user='" << user << "' domain='" << domain << "' realm='" << ri->meta.realm << "' -> ACCOUNT NOT FOUND" << std::endl; return false; } dsdb::Secrets sec = ri->dir->secretsOf(e->objectGuid); std::cerr << "[KDC] ntlmNtHash user='" << user << "' domain='" << domain << "' -> found dn='" << e->dn.str() << "' ntHash=" << sec.ntHash.size() << "B keys=" << sec.keys.size() << std::endl; if (sec.ntHash.size() != 16) return false; ntHash.assign(sec.ntHash.begin(), sec.ntHash.end()); Loading
plugin/smb/smb.cpp +5 −1 Changes for plugin/smb/smb.cpp: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -492,7 +492,11 @@ std::vector<uint8_t> SmbServer::handleMessage(Conn &c, const std::vector<uint8_t return errorResponse(req, smb::STATUS_OBJECT_NAME_NOT_FOUND); uint64_t fid = c.nextFid++; c.pipes[fid] = new RpcPipe(pname); c.pipes[fid]->setSessionKey(c.sessionKey); /* RPC-over-SMB session key (used e.g. to decrypt SAMR passwords): for * SMB 3.x it is the derived application key (SMBAppKey), not the raw * authentication session key. */ c.pipes[fid]->setSessionKey((c.dialect >= smb::SMB_3_0 && c.haveKeys) ? c.keys.application : c.sessionKey); smb::Smb2Header h; h.command=req.command; h.messageId=req.messageId; h.sessionId=c.sessionId; h.treeId=req.treeId; h.status=smb::STATUS_SUCCESS; h.creditReqResp=1; auto resp = smb::buildHeader(h); Loading
src/rpc/netlogon.cpp +2 −2 Changes for src/rpc/netlogon.cpp: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -85,7 +85,7 @@ DispatchResult netlogonDispatch(uint16_t opnum, const std::vector<uint8_t> &stub switch (opnum) { case NETR_SERVERREQCHALLENGE: { NdrPull in(stub); in.u32(); /* PrimaryName unique referent (NULL) */ if (in.u32() != 0) in.unistrBuffer(); /* PrimaryName [unique,string]: skip if present */ std::string computer = in.unistrBuffer(); uint8_t cc[8]; in.take(cc, 8); Chan ch; Loading @@ -100,7 +100,7 @@ DispatchResult netlogonDispatch(uint16_t opnum, const std::vector<uint8_t> &stub case NETR_SERVERAUTHENTICATE2: case NETR_SERVERAUTHENTICATE3: { NdrPull in(stub); in.u32(); /* PrimaryName unique (NULL) */ if (in.u32() != 0) in.unistrBuffer(); /* PrimaryName [unique,string]: skip if present */ std::string account = in.unistrBuffer(); in.u16(); /* secure_channel_type */ std::string computer = in.unistrBuffer(); Loading
src/rpc/samr.cpp +4 −0 Changes for src/rpc/samr.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -314,12 +314,16 @@ DispatchResult samrDispatch(uint16_t opnum, const std::vector<uint8_t> &stub, auto key16 = std::vector<uint8_t>(sessionKey.begin(), sessionKey.begin() + 16); auto dec = crypto::rc4(key16, enc); uint32_t pwLen = dec[512] | dec[513] << 8 | dec[514] << 16 | uint32_t(dec[515]) << 24; std::cerr << "[SAMR] SetUserInfo2 level=" << level << " sessKey=" << sessionKey.size() << "B rest=" << rest.size() << "B pwLen=" << pwLen << std::endl; if (pwLen <= 512) { std::string pw = crypto::fromUtf16le(dec.data() + (512 - pwLen), pwLen); std::string sam = dsdb::value(attrs, "sAMAccountName"); bool comp = dsdb::hasValue(attrs, "objectClass", "computer"); auto kind = comp ? dsdb::PrincipalKind::Computer : dsdb::PrincipalKind::User; std::string salt = dsdb::kerberosSalt(kind, d.meta.realm, sam, d.meta.dnsName); std::cerr << "[SAMR] SetUserInfo2 sam='" << sam << "' computer=" << comp << " salt='" << salt << "' pwBytes=" << pw.size() << std::endl; dsdb::Secrets old = dir.secretsOf(obj.guid); newSec = std::make_unique<dsdb::Secrets>(dsdb::deriveSecrets(pw, salt, old.kvno)); /* enable the account once it has a password */ Loading