PACK *WpcCallEx(char *url, INTERNET_SETTING *setting, UINT timeout_connect, UINT timeout_comm, char *function_name, PACK *pack, X *cert, K *key, void *sha1_cert_hash, bool *cancel, UINT max_recv_size, char *additional_header_name, char *additional_header_value) { URL_DATA data; BUF *b, *recv; UINT error; WPC_PACKET packet; // Validate arguments if (function_name == NULL || pack == NULL) { return PackError(ERR_INTERNAL_ERROR); } if (ParseUrl(&data, url, true, NULL) == false) { return PackError(ERR_INTERNAL_ERROR); } PackAddStr(pack, "function", function_name); b = WpcGeneratePacket(pack, cert, key); if (b == NULL) { return PackError(ERR_INTERNAL_ERROR); } SeekBuf(b, b->Size, 0); WriteBufInt(b, 0); SeekBuf(b, 0, 0); if (IsEmptyStr(additional_header_name) == false && IsEmptyStr(additional_header_value) == false) { StrCpy(data.AdditionalHeaderName, sizeof(data.AdditionalHeaderName), additional_header_name); StrCpy(data.AdditionalHeaderValue, sizeof(data.AdditionalHeaderValue), additional_header_value); } recv = HttpRequestEx(&data, setting, timeout_connect, timeout_comm, &error, false, b->Buf, NULL, NULL, sha1_cert_hash, cancel, max_recv_size); FreeBuf(b); if (recv == NULL) { return PackError(error); } if (WpcParsePacket(&packet, recv) == false) { FreeBuf(recv); return PackError(ERR_PROTOCOL_ERROR); } FreeBuf(recv); FreeX(packet.Cert); return packet.Pack; }
const PackReader::File & PackReader::getFile(const std::string & path){ if (files.find(lowercase(path)) != files.end()){ return files.find(lowercase(path))->second; } ostringstream out; out << "No such pak file '" << path << "'"; throw PackError(__FILE__, __LINE__, out.str()); }
PackReader::PackReader(const Filesystem::AbsolutePath & filename): filename(filename){ ifstream stream; Global::debug(0) << "Reading pak file " << filename.path() << endl; stream.open(filename.path().c_str(), std::ios::in | std::ios::binary); Storage::LittleEndianReader reader(stream); uint32_t magic = reader.readByte4(); if (magic != MAGIC){ ostringstream error; error << filename.path() << " is not a packfile! " << std::hex << magic; throw PackError(__FILE__, __LINE__, error.str()); } else { // cout << "Ok got a packfile" << endl; } uint32_t version = reader.readByte4(); /* just assume we can read all versions for now */ // cout << "Version is " << version << endl; reader.seekEnd(-4); uint32_t headerPosition = reader.readByte4(); reader.seek(headerPosition); // cout << "Header at 0x" << std::hex << headerPosition << std::dec << endl; bool done = false; try{ while (!done){ uint32_t current = reader.position(); uint32_t length = reader.readByte4(); uint32_t start = reader.readByte4(); uint32_t size = reader.readByte4(); /* will read upto 80 bytes, but potentially fewer if a null byte * is reached. */ string name = reader.readStringX(80); if (name.size() != 0){ files[sanitizePath(name)] = File(start, size); } done = name.size() == 0; // cout << name << " at " << start << " size " << size << " length " << length << endl; // cout << " seek to " << (current + length) << endl; // reader.seek(current + length); done |= stream.eof(); } } catch (const Storage::Eof & eof){ } stream.close(); handle.open(filename.path().c_str(), std::ios::in | std::ios::binary); Util::Thread::initializeLock(&readLock); }
// 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); }
// RPC call PACK *RpcCall(RPC *r, char *function_name, PACK *p) { PACK *ret; UINT num_retry = 0; UINT err = 0; // Validate arguments if (r == NULL || function_name == NULL) { return NULL; } // Debug("RpcCall: %s\n", function_name); Lock(r->Lock); { if (p == NULL) { p = NewPack(); } PackAddStr(p, "function_name", function_name); RETRY: err = 0; ret = RpcCallInternal(r, p); if (ret == NULL) { if (r->IsVpnServer && r->Sock != NULL) { if (num_retry < 1) { num_retry++; // Attempt to reconnect the RPC to the VPN Server err = AdminReconnect(r); if (err == ERR_NO_ERROR) { goto RETRY; } } } } FreePack(p); if (ret == NULL) { if (err == 0) { err = ERR_DISCONNECTED; } ret = PackError(err); PackAddInt(ret, "error_code", err); } } Unlock(r->Lock); return ret; }
// Wait for the next RPC call bool RpcRecvNextCall(RPC *r) { UINT size; void *tmp; SOCK *s; BUF *b; PACK *p; PACK *ret; // Validate arguments if (r == NULL) { return false; } s = r->Sock; if (RecvAll(s, &size, sizeof(UINT), s->SecureMode) == false) { return false; } size = Endian32(size); if (size > MAX_PACK_SIZE) { return false; } tmp = MallocEx(size, true); if (RecvAll(s, tmp, size, s->SecureMode) == false) { Free(tmp); return false; } b = NewBuf(); WriteBuf(b, tmp, size); SeekBuf(b, 0, 0); Free(tmp); p = BufToPack(b); FreeBuf(b); if (p == NULL) { return false; } ret = CallRpcDispatcher(r, p); FreePack(p); if (ret == NULL) { ret = PackError(ERR_NOT_SUPPORTED); } b = PackToBuf(ret); FreePack(ret); size = Endian32(b->Size); SendAdd(s, &size, sizeof(UINT)); SendAdd(s, b->Buf, b->Size); if (SendNow(s, s->SecureMode) == false) { FreeBuf(b); return false; } FreeBuf(b); return true; }
// 管理スレッド 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); }