Commit 9d99d5bb authored by jan.koester's avatar jan.koester
Browse files

test

parent afe4bae9
Loading
Loading
Loading
Loading
+4 −1
Changes for include/sharedd/api.h: 4 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -58,7 +58,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * address:port or [IPv6]:port to listen on).
 *
 * Status: smb_state / nfs_state / iscsi_state (disabled|running|failed),
 * smb_error / nfs_error / iscsi_error, shares, iscsi_targets.
 * smb_error / nfs_error / iscsi_error, shares, iscsi_targets; while SMB
 * runs smb_workgroup and smb_netbios_name, the names ksmbd uses: on a
 * system joined to an AD domain (adconnect) that domain's NetBIOS name and
 * the machine account, otherwise the settings' workgroup / netbios_name.
 *
 * An iSCSI target (served by the kernel's LIO), in replies and as
 * arguments:
+14 −0
Changes for src/main.cpp: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ private:
    Mdns _mdns{_cfg};
    std::string _smbError, _nfsError, _iscsiError;
    time_t _nextIscsiRetry = 0;
    time_t _nextJoinCheck = 0;
    int _nfsThreads = 0;
    sysbus::Service _bus;
    time_t _nextBusTry = 0;
@@ -430,6 +431,10 @@ sysbus::Message Daemon::handle(const sysbus::Message &call, const sysbus::Caller
        sysbus::Message r = sysbus::Message::reply(call);
        r.add("smb_state", !_cfg.settings.smb ? "disabled" : _smb.running() ? "running" : "failed");
        r.add("smb_error", _smbError);
        if (_smb.running()) {
            r.add("smb_workgroup", _smb.workgroup());
            r.add("smb_netbios_name", _smb.netbios());
        }
        r.add("nfs_state", !_cfg.settings.nfs ? "disabled" : _nfs.running() ? "running" : "failed");
        r.add("nfs_error", _nfsError);
        r.add("shares", (long long)_cfg.shares.size());
@@ -537,7 +542,16 @@ void Daemon::run() {
            if (_nextIscsiRetry) _iscsi.apply();
            _nextIscsiRetry = time(nullptr) + 30;
        }
        // joined or left a domain (adconnect): ksmbd takes over its names
        if (_smb.running() && time(nullptr) >= _nextJoinCheck) {
            if (_nextJoinCheck && _smb.namesChanged()) {
                std::cerr << "sharedd: SMB: the domain membership changed, restarting ksmbd" << std::endl;
                applyServers(true);
            }
            _nextJoinCheck = time(nullptr) + 60;
        }
        int timeout = _bus.running() && !retry ? -1 : 5000;
        if (_smb.running() && (timeout < 0 || timeout > 60000)) timeout = 60000;
        int mdnsDue = _mdns.timeoutMs();
        if (mdnsDue >= 0 && (timeout < 0 || mdnsDue < timeout)) timeout = mdnsDue;
        int r = poll(fds.data(), fds.size(), timeout);
+2 −2
Changes for src/rpc.cpp: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ struct ShareEntry {
} // namespace

std::string RpcPipes::hostName() const {
    return netbiosName(_cfg.settings);
    return _netbios.empty() ? netbiosName(_cfg.settings) : _netbios;
}

uint32_t RpcPipes::open(uint32_t handle, uint32_t method) {
@@ -520,7 +520,7 @@ RpcPipes::Bytes RpcPipes::wkstaGetInfo(const Bytes &in) {
        w.u32(6);
        w.u32(1);
        w.str(hostName());
        w.str(_cfg.settings.workgroup);
        w.str(_workgroup.empty() ? _cfg.settings.workgroup : _workgroup);
    } else {
        w.ptr(false);
        err = WerrUnknownLevel;
+7 −0
Changes for src/rpc.h: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -58,6 +58,12 @@ public:

    explicit RpcPipes(const Config &cfg) : _cfg(cfg) {}

    // the names ksmbd runs with (a domain member's differ from the settings)
    void setNames(const std::string &netbios, const std::string &workgroup) {
        _netbios = netbios;
        _workgroup = workgroup;
    }

    // ksmbd's pipe operations; each returns the status for the kernel
    // (0 or one of the KSMBD_RPC_E* codes) and fills out where it answers
    uint32_t open(uint32_t handle, uint32_t method);
@@ -91,6 +97,7 @@ private:
    std::string hostName() const;

    const Config &_cfg;
    std::string _netbios, _workgroup;
    std::map<uint32_t, Pipe> _pipes;
};

+66 −5
Changes for src/smb.cpp: 66 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -295,6 +295,11 @@ std::string lower(std::string s) {
    return s;
}

std::string upper(std::string s) {
    for (char &c : s) c = (char)toupper((unsigned char)c);
    return s;
}

int signingOption(const std::string &s) {
    if (s == "disabled") return 0;
    if (s == "enabled") return 1;
@@ -351,6 +356,44 @@ std::vector<std::string> accountNames(const std::string &account) {
    return names;
}

// adconnectd's joined domains (JOINED): the first one's NetBIOS name and
// computer name. false if adconnectd couldn't be asked; empty names: joined
// to none
bool joinedDomain(std::string &workgroup, std::string &netbios) {
    int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
    if (fd < 0) return false;
    sockaddr_un a{};
    a.sun_family = AF_UNIX;
    snprintf(a.sun_path, sizeof a.sun_path, "%s", SHAREDD_ADCONNECT_SOCKET);
    struct timeval tv = {10, 0};
    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
    if (connect(fd, (sockaddr *)&a, sizeof a) != 0) {
        close(fd);
        return false;
    }
    static const char req[] = "JOINED\n";
    std::string reply;
    bool ok = ::send(fd, req, sizeof req - 1, MSG_NOSIGNAL) == (ssize_t)(sizeof req - 1);
    char buf[4096];
    for (ssize_t n; ok && (n = recv(fd, buf, sizeof buf, 0)) > 0;) reply.append(buf, (size_t)n);
    close(fd);
    /* J <NetBIOS domain> <computer>, a line per domain, then END -- an
     * older adconnectd answers ERR */
    if (reply.size() < 4 || reply.compare(reply.size() - 4, 4, "END\n") != 0) return false;
    workgroup.clear();
    netbios.clear();
    if (reply.compare(0, 2, "J\t") != 0) return true;
    std::string line = reply.substr(2, reply.find('\n') - 2);
    size_t t = line.find('\t');
    if (t == std::string::npos) return false;
    workgroup = upper(line.substr(0, t));
    netbios = upper(line.substr(t + 1));
    if (workgroup.size() > 15) workgroup.resize(15);
    if (netbios.size() > 15) netbios.resize(15);
    return true;
}

#ifndef SHAREDD_UID_R
// passwd entry of an SMB account name (SMB user names are case-insensitive)
struct passwd *lookupUser(const std::string &account) {
@@ -570,6 +613,22 @@ bool SmbServer::send(int cmd, const void *payload, size_t len, bool ack, std::st
    return false;
}

namespace { bool adconnectPresent(); }

void SmbServer::names(std::string &workgroup, std::string &netbios, bool *asked) const {
    bool ok = adconnectPresent() && joinedDomain(workgroup, netbios);
    if (asked) *asked = ok;
    if (!ok || workgroup.empty()) workgroup = _cfg.settings.workgroup;
    if (!ok || netbios.empty()) netbios = netbiosName(_cfg.settings);
}

bool SmbServer::namesChanged() const {
    std::string workgroup, netbios;
    bool asked;
    names(workgroup, netbios, &asked);
    return asked && (workgroup != _workgroup || netbios != _netbios);
}

bool SmbServer::start(std::string &err) {
    close();
    // ksmbd's generic netlink family has no module alias
@@ -642,8 +701,10 @@ bool SmbServer::start(std::string &err) {
    req.signing = signingOption(s.signing);
    copy(req.min_prot, sizeof(req.min_prot), s.minProtocol);
    copy(req.max_prot, sizeof(req.max_prot), s.maxProtocol);
    copy(req.netbios_name, sizeof(req.netbios_name), netbiosName(s));
    copy(req.work_group, sizeof(req.work_group), s.workgroup);
    names(_workgroup, _netbios);
    _rpc.setNames(_netbios, _workgroup);
    copy(req.netbios_name, sizeof(req.netbios_name), _netbios);
    copy(req.work_group, sizeof(req.work_group), _workgroup);
    copy(req.server_string, sizeof(req.server_string), s.serverString);
    req.tcp_port = 445;
    req.ipc_timeout = 0;     // no heartbeat watchdog
@@ -660,7 +721,9 @@ bool SmbServer::start(std::string &err) {
        }
        usleep(500000);
    }
    std::cerr << "sharedd: SMB: ksmbd started as " << netbiosName(s) << " in " << s.workgroup << std::endl;
    std::cerr << "sharedd: SMB: ksmbd started as " << _netbios << " in " << _workgroup
              << (_workgroup != s.workgroup || _netbios != netbiosName(s) ? " (the joined domain's names)" : "")
              << std::endl;
    return true;
}

@@ -720,8 +783,6 @@ void SmbServer::handle(int cmd, const unsigned char *payload, size_t len) {
    }
}

namespace { bool adconnectPresent(); }

void SmbServer::login(const unsigned char *payload, size_t len) {
    if (len < sizeof(LoginRequestMsg)) return;
    LoginRequestMsg req;
Loading