diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc index 33ad8757a..406258ff8 100644 --- a/src/nix/unix/daemon.cc +++ b/src/nix/unix/daemon.cc @@ -174,22 +174,23 @@ static bool matchUser(std::string_view user, const struct group & gr) * * Otherwise: No. */ -static bool matchUser(const std::string & user, const std::string & group, const Strings & users) +static bool +matchUser(const std::optional & user, const std::optional & group, const Strings & users) { if (find(users.begin(), users.end(), "*") != users.end()) return true; - if (find(users.begin(), users.end(), user) != users.end()) + if (user && find(users.begin(), users.end(), *user) != users.end()) return true; for (auto & i : users) if (i.substr(0, 1) == "@") { - if (group == i.substr(1)) + if (group && *group == i.substr(1)) return true; struct group * gr = getgrnam(i.c_str() + 1); if (!gr) continue; - if (matchUser(user, *gr)) + if (user && matchUser(*user, *gr)) return true; } @@ -198,12 +199,9 @@ static bool matchUser(const std::string & user, const std::string & group, const struct PeerInfo { - bool pidKnown; - pid_t pid; - bool uidKnown; - uid_t uid; - bool gidKnown; - gid_t gid; + std::optional pid; + std::optional uid; + std::optional gid; }; /** @@ -211,7 +209,7 @@ struct PeerInfo */ static PeerInfo getPeerInfo(int remote) { - PeerInfo peer = {false, 0, false, 0, false, 0}; + PeerInfo peer; #if defined(SO_PEERCRED) @@ -221,9 +219,11 @@ static PeerInfo getPeerInfo(int remote) ucred cred; # endif socklen_t credLen = sizeof(cred); - if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1) - throw SysError("getting peer credentials"); - peer = {true, cred.pid, true, cred.uid, true, cred.gid}; + if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == 0) { + peer.pid = cred.pid; + peer.uid = cred.uid; + peer.gid = cred.gid; + } #elif defined(LOCAL_PEERCRED) @@ -233,9 +233,8 @@ static PeerInfo getPeerInfo(int remote) xucred cred; socklen_t credLen = sizeof(cred); - if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == -1) - throw SysError("getting peer credentials"); - peer = {false, 0, true, cred.cr_uid, false, 0}; + if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == 0) + peer.uid = cred.cr_uid; #endif @@ -266,15 +265,19 @@ static ref openUncachedStore() * * If the potential client is not allowed to talk to us, we throw an `Error`. */ -static std::pair authPeer(const PeerInfo & peer) +static std::pair> authPeer(const PeerInfo & peer) { TrustedFlag trusted = NotTrusted; - struct passwd * pw = peer.uidKnown ? getpwuid(peer.uid) : 0; - std::string user = pw ? pw->pw_name : std::to_string(peer.uid); + auto pw = peer.uid ? getpwuid(*peer.uid) : nullptr; + auto user = pw ? std::optional(pw->pw_name) + : peer.uid ? std::optional(std::to_string(*peer.uid)) + : std::nullopt; - struct group * gr = peer.gidKnown ? getgrgid(peer.gid) : 0; - std::string group = gr ? gr->gr_name : std::to_string(peer.gid); + auto gr = peer.gid ? getgrgid(*peer.gid) : 0; + auto group = gr ? std::optional(gr->gr_name) + : peer.gid ? std::optional(std::to_string(*peer.gid)) + : std::nullopt; const Strings & trustedUsers = authorizationSettings.trustedUsers; const Strings & allowedUsers = authorizationSettings.allowedUsers; @@ -283,7 +286,7 @@ static std::pair authPeer(const PeerInfo & peer) trusted = Trusted; if ((!trusted && !matchUser(user, group, allowedUsers)) || group == settings.buildUsersGroup) - throw Error("user '%1%' is not allowed to connect to the Nix daemon", user); + throw Error("user '%1%' is not allowed to connect to the Nix daemon", user.value_or("")); return {trusted, std::move(user)}; } @@ -360,23 +363,23 @@ static void daemonLoop(std::optional forceTrustClientOpt) unix::closeOnExec(remote.get()); - PeerInfo peer{.pidKnown = false}; + PeerInfo peer; TrustedFlag trusted; - std::string user; + std::optional userName; if (forceTrustClientOpt) trusted = *forceTrustClientOpt; else { peer = getPeerInfo(remote.get()); - auto [_trusted, _user] = authPeer(peer); + auto [_trusted, _userName] = authPeer(peer); trusted = _trusted; - user = _user; + userName = _userName; }; printInfo( (std::string) "accepted connection from pid %1%, user %2%" + (trusted ? " (trusted)" : ""), - peer.pidKnown ? std::to_string(peer.pid) : "", - peer.uidKnown ? user : ""); + peer.pid ? std::to_string(*peer.pid) : "", + userName.value_or("")); // Fork a child to handle the connection. ProcessOptions options; @@ -396,8 +399,8 @@ static void daemonLoop(std::optional forceTrustClientOpt) setSigChldAction(false); // For debugging, stuff the pid into argv[1]. - if (peer.pidKnown && savedArgv[1]) { - auto processName = std::to_string(peer.pid); + if (peer.pid && savedArgv[1]) { + auto processName = std::to_string(*peer.pid); strncpy(savedArgv[1], processName.c_str(), strlen(savedArgv[1])); } @@ -414,7 +417,7 @@ static void daemonLoop(std::optional forceTrustClientOpt) } catch (Error & error) { auto ei = error.info(); // FIXME: add to trace? - ei.msg = HintFmt("error processing connection: %1%", ei.msg.str()); + ei.msg = HintFmt("while processing connection: %1%", ei.msg.str()); logError(ei); } }