Verify the connecting client is our own process via /proc/net/tcp inode lookup.
| 151 | |
| 152 | // Verify the connecting client is our own process via /proc/net/tcp inode lookup. |
| 153 | static bool IsConnectionFromSteam(int clientFd) { |
| 154 | sockaddr_in peer{}; |
| 155 | socklen_t peerLen = sizeof(peer); |
| 156 | if (getpeername(clientFd, (sockaddr*)&peer, &peerLen) != 0) return false; |
| 157 | |
| 158 | uint16_t peerPort = ntohs(peer.sin_port); |
| 159 | uint32_t peerAddr = ntohl(peer.sin_addr.s_addr); |
| 160 | |
| 161 | sockaddr_in local{}; |
| 162 | socklen_t localLen = sizeof(local); |
| 163 | if (getsockname(clientFd, (sockaddr*)&local, &localLen) != 0) return false; |
| 164 | |
| 165 | uint16_t localPort = ntohs(local.sin_port); |
| 166 | uint32_t localAddr = ntohl(local.sin_addr.s_addr); |
| 167 | |
| 168 | // /proc/net/tcp format: sl local_address:port rem_address:port st ... inode |
| 169 | // Addresses are network-byte-order hex. |
| 170 | std::ifstream tcpFile("/proc/net/tcp"); |
| 171 | if (!tcpFile) return false; |
| 172 | |
| 173 | unsigned long socketInode = 0; |
| 174 | std::string line; |
| 175 | std::getline(tcpFile, line); // skip header |
| 176 | |
| 177 | while (std::getline(tcpFile, line)) { |
| 178 | unsigned int localAddrHex, localPortHex, remAddrHex, remPortHex; |
| 179 | unsigned long inode; |
| 180 | int st; |
| 181 | if (sscanf(line.c_str(), " %*d: %X:%X %X:%X %X %*X:%*X %*X:%*X %*X %*u %*u %lu", |
| 182 | &localAddrHex, &localPortHex, &remAddrHex, &remPortHex, &st, &inode) == 6) { |
| 183 | // Match client's row: its local=peer, its remote=us, ESTABLISHED |
| 184 | if (localAddrHex == htonl(peerAddr) && localPortHex == peerPort && |
| 185 | remAddrHex == htonl(localAddr) && remPortHex == localPort && |
| 186 | st == 1) { |
| 187 | socketInode = inode; |
| 188 | break; |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | tcpFile.close(); |
| 193 | |
| 194 | if (socketInode == 0) { |
| 195 | LOG("[HttpServer] PID check: socket inode not found for port %u", peerPort); |
| 196 | return false; |
| 197 | } |
| 198 | |
| 199 | // Find which PID owns this socket inode |
| 200 | pid_t myPid = getpid(); |
| 201 | char inodeTarget[64]; |
| 202 | snprintf(inodeTarget, sizeof(inodeTarget), "socket:[%lu]", socketInode); |
| 203 | |
| 204 | DIR* procDir = opendir("/proc"); |
| 205 | if (!procDir) return false; |
| 206 | |
| 207 | pid_t ownerPid = 0; |
| 208 | struct dirent* procEntry; |
| 209 | while ((procEntry = readdir(procDir)) != nullptr) { |
| 210 | char* endptr; |