kit/Kit.cpp | 8 --- net/ServerSocket.hpp | 55 +---------------------- net/Socket.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++- net/Socket.hpp | 3 + wsd/LOOLWSD.cpp | 13 +---- 5 files changed, 131 insertions(+), 69 deletions(-)
New commits: commit 201bcb0762c838e75b61f030725c9bf0ba59c1c3 Author: Michael Meeks <[email protected]> AuthorDate: Sat Mar 30 21:07:58 2019 +0000 Commit: Michael Meeks <[email protected]> CommitDate: Sat Mar 30 21:37:05 2019 +0000 Use peercreds to identify processes connecting rather than URL params. Change-Id: I241e80962fb8cf2f3fff1bb4be81d9f0ee74c648 diff --git a/kit/Kit.cpp b/kit/Kit.cpp index 819fb2698..ff4a3a7ed 100644 --- a/kit/Kit.cpp +++ b/kit/Kit.cpp @@ -2485,11 +2485,8 @@ void lokit_main( LOG_INF("Process is ready."); - static const std::string pid = std::to_string(Process::id()); std::string pathAndQuery(NEW_CHILD_URI); - pathAndQuery.append("?pid="); - pathAndQuery.append(pid); - pathAndQuery.append("&jailid="); + pathAndQuery.append("?jailid="); pathAndQuery.append(jailId); if (queryVersion) { @@ -2522,7 +2519,6 @@ void lokit_main( // Dummies const std::string jailId = "jailid"; - const std::string pid = "101"; #endif // MOBILEAPP @@ -2530,7 +2526,7 @@ void lokit_main( mainKit.runOnClientThread(); // We will do the polling on this thread. std::shared_ptr<SocketHandlerInterface> websocketHandler = - std::make_shared<KitWebSocketHandler>("child_ws_" + pid, loKit, jailId, mainKit); + std::make_shared<KitWebSocketHandler>("child_ws", loKit, jailId, mainKit); #if !MOBILEAPP mainKit.insertNewUnixSocket(MasterLocation, pathAndQuery, websocketHandler); #else diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp index 79a7795bc..dd07af4fe 100644 --- a/net/ServerSocket.hpp +++ b/net/ServerSocket.hpp @@ -61,58 +61,7 @@ public: /// Accepts an incoming connection (Servers only). /// Does not retry on error. /// Returns a valid Socket shared_ptr on success only. - std::shared_ptr<Socket> accept() - { - // Accept a connection (if any) and set it to non-blocking. - // There still need the client's address to filter request from POST(call from REST) here. -#if !MOBILEAPP - struct sockaddr_in6 clientInfo; - socklen_t addrlen = sizeof(clientInfo); - const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK); -#else - const int rc = fakeSocketAccept4(getFD()); -#endif - LOG_DBG("Accepted socket #" << rc << ", creating socket object."); - try - { - // Create a socket object using the factory. - if (rc != -1) - { -#if !MOBILEAPP - char addrstr[INET6_ADDRSTRLEN]; - - const void *inAddr; - if (clientInfo.sin6_family == AF_INET) - { - auto ipv4 = (struct sockaddr_in *)&clientInfo; - inAddr = &(ipv4->sin_addr); - } - else - { - auto ipv6 = (struct sockaddr_in6 *)&clientInfo; - inAddr = &(ipv6->sin6_addr); - } - - inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr)); - std::shared_ptr<Socket> _socket = _sockFactory->create(rc); - _socket->setClientAddress(addrstr); - LOG_DBG("Accepted socket has family " << clientInfo.sin6_family << - " address " << _socket->clientAddress()); -#else - std::shared_ptr<Socket> _socket = _sockFactory->create(rc); - _socket->setClientAddress("dummy"); -#endif - return _socket; - } - return std::shared_ptr<Socket>(nullptr); - } - catch (const std::exception& ex) - { - LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what()); - } - - return nullptr; - } + virtual std::shared_ptr<Socket> accept(); int getPollEvents(std::chrono::steady_clock::time_point /* now */, int & /* timeoutMaxMs */) override @@ -143,6 +92,7 @@ public: private: Socket::Type _type; SocketPoll& _clientPoller; +protected: std::shared_ptr<SocketFactory> _sockFactory; }; @@ -155,6 +105,7 @@ public: { } virtual bool bind(Type, int) { assert(false); return false; } + virtual std::shared_ptr<Socket> accept() override; std::string bind(); private: diff --git a/net/Socket.cpp b/net/Socket.cpp index a1762352e..02fb7f972 100644 --- a/net/Socket.cpp +++ b/net/Socket.cpp @@ -16,6 +16,7 @@ #include <iomanip> #include <stdio.h> #include <unistd.h> +#include <sys/types.h> #include <zlib.h> #include <Poco/DateTime.h> @@ -398,7 +399,8 @@ void StreamSocket::dumpState(std::ostream& os) int events = getPollEvents(std::chrono::steady_clock::now(), timeoutMaxMs); os << "\t" << getFD() << "\t" << events << "\t" << _inBuffer.size() << "\t" << _outBuffer.size() << "\t" - << " r: " << _bytesRecvd << "\t w: " << _bytesSent << "\t"; + << " r: " << _bytesRecvd << "\t w: " << _bytesSent << "\t" + << clientAddress() << "\t"; _socketHandler->dumpState(os); if (_inBuffer.size() > 0) Util::dumpHex(os, "\t\tinBuffer:\n", "\t\t", _inBuffer); @@ -483,6 +485,123 @@ bool ServerSocket::bind(Type type, int port) #endif } +std::shared_ptr<Socket> ServerSocket::accept() +{ + // Accept a connection (if any) and set it to non-blocking. + // There still need the client's address to filter request from POST(call from REST) here. +#if !MOBILEAPP + assert(_type != Socket::Type::Unix); + + struct sockaddr_in6 clientInfo; + socklen_t addrlen = sizeof(clientInfo); + const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK); +#else + const int rc = fakeSocketAccept4(getFD()); +#endif + LOG_DBG("Accepted socket #" << rc << ", creating socket object."); + try + { + // Create a socket object using the factory. + if (rc != -1) + { + std::shared_ptr<Socket> _socket = _sockFactory->create(rc); + +#if !MOBILEAPP + char addrstr[INET6_ADDRSTRLEN]; + + const void *inAddr; + if (clientInfo.sin6_family == AF_INET) + { + auto ipv4 = (struct sockaddr_in *)&clientInfo; + inAddr = &(ipv4->sin_addr); + } + else + { + auto ipv6 = (struct sockaddr_in6 *)&clientInfo; + inAddr = &(ipv6->sin6_addr); + } + + inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr)); + _socket->setClientAddress(addrstr); + + LOG_DBG("Accepted socket has family " << clientInfo.sin6_family << + " address " << _socket->clientAddress()); +#endif + return _socket; + } + return std::shared_ptr<Socket>(nullptr); + } + catch (const std::exception& ex) + { + LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what()); + } + + return nullptr; +} + +int Socket::getPid() const +{ + struct ucred creds; + socklen_t credSize = sizeof(struct ucred); + if (getsockopt(_fd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize) < 0) + { + LOG_TRC("Failed to get pid via peer creds on " << _fd << " " << strerror(errno)); + return -1; + } + return creds.pid; +} + +std::shared_ptr<Socket> LocalServerSocket::accept() +{ +#if !MOBILEAPP + const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK); +#else + const int rc = fakeSocketAccept4(getFD()); +#endif + try + { + LOG_DBG("Accepted prisoner socket #" << rc << ", creating socket object."); + if (rc < 0) + return std::shared_ptr<Socket>(nullptr); + + std::shared_ptr<Socket> _socket = _sockFactory->create(rc); +#if MOBILEAPP + // Sanity check this incoming socket + struct ucred creds; + socklen_t credSize = sizeof(struct ucred); + if (getsockopt(GetFD(), SOL_SOCKET, SO_PEERCRED, &creds, &credSize) < 0) + { + LOG_ERR("Failed to get peer creds on " << GetFD() << " " << strerror(errno)); + ::close(rc); + return std::shared_ptr<Socket>(nullptr); + } + + int uid = getuid(); + int gid = getgid(); + if (creds.uid != uid || cred.gid != gid) + { + LOG_ERR("Peercred mis-match on domain socket - closing connection. uid: " << + creds.uid << "vs." << uid << " gid: " << creds.gid << "vs." << gid); + ::close(rc); + return std::shared_ptr<Socket>(nullptr); + } + std::string addr("uds-to-pid-"); + addr.append(std::to_string(creds.pid)); + _socket->setClientAddress(addr); + + std::shared_ptr<Socket> _socket = _sockFactory->create(rc); + LOG_DBG("Accepted socket is UDS - address " << addr << + " and pid/gid " << creds.pid << "/" << creds.gid); +#endif + return _socket; + } + catch (const std::exception& ex) + { + LOG_SYS("Failed to create client socket #" << rc << ". Error: " << ex.what()); + return std::shared_ptr<Socket>(nullptr); + } +} + /// Returns true on success only. std::string LocalServerSocket::bind() { diff --git a/net/Socket.hpp b/net/Socket.hpp index 10460fe4b..c2355b7b7 100644 --- a/net/Socket.hpp +++ b/net/Socket.hpp @@ -173,6 +173,9 @@ public: } #if !MOBILEAPP + /// Uses peercreds to get prisoner PID if present or -1 + int getPid() const; + /// Sets the kernel socket send buffer in size bytes. /// Note: TCP will allocate twice this size for admin purposes, /// so a subsequent call to getSendBufferSize will return diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index 0b3ccfe86..b4060d643 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -1825,22 +1825,15 @@ private: // New Child is spawned. const Poco::URI::QueryParameters params = requestURI.getQueryParameters(); - Poco::Process::PID pid = -1; + int pid = socket->getPid(); std::string jailId; for (const auto& param : params) { - if (param.first == "pid") - { - pid = std::stoi(param.second); - } - else if (param.first == "jailid") - { + if (param.first == "jailid") jailId = param.second; - } + else if (param.first == "version") - { LOOLWSD::LOKitVersion = param.second; - } } if (pid <= 0) _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
