// Get the proxy server settings from the registry string of IE bool GetProxyServerNameAndPortFromIeProxyRegStr(char *name, UINT name_size, UINT *port, char *str, char *server_type) { #ifdef OS_WIN32 TOKEN_LIST *t; UINT i; bool ret = false; // Validate arguments if (name == NULL || port == NULL || str == NULL || server_type == NULL) { return false; } t = ParseToken(str, ";"); for (i = 0;i < t->NumTokens;i++) { char *s = t->Token[i]; UINT i; Trim(s); i = SearchStrEx(s, "=", 0, false); if (i != INFINITE) { char tmp[MAX_PATH]; StrCpy(name, name_size, s); name[i] = 0; if (StrCmpi(name, server_type) == 0) { char *host; StrCpy(tmp, sizeof(tmp), s + i + 1); if (ParseHostPort(tmp, &host, port, 0)) { StrCpy(name, name_size, host); Free(host); if (*port != 0) { ret = true; } break; } } } } FreeToken(t); return ret; #else // OS_WIN32 return true; #endif // OS_WIN32 }
// VPN Azure client main thread void AcMainThread(THREAD *thread, void *param) { AZURE_CLIENT *ac = (AZURE_CLIENT *)param; UINT last_ip_revision = INFINITE; UINT64 last_reconnect_tick = 0; UINT64 next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL; UINT num_reconnect_retry = 0; UINT64 next_ddns_retry_tick = 0; bool last_connect_ok = false; // Validate arguments if (ac == NULL || thread == NULL) { return; } while (ac->Halt == false) { UINT64 now = Tick64(); bool connect_was_ok = false; // Wait for enabling VPN Azure function if (ac->IsEnabled) { // VPN Azure is enabled DDNS_CLIENT_STATUS st; bool connect_now = false; bool azure_ip_changed = false; Lock(ac->Lock); { Copy(&st, &ac->DDnsStatus, sizeof(DDNS_CLIENT_STATUS)); if (StrCmpi(st.CurrentAzureIp, ac->DDnsStatusCopy.CurrentAzureIp) != 0) { if (IsEmptyStr(st.CurrentAzureIp) == false) { // Destination IP address is changed connect_now = true; num_reconnect_retry = 0; } } if (StrCmpi(st.CurrentHostName, ac->DDnsStatusCopy.CurrentHostName) != 0) { // DDNS host name is changed connect_now = true; num_reconnect_retry = 0; } Copy(&ac->DDnsStatusCopy, &st, sizeof(DDNS_CLIENT_STATUS)); } Unlock(ac->Lock); if (last_ip_revision != ac->IpStatusRevision) { last_ip_revision = ac->IpStatusRevision; connect_now = true; num_reconnect_retry = 0; } if (last_reconnect_tick == 0 || (now >= (last_reconnect_tick + next_reconnect_interval))) { UINT r; last_reconnect_tick = now; num_reconnect_retry++; next_reconnect_interval = (UINT64)num_reconnect_retry * AZURE_CONNECT_INITIAL_RETRY_INTERVAL; next_reconnect_interval = MIN(next_reconnect_interval, AZURE_CONNECT_MAX_RETRY_INTERVAL); r = (UINT)next_reconnect_interval; r = GenRandInterval(r / 2, r); next_reconnect_interval = r; connect_now = true; } if (IsEmptyStr(st.CurrentAzureIp) == false && IsEmptyStr(st.CurrentHostName) == false) { if (connect_now) { SOCK *s; char *host = NULL; UINT port = AZURE_SERVER_PORT; Debug("VPN Azure: Connecting to %s...\n", st.CurrentAzureIp); if (ParseHostPort(st.CurrentAzureIp, &host, &port, AZURE_SERVER_PORT)) { if (st.InternetSetting.ProxyType == PROXY_DIRECT) { s = ConnectEx2(host, port, 0, (bool *)&ac->Halt); } else { s = WpcSockConnect2(host, port, &st.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT); } if (s != NULL) { PACK *p; UINT64 established_tick = 0; Debug("VPN Azure: Connected.\n"); SetTimeout(s, AZURE_PROTOCOL_CONTROL_TIMEOUT_DEFAULT); Lock(ac->Lock); { ac->CurrentSock = s; ac->IsConnected = true; StrCpy(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp), st.CurrentAzureIp); } Unlock(ac->Lock); SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), false); // Receive parameter p = RecvPackWithHash(s); if (p != NULL) { UCHAR c; AZURE_PARAM param; bool hostname_changed = false; Zero(¶m, sizeof(param)); param.ControlKeepAlive = PackGetInt(p, "ControlKeepAlive"); param.ControlTimeout = PackGetInt(p, "ControlTimeout"); param.DataTimeout = PackGetInt(p, "DataTimeout"); param.SslTimeout = PackGetInt(p, "SslTimeout"); FreePack(p); param.ControlKeepAlive = MAKESURE(param.ControlKeepAlive, 1000, AZURE_SERVER_MAX_KEEPALIVE); param.ControlTimeout = MAKESURE(param.ControlTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT); param.DataTimeout = MAKESURE(param.DataTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT); param.SslTimeout = MAKESURE(param.SslTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT); Lock(ac->Lock); { Copy(&ac->AzureParam, ¶m, sizeof(AZURE_PARAM)); } Unlock(ac->Lock); SetTimeout(s, param.ControlTimeout); // Send parameter p = NewPack(); PackAddStr(p, "CurrentHostName", st.CurrentHostName); PackAddStr(p, "CurrentAzureIp", st.CurrentAzureIp); PackAddInt64(p, "CurrentAzureTimestamp", st.CurrentAzureTimestamp); PackAddStr(p, "CurrentAzureSignature", st.CurrentAzureSignature); Lock(ac->Lock); { if (StrCmpi(st.CurrentHostName, ac->DDnsStatus.CurrentHostName) != 0) { hostname_changed = true; } } Unlock(ac->Lock); if (hostname_changed == false) { if (SendPackWithHash(s, p)) { // Receive result if (RecvAll(s, &c, 1, false)) { if (c && ac->Halt == false) { connect_was_ok = true; established_tick = Tick64(); AcWaitForRequest(ac, s, ¶m); } } } } FreePack(p); } else { WHERE; } Debug("VPN Azure: Disconnected.\n"); Lock(ac->Lock); { ac->IsConnected = false; ac->CurrentSock = NULL; ClearStr(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp)); } Unlock(ac->Lock); if (established_tick != 0) { if ((established_tick + (UINT64)AZURE_CONNECT_MAX_RETRY_INTERVAL) <= Tick64()) { // If the connected time exceeds the AZURE_CONNECT_MAX_RETRY_INTERVAL, reset the retry counter. last_reconnect_tick = 0; num_reconnect_retry = 0; next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL; } } Disconnect(s); ReleaseSock(s); } else { Debug("VPN Azure: Error: Connect Failed.\n"); } Free(host); } } } } else { last_reconnect_tick = 0; num_reconnect_retry = 0; next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL; } if (ac->Halt) { break; } if (connect_was_ok) { // If connection goes out after connected, increment connection success count to urge DDNS client query next_ddns_retry_tick = Tick64() + MIN((UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF * (UINT64)(num_reconnect_retry + 1), (UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF_MAX); } if ((next_ddns_retry_tick != 0) && (Tick64() >= next_ddns_retry_tick)) { next_ddns_retry_tick = 0; ac->DDnsTriggerInt++; } Wait(ac->Event, rand() % 1000); } }
/** * @WARNING this test leaks all over the place. I'm strdup'ing because * ParseHostPort() might modify the string, and a string literal * will cause segfault since it is in read-only memory segment. */ static void test_ParseHostPort() { char *hostname, *port; ParseHostPort(xstrdup("www.cfengine.com"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("www.cfengine.com:80"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("www.cfengine.com:"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]:80"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]:"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4:80"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4:"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]:80"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]:"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; /***** CORNER CASES *****/ ParseHostPort(xstrdup(""), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[]"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[]:"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup(":"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; }
static int HailServer(const EvalContext *ctx, const GenericAgentConfig *config, char *host) { assert(host != NULL); AgentConnection *conn; char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], hostkey[CF_HOSTKEY_STRING_SIZE], user[CF_SMALLBUF]; bool gotkey; char reply[8]; bool trustkey = false; char *hostname, *port; ParseHostPort(host, &hostname, &port); if (hostname == NULL || strcmp(hostname, "localhost") == 0) { Log(LOG_LEVEL_INFO, "No remote hosts were specified to connect to"); return false; } if (port == NULL) { port = "5308"; } char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, hostname, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "HailServer: ERROR, could not resolve '%s'", hostname); return false; } Address2Hostkey(hostkey, sizeof(hostkey), ipaddr); GetCurrentUserName(user, CF_SMALLBUF); if (INTERACTIVE) { Log(LOG_LEVEL_VERBOSE, "Using interactive key trust..."); gotkey = HavePublicKey(user, ipaddr, hostkey) != NULL; if (!gotkey) { /* TODO print the hash of the connecting host. But to do that we * should open the connection first, and somehow pass that hash * here! redmine#7212 */ printf("WARNING - You do not have a public key from host %s = %s\n", hostname, ipaddr); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { if (fgets(reply, sizeof(reply), stdin) == NULL) { FatalError(ctx, "EOF trying to read answer from terminal"); } if (Chop(reply, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } if (strcmp(reply, "yes") == 0) { printf("Will trust the key...\n"); trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf("Will not trust the key...\n"); trustkey = false; break; } else { printf("Please reply yes or no...(%s)\n", reply); } } } } #ifndef __MINGW32__ if (BACKGROUND) { Log(LOG_LEVEL_INFO, "Hailing %s : %s (in the background)", hostname, port); } else #endif { Log(LOG_LEVEL_INFO, "........................................................................"); Log(LOG_LEVEL_INFO, "Hailing %s : %s", hostname, port); Log(LOG_LEVEL_INFO, "........................................................................"); } ConnectionFlags connflags = { .protocol_version = config->protocol_version, .trust_server = trustkey }; int err = 0; conn = ServerConnection(hostname, port, CONNTIMEOUT, connflags, &err); if (conn == NULL) { Log(LOG_LEVEL_ERR, "Failed to connect to host: %s", hostname); return false; } /* Send EXEC command. */ HailExec(conn, hostname, recvbuffer, sendbuffer); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_runagent"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { Log(LOG_LEVEL_WARNING, "'background_children' setting from 'body runagent control' is overridden by command-line option."); } else { BACKGROUND = BooleanFromString(value); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(value)) { strlcpy(OUTPUT_DIRECTORY, value, CF_BUFSIZE); Log(LOG_LEVEL_VERBOSE, "Setting output direcory to '%s'", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = value; } continue; } } } const char *expire_after = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (expire_after) { LASTSEENEXPIREAFTER = IntFromString(expire_after) * 60; } }
int FtpCommandParse(const char *input, FtpCommand *cmd) { int i, len, match; FtpCommand tmp; int c; const char *optional_number; assert(input != NULL); assert(cmd != NULL); /* see if our input starts with a valid command */ match = -1; for (i = 0; (i < kCommandNum) && (match == -1); ++i) { len = strlen(command_def[i].name); if (strncasecmp(input, command_def[i].name, len) == 0) { match = i; } } /* if we didn't find a match, return error */ if (match == -1) { return COMMAND_UNRECOGNIZED; } assert(match >= 0); assert(match < kCommandNum); /* copy our command */ strcpy(tmp.command, command_def[match].name); /* advance input past the command */ input += strlen(command_def[match].name); /* now act based on the command */ switch (command_def[match].arg_type) { case ARG_NONE: tmp.num_arg = 0; break; case ARG_STRING: if (*input != ' ') { goto Parameter_Error; } ++input; input = CopyLine(tmp.arg[0].string, input); tmp.num_arg = 1; break; case ARG_OPTIONAL_STRING: if (*input == ' ') { ++input; input = CopyLine(tmp.arg[0].string, input); tmp.num_arg = 1; } else { tmp.num_arg = 0; } break; case ARG_HOST_PORT: if (*input != ' ') { goto Parameter_Error; } input++; /* parse the host & port information (if any) */ input = ParseHostPort(&tmp.arg[0].host_port, input); if (input == NULL) { goto Parameter_Error; } tmp.num_arg = 1; break; case ARG_TYPE: if (*input != ' ') { goto Parameter_Error; } input++; c = toupper(*input); if ((c == 'A') || (c == 'E')) { tmp.arg[0].string[0] = c; tmp.arg[0].string[1] = '\0'; input++; if (*input == ' ') { input++; c = toupper(*input); if ((c != 'N') && (c != 'T') && (c != 'C')) { goto Parameter_Error; } tmp.arg[1].string[0] = c; tmp.arg[1].string[1] = '\0'; input++; tmp.num_arg = 2; } else { tmp.num_arg = 1; } } else if (c == 'I') { tmp.arg[0].string[0] = 'I'; tmp.arg[0].string[1] = '\0'; input++; tmp.num_arg = 1; } else if (c == 'L') { tmp.arg[0].string[0] = 'L'; tmp.arg[0].string[1] = '\0'; input++; input = ParseNumber(&tmp.arg[1].num, input, 255); if (input == NULL) { goto Parameter_Error; } tmp.num_arg = 2; } else { goto Parameter_Error; } break; case ARG_STRUCTURE: if (*input != ' ') { goto Parameter_Error; } input++; c = toupper(*input); if ((c != 'F') && (c != 'R') && (c != 'P')) { goto Parameter_Error; } input++; tmp.arg[0].string[0] = c; tmp.arg[0].string[1] = '\0'; tmp.num_arg = 1; break; case ARG_MODE: if (*input != ' ') { goto Parameter_Error; } input++; c = toupper(*input); if ((c != 'S') && (c != 'B') && (c != 'C')) { goto Parameter_Error; } input++; tmp.arg[0].string[0] = c; tmp.arg[0].string[1] = '\0'; tmp.num_arg = 1; break; case ARG_OFFSET: if (*input != ' ') { goto Parameter_Error; } input++; input = ParseOffset(&tmp.arg[0].offset, input); if (input == NULL) { goto Parameter_Error; } tmp.num_arg = 1; break; default: assert(0); } /* check for our ending newline */ if (*input != '\n') { Parameter_Error: return COMMAND_PARAMETERS_ERROR; } /* return our result */ *cmd = tmp; return 0; }
// Parse the URL bool ParseUrl(URL_DATA *data, char *str, bool is_post, char *referrer) { char tmp[MAX_SIZE * 3]; char server_port[MAX_HOST_NAME_LEN + 16]; char *s = NULL; char *host; UINT port; UINT i; // Validate arguments if (data == NULL || str == NULL) { return false; } Zero(data, sizeof(URL_DATA)); if (is_post) { StrCpy(data->Method, sizeof(data->Method), WPC_HTTP_POST_NAME); } else { StrCpy(data->Method, sizeof(data->Method), WPC_HTTP_GET_NAME); } if (referrer != NULL) { StrCpy(data->Referer, sizeof(data->Referer), referrer); } StrCpy(tmp, sizeof(tmp), str); Trim(tmp); // Determine the protocol if (StartWith(tmp, "http://")) { data->Secure = false; s = &tmp[7]; } else if (StartWith(tmp, "https://")) { data->Secure = true; s = &tmp[8]; } else { if (SearchStrEx(tmp, "://", 0, false) != INFINITE) { return false; } data->Secure = false; s = &tmp[0]; } // Get the "server name:port number" StrCpy(server_port, sizeof(server_port), s); i = SearchStrEx(server_port, "/", 0, false); if (i != INFINITE) { server_port[i] = 0; s += StrLen(server_port); StrCpy(data->Target, sizeof(data->Target), s); } else { StrCpy(data->Target, sizeof(data->Target), "/"); } if (ParseHostPort(server_port, &host, &port, data->Secure ? 443 : 80) == false) { return false; } StrCpy(data->HostName, sizeof(data->HostName), host); data->Port = port; Free(host); if ((data->Secure && data->Port == 443) || (data->Secure == false && data->Port == 80)) { StrCpy(data->HeaderHostName, sizeof(data->HeaderHostName), data->HostName); } else { Format(data->HeaderHostName, sizeof(data->HeaderHostName), "%s:%u", data->HostName, data->Port); } return true; }
// Get the internet connection settings of the system void GetSystemInternetSetting(INTERNET_SETTING *setting) { #ifdef OS_WIN32 bool use_proxy; // Validate arguments if (setting == NULL) { return; } Zero(setting, sizeof(INTERNET_SETTING)); use_proxy = MsRegReadInt(REG_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable"); if (use_proxy) { char *str = MsRegReadStr(REG_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer"); if (str != NULL) { char name[MAX_HOST_NAME_LEN + 1]; UINT port; if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name), &port, str, "https")) { setting->ProxyType = PROXY_HTTP; StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name); setting->ProxyPort = port; } else if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name), &port, str, "http")) { setting->ProxyType = PROXY_HTTP; StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name); setting->ProxyPort = port; } else if (GetProxyServerNameAndPortFromIeProxyRegStr(name, sizeof(name), &port, str, "socks")) { setting->ProxyType = PROXY_SOCKS; StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), name); setting->ProxyPort = port; } else { if (SearchStrEx(str, "=", 0, false) == INFINITE) { char *host; UINT port; if (ParseHostPort(str, &host, &port, 0)) { if (port != 0) { setting->ProxyType = PROXY_HTTP; StrCpy(setting->ProxyHostName, sizeof(setting->ProxyHostName), host); setting->ProxyPort = port; } Free(host); } } } Free(str); } } #else // OS_WIN32 Zero(setting, sizeof(INTERNET_SETTING)); #endif // OS_WIN32 }