modules/proxy/socks5.c File Reference

#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


Function Documentation

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 }


Variable Documentation

Initial value:

 {
  "socks5 proxy",
  SOCKBUF_LEVEL_PROXY,
  NULL, socks5_on_their_eof, NULL,
  NULL, NULL, NULL,
  NULL, socks5_on_their_delete
}

Definition at line 37 of file socks5.c.

Definition at line 8 of file proxy.c.

Referenced by http_reconnect().

Initial value:

 {
  "socks5 proxy",
  socks5_on_connect, socks5_on_eof, NULL,
  socks5_on_read, NULL
}

Definition at line 31 of file socks5.c.

Initial value:

 {
  "proxy", NULL,
  NULL, NULL,
  socks5_on_delete
}

Definition at line 25 of file socks5.c.


Generated on Sun Nov 30 18:43:36 2008 for eggdrop1.9 by  doxygen 1.5.6