Commit f845c0a6 authored by jan.koester's avatar jan.koester
Browse files

test

parent 1cb8bfb7
Loading
Loading
Loading
Loading
Loading
+6 −1
Changes for plugin/ad/ad.cpp: 6 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -1533,11 +1533,16 @@ std::vector<uint8_t> ActiveDirectory::handleBindRequest(const uint8_t *content,
            std::vector<uint8_t> krb5reply;
            if (!res.apRep.empty()) {
                /* RFC 1964 framing: 0x60, krb5 OID, tok id 02 00, AP-REP */
                if (res.rawApRepToken) {   /* TEMPORARY interop diagnosis */
                    krb5reply = {0x02, 0x00};
                    krb5reply.insert(krb5reply.end(), res.apRep.begin(), res.apRep.end());
                } else {
                    krb5reply = gss::wrapInitialToken(res.apRep, 0x0200);
                }
            }
            std::vector<uint8_t> creds;
            if (spnego) {
                std::vector<uint8_t> krb5oid(gss::KRB5_OID, gss::KRB5_OID + 11);
                std::vector<uint8_t> krb5oid = gss::firstMechOid(session.gssMechTypes);
                std::vector<uint8_t> mic = gss::getMic(session.gssKey, session.gssEtype,
                                                       true, session.sendSeq++, session.gssMechTypes);
                creds = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &krb5oid, krb5reply, mic);
+28 −2
Changes for plugin/krb5/krb5.cpp: 28 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <atomic>
#include <iostream>
#include <cstring>
#include <cstdlib>
@@ -3864,15 +3865,40 @@ bool Krb5KDC::gssAccept(const std::vector<uint8_t> &apReqData, GssAcceptResult &

    /* KRB5_AP_OPTS_MUTUAL_REQUIRED = 0x20000000: the AP-REP enc-part is
     * encrypted with the TICKET session key (not the subkey). */
    /* TEMPORARY Windows interop diagnosis: rotate through AP-REP variants
     * (FENRIRDS_APREP_VARIANT=0..3 pins one). A: framed, EncAPRepPart, own
     * seq; B: framed, EncAPRepPart, seq 0; C: unframed, EncAPRepPart, seq 0;
     * D: the pre-2026-10-30 reply (unframed, PA-ENC-TS enc part, seq 0). */
    static std::atomic<unsigned> s_variant{0};
    int variant;
    if (const char *pin = getenv("FENRIRDS_APREP_VARIANT"))
        variant = std::atoi(pin) & 3;
    else
        variant = 0;
    (void)s_variant;
    out.apRepVariant = variant;
    out.rawApRepToken = variant >= 2;
    /* our initial GSS sequence number, announced in the AP-REP */
    out.acceptorSeq = Krb5Crypto::randomNonce() & 0x3fffffff;
    out.acceptorSeq = variant == 0 ? (Krb5Crypto::randomNonce() & 0x3fffffff) : 0;
    if (ap.ap_options & 0x20000000) {
        Krb5Service svc("", "", ap.ticket.sname.realm, svcKey);
        if (variant == 3) {
            auto legacy = Asn1Der::encodePaEncTimestamp(auth.ctime, auth.cusec);
            Krb5ApRep ap_rep;
            ap_rep.pvno = 5;
            ap_rep.msg_type = KRB_AP_REP;
            ap_rep.enc_etype = et.session_key.enctype;
            ap_rep.enc_kvno = 0;
            ap_rep.enc_part = Krb5Crypto::encrypt(et.session_key.keydata, legacy, KRB5_KU_AP_REP_ENC_PART);
            out.apRep = ap_rep.serialize();
        } else {
            out.apRep = svc.buildApRep(auth, et.session_key, out.acceptorSeq);
        }
    }
    out.gssFlags = auth.has_gss_cksum ? auth.gss_flags : 0;
    out.initiatorSeq = auth.seq_number;
    std::cerr << "[KDC] gssAccept " << out.clientPrincipal << " subkey=" << auth.has_subkey
    std::cerr << "[KDC] gssAccept " << out.clientPrincipal << " variant=" << "ABCD"[out.apRepVariant]
              << " subkey=" << auth.has_subkey
              << " flags=0x" << std::hex << out.gssFlags << " initSeq=0x" << out.initiatorSeq
              << " accSeq=0x" << out.acceptorSeq << std::dec << " mutual=" << !out.apRep.empty() << std::endl;
    return true;
+32 −4
Changes for plugin/smb/smb.cpp: 32 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ void SmbServer::ConnectEvent(netplus::con &c, const int, ULONG_PTR) {
    std::lock_guard<std::mutex> l(_Lock); _Conns[&c] = Conn();
}
void SmbServer::DisconnectEvent(netplus::con &c, const int, ULONG_PTR) {
    std::cerr << "[SMB] disconnect" << std::endl;   /* TEMPORARY interop diagnosis */
    std::lock_guard<std::mutex> l(_Lock);
    auto it = _Conns.find(&c);
    if (it != _Conns.end()) {
@@ -357,6 +358,25 @@ std::vector<uint8_t> SmbServer::handleCompound(Conn &c, const std::vector<uint8_
        off += next;
    }

    /* TEMPORARY interop diagnosis: every request and its reply status */
    {
        size_t o = 0;
        size_t ri = 0;
        while (o + 64 <= msg.size()) {
            uint16_t cmd = uint16_t(msg[o + 12] | msg[o + 13] << 8);
            uint64_t sid = 0;
            for (int i = 0; i < 8; i++) sid |= uint64_t(msg[o + 40 + i]) << (8 * i);
            uint32_t st = ri < replies.size() ? rd32(replies[ri].pdu.data() + 8) : 0xffffffff;
            std::cerr << "[SMB] req cmd=" << cmd << " sid=0x" << std::hex << sid << " flags=0x"
                      << rd32(msg.data() + o + 16) << " -> status=0x" << st << std::dec
                      << (ri < replies.size() && !replies[ri].signKey.empty() ? " signed" : "") << std::endl;
            ++ri;
            uint32_t next = rd32(msg.data() + o + 20);
            if (!next) break;
            o += next;
        }
    }

    std::vector<uint8_t> out;
    for (size_t i = 0; i < replies.size(); ++i) {
        auto &pdu = replies[i].pdu;
@@ -715,17 +735,24 @@ SmbServer::Reply SmbServer::sessionSetup(Conn &c, const smb::Smb2Header &req,
    GssAcceptResult res;
    if (!g_KdcPlugin->gssAccept(inner, res))
        return fail("Kerberos AP-REQ not accepted");
    std::cerr << "[SMB] Kerberos session " << res.clientPrincipal << std::endl;
    std::cerr << "[SMB] Kerberos session " << res.clientPrincipal << " variant="
              << "ABCD"[res.apRepVariant] << " sid=0x" << std::hex << sid << std::dec << std::endl;
    s.authenticated = true;
    setPrincipal(res.clientPrincipal);
    s.sessionKey = res.sessionKey;
    std::vector<uint8_t> krb5reply;
    /* the reply mech token: RFC 1964 framing (0x60, krb5 OID, tok id 02 00) */
    if (!res.apRep.empty())
    if (!res.apRep.empty()) {
        if (res.rawApRepToken) {   /* TEMPORARY interop diagnosis */
            krb5reply = {0x02, 0x00};
            krb5reply.insert(krb5reply.end(), res.apRep.begin(), res.apRep.end());
        } else {
            krb5reply = gss::wrapInitialToken(res.apRep, 0x0200);
        }
    }
    std::vector<uint8_t> outTok;
    if (spnego) {
        std::vector<uint8_t> oid(gss::KRB5_OID, gss::KRB5_OID+11);
        std::vector<uint8_t> oid = gss::firstMechOid(mechTypes);
        auto m = gss::getMic(res.sessionKey, res.sessionEtype, true, res.acceptorSeq, mechTypes);
        outTok = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &oid, krb5reply, m);
    } else {
@@ -760,7 +787,8 @@ std::vector<uint8_t> SmbServer::treeConnect(Session &s, const smb::Smb2Header &r
        return errorResponse(req, ST_ACCESS_DENIED);
    uint32_t tid = s.nextTree++;
    s.trees[tid] = t;
    std::cerr << "[SMB] TREE_CONNECT '" << path << "' tid=" << tid << " user=" << s.principal << std::endl;
    std::cerr << "[SMB] TREE_CONNECT '" << path << "' tid=" << tid << " user=" << s.principal
              << " sid=0x" << std::hex << s.id << std::dec << std::endl;

    smb::Smb2Header h;
    h.command = req.command; h.messageId = req.messageId; h.sessionId = s.id;
+15 −0
Changes for src/crypto/gss.cpp: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -248,6 +248,21 @@ namespace {
    }
}

std::vector<uint8_t> firstMechOid(const std::vector<uint8_t> &m) {
    std::vector<uint8_t> krb5(KRB5_OID, KRB5_OID + sizeof(KRB5_OID));
    if (m.size() < 4 || m[0] != 0x30)
        return krb5;
    size_t off = 1, len = 0;
    if (!readLen(m.data(), m.size(), off, len) || off + len > m.size())
        return krb5;
    if (off + 2 > m.size() || m[off] != 0x06)
        return krb5;
    size_t oidLen = m[off + 1];
    if (oidLen > 0x7f || off + 2 + oidLen > m.size())
        return krb5;
    return std::vector<uint8_t>(m.begin() + off, m.begin() + off + 2 + oidLen);
}

bool parseSpnegoInit(const std::vector<uint8_t> &tok,
                     std::vector<uint8_t> &mechToken,
                     std::vector<uint8_t> &mechTypesDer) {
+7 −0
Changes for src/crypto/gss.h: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -59,6 +59,13 @@ namespace fenrirds {
            bool parseSpnegoInit(const std::vector<uint8_t> &tok,
                                 std::vector<uint8_t> &mechToken,
                                 std::vector<uint8_t> &mechTypesDer);
            /* the first mechanism OID (DER TLV 06 len ...) of a mechTypes
             * list as parseSpnegoInit returns it: the mech the client's
             * optimistic token belongs to. The reply must name exactly this
             * OID -- Windows offers the MS Kerberos OID 1.2.840.48018.1.2.2
             * first and drops the context if we answer with the standard
             * one. Falls back to the krb5 OID. */
            std::vector<uint8_t> firstMechOid(const std::vector<uint8_t> &mechTypesDer);
            /* parse a NegTokenResp (continuation): its responseToken */
            bool parseSpnegoResp(const std::vector<uint8_t> &tok,
                                 std::vector<uint8_t> &responseToken,
Loading