// 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); }
// RPC client connect UINT EcConnect(char *host, UINT port, char *password, RPC **rpc) { SOCK *s; UCHAR password_hash[SHA1_SIZE]; UCHAR rand[SHA1_SIZE]; UCHAR response[SHA1_SIZE]; bool retcode; // Validate arguments if (host == NULL) { host = "localhost"; } if (port == 0) { port = EL_ADMIN_PORT; } if (password == NULL) { password = ""; } if (rpc == NULL) { return ERR_INTERNAL_ERROR; } // Connect to the server s = Connect(host, port); if (s == NULL) { // Connection failure return ERR_CONNECT_FAILED; } SetTimeout(s, 5000); // Hash the password Hash(password_hash, password, StrLen(password), true); // Receive the random number Zero(rand, sizeof(rand)); RecvAll(s, rand, sizeof(rand), false); SecurePassword(response, password_hash, rand); // Send a response SendAll(s, response, sizeof(response), false); // Receive results retcode = false; if (RecvAll(s, &retcode, sizeof(retcode), false) == false) { // Disconnect ReleaseSock(s); return ERR_PROTOCOL_ERROR; } retcode = Endian32(retcode); if (retcode == false) { // Password incorrect ReleaseSock(s); return ERR_AUTH_FAILED; } // Successful connection SetTimeout(s, INFINITE); *rpc = StartRpcClient(s, NULL); ReleaseSock(s); return ERR_NO_ERROR; }
// Connection for NAT administrator RPC *NatAdminConnect(CEDAR *cedar, char *hostname, UINT port, void *hashed_password, UINT *err) { UCHAR secure_password[SHA1_SIZE]; UCHAR random[SHA1_SIZE]; SOCK *sock; RPC *rpc; PACK *p; UINT error; // Validate arguments if (cedar == NULL || hostname == NULL || port == 0 || hashed_password == NULL || err == NULL) { if (err != NULL) { *err = ERR_INTERNAL_ERROR; } return NULL; } // Connection sock = Connect(hostname, port); if (sock == NULL) { *err = ERR_CONNECT_FAILED; return NULL; } if (StartSSL(sock, NULL, NULL) == false) { *err = ERR_PROTOCOL_ERROR; ReleaseSock(sock); return NULL; } SetTimeout(sock, 5000); p = HttpClientRecv(sock); if (p == NULL) { *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } if (PackGetData2(p, "auth_random", random, SHA1_SIZE) == false) { FreePack(p); *err = ERR_PROTOCOL_ERROR; ReleaseSock(sock); return NULL; } FreePack(p); SecurePassword(secure_password, hashed_password, random); p = NewPack(); PackAddData(p, "secure_password", secure_password, SHA1_SIZE); if (HttpClientSend(sock, p) == false) { FreePack(p); *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } FreePack(p); p = HttpClientRecv(sock); if (p == NULL) { *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } error = GetErrorFromPack(p); FreePack(p); if (error != ERR_NO_ERROR) { *err = error; ReleaseSock(sock); return NULL; } SetTimeout(sock, TIMEOUT_INFINITE); rpc = StartRpcClient(sock, NULL); ReleaseSock(sock); return rpc; }
// 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); }
// Password authentication of user bool SamAuthUserByPassword(HUB *h, char *username, void *random, void *secure_password, char *mschap_v2_password, UCHAR *mschap_v2_server_response_20, UINT *err) { bool b = false; UCHAR secure_password_check[SHA1_SIZE]; bool is_mschap = false; IPC_MSCHAP_V2_AUTHINFO mschap; UINT dummy = 0; // Validate arguments if (h == NULL || username == NULL || secure_password == NULL) { return false; } if (err == NULL) { err = &dummy; } *err = 0; Zero(&mschap, sizeof(mschap)); is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, mschap_v2_password); if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0) { // Administrator mode SecurePassword(secure_password_check, h->SecurePassword, random); if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0) { return true; } else { return false; } } AcLock(h); { USER *u; u = AcGetUser(h, username); if (u) { Lock(u->lock); { if (u->AuthType == AUTHTYPE_PASSWORD) { AUTHPASSWORD *auth = (AUTHPASSWORD *)u->AuthData; if (is_mschap == false) { // Normal password authentication SecurePassword(secure_password_check, auth->HashedKey, random); if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0) { b = true; } } else { // MS-CHAP v2 authentication via PPP UCHAR challenge8[8]; UCHAR client_response[24]; if (IsZero(auth->NtLmSecureHash, MD5_SIZE)) { // NTLM hash is not registered in the user account *err = ERR_MSCHAP2_PASSWORD_NEED_RESET; } else { UCHAR nt_pw_hash_hash[16]; Zero(challenge8, sizeof(challenge8)); Zero(client_response, sizeof(client_response)); MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_ServerChallenge, mschap.MsChapV2_PPPUsername); MsChapV2Client_GenerateResponse(client_response, challenge8, auth->NtLmSecureHash); if (Cmp(client_response, mschap.MsChapV2_ClientResponse, 24) == 0) { // Hash matched b = true; // Calculate the response GenerateNtPasswordHashHash(nt_pw_hash_hash, auth->NtLmSecureHash); MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_pw_hash_hash, client_response, challenge8); } } } } } Unlock(u->lock); ReleaseUser(u); } } AcUnlock(h); return b; }
// 管理スレッド 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); }