/*++ Copyright (c) 1997 Microsoft Corporation Copyright (c) 1996 Hummingbird Corporation of Canada Module Name: wsock32.c Abstract: Contains Socks V4 support, written by Hummingbird corporation. Licensed from Hummingbird for ulimited use by Microsoft. Ported to WININET code base. Contents: FindSocket closesocket connect getpeername ALL WSOCK32.DLL exports. Author: Arthur L Bierer (arthurbi) 13-Dec-1996 Environment: Win32 user-mode DLL Revision History: 13-Dec-1996 arthurbi Created, removed flagrent calls to CRTs, and unchecked memory allocations. 29-Aug-1997 rfirth Further reduced from general-purpose SOCKS implementation to Wininet- specific SOCKS support --*/ #define _WINSOCKAPI_ #include #ifdef DO_FILE_CONFIG #include #include #include #include #include #include #endif #ifdef OLD_SOCKS struct User { char *Name; struct User *Next; }; struct Server { char *Name; struct Server *Next; unsigned short port; }; struct Hosts { struct User *Users; struct Server *Servers; unsigned long dst; unsigned long mask; unsigned short port; unsigned char op; unsigned char type; struct Hosts *Next; } *Head=NULL; struct Sockets { int s; HWND hWnd; unsigned int wMsg; long lEvent; unsigned long Blocking; int type; unsigned long ip; unsigned short port; struct Sockets *Next; struct Sockets *Last; int Socked:1; } *SHead=NULL; HANDLE SMutex; #define CREATE_MUTEX() SMutex = CreateMutex(NULL, FALSE, NULL) #define DELETE_MUTEX() if (SMutex) CloseHandle(SMutex) #define ENTER_MUTEX() WaitForSingleObject(SMutex, INFINITE) #define LEAVE_MUTEX() ReleaseMutex(SMutex) #else struct Hosts { char * user; int userlen; unsigned long ip; unsigned short port; } *Head = NULL; struct Sockets { int s; int type; unsigned long ip; unsigned short port; struct Sockets * Next; struct Sockets * Last; int Socked : 1; int Blocking : 1; } *SHead = NULL; CRITICAL_SECTION CritSec; #define CREATE_MUTEX() InitializeCriticalSection(&CritSec) #define DELETE_MUTEX() DeleteCriticalSection(&CritSec) #define ENTER_MUTEX() EnterCriticalSection(&CritSec) #define LEAVE_MUTEX() LeaveCriticalSection(&CritSec) #endif #define DENY 1 #define DIRECT 2 #define SOCKD 3 #define ANY 0 #define EQ 1 #define NEQ 2 #define LT 3 #define GT 4 #define LE 5 #define GE 6 /* * Internet address (old style... should be updated) */ struct in_addr { union { struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { unsigned short s_w1,s_w2; } S_un_w; unsigned long S_addr; } S_un; #define s_addr S_un.S_addr /* can be used for most tcp & ip code */ #define s_host S_un.S_un_b.s_b2 /* host on imp */ #define s_net S_un.S_un_b.s_b1 /* network */ #define s_imp S_un.S_un_w.s_w2 /* imp */ #define s_impno S_un.S_un_b.s_b4 /* imp # */ #define s_lh S_un.S_un_b.s_b3 /* logical host */ }; /* * Socket address, internet style. */ struct sockaddr_in { short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; struct servent { char * s_name; /* official service name */ char * * s_aliases; /* alias list */ short s_port; /* port # */ char * s_proto; /* protocol to use */ }; struct hostent { char * h_name; /* official name of host */ char * * h_aliases; /* alias list */ short h_addrtype; /* host address type */ short h_length; /* length of address */ char * * h_addr_list; /* list of addresses */ #define h_addr h_addr_list[0] /* address, for backward compat */ }; #define WSABASEERR 10000 #define WSAECONNREFUSED (WSABASEERR+61) #define WSAEWOULDBLOCK (WSABASEERR+35) #define WSAENOBUFS (WSABASEERR+55) #define SOCKET_ERROR (-1) #define INVALID_SOCKET (int)(~0) /* * Define flags to be used with the WSAAsyncSelect() call. */ #define FD_READ 0x01 #define FD_WRITE 0x02 #define FD_OOB 0x04 #define FD_ACCEPT 0x08 #define FD_CONNECT 0x10 #define FD_CLOSE 0x20 #define SOCK_STREAM 1 /* stream socket */ /* * Commands for ioctlsocket(), taken from the BSD file fcntl.h. * * * Ioctl's have the command encoded in the lower word, * and the size of any in or out parameters in the upper * word. The high 2 bits of the upper word are used * to encode the in/out status of the parameter; for now * we restrict parameters to at most 128 bytes. */ #define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ #define IOC_VOID 0x20000000 /* no parameters */ #define IOC_OUT 0x40000000 /* copy out parameters */ #define IOC_IN 0x80000000 /* copy in parameters */ #define IOC_INOUT (IOC_IN|IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */ #define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) #define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) #define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) #define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ #define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ #define FIOASYNC _IOW('f', 125, unsigned long) /* set/clear async i/o */ #define SO_SET_SOCKS_FIREWALL 0xF0000 DWORD (WINAPI * VArecv)(int a,int b,int c, int d); DWORD (WINAPI * VAsend)(int a,int b,int c, int d); DWORD (WINAPI * VEnumProtocolsA)(int a,int b,int c); DWORD (WINAPI * VEnumProtocolsW)(int a,int b,int c); DWORD (WINAPI * VGetAddressByNameA)(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j); DWORD (WINAPI * VGetAddressByNameW)(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j); DWORD (WINAPI * VGetNameByTypeA)(int a,int b,int c); DWORD (WINAPI * VGetNameByTypeW)(int a,int b,int c); DWORD (WINAPI * VGetServiceA)(int a,int b,int c,int d,int e,int f,int g); DWORD (WINAPI * VGetServiceW)(int a,int b,int c,int d,int e,int f,int g); DWORD (WINAPI * VGetTypeByNameA)(int a,int b); DWORD (WINAPI * VGetTypeByNameW)(int a,int b); DWORD (WINAPI * VNPLoadNameSpaces)(int a,int b,int c); DWORD (WINAPI * VSetServiceA)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * VSetServiceW)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * VTransmitFile)(int a,int b,int c,int d,int e,int f,int g); DWORD (WINAPI * VWSAAsyncGetHostByAddr)(int a,int b,int c,int d,int e,int f,int g); DWORD (WINAPI * VWSAAsyncGetHostByName)(int a,int b,int c,int d,int e); DWORD (WINAPI * VWSAAsyncGetProtoByName)(int a,int b,int c,int d,int e); DWORD (WINAPI * VWSAAsyncGetProtoByNumber)(int a,int b,int c,int d,int e); DWORD (WINAPI * VWSAAsyncGetServByName)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * VWSAAsyncGetServByPort)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * VWSAAsyncSelect)(int s, HWND hWnd, unsigned int wMsg, long lEvent); DWORD (WINAPI * VWSACancelAsyncRequest)(int a); DWORD (WINAPI * VWSACancelBlockingCall)(void); DWORD (WINAPI * VWSACleanup)(void); DWORD (WINAPI * VWSAGetLastError)(void); DWORD (WINAPI * VWSAIsBlocking)(void); DWORD (WINAPI * VWSARecvEx)(int a,int b,int c,int d); DWORD (WINAPI * VWSASetBlockingHook)(int a); DWORD (WINAPI * VWSASetLastError)(int a); DWORD (WINAPI * VWSAStartup)(int a,int b); DWORD (WINAPI * VWSAUnhookBlockingHook)(void); DWORD ( * VWSHEnumProtocols)(int a,int b,int c,int d); DWORD (WINAPI * VWsControl)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * V__WSAFDIsSet)(int a,int b); DWORD (WINAPI * Vaccept)(int a,int b,int c); DWORD (WINAPI * Vbind)(int a,int b,int c); DWORD (WINAPI * Vclosesocket)(int a); DWORD (WINAPI * Vclosesockinfo)(int a); DWORD (WINAPI * Vconnect)(int s, const struct sockaddr_in FAR *name, int namelen); DWORD (WINAPI * Vdn_expand)(int a,int b,int c,int d,int e); DWORD (WINAPI * Vgethostbyaddr)(int a,int b,int c); struct hostent * (WINAPI * Vgethostbyname)(char *); DWORD (WINAPI * Vgethostname)(int a,int b); DWORD (WINAPI * Vgetnetbyname)(int a); DWORD (WINAPI * Vgetpeername)(int s, struct sockaddr_in *name,int *namelen); DWORD (WINAPI * Vgetprotobyname)(int a); DWORD (WINAPI * Vgetprotobynumber)(int a); struct servent * (WINAPI * Vgetservbyname)(const char FAR * name, const char FAR * proto); DWORD (WINAPI * Vgetservbyport)(int a,int b); DWORD (WINAPI * Vgetsockname)(int a,int b,int c); DWORD (WINAPI * Vgetsockopt)(int a,int b,int c,int d,int e); DWORD (WINAPI * Vhtonl)(int a); DWORD (WINAPI * Vhtons)(int a); DWORD (WINAPI * Vinet_addr)(char *p); DWORD (WINAPI * Vinet_network)(int a); DWORD (WINAPI * Vinet_ntoa)(int a); DWORD (WINAPI * Vioctlsocket)(int s, long cmd, unsigned long *argp); DWORD (WINAPI * Vlisten)(int a,int b); DWORD (WINAPI * Vntohl)(int a); DWORD (WINAPI * Vntohs)(int a); DWORD (WINAPI * Vrcmd)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * Vrecv)(int a,int b,int c,int d); DWORD (WINAPI * Vrecvfrom)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * Vrexec)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * Vrresvport)(int a); DWORD (WINAPI * Vs_perror)(int a,int b); DWORD (WINAPI * Vselect)(int a,int b,int c,int d,int e); DWORD (WINAPI * Vsend)(int a,int b,int c,int d); DWORD (WINAPI * Vsendto)(int a,int b,int c,int d,int e,int f); DWORD (WINAPI * Vsethostname)(int a,int b); DWORD (WINAPI * Vsetsockopt)(int s,int level,int optname,const char FAR * optval, int optlen); DWORD (WINAPI * Vshutdown)(int a,int b); DWORD (WINAPI * Vsocket)(int a,int b,int c); DWORD (WINAPI * VWEP)(void); DWORD (WINAPI * VAcceptEx)(int a,int b,int c,int d,int e,int f,int g,int h); DWORD (WINAPI * VGetAcceptExSockaddrs)(int a,int b,int c,int d,int e,int f,int g,int h); DWORD (WINAPI * VMigrateWinsockConfiguration)(int a,int b, int c); DWORD (WINAPI * VWSApSetPostRoutine)(void *a); BOOL (WINAPI * VPostMessage)(HWND hWnd, unsigned int wMsg, WPARAM wPAram, LPARAM lParam) = NULL; BOOL MyPostMessage(HWND hWnd, unsigned int wMsg, WPARAM wParam, LPARAM lParam) { if ( VPostMessage) return(VPostMessage(hWnd,wMsg, wParam, lParam)); PostMessage(hWnd,wMsg, wParam, lParam); } struct Sockets * FindSocket( int s ) /*++ Routine Description: Find or create SOCKS socket object. Returns with MUTEX held Arguments: s - associated socket handle Return Value: struct Sockets * Success - address of Sockets object Failure - NULL --*/ { struct Sockets *So; ENTER_MUTEX(); So = SHead; while (So) { if (s == So->s) { return So; } So = So->Next; } if (So = (struct Sockets *)LocalAlloc(LPTR, sizeof(struct Sockets))) { So->s = s; So->Next = SHead; SHead = So; if (So->Next) { (So->Next)->Last = So; } } return So; } //LPSTR //NewString( // IN LPCSTR String // ) // ///*++ // //Routine Description: // // kind of version of strdup() but using LocalAlloc to allocate memory // //Arguments: // // String - pointer to string to make copy of // //Return Value: // // LPSTR // Success - pointer to duplicated string // Failure - NULL // //--*/ // //{ // int len = strlen(String) + 1; // LPSTR string; // // if (string = (LPSTR)LocalAlloc(LMEM_FIXED, len)) { // CopyMemory(string, String, len); // } // return string; //} DWORD WINAPI __WSAFDIsSet(int a,int b) { return(V__WSAFDIsSet(a, b)); } DWORD WINAPI accept(int a,int b,int c) { return(Vaccept(a, b, c)); } DWORD WINAPI Arecv(int a,int b,int c,int d) { return(VArecv(a,b,c,d)); } DWORD WINAPI Asend(int a,int b,int c,int d) { return(VAsend(a,b,c,d)); } DWORD WINAPI bind(int a,int b,int c) { return(Vbind(a, b, c)); } DWORD WINAPI AcceptEx(int a,int b,int c,int d,int e,int f,int g,int h) { return(VAcceptEx(a,b,c,d,e,f,g,h)); } DWORD WINAPI GetAcceptExSockaddrs(int a,int b,int c,int d,int e,int f,int g,int h) { return(VGetAcceptExSockaddrs(a,b,c,d,e,f,g,h)); } DWORD WINAPI MigrateWinsockConfiguration(int a,int b, int c) { return(VMigrateWinsockConfiguration(a,b,c)); } DWORD WINAPI WSApSetPostRoutine(void *a) { VPostMessage=a; return(VWSApSetPostRoutine(a)); } DWORD WINAPI closesocket( int s ) /*++ Routine Description: Closes socket handle and destroys associated Sockets object if found Arguments: s - socket handle Return Value: int Success - 0 Failure - -1 --*/ { struct Sockets * So = FindSocket(s); if (So == NULL) { VWSASetLastError(WSAENOBUFS); LEAVE_MUTEX(); return SOCKET_ERROR; } if (So->Last == NULL) { SHead = So->Next; } else { (So->Last)->Next = So->Next; } if (So->Next) { (So->Next)->Last = So->Last; } LEAVE_MUTEX(); LocalFree(So); return Vclosesocket(s); } DWORD WINAPI closesockinfo(int a) { return(Vclosesockinfo(a)); } DWORD WINAPI connect( int s, const struct sockaddr_in FAR * name, int namelen ) /*++ Routine Description: Connect to remote host via SOCKS proxy. Modified from original. If we are here then we are going specifically via a known SOCKS proxy. There is now only one Hosts object, containing a single SOCKD socks proxy address and user name Arguments: s - socket to connect name - sockaddr of remote host namelen - length of sockaddr Return Value: int Success - 0 Failure - -1 --*/ { unsigned long ip; unsigned short port; struct Hosts * pHost; int serr; int blocking; struct Sockets * pSocket; struct sockaddr_in sin; struct { unsigned char VN; unsigned char CD; unsigned short DSTPORT; unsigned long DSTIP; char UserId[255]; } request; int length; char response[256]; int val; // // get IP address and port we want to connect to on other side of firewall // port = name->sin_port; ip = name->sin_addr.s_addr; // // initialize sockaddr for connecting to SOCKS firewall // memset(&sin, 0, sizeof(sin)); sin.sin_family = 2; // // initialize SOCKS request packet // request.VN = 4; request.CD = 1; request.DSTPORT = port; request.DSTIP = ip; pSocket = FindSocket(s); if (pSocket == NULL) { VWSASetLastError(WSAENOBUFS); LEAVE_MUTEX(); return SOCKET_ERROR; } pHost = Head; if (!pHost || (pSocket->type != SOCK_STREAM) || (pSocket->Socked)) { LEAVE_MUTEX(); return Vconnect(s, name, namelen); } // // get information from pSocket and pHost structures before releasing mutex // blocking = pSocket->Blocking; pSocket->port = port; pSocket->ip = ip; memcpy(request.UserId, pHost->user, pHost->userlen); length = pHost->userlen + 8; // 8 == sizeof fixed portion of request sin.sin_port = pHost->port; sin.sin_addr.s_addr = pHost->ip; // // from this point, we cannot touch pHost or pSocket until we take the mutex // again // LEAVE_MUTEX(); // // put socket into blocking mode // val = 0; Vioctlsocket(s, FIONBIO, &val); // // communicate with SOCKS firewall: send SOCKS request & receive response // serr = Vconnect(s, &sin, sizeof(sin)); if (serr != SOCKET_ERROR) { serr = Vsend(s, (int)&request, length, 0); if (serr == length) { serr = Vrecv(s, (int)response, sizeof(response), 0); } } // // if originally non-blocking, make socket non-blocking again // if (blocking) { Vioctlsocket(s, FIONBIO, &blocking); } // // if success, mark the socket as being connected through firewall // if ((serr == SOCKET_ERROR) || (response[1] != 90)) { VWSASetLastError(WSAECONNREFUSED); serr = SOCKET_ERROR; } else { // // if we can't find/crea // pSocket = FindSocket(s); if (pSocket) { pSocket->Socked = 1; serr = 0; } else { VWSASetLastError(WSAENOBUFS); serr = SOCKET_ERROR; } LEAVE_MUTEX(); } return serr; } DWORD WINAPI dn_expand(int a,int b,int c,int d,int e) { return(Vdn_expand(a, b, c, d, e)); } DWORD WINAPI EnumProtocolsA(int a,int b,int c) { return(VEnumProtocolsA(a, b, c)); } DWORD WINAPI EnumProtocolsW(int a,int b,int c) { return(VEnumProtocolsW(a, b, c)); } DWORD WINAPI GetAddressByNameA(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j) { return(VGetAddressByNameA(a, b, c, d, e, f, g, h, i, j)); } DWORD WINAPI GetAddressByNameW(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j) { return(VGetAddressByNameW(a, b, c, d, e, f, g, h, i, j)); } DWORD WINAPI gethostbyaddr(int a,int b,int c) { return(Vgethostbyaddr(a, b, c)); } struct hostent FAR * WINAPI gethostbyname(char *a) { return(Vgethostbyname(a)); } DWORD WINAPI gethostname(int a,int b) { return(Vgethostname(a, b)); } DWORD WINAPI GetNameByTypeA(int a,int b,int c) { return(VGetNameByTypeA(a, b, c)); } DWORD WINAPI GetNameByTypeW(int a,int b,int c) { return(VGetNameByTypeW(a, b, c)); } DWORD WINAPI getnetbyname(int a) { return(Vgetnetbyname(a)); } DWORD WINAPI getpeername( int s, struct sockaddr_in * name, int *namelen ) /*++ Routine Description: description-of-function. Arguments: s - name - namelen - Return Value: int --*/ { DWORD ret; struct Sockets *So; ret = Vgetpeername(s, name, namelen); if (ret == 0) { So = FindSocket(s); if (So) { if (So->Socked) { if (*namelen >= sizeof(struct sockaddr_in)) { name->sin_port = So->port; name->sin_addr.s_addr = So->ip; } } } else { VWSASetLastError(WSAENOBUFS); ret = SOCKET_ERROR; } LEAVE_MUTEX(); } return ret; } DWORD WINAPI getprotobyname(int a) { return(Vgetprotobyname(a)); } DWORD WINAPI getprotobynumber(int a) { return(Vgetprotobynumber(a)); } struct servent * WINAPI getservbyname(const char FAR * name, const char FAR * proto) { return(Vgetservbyname(name, proto)); } DWORD WINAPI getservbyport(int a,int b) { return(Vgetservbyport(a, b)); } DWORD WINAPI GetServiceA(int a,int b,int c,int d,int e,int f,int g) { return(VGetServiceA(a, b, c, d, e, f, g)); } DWORD WINAPI GetServiceW(int a,int b,int c,int d,int e,int f,int g) { return(VGetServiceW(a, b, c, d, e, f, g)); } DWORD WINAPI getsockname(int a,int b,int c) { return(Vgetsockname(a, b, c)); } DWORD WINAPI getsockopt(int a,int b,int c,int d,int e) { return(Vgetsockopt(a, b, c, d, e)); } DWORD WINAPI GetTypeByNameA(int a,int b) { return(VGetTypeByNameA(a, b)); } DWORD WINAPI GetTypeByNameW(int a,int b) { return(VGetTypeByNameW(a, b)); } DWORD WINAPI htonl(int a) { return(Vhtonl(a)); } DWORD WINAPI htons(int a) { return(Vhtons(a)); } DWORD WINAPI inet_addr(char *p) { return(Vinet_addr(p)); } DWORD WINAPI inet_network(int a) { return(Vinet_network(a)); } DWORD WINAPI inet_ntoa(int a) { return(Vinet_ntoa(a)); } DWORD WINAPI ioctlsocket(int s, long cmd, unsigned long *argp) { if (cmd == FIONBIO) { struct Sockets * So = FindSocket(s); if (So == NULL) { VWSASetLastError(WSAENOBUFS); LEAVE_MUTEX(); return SOCKET_ERROR; } So->Blocking = *argp ? 1 : 0; LEAVE_MUTEX(); } return Vioctlsocket(s, cmd, argp); } DWORD WINAPI listen(int a,int b) { return(Vlisten(a, b)); } DWORD WINAPI NPLoadNameSpaces(int a,int b,int c) { return(VNPLoadNameSpaces(a, b, c)); } DWORD WINAPI ntohl(int a) { return(Vntohl(a)); } DWORD WINAPI ntohs(int a) { return(Vntohs(a)); } DWORD WINAPI rcmd(int a,int b,int c,int d,int e,int f) { return(Vrcmd(a, b, c, d, e, f)); } DWORD WINAPI recv(int a,int b,int c,int d) { return(Vrecv(a, b, c, d)); } DWORD WINAPI recvfrom(int a,int b,int c,int d,int e,int f) { return(Vrecvfrom(a, b, c, d, e, f)); } DWORD WINAPI rexec(int a,int b,int c,int d,int e,int f) { return(Vrexec(a, b, c, d, e, f)); } DWORD WINAPI rresvport(int a) { return(Vrresvport(a)); } DWORD WINAPI s_perror(int a,int b) { return(Vs_perror(a, b)); } DWORD WINAPI select(int a,int b,int c,int d,int e) { return(Vselect(a, b, c, d, e)); } DWORD WINAPI send(int a,int b,int c,int d) { return(Vsend(a, b, c, d)); } DWORD WINAPI sendto(int a,int b,int c,int d,int e,int f) { return(Vsendto(a, b, c, d, e, f)); } DWORD WINAPI sethostname(int a,int b) { return(Vsethostname(a, b)); } DWORD WINAPI SetServiceA(int a,int b,int c,int d,int e,int f) { return(VSetServiceA(a, b, c, d, e, f)); } DWORD WINAPI SetServiceW(int a,int b,int c,int d,int e,int f) { return(VSetServiceW(a, b, c, d, e, f)); } DWORD WINAPI setsockopt( int s, int level, int optname, const char FAR * optval, int optlen ) /*++ Routine Description: If SO_SET_SOCKS_FIREWALL, create SOCKS information if it is new or changed from current, else pass on the request to wsock32!setsockopt() Arguments: s - socket on which to set option level - option type parameter (SO_SET_SOCKS_FIREWALL) optname - option type sub-parameter (SOCKS firewall port # in host format) optval - value to set (pointer to SOCKS information: DWORD ip address; LPSTR username ) optlen - length of value (8) Return Value: DWORD Success - 0 Failure - -1 --*/ { int rc; if (level != SO_SET_SOCKS_FIREWALL) { rc = Vsetsockopt(s, level, optname, optval, optlen); } else { struct Hosts * pHost; struct FirewallInfo { DWORD ipAddress; LPSTR userName; } * pInfo = (struct FirewallInfo *)optval; optname = Vhtons(optname); ENTER_MUTEX(); if (pHost = Head) { if ((pHost->ip != pInfo->ipAddress) || (pHost->port != optname) || (pHost->user && lstrcmp(pHost->user, pInfo->userName))) { //char buf[256]; //wsprintf(buf, // "throwing out: host: %d.%d.%d.%d:%d,%s; info: %d.%d.%d.%d:%d,%s\n", // pHost->ip & 0xff, // (pHost->ip >> 8) & 0xff, // (pHost->ip >> 16) & 0xff, // (pHost->ip >> 24) & 0xff, // Vhtons(pHost->port) & 0xffff, // pHost->user, // pInfo->ipAddress & 0xff, // (pInfo->ipAddress >> 8) & 0xff, // (pInfo->ipAddress >> 16) & 0xff, // (pInfo->ipAddress >> 24) & 0xff, // Vhtons(optname) & 0xffff, // pInfo->userName // ); //OutputDebugString(buf); LocalFree(pHost); pHost = NULL; } } if (!pHost) { int userlen = lstrlen(pInfo->userName) + 1; if (pHost = (struct Hosts *)LocalAlloc(LPTR, sizeof(struct Hosts) + userlen )) { memcpy(pHost + 1, pInfo->userName, userlen); pHost->user = (LPSTR)(pHost + 1); pHost->userlen = userlen; pHost->ip = pInfo->ipAddress; pHost->port = (unsigned short)optname; } } Head = pHost; if (pHost) { rc = 0; } else { VWSASetLastError(WSAENOBUFS); rc = SOCKET_ERROR; } LEAVE_MUTEX(); } return rc; } DWORD WINAPI shutdown(int a,int b) { return(Vshutdown(a, b)); } DWORD WINAPI socket(int af,int type,int protocol) { struct Sockets * So; int s; s = Vsocket(af, type, protocol); if (s != INVALID_SOCKET) { So = FindSocket(s); if (So) { So->type = type; } else { Vclosesocket(s); VWSASetLastError(WSAENOBUFS); s = INVALID_SOCKET; } LEAVE_MUTEX(); } return s; } DWORD WINAPI TransmitFile(int a,int b,int c,int d,int e,int f,int g) { return(VTransmitFile(a, b, c, d, e, f, g)); } DWORD WINAPI WEP() { return(VWEP()); } DWORD WINAPI WSAAsyncGetHostByAddr(int a,int b,int c,int d,int e,int f,int g) { return(VWSAAsyncGetHostByAddr(a, b, c, d, e, f, g)); } DWORD WINAPI WSAAsyncGetHostByName(int a,int b,int c,int d,int e) { return(VWSAAsyncGetHostByName(a, b, c, d, e)); } DWORD WINAPI WSAAsyncGetProtoByName(int a,int b,int c,int d,int e) { return(VWSAAsyncGetProtoByName(a, b, c, d, e)); } DWORD WINAPI WSAAsyncGetProtoByNumber(int a,int b,int c,int d,int e) { return(VWSAAsyncGetProtoByNumber(a, b, c, d, e)); } DWORD WINAPI WSAAsyncGetServByName(int a,int b,int c,int d,int e,int f) { return(VWSAAsyncGetServByName(a, b, c, d, e, f)); } DWORD WINAPI WSAAsyncGetServByPort(int a,int b,int c,int d,int e,int f) { return(VWSAAsyncGetServByPort(a, b, c, d, e, f)); } DWORD WINAPI WSAAsyncSelect(int s, HWND hWnd, unsigned int wMsg, long lEvent) { return(VWSAAsyncSelect(s,hWnd,wMsg,lEvent)); } DWORD WINAPI WSACancelAsyncRequest(int a) { return(VWSACancelAsyncRequest(a)); } DWORD WINAPI WSACancelBlockingCall() { return(VWSACancelBlockingCall()); } DWORD WINAPI WSACleanup() { return(VWSACleanup()); } DWORD WINAPI WSAGetLastError() { return(VWSAGetLastError()); } DWORD WINAPI WSAIsBlocking() { return(VWSAIsBlocking()); } DWORD WINAPI WSARecvEx(int a,int b,int c,int d) { return(VWSARecvEx(a, b, c, d)); } DWORD WINAPI WSASetBlockingHook(int a) { return(VWSASetBlockingHook(a)); } DWORD WINAPI WSASetLastError(int a) { return(VWSASetLastError(a)); } DWORD WINAPI WSAStartup(int a,int b) { return(VWSAStartup(a, b)); } DWORD WINAPI WSAUnhookBlockingHook() { return(VWSAUnhookBlockingHook()); } DWORD WINAPI WsControl(int a,int b,int c,int d,int e,int f) { return(VWsControl(a,b,c,d,e,f)); } DWORD WSHEnumProtocols(int a,int b, int c,int d) { return(VWSHEnumProtocols(a,b,c,d)); } //#ifdef DO_FILE_CONFIG // //void //ParseList(char *List,struct Server **Head,int IsSvr) { // // char *p; // char *p1; // char *pTok; // struct Server *tmp,*Current=NULL; // // *Head = NULL; // // if ( *(List+1) != '=') // return; // pTok = List+2; // List=StrTokEx(&pTok,"\t "); // p = StrTokEx(&List,","); // while ( p) { // if (IsSvr) { // tmp = (struct Server *)LocalAlloc(LPTR, (sizeof(struct Server))); // if ( tmp == NULL ) // return; // // p1 = strchr(p,':'); // if (p1) { // *p1++ = 0; // tmp->port = atoi(p1); // } // else // tmp->port = 1080; // } // else { // tmp = (struct Server *)LocalAlloc(LPTR, (sizeof(struct Server))); // if ( tmp == NULL ) // return; // } // tmp->Name = NewString(p); // tmp->Next = NULL; // if (Current == NULL) { // Current = *Head = tmp; // } // else { // Current->Next = tmp; // Current=tmp; // } // p = StrTokEx(&List,","); // } //} // // //void //LoadConfig(void) { // // struct Hosts *Current=NULL,*tmp; // char Buffer[1024]; // FILE *f; // char *p; // char *ServerList; // char *UserList; // struct Server *Default=NULL; // HKEY Key; // // GetSystemDirectory(Buffer,sizeof(Buffer)); // strcat(Buffer, "\\socks.cnf"); // f = fopen(Buffer,"rt"); // if ( f == NULL) // return; // if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\HummingBird", 0, KEY_QUERY_VALUE, &Key) == ERROR_SUCCESS) { // int Type, Length=sizeof(Buffer); // if ( RegQueryValueEx(Key, "SOCKS_SERVER", NULL, &Type, Buffer, &Length) == ERROR_SUCCESS) { // Buffer[Length] = '\0'; // Default=LocalAlloc(LPTR, sizeof(struct Server)); // if ( Default == NULL ) // return; // // p = strchr(Buffer,':'); // if (p) { // *p++ = 0; // Default->port = atoi(p); // } // else // Default->port = 1080; // Default->Name = NewString(Buffer); // Default->Next = NULL; // } // RegCloseKey(Key); // } // // while ( fgets(Buffer,sizeof(Buffer)-1,f) != NULL) { // Buffer[strlen(Buffer)-1]='\0'; // if ( Buffer[0] == '#') // continue; // tmp = (struct Hosts *) LocalAlloc(LPTR, sizeof(struct Hosts)); // if ( tmp == NULL ) // return; // // memset(tmp,0,sizeof(struct Hosts)); // ServerList=NULL; // UserList=NULL; // p = StrTokEx(&Buffer,"\t "); // if ( p == NULL) { // LocalFree(tmp); // continue; // } // if ( lstrcmpi(p,"DENY") == 0) { // tmp->type = DENY; // } else if (lstrcmpi(p,"DIRECT") == 0) { // tmp->type = DIRECT; // } else if (lstrcmpi(p,"SOCKD") == 0) { // tmp->type = SOCKD; // } else { // LocalFree(tmp); // continue; // } //LookMore: // p = StrTokEx(&Buffer,"\t "); // if ( p == NULL) { // LocalFree(tmp); // continue; // } // if (*p == '*') { // UserList=p; // goto LookMore; // } // if (*p == '@') { // ServerList=p; // goto LookMore; // } // tmp->dst = Vinet_addr(p); // p = StrTokEx(&Buffer,"\t "); // if ( p == NULL) { // LocalFree(tmp); // continue; // } // tmp->mask = Vinet_addr(p); // p = StrTokEx(&Buffer,"\t "); // if (p) { // if ( lstrcmpi(p,"EQ") == 0) // tmp->op = EQ; // else if ( lstrcmpi(p,"NEQ") == 0) // tmp->op = NEQ; // else if ( lstrcmpi(p,"LT") == 0) // tmp->op = LT; // else if ( lstrcmpi(p,"GT") == 0) // tmp->op = GT; // else if ( lstrcmpi(p,"LE") == 0) // tmp->op = LE; // else if ( lstrcmpi(p,"GE") == 0) // tmp->op = GE; // else { // LocalFree(tmp); // continue; // } // p = StrTokEx(&Buffer,"\t "); // if ( p == NULL) { // LocalFree(tmp); // continue; // } // if ( isdigit(*p)) // tmp->port = atoi(p); // else { // struct servent *se; // se=Vgetservbyname(p,"tcp"); // if ( se == NULL) { // LocalFree(tmp); // continue; // } // tmp->port = se->s_port; // } // } // if ( UserList) // ParseList(UserList,(struct Server **)&tmp->Users,0); // if ( ServerList) // ParseList(ServerList,&tmp->Servers,1); // if ( (tmp->type == SOCKD) && (tmp->Servers == NULL)) // tmp->Servers=Default; // if ( Current == NULL) { // Head = Current = tmp; // } // else { // Current->Next = tmp; // Current = tmp; // } // } // fclose(f); //} // //#endif HMODULE hModule = NULL; int LoadCount = 0; BOOL WINAPI DllMain( IN HINSTANCE hInstance, IN DWORD reason, IN LPVOID Reserved ) { HKEY hKey; TCHAR szRegBuf[MAX_PATH+1]; DWORD dwRegBufSize = sizeof(szRegBuf); DWORD dwRegType; LONG lResult; switch(reason) { case DLL_PROCESS_DETACH: if (LoadCount == 0) { DELETE_MUTEX(); return 1; } if (--LoadCount == 0) { FreeLibrary(hModule); } return 1; case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: if (++LoadCount == 1) { break; } default: return 1; } // Load an alternate Winsock DLL based on a registry value, // in the event that a customer wants to load a different wsock32. // if (ERROR_SUCCESS == (lResult = RegOpenKeyEx( HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), 0, KEY_QUERY_VALUE, &hKey ))) { if (ERROR_SUCCESS == (lResult = RegQueryValueEx( hKey, TEXT("AlternateWinsock"), NULL, &dwRegType, (LPBYTE) szRegBuf, &dwRegBufSize )) && dwRegType == REG_SZ) // only allow type REG_SZ { // Found a string, so try to load it as the alternate Winsock DLL. hModule = LoadLibrary(szRegBuf); } RegCloseKey(hKey); } if (lResult != ERROR_SUCCESS) { hModule = LoadLibrary("WSOCK32.DLL"); } if (hModule < (HMODULE) HINSTANCE_ERROR) { MessageBox(NULL, "Unable to find old WSOCK32.DLL named \"WSOCK32.DLL\".", "Microsoft/Hummingbird SOCKS Shim", MB_OK ); LoadCount = 0; return 0; } (FARPROC) VArecv=GetProcAddress(hModule,"Arecv"); (FARPROC) VAsend=GetProcAddress(hModule,"Asend"); (FARPROC) VEnumProtocolsA=GetProcAddress(hModule,"EnumProtocolsA"); (FARPROC) VEnumProtocolsW=GetProcAddress(hModule,"EnumProtocolsW"); (FARPROC) VGetAddressByNameA=GetProcAddress(hModule,"GetAddressByNameA"); (FARPROC) VGetAddressByNameW=GetProcAddress(hModule,"GetAddressByNameW"); (FARPROC) VGetNameByTypeA=GetProcAddress(hModule,"GetNameByTypeA"); (FARPROC) VGetNameByTypeW=GetProcAddress(hModule,"GetNameByTypeW"); (FARPROC) VGetServiceA=GetProcAddress(hModule,"GetServiceA"); (FARPROC) VGetServiceW=GetProcAddress(hModule,"GetServiceW"); (FARPROC) VGetTypeByNameA=GetProcAddress(hModule,"GetTypeByNameA"); (FARPROC) VGetTypeByNameW=GetProcAddress(hModule,"GetTypeByNameW"); (FARPROC) VNPLoadNameSpaces=GetProcAddress(hModule,"NPLoadNameSpaces"); (FARPROC) VSetServiceA=GetProcAddress(hModule,"SetServiceA"); (FARPROC) VSetServiceW=GetProcAddress(hModule,"SetServiceW"); (FARPROC) VTransmitFile=GetProcAddress(hModule,"TransmitFile"); (FARPROC) VWSAAsyncGetHostByAddr=GetProcAddress(hModule,"WSAAsyncGetHostByAddr"); (FARPROC) VWSAAsyncGetHostByName=GetProcAddress(hModule,"WSAAsyncGetHostByName"); (FARPROC) VWSAAsyncGetProtoByName=GetProcAddress(hModule,"WSAAsyncGetProtoByName"); (FARPROC) VWSAAsyncGetProtoByNumber=GetProcAddress(hModule,"WSAAsyncGetProtoByNumber"); (FARPROC) VWSAAsyncGetServByName=GetProcAddress(hModule,"WSAAsyncGetServByName"); (FARPROC) VWSAAsyncGetServByPort=GetProcAddress(hModule,"WSAAsyncGetServByPort"); (FARPROC) VWSAAsyncSelect=GetProcAddress(hModule,"WSAAsyncSelect"); (FARPROC) VWSACancelAsyncRequest=GetProcAddress(hModule,"WSACancelAsyncRequest"); (FARPROC) VWSACancelBlockingCall=GetProcAddress(hModule,"WSACancelBlockingCall"); (FARPROC) VWSACleanup=GetProcAddress(hModule,"WSACleanup"); (FARPROC) VWSAGetLastError=GetProcAddress(hModule,"WSAGetLastError"); (FARPROC) VWSAIsBlocking=GetProcAddress(hModule,"WSAIsBlocking"); (FARPROC) VWSARecvEx=GetProcAddress(hModule,"WSARecvEx"); (FARPROC) VWSASetBlockingHook=GetProcAddress(hModule,"WSASetBlockingHook"); (FARPROC) VWSASetLastError=GetProcAddress(hModule,"WSASetLastError"); (FARPROC) VWSAStartup=GetProcAddress(hModule,"WSAStartup"); (FARPROC) VWSAUnhookBlockingHook=GetProcAddress(hModule,"WSAUnhookBlockingHook"); (FARPROC) VWSHEnumProtocols=GetProcAddress(hModule,"WSHEnumProtocols"); (FARPROC) VWsControl=GetProcAddress(hModule,"WsControl"); (FARPROC) V__WSAFDIsSet=GetProcAddress(hModule,"__WSAFDIsSet"); (FARPROC) Vaccept=GetProcAddress(hModule,"accept"); (FARPROC) Vbind=GetProcAddress(hModule,"bind"); (FARPROC) Vclosesocket=GetProcAddress(hModule,"closesocket"); (FARPROC) Vclosesockinfo=GetProcAddress(hModule,"closesockinfo"); (FARPROC) Vconnect=GetProcAddress(hModule,"connect"); (FARPROC) Vdn_expand=GetProcAddress(hModule,"dn_expand"); (FARPROC) Vgethostbyaddr=GetProcAddress(hModule,"gethostbyaddr"); (FARPROC) Vgethostbyname=GetProcAddress(hModule,"gethostbyname"); (FARPROC) Vgethostname=GetProcAddress(hModule,"gethostname"); (FARPROC) Vgetnetbyname=GetProcAddress(hModule,"getnetbyname"); (FARPROC) Vgetpeername=GetProcAddress(hModule,"getpeername"); (FARPROC) Vgetprotobyname=GetProcAddress(hModule,"getprotobyname"); (FARPROC) Vgetprotobynumber=GetProcAddress(hModule,"getprotobynumber"); (FARPROC) Vgetservbyname=GetProcAddress(hModule,"getservbyname"); (FARPROC) Vgetservbyport=GetProcAddress(hModule,"getservbyport"); (FARPROC) Vgetsockname=GetProcAddress(hModule,"getsockname"); (FARPROC) Vgetsockopt=GetProcAddress(hModule,"getsockopt"); (FARPROC) Vhtonl=GetProcAddress(hModule,"htonl"); (FARPROC) Vhtons=GetProcAddress(hModule,"htons"); (FARPROC) Vinet_addr=GetProcAddress(hModule,"inet_addr"); (FARPROC) Vinet_network=GetProcAddress(hModule,"inet_network"); (FARPROC) Vinet_ntoa=GetProcAddress(hModule,"inet_ntoa"); (FARPROC) Vioctlsocket=GetProcAddress(hModule,"ioctlsocket"); (FARPROC) Vlisten=GetProcAddress(hModule,"listen"); (FARPROC) Vntohl=GetProcAddress(hModule,"ntohl"); (FARPROC) Vntohs=GetProcAddress(hModule,"ntohs"); (FARPROC) Vrcmd=GetProcAddress(hModule,"rcmd"); (FARPROC) Vrecv=GetProcAddress(hModule,"recv"); (FARPROC) Vrecvfrom=GetProcAddress(hModule,"recvfrom"); (FARPROC) Vrexec=GetProcAddress(hModule,"rexec"); (FARPROC) Vrresvport=GetProcAddress(hModule,"rresvport"); (FARPROC) Vs_perror=GetProcAddress(hModule,"s_perror"); (FARPROC) Vselect=GetProcAddress(hModule,"select"); (FARPROC) Vsend=GetProcAddress(hModule,"send"); (FARPROC) Vsendto=GetProcAddress(hModule,"sendto"); (FARPROC) Vsethostname=GetProcAddress(hModule,"sethostname"); (FARPROC) Vsetsockopt=GetProcAddress(hModule,"setsockopt"); (FARPROC) Vshutdown=GetProcAddress(hModule,"shutdown"); (FARPROC) Vsocket=GetProcAddress(hModule,"socket"); (FARPROC) VWEP=GetProcAddress(hModule,"WEP"); (FARPROC) VAcceptEx = GetProcAddress(hModule,"AcceptEx"); (FARPROC) VGetAcceptExSockaddrs = GetProcAddress(hModule,"GetAcceptExSockaddrs"); (FARPROC) VMigrateWinsockConfiguration = GetProcAddress(hModule,"MigrateWinsockConfiguration"); (FARPROC) VWSApSetPostRoutine = GetProcAddress(hModule,"WSApSetPostRoutine"); CREATE_MUTEX(); #ifdef DO_FILE_CONFIG LoadConfig(); #endif return 1; }