// iptables thread void NsIpTablesThread(THREAD *thread, void *param) { IPTABLES_STATE *state; NATIVE_STACK *s; UINT counter = 0; BUF *seed_buf; char exe_name[MAX_PATH]; if (thread == NULL || param == NULL) { return; } s = (NATIVE_STACK *)param; seed_buf = NewBuf(); WriteBuf(seed_buf, s->MacAddress, 6); GetExeName(exe_name, sizeof(exe_name)); WriteBufStr(seed_buf, exe_name); state = StartAddIpTablesEntryForNativeStack(seed_buf->Buf, seed_buf->Size); FreeBuf(seed_buf); if (state == NULL) { NoticeThreadInit(thread); return; } s->IpTablesInitOk = true; NoticeThreadInit(thread); while (true) { UINT wait_interval; if (s->IpTablesHalt) { break; } if (MaintainAddIpTablesEntryForNativeStack(state)) { counter = 0; } counter++; wait_interval = NS_CHECK_IPTABLES_INTERVAL_INIT * counter; wait_interval = MIN(wait_interval, NS_CHECK_IPTABLES_INTERVAL_MAX); //Debug("NsIpTablesThread: wait for %u\n", wait_interval); Wait(s->IpTablesHaltEvent, wait_interval); } EndAddIpTablesEntryForNativeStack(state); }
// Thread that processes the accepted TCP connection void TCPAcceptedThread(THREAD *t, void *param) { TCP_ACCEPTED_PARAM *data; LISTENER *r; SOCK *s; CONNECTION *c; bool flag1; char tmp[128]; // Validate arguments if (t == NULL || param == NULL) { return; } // Initialize data = (TCP_ACCEPTED_PARAM *)param; r = data->r; s = data->s; AddRef(r->ref); AddRef(s->ref); // Create a connection c = NewServerConnection(r->Cedar, s, t); // Register to Cedar as a transient connection AddConnection(c->Cedar, c); NoticeThreadInit(t); AcceptInit(s); StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname); IPToStr(tmp, sizeof(tmp), &s->RemoteIP); if (IS_SPECIAL_PORT(s->RemotePort) == false) { SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort); } // Reception ConnectionAccept(c); flag1 = c->flag1; // Release SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name); ReleaseConnection(c); // Release if (flag1 == false) { Debug("%s %u flag1 == false\n", __FILE__, __LINE__); IPToStr(tmp, sizeof(tmp), &s->RemoteIP); if (IS_SPECIAL_PORT(s->RemotePort) == false) { SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort); } Disconnect(s); } ReleaseSock(s); ReleaseListener(r); }
// BPF でのパケットキャプチャの中継用スレッド void BpfThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; int fd = e->Socket; int len; int rest; // バッファ中の残りバイト数 UCHAR *next; //バッファ中の次のパケットの先頭 struct CAPTUREBLOCK *block; // キューに追加するデータ UCHAR *data; struct bpf_hdr *hdr; // バッファを確保 UCHAR *buf = Malloc(e->BufSize); // 初期化完了を通知 NoticeThreadInit(thread); while(1){ // ループの脱出判定 if(e->Socket == INVALID_SOCKET){ break; } rest = read(fd, buf, e->BufSize); if(rest < 0 && errno != EAGAIN){ // エラー close(fd); e->Socket = INVALID_SOCKET; Free(buf); Cancel(e->Cancel); return; } next = buf; LockQueue(e->Queue); while(rest>0){ // パケットの切り出し hdr = (struct bpf_hdr*)next; // Queue中のパケットサイズが限界を超えたらパケットを破棄する if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){ data = Malloc(hdr->bh_caplen); Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen); block = NewCaptureBlock(data, hdr->bh_caplen); InsertQueue(e->Queue, block); e->QueueSize += hdr->bh_caplen; } // 次のパケットの頭出し rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); } UnlockQueue(e->Queue); Cancel(e->Cancel); } Free(buf); Cancel(e->Cancel); return; }
// Relay thread for captured packet (BPF) void BpfThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; int fd = e->Socket; int len; int rest; // Rest size in buffer UCHAR *next; // Head of next packet in buffer struct CAPTUREBLOCK *block; // Data to enqueue UCHAR *data; struct bpf_hdr *hdr; // Allocate the buffer UCHAR *buf = Malloc(e->BufSize); // Notify initialize completed NoticeThreadInit(thread); while(1){ // Determining to exit loop if(e->Socket == INVALID_SOCKET){ break; } rest = read(fd, buf, e->BufSize); if(rest < 0 && errno != EAGAIN){ // Error close(fd); e->Socket = INVALID_SOCKET; Free(buf); Cancel(e->Cancel); return; } next = buf; LockQueue(e->Queue); while(rest>0){ // Cut out a packet hdr = (struct bpf_hdr*)next; // Discard arriving packet when queue filled if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){ data = Malloc(hdr->bh_caplen); Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen); block = NewCaptureBlock(data, hdr->bh_caplen); InsertQueue(e->Queue, block); e->QueueSize += hdr->bh_caplen; } // Find the head of next packet rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); } UnlockQueue(e->Queue); Cancel(e->Cancel); } Free(buf); Cancel(e->Cancel); return; }
// Bridging thread void BrBridgeThread(THREAD *thread, void *param) { BRIDGE *b; CONNECTION *c; SESSION *s; HUB *h; char name[MAX_SIZE]; // Validate arguments if (thread == NULL || param == NULL) { return; } b = (BRIDGE *)param; // Create a connection object c = NewServerConnection(b->Cedar, NULL, thread); c->Protocol = CONNECTION_HUB_BRIDGE; // Create a session object s = NewServerSession(b->Cedar, c, b->Hub, BRIDGE_USER_NAME, b->Policy); HLog(b->Hub, "LH_START_BRIDGE", b->Name, s->Name); StrCpy(name, sizeof(name), b->Name); h = b->Hub; AddRef(h->ref); s->BridgeMode = true; s->Bridge = b; c->Session = s; ReleaseConnection(c); // Dummy user name for local-bridge s->Username = CopyStr(BRIDGE_USER_NAME_PRINT); b->Session = s; AddRef(s->ref); // Notify completion NoticeThreadInit(thread); // Main procedure of the session Debug("Bridge %s Start.\n", b->Name); SessionMain(s); Debug("Bridge %s Stop.\n", b->Name); HLog(h, "LH_STOP_BRIDGE", name); ReleaseHub(h); ReleaseSession(s); }
// Thread to try to lock void CheckDeadLockThread(THREAD *t, void *param) { DEADCHECK *c = (DEADCHECK *)param; if (t == NULL || c == NULL) { return; } NoticeThreadInit(t); Lock(c->Lock); Unlock(c->Lock); c->Unlocked = true; }
// Link server thread void LinkServerSessionThread(THREAD *t, void *param) { LINK *k = (LINK *)param; CONNECTION *c; SESSION *s; POLICY *policy; wchar_t name[MAX_SIZE]; // Validate arguments if (t == NULL || param == NULL) { return; } // Create a server connection c = NewServerConnection(k->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_LINK_SERVER; // Create a policy policy = ZeroMalloc(sizeof(POLICY)); Copy(policy, k->Policy, sizeof(POLICY)); // Create a server session s = NewServerSession(k->Cedar, c, k->Hub, LINK_USER_NAME, policy); s->LinkModeServer = true; s->Link = k; c->Session = s; ReleaseConnection(c); // User name s->Username = CopyStr(LINK_USER_NAME_PRINT); k->ServerSession = s; AddRef(k->ServerSession->ref); // Notify the initialization completion NoticeThreadInit(t); UniStrCpy(name, sizeof(name), k->Option->AccountName); HLog(s->Hub, "LH_LINK_START", name, s->Name); // Main function of session SessionMain(s); HLog(s->Hub, "LH_LINK_STOP", name); ReleaseSession(s); }
// リンクサーバースレッド void LinkServerSessionThread(THREAD *t, void *param) { LINK *k = (LINK *)param; CONNECTION *c; SESSION *s; POLICY *policy; wchar_t name[MAX_SIZE]; // 引数チェック if (t == NULL || param == NULL) { return; } // サーバーコネクションの作成 c = NewServerConnection(k->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_LINK_SERVER; // ポリシーの作成 policy = ZeroMalloc(sizeof(POLICY)); Copy(policy, k->Policy, sizeof(POLICY)); // サーバーセッションの作成 s = NewServerSession(k->Cedar, c, k->Hub, LINK_USER_NAME, policy); s->LinkModeServer = true; s->Link = k; c->Session = s; ReleaseConnection(c); // ユーザー名 s->Username = CopyStr(LINK_USER_NAME_PRINT); k->ServerSession = s; AddRef(k->ServerSession->ref); // 初期化完了を通知 NoticeThreadInit(t); UniStrCpy(name, sizeof(name), k->Option->AccountName); HLog(s->Hub, "LH_LINK_START", name, s->Name); // セッションのメイン関数 SessionMain(s); HLog(s->Hub, "LH_LINK_STOP", name); ReleaseSession(s); }
// Relay thread for captured packet (Pcap) void PcapThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; pcap_t *p = e->Pcap; int ret; // Notify initialize completed NoticeThreadInit(thread); // Return -1:Error -2:Terminated externally ret = pcap_loop(p, -1, PcapHandler, (u_char*) e); if(ret == -1){ e->Socket = INVALID_SOCKET; pcap_perror(p, "capture"); } return; }
// Pcap でのパケットキャプチャの中継用スレッド void PcapThread(THREAD *thread, void *param) { ETH *e = (ETH*)param; pcap_t *p = e->Pcap; int ret; // 初期化完了を通知 NoticeThreadInit(thread); // 帰り値 -1:エラー -2:外部からの終了 ret = pcap_loop(p, -1, PcapHandler, (u_char*) e); if(ret == -1){ e->Socket = INVALID_SOCKET; pcap_perror(p, "capture"); } return; }
// Listener Thread void ListenerThread(THREAD *thread, void *param) { LISTENER *r; // Validate arguments if (thread == NULL || param == NULL) { return; } // Initialize r = (LISTENER *)param; AddRef(r->ref); r->Thread = thread; AddRef(thread->ref); NoticeThreadInit(thread); // Main loop switch (r->Protocol) { case LISTENER_TCP: case LISTENER_INPROC: case LISTENER_RUDP: case LISTENER_DNS: case LISTENER_ICMP: case LISTENER_REVERSE: // TCP or other stream-based protocol ListenerTCPMainLoop(r); break; case LISTENER_UDP: // UDP protocol ListenerUDPMainLoop(r); break; } // Release ReleaseListener(r); }
// Management port Listen thread void NiListenThread(THREAD *thread, void *param) { NAT *n = (NAT *)param; SOCK *a; UINT i; bool b = false; // Validate arguments if (thread == NULL || param == NULL) { return; } // Initialize the management list n->AdminList = NewList(NULL); while (true) { a = Listen(DEFAULT_NAT_ADMIN_PORT); if (b == false) { b = true; NoticeThreadInit(thread); } if (a != NULL) { break; } Wait(n->HaltEvent, NAT_ADMIN_PORT_LISTEN_INTERVAL); if (n->Halt) { return; } } n->AdminListenSock = a; AddRef(a->ref); // Waiting while (true) { SOCK *s = Accept(a); THREAD *t; NAT_ADMIN *admin; if (s == NULL) { break; } if (n->Halt) { ReleaseSock(s); break; } admin = ZeroMalloc(sizeof(NAT_ADMIN)); admin->Nat = n; admin->Sock = s; t = NewThread(NiAdminThread, admin); WaitThreadInit(t); ReleaseThread(t); } // Disconnect all management connections LockList(n->AdminList); { for (i = 0;i < LIST_NUM(n->AdminList);i++) { NAT_ADMIN *a = LIST_DATA(n->AdminList, i); Disconnect(a->Sock); WaitThread(a->Thread, INFINITE); ReleaseThread(a->Thread); ReleaseSock(a->Sock); Free(a); } } UnlockList(n->AdminList); ReleaseList(n->AdminList); ReleaseSock(a); }
// Layer-3 switch thread void L3SwThread(THREAD *t, void *param) { L3SW *s; bool shutdown_now = false; // Validate arguments if (t == NULL || param == NULL) { return; } s = (L3SW *)param; s->Active = true; NoticeThreadInit(t); // Operation start SLog(s->Cedar, "L3_SWITCH_START", s->Name); while (s->Halt == false) { if (s->Online == false) { // Because the L3 switch is off-line now, // attempt to make it on-line periodically LockList(s->Cedar->HubList); { Lock(s->lock); { UINT i; UINT n = 0; bool all_exists = true; if (LIST_NUM(s->IfList) == 0) { // Don't operate if there is no interface all_exists = false; } for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); HUB *h = GetHub(s->Cedar, f->HubName); if (h != NULL) { if (h->Offline || h->Type == HUB_TYPE_FARM_DYNAMIC) { all_exists = false; } else { n++; } ReleaseHub(h); } else { all_exists = false; } } if (all_exists && n >= 1) { // Start the operation because all Virtual HUBs for // interfaces are enabled SLog(s->Cedar, "L3_SWITCH_ONLINE", s->Name); L3InitAllInterfaces(s); s->Online = true; } } Unlock(s->lock); } UnlockList(s->Cedar->HubList); } else { // Examine periodically whether all sessions terminated UINT i; bool any_halted = false; LIST *o = NULL; SHUTDOWN: Lock(s->lock); { for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); if (f->Session->Halt || f->Hub->Offline != false) { any_halted = true; break; } } if (shutdown_now) { any_halted = true; } if (any_halted) { SLog(s->Cedar, "L3_SWITCH_OFFLINE", s->Name); o = NewListFast(NULL); // If there is any terminated session, terminate all sessions for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); Insert(o, f->Session); } // Restore to the offline s->Online = false; } } Unlock(s->lock); if (o != NULL) { UINT i; for (i = 0;i < LIST_NUM(o);i++) { SESSION *s = LIST_DATA(o, i); StopSession(s); } L3FreeAllInterfaces(s); ReleaseList(o); o = NULL; } } SleepThread(50); } if (s->Online != false) { shutdown_now = true; goto SHUTDOWN; } // Stop the operation SLog(s->Cedar, "L3_SWITCH_STOP", s->Name); }
// Layer-3 interface thread void L3IfThread(THREAD *t, void *param) { L3IF *f; CONNECTION *c; SESSION *s; POLICY *policy; char tmp[MAX_SIZE]; char name[MAX_SIZE]; char username[MAX_SIZE]; // Validate arguments if (t == NULL || param == NULL) { return; } f = (L3IF *)param; StrCpy(username, sizeof(username), L3_USERNAME); if (f->Switch != NULL) { StrCat(username, sizeof(username), f->Switch->Name); } // Create a connection c = NewServerConnection(f->Switch->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_LAYER3; // Create a Session policy = ClonePolicy(GetDefaultPolicy()); // Not to limit the number of broadcast by policy policy->NoBroadcastLimiter = true; s = NewServerSession(f->Switch->Cedar, c, f->Hub, username, policy); c->Session = s; ReleaseConnection(c); // Determine the name of the session GetMachineHostName(tmp, sizeof(tmp)); if (f->Switch->Cedar->Server->ServerType == SERVER_TYPE_STANDALONE) { Format(name, sizeof(name), "SID-L3-%s-%u", f->Switch->Name, Inc(f->Hub->SessionCounter)); } else { Format(name, sizeof(name), "SID-L3-%s-%s-%u", tmp, f->Switch->Name, Inc(f->Hub->SessionCounter)); } ConvertSafeFileName(name, sizeof(name), name); StrUpper(name); Free(s->Name); s->Name = CopyStr(name); s->L3SwitchMode = true; s->L3If = f; if (s->Username != NULL) { Free(s->Username); } s->Username = CopyStr(username); StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username); f->Session = s; AddRef(s->ref); // Notify the initialization completion NoticeThreadInit(t); // Session main process SessionMain(s); // Release the session ReleaseSession(s); }
// Real-time clock measuring thread void Tick64Thread(THREAD *thread, void *param) { UINT n = 0; bool first = false; bool create_first_entry = true; UINT tick_span; // Validate arguments if (thread == NULL) { return; } #ifdef OS_WIN32 // Raise the priority of the Win32 thread MsSetThreadPriorityRealtime(); tick_span = TICK64_SPAN_WIN32; #else // OS_WIN32 // Raise the priority of a POSIX threads UnixSetThreadPriorityRealtime(); tick_span = TICK64_SPAN; #endif // OS_WIN32 while (true) { UINT tick; UINT64 tick64; #ifndef OS_WIN32 tick = TickRealtime(); // Get the current system clock if (tk64->LastTick > tick) { if ((tk64->LastTick - tick) >= (UINT64)0x0fffffff) { // The Tick has gone lap around tk64->RoundCount++; } else { // tick skewed (System administrator might change hardware clock) // Normally, the clock skew appears as sub-seconds error tick = tk64->LastTick; } } tk64->LastTick = tick; tick64 = (UINT64)tk64->RoundCount * (UINT64)4294967296LL + (UINT64)tick; Lock(tk64->TickLock); { if (tk64->TickStart == 0) { tk64->TickStart = tick64; } tick64 = tk64->Tick = tick64 - tk64->TickStart + (UINT64)1; } Unlock(tk64->TickLock); #else // OS_WIN32 tick64 = Win32FastTick64(); tick = (UINT)tick64; #endif // OS_WIN32 if (create_first_entry) { ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME)); t->Tick = tick64; t->Time = SystemTime64(); tk64->Tick64WithTime64 = tick64; tk64->Time64 = t->Time; Add(tk64->AdjustTime, t); // Notify the completion of the initialization NoticeThreadInit(thread); create_first_entry = false; } // Time correction n += tick_span; if (n >= 1000 || first == false) { UINT64 now = SystemTime64(); if (now < tk64->Time64 || Diff64((now - tk64->Time64) + tk64->Tick64WithTime64, tick64) >= tick_span) { ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME)); LockList(tk64->AdjustTime); { t->Tick = tick64; t->Time = now; Add(tk64->AdjustTime, t); Debug("Adjust Time: Tick = %I64u, Time = %I64u\n", t->Tick, t->Time); // To prevent consuming memory infinite on a system that clock is skewd if (LIST_NUM(tk64->AdjustTime) > MAX_ADJUST_TIME) { // Remove the second ADJUST_TIME *t2 = LIST_DATA(tk64->AdjustTime, 1); Delete(tk64->AdjustTime, t2); Debug("NUM_ADJUST TIME: %u\n", LIST_NUM(tk64->AdjustTime)); Free(t2); } } UnlockList(tk64->AdjustTime); tk64->Time64 = now; tk64->Tick64WithTime64 = tick64; } first = true; n = 0; } if (tk64->Halt) { break; } #ifdef OS_WIN32 Wait(halt_tick_event, tick_span); #else // OS_WIN32 SleepThread(tick_span); #endif // OS_WIN32 } }
// Management thread void NiAdminThread(THREAD *thread, void *param) { NAT_ADMIN *a = (NAT_ADMIN *)param; NAT *n; SOCK *s; UCHAR random[SHA1_SIZE]; UINT err; // Validate arguments if (thread == NULL || param == NULL) { return; } // Random number generation Rand(random, sizeof(random)); a->Thread = thread; AddRef(a->Thread->ref); s = a->Sock; AddRef(s->ref); n = a->Nat; LockList(n->AdminList); { Add(n->AdminList, a); } UnlockList(n->AdminList); NoticeThreadInit(thread); err = ERR_AUTH_FAILED; if (StartSSL(s, n->AdminX, n->AdminK)) { PACK *p; // Send the random number p = NewPack(); PackAddData(p, "auth_random", random, sizeof(random)); if (HttpServerSend(s, p)) { PACK *p; // Receive a password p = HttpServerRecv(s); if (p != NULL) { UCHAR secure_password[SHA1_SIZE]; UCHAR secure_check[SHA1_SIZE]; if (PackGetData2(p, "secure_password", secure_password, sizeof(secure_password))) { SecurePassword(secure_check, n->HashedPassword, random); if (Cmp(secure_check, secure_password, SHA1_SIZE) == 0) { UCHAR test[SHA1_SIZE]; // Password match Hash(test, "", 0, true); SecurePassword(test, test, random); #if 0 if (Cmp(test, secure_check, SHA1_SIZE) == 0 && s->RemoteIP.addr[0] != 127) { // A client can not connect from the outside with blank password err = ERR_NULL_PASSWORD_LOCAL_ONLY; } else #endif { // Successful connection err = ERR_NO_ERROR; NiAdminMain(n, s); } } } FreePack(p); } } FreePack(p); if (err != ERR_NO_ERROR) { p = PackError(err); HttpServerSend(s, p); FreePack(p); } } Disconnect(s); ReleaseSock(s); }
// SecureNAT server-side thread void SnSecureNATThread(THREAD *t, void *param) { SNAT *s; CONNECTION *c; SESSION *se; POLICY *policy; HUB *h; // Validate arguments if (t == NULL || param == NULL) { return; } s = (SNAT *)param; // Create a server connection c = NewServerConnection(s->Cedar, NULL, t); c->Protocol = CONNECTION_HUB_SECURE_NAT; // Apply the default policy policy = ClonePolicy(GetDefaultPolicy()); // Not to limit the number of broadcast policy->NoBroadcastLimiter = true; h = s->Hub; AddRef(h->ref); // create a server session se = NewServerSession(s->Cedar, c, s->Hub, SNAT_USER_NAME, policy); se->SecureNATMode = true; se->SecureNAT = s; c->Session = se; ReleaseConnection(c); HLog(se->Hub, "LH_NAT_START", se->Name); // User name se->Username = CopyStr(SNAT_USER_NAME_PRINT); s->Session = se; AddRef(se->ref); // Notification initialization completion NoticeThreadInit(t); ReleaseCancel(s->Nat->Virtual->Cancel); s->Nat->Virtual->Cancel = se->Cancel1; AddRef(se->Cancel1->ref); if (s->Nat->Virtual->NativeNat != NULL) { CANCEL *old_cancel = NULL; Lock(s->Nat->Virtual->NativeNat->CancelLock); { if (s->Nat->Virtual->NativeNat->Cancel != NULL) { old_cancel = s->Nat->Virtual->NativeNat->Cancel; s->Nat->Virtual->NativeNat->Cancel = se->Cancel1; AddRef(se->Cancel1->ref); } } Unlock(s->Nat->Virtual->NativeNat->CancelLock); if (old_cancel != NULL) { ReleaseCancel(old_cancel); } } // Main function of the session Debug("SecureNAT Start.\n"); SessionMain(se); Debug("SecureNAT Stop.\n"); HLog(se->Hub, "LH_NAT_STOP"); ReleaseHub(h); ReleaseSession(se); }
// 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); }
// 管理スレッド void NiAdminThread(THREAD *thread, void *param) { NAT_ADMIN *a = (NAT_ADMIN *)param; NAT *n; SOCK *s; UCHAR random[SHA1_SIZE]; UINT err; // 引数チェック if (thread == NULL || param == NULL) { return; } // 乱数生成 Rand(random, sizeof(random)); a->Thread = thread; AddRef(a->Thread->ref); s = a->Sock; AddRef(s->ref); n = a->Nat; LockList(n->AdminList); { Add(n->AdminList, a); } UnlockList(n->AdminList); NoticeThreadInit(thread); err = ERR_AUTH_FAILED; if (StartSSL(s, n->AdminX, n->AdminK)) { PACK *p; // 乱数を送信する p = NewPack(); PackAddData(p, "auth_random", random, sizeof(random)); if (HttpServerSend(s, p)) { PACK *p; // パスワードを受け取る p = HttpServerRecv(s); if (p != NULL) { UCHAR secure_password[SHA1_SIZE]; UCHAR secure_check[SHA1_SIZE]; if (PackGetData2(p, "secure_password", secure_password, sizeof(secure_password))) { SecurePassword(secure_check, n->HashedPassword, random); if (Cmp(secure_check, secure_password, SHA1_SIZE) == 0) { UCHAR test[SHA1_SIZE]; // パスワード一致 Hash(test, "", 0, true); SecurePassword(test, test, random); #if 0 if (Cmp(test, secure_check, SHA1_SIZE) == 0 && s->RemoteIP.addr[0] != 127) { // 空白パスワードは外部から接続できない err = ERR_NULL_PASSWORD_LOCAL_ONLY; } else #endif { // 接続成功 err = ERR_NO_ERROR; NiAdminMain(n, s); } } } FreePack(p); } } FreePack(p); if (err != ERR_NO_ERROR) { p = PackError(err); HttpServerSend(s, p); FreePack(p); } } Disconnect(s); ReleaseSock(s); }