// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any later version. // // This software is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "cpp.h" #ifdef _WIN32 #include "boinc_win.h" #else #include "config.h" #include #ifdef HAVE_SYS_SOCKET_H #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #endif #include #include #include "error_numbers.h" #include "filesys.h" #include "util.h" #include "network.h" #include "client_msgs.h" #include "parse.h" #include "proxy.h" // Read the contents of the socket into buf // static int proxy_read_reply(int socket, char* buf, int len) { int i, n; for (i=0; i 0) { len = send(socket, buf+ret, size, 0); if ( len == -1 && errno != ) fatal("atomic_out() failed to send(), %d\n", socks_errno()); ret += len; size -= len; } return ret; } */ void print_buf( char *buf, int n ) { for (int i=0;iuse_http_proxy; strcpy(pi.http_user_name, new_pi->http_user_name); strcpy(pi.http_user_passwd, new_pi->http_user_passwd); strcpy(pi.http_server_name, new_pi->http_server_name); pi.http_server_port = new_pi->http_server_port; pi.use_http_auth = new_pi->use_http_auth; pi.use_socks_proxy = new_pi->use_socks_proxy; strcpy(pi.socks5_user_name, new_pi->socks5_user_name); strcpy(pi.socks5_user_passwd, new_pi->socks5_user_passwd); strcpy(pi.socks_server_name, new_pi->socks_server_name); pi.socks_server_port = new_pi->socks_server_port; pi.socks_version = new_pi->socks_version; return 0; } char *PROXY::get_proxy_server_name(char *regular_server) { if (pi.use_socks_proxy) return pi.socks_server_name; else if (pi.use_http_proxy) return pi.http_server_name; else return regular_server; } int PROXY::get_proxy_port(int regular_port) { if (pi.use_socks_proxy) return pi.socks_server_port; else if (pi.use_http_proxy) return pi.http_server_port; else return regular_port; } int PROXY::proxy_failed(int failure_code) { proxy_state = PROXY_STATE_DONE; proxy_retval = failure_code; return 0; } // Initialize proxy_data with a socks4 or socks5 connection request // see http://www.socks.nec.com/rfc/rfc1928.txt // see http://www.socks.nec.com/protocol/socks4.protocol // TODO: add support for GSSAPI authentication, IPv6 addresses, name -> IP resolution // One current problem is that the client may not fully read/write messages // to the server if buffers are full. proxy_atomic_send is an attempt to // compensate, it should be fully implemented and tested if this becomes a // significant issue. I'm not too worried though, since the messages are // always very small, and unlikely to cause space concerns (Eric Heien 3/26/04) // Check available methods on the socks server // int PROXY::socks_prepare_method_req(char *buf) { int nbytes = 0; char *marker = buf; if (pi.socks_version != SOCKS_VERSION_5) return ERR_SOCKS_UNKNOWN_FAILURE; nbytes = 3; *marker++ = SOCKS_VERSION_5; if (*pi.socks5_user_name && *pi.socks5_user_passwd) { *marker++ = 2; // 2 possible methods *marker++ = SOCKS_AUTH_USER_PASS; // user/pass nbytes++; } else { *marker++ = 1; // 1 possible method: } *marker++ = SOCKS_AUTH_NONE_NEEDED; // no authentication return nbytes; } int PROXY::socks_prepare_user_pass(char *buf) { int nbytes; char *marker = buf; if (pi.socks_version != SOCKS_VERSION_5) return ERR_SOCKS_UNKNOWN_FAILURE; // Send user and password *marker++ = SOCKS5_USER_SUBNEG_VERSION_1; *marker++ = strlen(pi.socks5_user_name); strncpy(marker, pi.socks5_user_name, strlen(pi.socks5_user_name)); marker += strlen(pi.socks5_user_name); *marker++ = strlen(pi.socks5_user_passwd); strncpy(marker, pi.socks5_user_passwd, strlen(pi.socks5_user_passwd)); nbytes = 1+1+strlen(pi.socks5_user_name)+1+strlen(pi.socks5_user_passwd); return nbytes; } int PROXY::socks_prepare_connect_req(char *buf, int ns_port, int ip_addr, char *domain_name) { int nbytes; char *marker = buf, *p; if (pi.socks_version == SOCKS_VERSION_4) { *marker++ = SOCKS_VERSION_4; *marker++ = 1; // Request connection p = (char*)&ns_port; // to this port for (int i=0;i<2;i++) *marker++ = *p++; p = (char*)&ip_addr; // at this IP address for (int i=0;i<4;i++) *marker++ = *p++; strncpy(marker, pi.socks5_user_name, strlen(pi.socks5_user_name)); nbytes = 1+1+2+4+strlen(pi.socks5_user_name); } else if (pi.socks_version == SOCKS_VERSION_5) { if (strlen(domain_name) > 255) return ERR_SOCKS_UNKNOWN_FAILURE; *marker++ = SOCKS_VERSION_5; *marker++ = 1; // request connection *marker++ = 0; // reserved nbytes = 3; if (strlen(domain_name) > 0) { nbytes += 2+strlen(domain_name); *marker++ = SOCKS5_ADDR_TYPE_DOMAIN_NAME; *marker++ = strlen(domain_name); p = domain_name; for (unsigned int i=0;i