Commit 577871f5 authored by jan.koester's avatar jan.koester
Browse files

test

parent 471818a1
Loading
Loading
Loading
Loading
Loading
+67 −4
Changes for plugin/ad/ad.cpp: 67 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@
#include <cstring>
#include <map>
#include <algorithm>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sstream>
#include <memory>
#include <functional>
@@ -360,7 +363,9 @@ ActiveDirectory::ActiveDirectory(AuthBackend &adminBackend,
                                 const std::string &bindAddr,
                                 int port, int maxconn,
                                 const std::string &adminPassword,
                                 const std::string &dcHost)
                                 const std::string &dcHost,
                                 const std::string &sslCert,
                                 const std::string &sslKey)
    : _AdminBackend(adminBackend),
      _BindAddr(bindAddr), _Port(port), _MaxConn(maxconn),
      _AdminPassword(adminPassword), _DcHost(dcHost),
@@ -376,6 +381,31 @@ ActiveDirectory::ActiveDirectory(AuthBackend &adminBackend,

    std::cerr << "AD/LDAP plugin listening on " << bindAddr << ":" << port
              << " (+CLDAP udp)" << std::endl;

    /* the Global Catalog: the same server, forest-wide and read-only */
    if (_GcPort > 0) {
        _ServerSockets.push_back(new netplus::tcp(bindAddr.c_str(), _GcPort, maxconn, 0));
        std::cerr << "Global Catalog listening on " << bindAddr << ":" << _GcPort << std::endl;
    }
    /* LDAPS and GC over TLS with the server certificate (/SSL/CERT, /SSL/KEY) */
    if (!sslCert.empty()) {
        netplus::tls::CertificateBundle b;
        bool loaded = false;
        try { loaded = b.loadFromFile(sslCert, sslKey); } catch (const std::exception &e) {
            std::cerr << "LDAPS: certificate " << sslCert << ": " << e.what() << std::endl;
        }
        if (loaded) {
            _Certs[dcHost.empty() ? std::string("default") : dcHost] = std::move(b);
            for (int p : {_LdapsPort, _GcsPort}) {
                if (p <= 0) continue;
                _ServerSockets.push_back(new netplus::ssl(_Certs, bindAddr, p, maxconn, 0));
                std::cerr << (p == _GcsPort ? "Global Catalog (TLS)" : "LDAPS") << " listening on "
                          << bindAddr << ":" << p << std::endl;
            }
        } else {
            std::cerr << "LDAPS: no usable certificate, ports 636/3269 stay closed" << std::endl;
        }
    }
}

void ActiveDirectory::init() {
@@ -1139,9 +1169,21 @@ void ActiveDirectory::CreateConnection(std::shared_ptr<netplus::con> &res) {
}

void ActiveDirectory::ConnectEvent(netplus::con &curcon, const int, ULONG_PTR) {
    std::cerr << "[LDAP] TCP connect" << std::endl;
    LdapSession sess;
    /* which listener: our side of the connection */
    sockaddr_in la{};
    socklen_t ll = sizeof(la);
    int lport = 0;
    if (!curcon.slots.empty() && curcon.slots[0].csock &&
        getsockname(curcon.slots[0].csock->fd(), reinterpret_cast<sockaddr*>(&la), &ll) == 0 &&
        la.sin_family == AF_INET)
        lport = ntohs(la.sin_port);
    sess.globalCatalog = lport > 0 && (lport == _GcPort || lport == _GcsPort);
    sess.tls = lport > 0 && (lport == _LdapsPort || lport == _GcsPort);
    std::cerr << "[LDAP] TCP connect port=" << lport << (sess.globalCatalog ? " (GC)" : "")
              << (sess.tls ? " (TLS)" : "") << std::endl;
    std::lock_guard<std::mutex> lock(_Lock);
    _Sessions[&curcon] = LdapSession();
    _Sessions[&curcon] = sess;
}

void ActiveDirectory::DisconnectEvent(netplus::con &curcon, const int, ULONG_PTR) {
@@ -1347,6 +1389,12 @@ std::vector<uint8_t> ActiveDirectory::handleMessage(const uint8_t *data, size_t
                  << ") authed=" << session.authenticated << " as='" << session.bindDN << "'" << std::endl;
    }

    /* the Global Catalog is read-only */
    if (session.globalCatalog && (appTag == LDAP_ADD_REQUEST || appTag == LDAP_MODIFY_REQUEST ||
                                  appTag == LDAP_DEL_REQUEST || appTag == LDAP_MODRDN_REQUEST))
        return buildLdapMessage(msgId, uint8_t(LdapBer::CLASS_APPLICATION | LdapBer::CONSTRUCTED | (appTag + 1)),
                                buildLdapResult(LDAP_UNWILLING_TO_PERFORM, "", "the global catalog is read-only"));

    switch (appTag) {
    case LDAP_BIND_REQUEST:   return handleBindRequest(content, contentLen, msgId, session);
    case LDAP_UNBIND_REQUEST: return handleUnbindRequest(msgId, session);
@@ -1700,6 +1748,7 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content
            out.insert(out.end(), e.begin(), e.end());
        }
        int32_t total = int32_t(ps.entries.size());
        std::cerr << "[LDAP] paged msgId=" << msgId << " page up to " << ps.pos << "/" << total << std::endl;
        if (ps.pos >= ps.entries.size()) {
            session.paged.erase(key);
            key.clear();
@@ -1819,6 +1868,16 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content
                return false;
            }
            LdapEntry le = renderEntry(ent, requested, typesOnly, d.dir.get());
            if (session.globalCatalog) {
                /* only the partial attribute set (schema GC flag) */
                std::vector<LdapAttribute> keep;
                for (auto &a : le.attributes) {
                    auto *def = dsdb::findAttribute(a.type);
                    if (def && (def->flags & dsdb::A_GC))
                        keep.push_back(std::move(a));
                }
                le.attributes = std::move(keep);
            }
            {
                std::string dump;
                for (auto &at : le.attributes) {
@@ -2778,6 +2837,7 @@ fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend,
    int maxconn = 128;
    std::string adminPassword;
    std::string dcHost;
    std::string sslCert, sslKey;

    if (configJson) {
        json_object *jobj = json_tokener_parse(configJson);
@@ -2792,11 +2852,14 @@ fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend,
            if (jmax)  maxconn  = json_object_get_int(jmax);
            if (jpw)   adminPassword = json_object_get_string(jpw);
            if (auto *jh = json_object_object_get(jobj, "dns_hostname")) dcHost = json_object_get_string(jh);
            if (auto *jc = json_object_object_get(jobj, "ssl_cert")) sslCert = json_object_get_string(jc);
            if (auto *jk = json_object_object_get(jobj, "ssl_key")) sslKey = json_object_get_string(jk);
            json_object_put(jobj);
        }
    }

    return new fenrirds::ActiveDirectory(backend, bindAddr, port, maxconn, adminPassword, dcHost);
    return new fenrirds::ActiveDirectory(backend, bindAddr, port, maxconn, adminPassword, dcHost,
                                         sslCert, sslKey);
}

void fenrirds_plugin_destroy(fenrirds::Plugin *p) {
+10 −1
Changes for plugin/ad/ad.h: 10 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@

#include <uuidp.h>
#include <netplus/socket.h>
#include <netplus/crypto/tls.h>
#include <netplus/connection.h>
#include <netplus/eventapi.h>

@@ -279,7 +280,9 @@ namespace fenrirds {
                        const std::string &bindAddr = "0.0.0.0",
                        int port = 389, int maxconn = 128,
                        const std::string &adminPassword = "",
                        const std::string &dcHost = "");
                        const std::string &dcHost = "",
                        const std::string &sslCert = std::string(),
                        const std::string &sslKey = std::string());
        ~ActiveDirectory() override;

        /* Plugin interface */
@@ -419,6 +422,12 @@ namespace fenrirds {
        std::mutex                             _Lock;

        std::vector<netplus::socket*>          _ServerSockets;
        /* Global Catalog (3268) and, with a certificate, LDAPS (636) and
         * GC over TLS (3269); 0 disables a port */
        int                                    _GcPort = 3268;
        int                                    _LdapsPort = 636;
        int                                    _GcsPort = 3269;
        std::map<std::string, netplus::tls::CertificateBundle> _Certs;   /* outlives the ssl sockets */
        void                                  *_Event;

        netplus::udp                          *_Cldap = nullptr;
+5 −0
Changes for src/fenrirds.cpp: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1350,6 +1350,11 @@ int main(int argc,char *argv[]){
            if (adMax)
                json_object_object_add(jcfg, "ad_maxconn",
                    json_object_new_int(config.getIntValue(adMax, 0)));
            /* the server certificate, for LDAPS / GC over TLS */
            if (auto *k = cfgKey("/SSL/CERT"))
                json_object_object_add(jcfg, "ssl_cert", json_object_new_string(config.getValue(k, 0).c_str()));
            if (auto *k = cfgKey("/SSL/KEY"))
                json_object_object_add(jcfg, "ssl_key", json_object_new_string(config.getValue(k, 0).c_str()));

            /* DNS plugin config */
            if (auto *k = cfgKey("/DNS/BIND"))