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

test

parent 3fd28f32
Loading
Loading
Loading
Loading
Loading
+1 −0
Changes for CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ include_directories(
add_subdirectory(src)
add_subdirectory(plugin/krb5)
add_subdirectory(plugin/ad)
add_subdirectory(plugin/dns)
add_subdirectory(client)
add_subdirectory(cli)

+2 −2
Changes for docs/ROADMAP.md: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -59,9 +59,9 @@ The directory layer maps them onto AD objects and adds generic objects:
|---|---|---|
| 0 | Rename authdb -> FenrirDirectoryServer (`fenrirds`) | done |
| 1 | Core lib + crypto (MD4/MD5/HMAC-MD5/RC4/AES-CMAC/CFB8/SP800-108) + dsdb | |
| 2 | LDAP: all operations, controls (paged, SD flags, ...), rootDSE, schema entry, SASL GSSAPI/GSS-SPNEGO (Kerberos+NTLM, sign/seal), LDAPS, GC port, CLDAP netlogon ping | bind(simple)/search/add/modify/delete/modrdn + rootDSE done; authenticated add/modify/delete + unicodePwd->bind wire-tested; admin password via AD/ADMIN_PASSWORD at provisioning. TODO: SASL, controls (paged), schema subentry, LDAPS, GC/CLDAP |
| 2 | LDAP: all operations, controls (paged, SD flags, ...), rootDSE, schema entry, SASL GSSAPI/GSS-SPNEGO (Kerberos+NTLM, sign/seal), LDAPS, GC port, CLDAP netlogon ping | bind(simple+SASL GSSAPI)/search/add/modify/delete/modrdn + rootDSE done & wire-tested; SASL GSSAPI bind works end to end (AP-REQ via KDC acceptor, mutual AP-REP, CFX wrap/unwrap sec-layer). TODO: GSS-SPNEGO wrap, sign/seal security layer (SSF>0), controls (paged), schema subentry, LDAPS, GC/CLDAP |
| 3 | LDIF import/export (RFC 2849): library, `fenrirdsctl`, HTTP API, admin UI | |
| 4 | DNS server: AD zones and SRV records, dynamic update (unsigned + GSS-TSIG), forwarding | |
| 4 | DNS server: AD zones and SRV records, dynamic update (unsigned + GSS-TSIG), forwarding | UDP+TCP server, SRV/A/NS/SOA for domain + _msdcs, generated from directory + configured DC host/IP; wire-tested (dig-style). TODO: directory-backed dnsNode records, dynamic update (RFC2136 + GSS-TSIG), forwarding, AAAA, reverse zones |
| 5 | Kerberos for AD: PAC (logon info, UPN/DNS info, signatures), lookups by sAMAccountName/SPN/UPN, AD salts, RC4-HMAC, kpasswd | KDC on dsdb::Directory (lookups SPN/sAMAccountName($)/UPN, keys from Secrets, krbtgt=TGS key, AD salts). PAC (logon info NDR, client info, UPN/DNS, server+KDC HMAC-SHA1-96 signatures, S-1-22-3 UUID SID in extra SIDs) in TGT + service ticket. AS+TGS wire-tested end to end. TODO: PAC verify on TGS, RC4-HMAC preauth, kpasswd, S4U |
| 6 | NTLM server, DCE/RPC (NDR, auth: NTLMSSP/Kerberos/netlogon schannel), endpoint mapper | |
| 7 | RPC services: lsarpc, samr, netlogon, drsuapi (bind/crack names), srvsvc/wkssvc | |
+63 −4
Changes for plugin/ad/ad.cpp: 63 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <netplus/eventapi.h>

#include "ad.h"
#include "crypto/gss.h"
#include "fenrirds.h"
#include "domains.h"
#include "backend.h"
@@ -567,17 +568,75 @@ std::vector<uint8_t> ActiveDirectory::handleBindRequest(const uint8_t *content,
    }

    if (authChoice == 3) {
        /* SaslCredentials ::= SEQUENCE { mechanism, credentials OPTIONAL } */
        std::string mechanism;
        std::vector<uint8_t> inTok;
        {
            size_t soff = 0;
            uint8_t stag;
            const uint8_t *sdata;
            size_t slen;
            if (LdapBer::parseTLV(data, dataLen, soff, stag, sdata, slen))
                LdapBer::parseOctetString(sdata, slen, mechanism);
        /* SASL (GSSAPI / GSS-SPNEGO) comes in phase 2b */
        return buildLdapMessage(msgId, appResp,
            buildLdapResult(LDAP_AUTH_METHOD_NOT_SUPPORTED, "",
                            "SASL " + mechanism + " not yet implemented"));
            if (soff < dataLen && LdapBer::parseTLV(data, dataLen, soff, stag, sdata, slen))
                inTok.assign(sdata, sdata + slen);
        }

        /* a bind response that may carry serverSaslCreds ([7] OCTET STRING) */
        auto bindResp = [&](int code, const std::vector<uint8_t> *creds) {
            auto r = buildLdapResult(static_cast<LdapResultCode>(code), "", "");
            if (creds) {
                r.push_back(0x87);
                LdapBer::encodeLength(r, creds->size());
                r.insert(r.end(), creds->begin(), creds->end());
            }
            return buildLdapMessage(msgId, appResp, r);
        };
        const int SASL_BIND_IN_PROGRESS = 14;

        if (toLower(mechanism) != "gssapi") {
            session.gssState = LdapSession::GssNone;
            return bindResp(LDAP_AUTH_METHOD_NOT_SUPPORTED, nullptr);
        }
        if (!g_KdcPlugin)
            return bindResp(LDAP_AUTH_METHOD_NOT_SUPPORTED, nullptr);

        if (session.gssState == LdapSession::GssNone) {
            uint16_t tokId = 0;
            std::vector<uint8_t> apReq;
            if (!fenrirds::crypto::gss::parseInitialToken(inTok, tokId, apReq))
                return bindResp(LDAP_INVALID_CREDENTIALS, nullptr);
            GssAcceptResult res;
            if (!g_KdcPlugin->gssAccept(apReq, res))
                return bindResp(LDAP_INVALID_CREDENTIALS, nullptr);
            session.gssKey = res.sessionKey;
            session.gssEtype = res.sessionEtype;
            session.gssClient = res.clientPrincipal;
            session.gssState = LdapSession::GssSentApRep;
            std::vector<uint8_t> creds;
            if (!res.apRep.empty()) {
                creds = {0x02, 0x00};   /* GSS AP-REP token id, no 0x60 wrapper */
                creds.insert(creds.end(), res.apRep.begin(), res.apRep.end());
            }
            return bindResp(SASL_BIND_IN_PROGRESS, &creds);
        }

        if (session.gssState == LdapSession::GssSentApRep) {
            /* offer the SASL security layer: none (0x01), max message size 0 */
            std::vector<uint8_t> sec = {0x01, 0x00, 0x00, 0x00};
            auto tok = fenrirds::crypto::gss::wrap(session.gssKey, session.gssEtype, true, 0, sec);
            session.gssState = LdapSession::GssSentSecLayer;
            return bindResp(SASL_BIND_IN_PROGRESS, &tok);
        }

        /* GssSentSecLayer: client's wrapped layer choice + authzid */
        fenrirds::crypto::Bytes plain;
        if (!fenrirds::crypto::gss::unwrap(session.gssKey, session.gssEtype, false, inTok, plain))
            return bindResp(LDAP_INVALID_CREDENTIALS, nullptr);
        session.authenticated = true;
        session.bindDN = session.gssClient;
        session.gssState = LdapSession::GssNone;
        return bindResp(LDAP_SUCCESS, nullptr);
    }

    return buildLdapMessage(msgId, appResp,
+6 −0
Changes for plugin/ad/ad.h: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -206,6 +206,12 @@ namespace fenrirds {
        std::string  bindDN;         /* DN of the authenticated principal */
        uuid::uuid   userUid;        /* UUID if bound as a user          */
        std::string  realm;          /* domain realm for the session     */

        /* SASL GSSAPI state */
        enum GssState { GssNone, GssSentApRep, GssSentSecLayer } gssState = GssNone;
        std::vector<uint8_t> gssKey;        /* the context session key */
        int                  gssEtype = 0;
        std::string          gssClient;     /* client principal name@REALM */
    };

    /***************************************************************************
+26 −0
Changes for plugin/dns/CMakeLists.txt: 26 added lines, 0 removed lines.
Original line number Diff line number Diff line
add_library(fenrirds-dns SHARED
    dns.cpp
)

target_include_directories(fenrirds-dns
    PUBLIC
    ${JSONC_INCLUDE_DIR}
)

target_link_libraries(fenrirds-dns
    PUBLIC
    fenrirds-core
    uuidp::uuidp
    json-c::json-c
    netplus::netplus
    confplus::confplus
)

set_target_properties(fenrirds-dns PROPERTIES
    OUTPUT_NAME "fenrirds-dns"
    VERSION ${version}
    SOVERSION 0
)

install(TARGETS fenrirds-dns DESTINATION ${CMAKE_INSTALL_LIBDIR}/fenrirds)
install(FILES dns.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fenrirds)
Loading