#include <eggdrop/eggdrop.h>
#include <errno.h>
#include <netinet/in.h>
#include "proxy.h"
Go to the source code of this file.
Data Structures | |
struct | proxy_info_t |
Functions | |
static int | socks5_on_read (void *client_data, int idx, char *data, int len) |
static int | socks5_on_eof (void *client_data, int idx, int err, const char *errmsg) |
static int | socks5_on_connect (void *client_data, int idx, const char *peer_ip, int peer_port) |
static int | socks5_on_delete (event_owner_t *owner, void *client_data) |
static int | socks5_on_their_eof (void *client_data, int idx, int err, const char *errmsg) |
static int | socks5_on_their_delete (void *client_data, int idx) |
static void | socks5_err (proxy_info_t *info, int err, const char *errmsg) |
static void | send_connect_request (proxy_info_t *info) |
static void | socks5_auth_method (char *data, int len, proxy_info_t *info) |
static void | socks5_auth_reply (char *data, int len, proxy_info_t *info) |
static void | socks5_connect_reply (char *data, int len, proxy_info_t *info) |
int | socks5_reconnect (int idx, const char *host, int port) |
Variables | |
proxy_config_t | proxy_config |
event_owner_t | socks5_owner |
static sockbuf_handler_t | socks5_events |
static sockbuf_filter_t | delete_listener |
static void send_connect_request | ( | proxy_info_t * | info | ) | [static] |
Definition at line 60 of file socks5.c.
References proxy_info_t::host, proxy_info_t::our_idx, proxy_info_t::port, and sockbuf_write().
Referenced by socks5_auth_method(), and socks5_auth_reply().
00061 { 00062 char buf[512]; 00063 int len; 00064 unsigned short port; 00065 struct sockaddr_in addr; 00066 #ifdef IPV6 00067 struct sockaddr_in6 addr6; 00068 #endif 00069 00070 /* VER CMD RESERVED */ 00071 buf[0] = 5; buf[1] = 1; buf[2] = 0; 00072 00073 /* Try a regular ipv4 address first. */ 00074 /* FIXME: Check DO_IPV4 here? */ 00075 if (inet_pton(AF_INET, info->host, &addr) > 0) { 00076 buf[3] = 1; 00077 memcpy(buf+4, &addr.sin_addr, 4); 00078 len = 8; 00079 } 00080 #ifdef IPV6 00081 else if (inet_pton(AF_INET6, info->host, &addr6) > 0) { 00082 buf[3] = 4; 00083 memcpy(buf+4, &addr6.sin6_addr, 16); 00084 len = 20; 00085 } 00086 #endif 00087 else { 00088 buf[3] = 3; 00089 len = strlen(info->host) % 255; 00090 buf[4] = len; 00091 memcpy(buf+5, info->host, len); 00092 len += 5; 00093 } 00094 00095 port = htons(info->port); 00096 memcpy(buf+len, &port, 2); 00097 len += 2; 00098 00099 sockbuf_write(info->our_idx, buf, len); 00100 }
static void socks5_auth_method | ( | char * | data, | |
int | len, | |||
proxy_info_t * | info | |||
) | [static] |
Definition at line 106 of file socks5.c.
References proxy_info_t::our_idx, proxy_info_t::password, send_connect_request(), sockbuf_write(), socks5_err(), proxy_info_t::status, and proxy_info_t::username.
Referenced by socks5_on_read().
00107 { 00108 /* If it's a bad reply, abort. */ 00109 if (len < 2) { 00110 socks5_err(info, ECONNABORTED, "Invalid reply from SOCKS5 server"); 00111 return; 00112 } 00113 00114 if (data[0] != 5) { 00115 socks5_err(info, ECONNABORTED, "SOCKS5 server replied with SOCKS4 protocol"); 00116 return; 00117 } 00118 00119 if (data[1] == 0) { 00120 /* No auth required. */ 00121 send_connect_request(info); 00122 info->status = 3; 00123 } 00124 else if (data[1] == 2) { 00125 /* User/password authentication */ 00126 int ulen, plen; 00127 char buf[520]; 00128 00129 /* Username and password can be 255 max. */ 00130 if (info->username) ulen = strlen(info->username) % 255; 00131 else ulen = 0; 00132 if (info->password) plen = strlen(info->password) % 255; 00133 else plen = 0; 00134 00135 buf[0] = 1; 00136 buf[1] = ulen; 00137 memcpy(buf+2, info->username, ulen); 00138 buf[2+ulen] = plen; 00139 memcpy(buf+2+ulen+1, info->password, plen); 00140 sockbuf_write(info->our_idx, buf, 1+1+ulen+1+plen); 00141 info->status = 2; 00142 } 00143 else { 00144 /* We can't authenticate with this server, boo. */ 00145 socks5_err(info, ECONNABORTED, "SOCKS5 server doesn't accept our methods of authentication"); 00146 } 00147 return; 00148 }
static void socks5_auth_reply | ( | char * | data, | |
int | len, | |||
proxy_info_t * | info | |||
) | [static] |
Definition at line 152 of file socks5.c.
References send_connect_request(), socks5_err(), and proxy_info_t::status.
Referenced by socks5_on_read().
00153 { 00154 /* Abort if it's an invalid reply. */ 00155 if (len < 2) { 00156 socks5_err(info, ECONNABORTED, "Invalid reply from SOCKS5 server"); 00157 return; 00158 } 00159 00160 if (data[1] != 0) { 00161 /* Authentication failed! */ 00162 socks5_err(info, ECONNREFUSED, "SOCKS5 authentication failed"); 00163 } 00164 else { 00165 /* Send the connection request. */ 00166 send_connect_request(info); 00167 info->status = 3; 00168 } 00169 }
static void socks5_connect_reply | ( | char * | data, | |
int | len, | |||
proxy_info_t * | info | |||
) | [static] |
Definition at line 175 of file socks5.c.
References proxy_info_t::host, NULL, proxy_info_t::our_idx, proxy_info_t::port, sockbuf_delete(), sockbuf_detach_filter(), sockbuf_get_sock(), SOCKBUF_LEVEL_INTERNAL, sockbuf_on_connect(), sockbuf_set_sock(), socks5_err(), and proxy_info_t::their_idx.
Referenced by socks5_on_read().
00176 { 00177 int sock; 00178 00179 /* Abort if it's an invalid reply or the connection failed. */ 00180 /* It's actually supposed to be more than 2 bytes, but we only care 00181 about the 2nd field (status). */ 00182 00183 /* Here are the reply field definitions (from rfc1928) 00184 0 - success 00185 1 - general SOCKS server failure 00186 2 - connection not allowed by ruleset 00187 3 - network unreachable 00188 4 - host unreachable 00189 5 - connection refused 00190 6 - ttl expired 00191 7 - command not supported 00192 8 - address type not supported 00193 */ 00194 if (len < 2 || data[1] != 0) { 00195 char *errmsg; 00196 00197 if (len < 2) errmsg = "Invalid reply from SOCKS5 server"; 00198 else switch (data[1]) { 00199 case 1: errmsg = "SOCKS5 general server failure"; break; 00200 case 2: errmsg = "SOCKS5 connection now allowed by ruleset"; break; 00201 case 3: errmsg = "SOCKS5 network unreachable"; break; 00202 case 4: errmsg = "SOCKS5 host unreachable"; break; 00203 case 5: errmsg = "SOCKS5 connection refused"; break; 00204 case 6: errmsg = "SOCKS5 TTL expired"; break; 00205 case 7: errmsg = "SOCKS5 command not supported"; break; 00206 case 8: errmsg = "SOCKS5 address type not supported"; break; 00207 default: errmsg = "SOCKS5 unknown error"; 00208 } 00209 socks5_err(info, ECONNABORTED, errmsg); 00210 return; 00211 } 00212 00213 /* We're connected! Simulate a CONNECT event for the other idx. */ 00214 /* putlog(LOG_MISC, "*", "socks5 connected"); */ 00215 sockbuf_detach_filter(info->their_idx, &delete_listener, NULL); 00216 sock = sockbuf_get_sock(info->our_idx); 00217 sockbuf_set_sock(info->our_idx, -1, 0); 00218 sockbuf_set_sock(info->their_idx, sock, 0); 00219 sockbuf_on_connect(info->their_idx, SOCKBUF_LEVEL_INTERNAL, info->host, info->port); 00220 info->their_idx = -1; 00221 sockbuf_delete(info->our_idx); 00222 return; 00223 }
static void socks5_err | ( | proxy_info_t * | info, | |
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 47 of file socks5.c.
References NULL, proxy_info_t::our_idx, sockbuf_delete(), sockbuf_detach_filter(), SOCKBUF_LEVEL_INTERNAL, sockbuf_on_eof(), and proxy_info_t::their_idx.
Referenced by socks5_auth_method(), socks5_auth_reply(), socks5_connect_reply(), and socks5_on_eof().
00048 { 00049 /* putlog(LOG_MISC, "*", "socks5 err"); */ 00050 sockbuf_detach_filter(info->their_idx, &delete_listener, NULL); 00051 errno = err; 00052 sockbuf_on_eof(info->their_idx, SOCKBUF_LEVEL_INTERNAL, err, errmsg); 00053 info->their_idx = -1; 00054 sockbuf_delete(info->our_idx); 00055 }
static int socks5_on_connect | ( | void * | client_data, | |
int | idx, | |||
const char * | peer_ip, | |||
int | peer_port | |||
) | [static] |
Definition at line 300 of file socks5.c.
References proxy_info_t::password, sockbuf_write(), proxy_info_t::status, and proxy_info_t::username.
00301 { 00302 proxy_info_t *info = client_data; 00303 char both[] = "\005\002\002\000"; 00304 char anon[] = "\005\001\000"; 00305 00306 /* putlog(LOG_MISC, "*", "socks5 connected!"); */ 00307 /* Send the accepted auth methods (user/pass and/or none). */ 00308 if (info->username && info->password) sockbuf_write(idx, both, 4); 00309 else sockbuf_write(idx, anon, 3); 00310 info->status = 1; 00311 return(0); 00312 }
static int socks5_on_delete | ( | event_owner_t * | owner, | |
void * | client_data | |||
) | [static] |
Definition at line 259 of file socks5.c.
References proxy_info_t::host, NULL, proxy_info_t::password, sockbuf_detach_filter(), SOCKBUF_LEVEL_INTERNAL, sockbuf_on_eof(), proxy_info_t::their_idx, and proxy_info_t::username.
00260 { 00261 proxy_info_t *info = client_data; 00262 00263 /* putlog(LOG_MISC, "*", "socks5 deleted"); */ 00264 if (info->their_idx != -1) { 00265 int their_idx = info->their_idx; 00266 sockbuf_detach_filter(their_idx, &delete_listener, NULL); 00267 sockbuf_on_eof(their_idx, SOCKBUF_LEVEL_INTERNAL, ECONNREFUSED, "socks5 idx deleted unexpectedly!"); 00268 } 00269 free(info->host); 00270 if (info->username) free(info->username); 00271 if (info->password) free(info->password); 00272 free(info); 00273 return(0); 00274 }
static int socks5_on_eof | ( | void * | client_data, | |
int | idx, | |||
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 248 of file socks5.c.
References socks5_err().
00249 { 00250 proxy_info_t *info = client_data; 00251 if (!err) err = ECONNREFUSED; 00252 if (!errmsg) errmsg = "Unexpected EOF from SOCKS5 server"; 00253 socks5_err(info, err, errmsg); 00254 return(0); 00255 }
static int socks5_on_read | ( | void * | client_data, | |
int | idx, | |||
char * | data, | |||
int | len | |||
) | [static] |
Definition at line 227 of file socks5.c.
References socks5_auth_method(), socks5_auth_reply(), socks5_connect_reply(), and proxy_info_t::status.
00228 { 00229 proxy_info_t *info = client_data; 00230 00231 /* putlog(LOG_MISC, "*", "socks5 read, status = %d", info->status); */ 00232 switch (info->status) { 00233 case 1: 00234 socks5_auth_method(data, len, info); 00235 break; 00236 case 2: 00237 socks5_auth_reply(data, len, info); 00238 break; 00239 case 3: 00240 socks5_connect_reply(data, len, info); 00241 break; 00242 } 00243 return(0); 00244 }
static int socks5_on_their_delete | ( | void * | client_data, | |
int | idx | |||
) | [static] |
Definition at line 277 of file socks5.c.
References proxy_info_t::our_idx, sockbuf_delete(), and proxy_info_t::their_idx.
00278 { 00279 proxy_info_t *info = client_data; 00280 00281 info->their_idx = -1; 00282 sockbuf_delete(info->our_idx); 00283 return(0); 00284 }
static int socks5_on_their_eof | ( | void * | client_data, | |
int | idx, | |||
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 287 of file socks5.c.
References proxy_info_t::our_idx, sockbuf_delete(), and proxy_info_t::their_idx.
00288 { 00289 proxy_info_t *info = client_data; 00290 00291 info->their_idx = -1; 00292 sockbuf_delete(info->our_idx); 00293 return(0); 00294 }
int socks5_reconnect | ( | int | idx, | |
const char * | host, | |||
int | port | |||
) |
Definition at line 314 of file socks5.c.
References egg_client(), proxy_info_t::host, proxy_config_t::host, NULL, proxy_info_t::our_idx, proxy_config_t::password, proxy_info_t::password, proxy_info_t::port, proxy_config_t::port, sockbuf_attach_filter(), sockbuf_new(), sockbuf_set_handler(), proxy_info_t::status, str_redup(), proxy_info_t::their_idx, proxy_config_t::username, and proxy_info_t::username.
00315 { 00316 proxy_info_t *info; 00317 int our_idx; 00318 00319 if (!proxy_config.host) return(-1); 00320 00321 our_idx = egg_client(-1, proxy_config.host, proxy_config.port, NULL, 0, -1); 00322 00323 if (our_idx < 0) return(-1); 00324 00325 info = (proxy_info_t *)calloc(1, sizeof(*info)); 00326 info->host = strdup(host); 00327 info->port = port; 00328 str_redup(&info->username, proxy_config.username); 00329 str_redup(&info->password, proxy_config.password); 00330 info->status = 0; 00331 00332 info->our_idx = our_idx; 00333 if (idx >= 0) info->their_idx = idx; 00334 else info->their_idx = sockbuf_new(); 00335 00336 sockbuf_set_handler(info->our_idx, &socks5_events, info, &socks5_owner); 00337 sockbuf_attach_filter(info->their_idx, &delete_listener, info); 00338 00339 return(info->their_idx); 00340 }
sockbuf_filter_t delete_listener [static] |
Initial value:
{ "socks5 proxy", SOCKBUF_LEVEL_PROXY, NULL, socks5_on_their_eof, NULL, NULL, NULL, NULL, NULL, socks5_on_their_delete }
sockbuf_handler_t socks5_events [static] |
Initial value:
{ "socks5 proxy", socks5_on_connect, socks5_on_eof, NULL, socks5_on_read, NULL }
Initial value:
{ "proxy", NULL, NULL, NULL, socks5_on_delete }