Ejemplo n.º 1
0
static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, char *user, char *pass) {
	char *dns_name = NULL;
	char hostnamebuf[MSG_LEN_MAX];
	size_t dns_len = 0;

	PFUNC();

	// we use ip addresses with 224.* to lookup their dns name in our table, to allow remote DNS resolution
	// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
	// the results returned from gethostbyname et al.)
	// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
	if(ip.octet[0] == remote_dns_subnet) {
		dns_len = at_get_host_for_ip(ip, hostnamebuf);
		if(!dns_len) goto err;
		else dns_name = hostnamebuf;
	}
	
	PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");

	size_t ulen = strlen(user);
	size_t passlen = strlen(pass);

	if(ulen > 0xFF || passlen > 0xFF || dns_len > 0xFF) {
		proxychains_write_log(LOG_PREFIX "error: maximum size of 255 for user/pass or domain name!\n");
		goto err;
	}

	int len;
	unsigned char buff[BUFF_SIZE];
	char ip_buf[16];
	
	switch (pt) {
		case HTTP_TYPE:{
			if(!dns_len) {
				pc_stringfromipv4(&ip.octet[0], ip_buf);
				dns_name = ip_buf;
			}
			#define HTTP_AUTH_MAX ((0xFF * 2) + 1 + 1) /* 2 * 0xff: username and pass, plus 1 for ':' and 1 for zero terminator. */
			char src[HTTP_AUTH_MAX];
			char dst[(4 * HTTP_AUTH_MAX)];
			if(ulen) {
				snprintf(src, sizeof(src), "%s:%s", user, pass);
				encode_base_64(src, dst, sizeof(dst));
			} else dst[0] = 0;

			len = snprintf((char *) buff, sizeof(buff),
			               "CONNECT %s:%d HTTP/1.0\r\n%s%s%s\r\n",
			                dns_name,  ntohs(port),
			                ulen ? "Proxy-Authorization: Basic " : dst,
			                dst, ulen ? "\r\n" : dst);

			if(len != send(sock, buff, len, 0))
				goto err;

			len = 0;
			// read header byte by byte.
			while(len < BUFF_SIZE) {
				if(1 == read_n_bytes(sock, (char *) (buff + len), 1))
					len++;
				else
					goto err;
				if(len > 4 &&
				   buff[len - 1] == '\n' &&
				   buff[len - 2] == '\r' && buff[len - 3] == '\n' && buff[len - 4] == '\r')
					break;
			}

			// if not ok (200) or response greather than BUFF_SIZE return BLOCKED;
			if(len == BUFF_SIZE || !(buff[9] == '2' && buff[10] == '0' && buff[11] == '0')) {
				PDEBUG("HTTP proxy blocked: buff=\"%s\"\n", buff);
				return BLOCKED;
			}

			return SUCCESS;
		}
		break;
		case SOCKS4_TYPE:{
			buff[0] = 4;	// socks version
			buff[1] = 1;	// connect command
			memcpy(&buff[2], &port, 2);	// dest port
			if(dns_len) {
				ip.octet[0] = 0;
				ip.octet[1] = 0;
				ip.octet[2] = 0;
				ip.octet[3] = 1;
			}
			memcpy(&buff[4], &ip, 4);	// dest host
			len = ulen + 1;	// username
			if(len > 1)
				memcpy(&buff[8], user, len);
			else {
				buff[8] = 0;
			}

			// do socksv4a dns resolution on the server
			if(dns_len) {
				memcpy(&buff[8 + len], dns_name, dns_len + 1);
				len += dns_len + 1;
			}

			if((len + 8) != write_n_bytes(sock, (char *) buff, (8 + len)))
				goto err;

			if(8 != read_n_bytes(sock, (char *) buff, 8))
				goto err;

			if(buff[0] != 0 || buff[1] != 90)
				return BLOCKED;

			return SUCCESS;
		}
		break;
		case SOCKS5_TYPE:{
			int n_methods = ulen ? 2 : 1;
			buff[0] = 5;	// version
			buff[1] = n_methods ;	// number of methods
			buff[2] = 0;	// no auth method
			if(ulen) buff[3] = 2;    /// auth method -> username / password
			if(2+n_methods != write_n_bytes(sock, (char *) buff, 2+n_methods))
				goto err;

			if(2 != read_n_bytes(sock, (char *) buff, 2))
				goto err;

			if(buff[0] != 5 || (buff[1] != 0 && buff[1] != 2)) {
				if(buff[0] == 5 && buff[1] == 0xFF)
					return BLOCKED;
				else
					goto err;
			}

			if(buff[1] == 2) {
				// authentication
				char in[2];
				char out[515];
				char *cur = out;
				size_t c;
				*cur++ = 1;	// version
				c = ulen & 0xFF;
				*cur++ = c;
				memcpy(cur, user, c);
				cur += c;
				c = passlen & 0xFF;
				*cur++ = c;
				memcpy(cur, pass, c);
				cur += c;

				if((cur - out) != write_n_bytes(sock, out, cur - out))
					goto err;


				if(2 != read_n_bytes(sock, in, 2))
					goto err;
				if(in[0] != 1 || in[1] != 0) {
					if(in[0] != 1)
						goto err;
					else
						return BLOCKED;
				}
			}
			int buff_iter = 0;
			buff[buff_iter++] = 5;	// version
			buff[buff_iter++] = 1;	// connect
			buff[buff_iter++] = 0;	// reserved

			if(!dns_len) {
				buff[buff_iter++] = 1;	// ip v4
				memcpy(buff + buff_iter, &ip, 4);	// dest host
				buff_iter += 4;
			} else {
				buff[buff_iter++] = 3;	//dns
				buff[buff_iter++] = dns_len & 0xFF;
				memcpy(buff + buff_iter, dns_name, dns_len);
				buff_iter += dns_len;
			}

			memcpy(buff + buff_iter, &port, 2);	// dest port
			buff_iter += 2;


			if(buff_iter != write_n_bytes(sock, (char *) buff, buff_iter))
				goto err;

			if(4 != read_n_bytes(sock, (char *) buff, 4))
				goto err;

			if(buff[0] != 5 || buff[1] != 0)
				goto err;

			switch (buff[3]) {
				case 1:
					len = 4;
					break;
				case 4:
					len = 16;
					break;
				case 3:
					len = 0;
					if(1 != read_n_bytes(sock, (char *) &len, 1))
						goto err;
					break;
				default:
					goto err;
			}

			if(len + 2 != read_n_bytes(sock, (char *) buff, len + 2))
				goto err;

			return SUCCESS;
		}
		break;
	}

	err:
	return SOCKET_ERROR;
}
Ejemplo n.º 2
0
static int tunnel_to(int sock, unsigned int ip, unsigned short port, proxy_type pt,char *user,char *pass)
{
        int len;
        char buff[BUFF_SIZE];
        bzero (buff,sizeof(buff));
        switch(pt)
        {
        	case HTTP_TYPE:
         		{
             		sprintf(buff,"CONNECT %s:%d HTTP/1.0\r\n",
			        inet_ntoa( * (struct in_addr *) &ip),
			        ntohs(port));
           			if (user[0])
                		{
					char src[256];
     					char dst[512];
					strcpy(src,user);
					strcat(src,":");
					strcat(src,pass);
					encode_base_64(src,dst,512);
					strcat(buff,"Proxy-Authorization: Basic ");
					strcat(buff,dst);
					strcat(buff,"\r\n\r\n");
				}
    				else
					strcat(buff,"\r\n");
			
           			len=strlen(buff);

			        if(len!=send(sock,buff,len,0))
			                return SOCKET_ERROR;
			
           			bzero(buff,sizeof(buff));
                        len=0 ;
      			 // read header byte by byte.
			       while(len<BUFF_SIZE)
			       {
			                if(1==read_n_bytes(sock,buff+len,1))
			                        len++;
			                else
			                        return SOCKET_ERROR;
			                if (    len > 4     &&
		                        	buff[len-1]=='\n'  &&
			                        buff[len-2]=='\r'  &&
			                        buff[len-3]=='\n'  &&
			                        buff[len-4]=='\r'  )
		                        break;
			       }

			       // if not ok (200) or response greather than BUFF_SIZE return BLOCKED;
			       if (     (len==BUFF_SIZE)  ||
			                ! (     buff[9] =='2'         &&
			                        buff[10]=='0'        &&
			                        buff[11]=='0'         ))
                                  return BLOCKED;
			       return SUCCESS;
           		}
            	break;
            case SOCKS4_TYPE:
            	{
               		memset(buff,0,sizeof(buff));
                 		buff[0]=4; // socks version
  				buff[1]=1; // connect command
				memcpy(&buff[2],&port,2); // dest port
				memcpy(&buff[4],&ip,4); // dest host
				len=strlen(user)+1; // username
    				if(len>1)	
         				strcpy(&buff[8],user);
				if((len+8)!=write_n_bytes(sock,buff,(8+len)))
					return SOCKET_ERROR;

 				if(8!=read_n_bytes(sock,buff,8))
					return SOCKET_ERROR;
            	
				if (buff[0]!=0||buff[1]!=90)
					return BLOCKED;
     				
         			return SUCCESS;
               	}
                	break;
            case SOCKS5_TYPE:
            	{
               		if(user)
                 		{
                 			buff[0]=5;   //version
					buff[1]=2;	//nomber of methods
					buff[2]=0;   // no auth method
	    				buff[3]=2;  /// auth method -> username / password
                              if(4!=write_n_bytes(sock,buff,4))
					 	return SOCKET_ERROR;
       			}
            		else
                		{
            			buff[0]=5;   //version
					buff[1]=1;	//nomber of methods
					buff[2]=0;   // no auth method
                              if(3!=write_n_bytes(sock,buff,3))
					 	return SOCKET_ERROR;
       			}

				memset(buff,0,sizeof(buff));

				if(2!=read_n_bytes(sock,buff,2))
			 		return SOCKET_ERROR;
			
      			if (buff[0]!=5||(buff[1]!=0&&buff[1]!=2))
         			{
        				if((buff[0]==0x05)&&(buff[1]==(char)0xFF))
             						return BLOCKED;
						else
							return SOCKET_ERROR;
          			}
          			
          			if (buff[1]==2)
               		{
					// authentication
					char in[2];
     					char out[515]; char* cur=out;
					int c;
     					*cur++=1; // version
					c=strlen(user);
					*cur++=c;
					strncpy(cur,user,c);
					cur+=c;
					c=strlen(pass);
					*cur++=c;
					strncpy(cur,pass,c);
					cur+=c;
					
     					if((cur-out)!=write_n_bytes(sock,out,cur-out))
					 	return SOCKET_ERROR;
     					
          				
					if(2!=read_n_bytes(sock,in,2))
			 			return SOCKET_ERROR;
					if(in[0]!=1||in[1]!=0)
       				{
						if(in[0]!=1)
      						return SOCKET_ERROR;
						else
      						return BLOCKED;
					}
				}	

     				buff[0]=5;       // version
				buff[1]=1;       // connect
				buff[2]=0;       // reserved
				buff[3]=1;       // ip v4

			 	memcpy(&buff[4],&ip,4); // dest host
				memcpy(&buff[8],&port,2); // dest port
				

			      if(10!=write_n_bytes(sock,buff,10))
					return SOCKET_ERROR;
		
			      if(4!=read_n_bytes(sock,buff,4))
					return SOCKET_ERROR;

				if (buff[0]!=5||buff[1]!=0)
			      	return SOCKET_ERROR;

			  	switch (buff[3])
			      {
					case 1: len=4;  break;
					case 4: len=16; break;
					case 3: len=0;
			  			if(1!=read_n_bytes(sock,(char*)&len,1))
			 				return SOCKET_ERROR;
        					break;
					default:
						return SOCKET_ERROR;
				}

     				if((len+2)!=read_n_bytes(sock,buff,(len+2)))
					return SOCKET_ERROR;

				return SUCCESS;
                	}
                	break;	

        }

return SOCKET_ERROR;
}