// Main procedure for management void NiAdminMain(NAT *n, SOCK *s) { RPC *r; PACK *p; // Validate arguments if (n == NULL || s == NULL) { return; } p = NewPack(); HttpServerSend(s, p); FreePack(p); r = StartRpcServer(s, NiRpcServer, n); RpcServer(r); RpcFree(r); }
// Listener thread void ElListenerProc(THREAD *thread, void *param) { TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param; EL *e; SOCK *s; UCHAR rand[SHA1_SIZE]; UCHAR pass1[SHA1_SIZE], pass2[SHA1_SIZE]; // Validate arguments if (data == NULL || thread == NULL) { return; } e = (EL *)data->r->ThreadParam; s = data->s; AddRef(s->ref); SetTimeout(s, 5000); LockList(e->AdminThreadList); { AddRef(thread->ref); AddRef(s->ref); Insert(e->AdminThreadList, thread); Insert(e->AdminSockList, s); } UnlockList(e->AdminThreadList); NoticeThreadInit(thread); // Submit a challenge Rand(rand, sizeof(rand)); SendAll(s, rand, sizeof(rand), false); // Receive a response SecurePassword(pass1, e->HashedPassword, rand); Zero(pass2, sizeof(pass2)); RecvAll(s, pass2, sizeof(pass2), false); if (Cmp(pass1, pass2, SHA1_SIZE) != 0) { // Password incorrect bool code = false; code = Endian32(code); SendAll(s, &code, sizeof(code), false); } else { // Password match bool code = true; RPC *r; code = Endian32(code); SendAll(s, &code, sizeof(code), false); SetTimeout(s, INFINITE); // Start operation as a RPC server r = StartRpcServer(s, ElRpcServer, e); RpcServer(r); RpcFree(r); } Disconnect(s); ReleaseSock(s); LockList(e->AdminThreadList); { if (Delete(e->AdminThreadList, thread)) { ReleaseThread(thread); } if (Delete(e->AdminSockList, s)) { ReleaseSock(s); } } UnlockList(e->AdminThreadList); }
int main(int argc, char *argv[]) { #ifdef _WIN32 nodaemon = 1; WSADATA wsadata; WSAStartup(0x0202, &wsadata); #endif SOCKET s = INVALID_SOCKET; s = socket(AF_INET6, SOCK_STREAM, 0); if (s != INVALID_SOCKET) { HaveIPv6Stack = 1; close(s); s = INVALID_SOCKET; } s = socket(AF_INET, SOCK_STREAM, 0); if (s != INVALID_SOCKET) { HaveIPv4Stack = 1; close(s); } int o; const static char* const optstring = "u:g:L:p:i:P:l:r:feD46"; for (opterr = 0; ( o = getopt(argc, argv, optstring) ) > 0; ) switch (o) { case '4': if (!HaveIPv4Stack) { fprintf(stderr, "Fatal: Your system does not support %s.\n", cIPv4); return !0; } v4required = 1; break; case '6': if (!HaveIPv6Stack) { fprintf(stderr, "Fatal: Your system does not support %s.\n", cIPv6); return !0; } v6required = 1; break; case 'p': fn_pid = optarg; break; case 'i': fn_ini = optarg; break; case 'l': fn_log = optarg; break; case 'L': maxsockets++; break; case 'f': nodaemon = 1; logstdout = 1; break; case 'D': nodaemon = 1; break; case 'e': logstdout = 1; break; case 'r': RandomizationLevel = atoi(optarg); if (RandomizationLevel < 0 || RandomizationLevel > 2) RandomizationLevel = 1; break; case 'g': if (GetGid()) return !0; break; case 'u': if (GetUid()) return !0; break; case 'P': break; default: Usage(argv[0]); return !0; } if (optind != argc) { Usage(argv[0]); return !0; } int allocsockets = maxsockets ? maxsockets : 2; SocketList = malloc(allocsockets * sizeof(SOCKET)); #if defined(__BSD__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) optind = 1; optreset = 1; // Makes BSD getopt happy #else optind = 0; // Makes GLIBC getopt happy #endif for (opterr = 0; ( o = getopt(argc, argv, optstring) ) > 0; ) switch (o) { case 'L': AddSocketAddress(optarg); break; case 'P': defaultport = optarg; break; default: break; } if (!maxsockets) { if (HaveIPv6Stack && (v6required || !v4required)) AddSocketAddress("::"); if (HaveIPv4Stack && (v4required || !v6required)) AddSocketAddress("0.0.0.0"); } if (!numsockets) { fprintf(stderr, "Fatal: Could not listen on any socket.\n"); return !0; } #ifndef _WIN32 if ((gid != INVALID_GID && setgid(gid)) || (uid != INVALID_GID && setuid(uid))) { fprintf(stderr, "Fatal: setgid/setuid for %s failed.\n", optarg); return !0; } #endif if (RandomizationLevel == 1) { int i; srand((unsigned int)time(NULL)); int serverType = rand() % _countof(HostOS); int16_t lang = LcidList[rand() % _countof(LcidList)]; for (i = 0; i < _countof(RandomPid); i++) { GenerateRandomPid(AppList[i].guid, RandomPid[i], serverType, lang); } } #ifndef _WIN32 // Windows has no fork or signal handling if ( !nodaemon) if (daemon(!0, logstdout)) { fprintf(stderr, "Fatal: Could not daemonize to background.\n"); return errno; } { struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_NOCLDWAIT }; if ( sigemptyset(&sa.sa_mask) || sigaction(SIGCHLD, &sa, 0) ) return errno; } #endif logger("KMS emulator started successfully\n"); if (fn_pid) { FILE *_f = fopen(fn_pid, "w"); if ( _f ) { fprintf(_f, "%u", getpid()); fclose(_f); } else { logger("Warning: Cannot write pid file.\n"); } } srand( (int)time(NULL) ); RpcAssocGroup = rand(); for (;;) { socklen_t len; struct sockaddr_storage addr; SOCKET s_client; for (;;) if ( (s_client = network_accept_any(SocketList, numsockets, NULL, NULL)) < 0 ) { if ( errno != EINTR ) return errno; } else break; RpcAssocGroup++; len = sizeof addr; if (getsockname(s_client, (struct sockaddr*)&addr, &len) || getnameinfo((struct sockaddr*)&addr, len, NULL, 0, RpcSecondaryAddress, sizeof(RpcSecondaryAddress), NI_NUMERICSERV)) { strcpy(RpcSecondaryAddress, "1688"); // In case of failure use default port (doesn't seem to break activation) } RpcSecondaryAddressLength = LE16(strlen(RpcSecondaryAddress) + 1); #ifndef _WIN32 int pid; if ( (pid = fork()) < 0 ) return errno; else if ( pid ) close(s_client); else #endif { char ipstr[256], text[256]; struct timeval to = { .tv_sec = 60, .tv_usec = 0 }; setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (char*)&to, sizeof(to)); setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (char*)&to, sizeof(to)); len = sizeof addr; if (getpeername(s_client, (struct sockaddr*)&addr, &len) || !ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len)) { *ipstr = 0; } char *connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4; static char *const cAccepted = "accepted"; static char *const cClosed = "closed"; static char *const fIP = "%s connection %s: %s.\n"; CloseAllListeningSockets(); sprintf(text, fIP, connection_type, cAccepted, ipstr); if (*ipstr) logger(text); RpcServer(s_client); #ifdef _WIN32 shutdown(s_client, SD_BOTH); #endif close(s_client); sprintf(text, fIP, connection_type, cClosed, ipstr); if (*ipstr) logger(text); #ifndef _WIN32 return 0; #endif } } unlink(fn_pid); CloseAllListeningSockets(); return 0; }