diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-17 21:56:50 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2005-12-17 21:56:50 +0100 |
commit | 7c0a4975a538ab75405e64919bbdfee51b898b2e (patch) | |
tree | 47d211522bbed3fda3b33b0233e91e3cf5cb9e23 | |
parent | b5a22e33a1aa2500093e783e79de2f44bf53c150 (diff) | |
parent | ad8b8a367c8e5dd2816096959682e2187df07c6c (diff) |
Moved HTTP-stuff (right now only for passport) into a separate module. This
all works 100% asynchronous and non-blocking, so almost all I/O in BitlBee
should be completely non-blocking now!
Right now support for other modules than GnuTLS is probably broken, I'll fix
it later.
-rw-r--r-- | protocols/Makefile | 2 | ||||
-rw-r--r-- | protocols/http_client.c | 382 | ||||
-rw-r--r-- | protocols/http_client.h | 54 | ||||
-rw-r--r-- | protocols/msn/ns.c | 2 | ||||
-rw-r--r-- | protocols/msn/passport.c | 306 | ||||
-rw-r--r-- | protocols/msn/passport.h | 6 | ||||
-rw-r--r-- | protocols/proxy.c | 2 | ||||
-rw-r--r-- | protocols/ssl_bogus.c | 2 | ||||
-rw-r--r-- | protocols/ssl_client.h | 5 | ||||
-rw-r--r-- | protocols/ssl_gnutls.c | 33 | ||||
-rw-r--r-- | protocols/ssl_nss.c | 4 | ||||
-rw-r--r-- | protocols/ssl_openssl.c | 4 | ||||
-rw-r--r-- | sock.h | 3 | ||||
-rw-r--r-- | url.c | 48 | ||||
-rw-r--r-- | url.h | 3 |
15 files changed, 592 insertions, 264 deletions
diff --git a/protocols/Makefile b/protocols/Makefile index c5f938fd..1ed6b52e 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = md5.o nogaim.o proxy.o sha.o util.o $(SSL_CLIENT) +objects = http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) util.o # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into diff --git a/protocols/http_client.c b/protocols/http_client.c new file mode 100644 index 00000000..51424e1c --- /dev/null +++ b/protocols/http_client.c @@ -0,0 +1,382 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* HTTP(S) module */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <string.h> +#include <stdio.h> + +#include "sock.h" +#include "http_client.h" +#include "url.h" + + +static void http_connected( gpointer data, int source, GaimInputCondition cond ); +static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond ); +static void http_incoming_data( gpointer data, int source, GaimInputCondition cond ); + + +void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) +{ + struct http_request *req; + int error = 0; + + req = g_new0( struct http_request, 1 ); + + if( ssl ) + { + req->ssl = ssl_connect( host, port, http_ssl_connected, req ); + if( req->ssl == NULL ) + error = 1; + } + else + { + req->fd = proxy_connect( host, port, http_connected, req ); + if( req->fd < 0 ) + error = 1; + } + + if( error ) + { + g_free( req ); + return( NULL ); + } + + req->func = func; + req->data = data; + req->request = g_strdup( request ); + req->request_length = strlen( request ); + + return( req ); +} + +/* This one is actually pretty simple... Might get more calls if we can't write + the whole request at once. */ +static void http_connected( gpointer data, int source, GaimInputCondition cond ) +{ + struct http_request *req = data; + int st; + + if( source < 0 ) + goto error; + + if( req->inpa > 0 ) + gaim_input_remove( req->inpa ); + + sock_make_nonblocking( req->fd ); + + if( req->ssl ) + { + st = ssl_write( req->ssl, req->request + req->bytes_written, + req->request_length - req->bytes_written ); + if( st < 0 ) + { + if( ssl_errno != SSL_AGAIN ) + { + ssl_disconnect( req->ssl ); + goto error; + } + } + } + else + { + st = write( source, req->request + req->bytes_written, + req->request_length - req->bytes_written ); + if( st < 0 ) + { + if( !sockerr_again() ) + { + closesocket( req->fd ); + goto error; + } + } + } + + if( st > 0 ) + req->bytes_written += st; + + if( req->bytes_written < req->request_length ) + req->inpa = gaim_input_add( source, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE, + http_connected, req ); + else + req->inpa = gaim_input_add( source, GAIM_INPUT_READ, http_incoming_data, req ); + + return; + +error: + req->func( req ); + + g_free( req->request ); + g_free( req ); + + return; +} + +static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond ) +{ + struct http_request *req = data; + + if( source == NULL ) + return http_connected( data, -1, cond ); + + req->fd = ssl_getfd( source ); + + return http_connected( data, req->fd, cond ); +} + +static void http_incoming_data( gpointer data, int source, GaimInputCondition cond ) +{ + struct http_request *req = data; + int evil_server = 0; + char buffer[2048]; + char *end1, *end2; + int st; + + if( req->inpa > 0 ) + gaim_input_remove( req->inpa ); + + if( req->ssl ) + { + st = ssl_read( req->ssl, buffer, sizeof( buffer ) ); + if( st < 0 ) + { + if( ssl_errno != SSL_AGAIN ) + { + /* goto cleanup; */ + + /* YAY! We have to deal with crappy Microsoft + servers that LOVE to send invalid TLS + packets that abort connections! \o/ */ + + goto got_reply; + } + } + else if( st == 0 ) + { + goto got_reply; + } + } + else + { + st = read( req->fd, buffer, sizeof( buffer ) ); + if( st < 0 ) + { + if( !sockerr_again() ) + { + goto cleanup; + } + } + else if( st == 0 ) + { + goto got_reply; + } + } + + if( st > 0 ) + { + req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 ); + memcpy( req->reply_headers + req->bytes_read, buffer, st ); + req->bytes_read += st; + } + + /* There will be more! */ + req->inpa = gaim_input_add( req->fd, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ, + http_incoming_data, req ); + + return; + +got_reply: + /* Zero termination is very convenient. */ + req->reply_headers[req->bytes_read] = 0; + + /* Find the separation between headers and body, and keep stupid + webservers in mind. */ + end1 = strstr( req->reply_headers, "\r\n\r\n" ); + end2 = strstr( req->reply_headers, "\n\n" ); + + if( end2 && end2 < end1 ) + { + end1 = end2 + 1; + evil_server = 1; + } + else + { + end1 += 2; + } + + if( end1 ) + { + *end1 = 0; + + if( evil_server ) + req->reply_body = end1 + 1; + else + req->reply_body = end1 + 2; + } + + if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) + { + if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 ) + req->status_code = -1; + } + else + { + req->status_code = -1; + } + + if( req->status_code == 301 || req->status_code == 302 ) + { + char *loc, *new_request, *new_host; + int error = 0, new_port, new_proto; + + loc = strstr( req->reply_headers, "\nLocation: " ); + if( loc == NULL ) /* We can't handle this redirect... */ + goto cleanup; + + loc += 11; + while( *loc == ' ' ) + loc ++; + + /* TODO/FIXME: Possibly have to handle relative redirections, + and rewrite Host: headers. Not necessary for now, it's + enough for passport authentication like this. */ + + if( *loc == '/' ) + { + /* Just a different pathname... */ + + /* Since we don't cache the servername, and since we + don't need this yet anyway, I won't implement it. */ + + goto cleanup; + } + else + { + /* A whole URL */ + url_t *url; + char *s; + + s = strstr( loc, "\r\n" ); + if( s == NULL ) + goto cleanup; + + url = g_new0( url_t, 1 ); + *s = 0; + + if( !url_set( url, loc ) ) + { + g_free( url ); + goto cleanup; + } + + /* Okay, this isn't fun! We have to rebuild the request... :-( */ + new_request = g_malloc( req->request_length + strlen( url->file ) ); + + /* So, now I just allocated enough memory, so I'm + going to use strcat(), whether you like it or not. :-) */ + + /* First, find the GET/POST/whatever from the original request. */ + s = strchr( req->request, ' ' ); + if( s == NULL ) + { + g_free( new_request ); + g_free( url ); + goto cleanup; + } + + *s = 0; + sprintf( new_request, "%s %s HTTP/1.0\r\n", req->request, url->file ); + *s = ' '; + + s = strstr( req->request, "\r\n" ); + if( s == NULL ) + { + g_free( new_request ); + g_free( url ); + goto cleanup; + } + + strcat( new_request, s + 2 ); + new_host = g_strdup( url->host ); + new_port = url->port; + new_proto = url->proto; + + g_free( url ); + } + + if( req->ssl ) + ssl_disconnect( req->ssl ); + else + closesocket( req->fd ); + + req->fd = -1; + req->ssl = 0; + + if( new_proto == PROTO_HTTPS ) + { + req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req ); + if( req->ssl == NULL ) + error = 1; + } + else + { + req->fd = proxy_connect( new_host, new_port, http_connected, req ); + if( req->fd < 0 ) + error = 1; + } + g_free( new_host ); + + if( error ) + { + g_free( new_request ); + goto cleanup; + } + + g_free( req->request ); + g_free( req->reply_headers ); + req->request = new_request; + req->request_length = strlen( new_request ); + req->bytes_read = req->bytes_written = req->inpa = 0; + req->reply_headers = req->reply_body = NULL; + + return; + } + + /* Assume that a closed connection means we're finished, this indeed + breaks with keep-alive connections and faulty connections. */ + req->finished = 1; + +cleanup: + if( req->ssl ) + ssl_disconnect( req->ssl ); + else + closesocket( req->fd ); + + req->func( req ); + + g_free( req->request ); + g_free( req->reply_headers ); + g_free( req ); +} diff --git a/protocols/http_client.h b/protocols/http_client.h new file mode 100644 index 00000000..53c6fcd6 --- /dev/null +++ b/protocols/http_client.h @@ -0,0 +1,54 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* HTTP(S) module */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <glib.h> + +#include "ssl_client.h" + +struct http_request; + +typedef void (*http_input_function)( struct http_request * ); + +struct http_request +{ + char *request; + int request_length; + int status_code; + char *reply_headers; + char *reply_body; + int finished; + + void *ssl; + int fd; + + int inpa; + int bytes_written; + int bytes_read; + + http_input_function func; + gpointer data; +}; + +void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f1bda1a4..2d90b2f3 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -207,7 +207,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* Time for some Passport black magic... */ - if( !passport_get_id( gc, gc->username, gc->password, cmd[4], msn_auth_got_passport_id ) ) + if( !passport_get_id( msn_auth_got_passport_id, gc, gc->username, gc->password, cmd[4] ) ) { hide_login_progress_error( gc, "Error while contacting Passport server" ); signoff( gc ); diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 640126a0..e04d14cb 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -19,7 +19,7 @@ * */ -#include "ssl_client.h" +#include "http_client.h" #include "passport.h" #include "msn.h" #include "bitlbee.h" @@ -30,34 +30,91 @@ static char *prd_cached = NULL; -static char *passport_create_header( char *reply, char *email, char *pwd ); +static int passport_get_id_real( gpointer func, gpointer data, char *header ); +static void passport_get_id_ready( struct http_request *req ); + static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ); -static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond ); -static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url ); -static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond ); -static void destroy_reply( struct passport_reply *rep ); +static void passport_retrieve_dalogin_ready( struct http_request *req ); +static char *passport_create_header( char *cookie, char *email, char *pwd ); +static void destroy_reply( struct passport_reply *rep ); -int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func ) +int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ) { char *header = passport_create_header( cookie, username, password ); - if( prd_cached ) - { - int st; - - st = passport_get_id_from( data, func, header, prd_cached ); - g_free( header ); - return( st ); - } + if( prd_cached == NULL ) + return passport_retrieve_dalogin( func, data, header ); else + return passport_get_id_real( func, data, header ); +} + +static int passport_get_id_real( gpointer func, gpointer data, char *header ) +{ + struct passport_reply *rep; + char *server, *dummy, *reqs; + struct http_request *req; + + rep = g_new0( struct passport_reply, 1 ); + rep->data = data; + rep->func = func; + + server = g_strdup( prd_cached ); + dummy = strchr( server, '/' ); + + if( dummy == NULL ) { - return( passport_retrieve_dalogin( data, func, header ) ); + destroy_reply( rep ); + return( 0 ); } + + reqs = g_malloc( strlen( header ) + strlen( dummy ) + 128 ); + sprintf( reqs, "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); + + *dummy = 0; + req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep ); + + g_free( server ); + g_free( reqs ); + + if( req == NULL ) + destroy_reply( rep ); + + return( req != NULL ); } +static void passport_get_id_ready( struct http_request *req ) +{ + struct passport_reply *rep = req->data; + + if( !g_slist_find( msn_connections, rep->data ) ) + { + destroy_reply( rep ); + return; + } + + if( req->status_code == 200 ) + { + char *dummy; + + if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) ) + { + char *responseend; + + dummy += strlen( "from-PP='" ); + responseend = strchr( dummy, '\'' ); + if( responseend ) + *responseend = 0; + + rep->result = g_strdup( dummy ); + } + } + + rep->func( rep ); + destroy_reply( rep ); +} -static char *passport_create_header( char *reply, char *email, char *pwd ) +static char *passport_create_header( char *cookie, char *email, char *pwd ) { char *buffer = g_new0( char, 2048 ); char *currenttoken; @@ -71,7 +128,7 @@ static char *passport_create_header( char *reply, char *email, char *pwd ) strcpy( pwd_enc, pwd ); http_encode( pwd_enc ); - currenttoken = strstr( reply, "lc=" ); + currenttoken = strstr( cookie, "lc=" ); if( currenttoken == NULL ) return( NULL ); @@ -87,227 +144,68 @@ static char *passport_create_header( char *reply, char *email, char *pwd ) return( buffer ); } - -static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ) +#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n" +static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) { struct passport_reply *rep = g_new0( struct passport_reply, 1 ); - void *ssl; + struct http_request *req; rep->data = data; rep->func = func; rep->header = header; - ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep ); + req = http_dorequest( "nexus.passport.com", 443, 1, PPR_REQUEST, passport_retrieve_dalogin_ready, rep ); - if( !ssl ) + if( !req ) destroy_reply( rep ); - return( ssl != NULL ); + return( req != NULL ); } -#define PPR_BUFFERSIZE 2048 -#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n" -static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond ) +static void passport_retrieve_dalogin_ready( struct http_request *req ) { - int ret; - char buffer[PPR_BUFFERSIZE+1]; - struct passport_reply *rep = data; + struct passport_reply *rep = req->data; + char *dalogin; + char *urlend; if( !g_slist_find( msn_connections, rep->data ) ) { - if( ssl ) ssl_disconnect( ssl ); destroy_reply( rep ); return; } - if( !ssl ) - { - rep->func( rep ); - destroy_reply( rep ); - return; - } - - ssl_write( ssl, PPR_REQUEST, strlen( PPR_REQUEST ) ); + dalogin = strstr( req->reply_headers, "DALogin=" ); - if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 ) - { + if( !dalogin ) goto failure; - } - - { - char *dalogin = strstr( buffer, "DALogin=" ); - char *urlend; - - if( !dalogin ) - goto failure; - - dalogin += strlen( "DALogin=" ); - urlend = strchr( dalogin, ',' ); - if( urlend ) - *urlend = 0; - - /* strip the http(s):// part from the url */ - urlend = strstr( urlend, "://" ); - if( urlend ) - dalogin = urlend + strlen( "://" ); - - if( prd_cached == NULL ) - prd_cached = g_strdup( dalogin ); - } - - if( passport_get_id_from( rep->data, rep->func, rep->header, prd_cached ) ) - { - ssl_disconnect( ssl ); - destroy_reply( rep ); - return; - } -failure: - ssl_disconnect( ssl ); - rep->func( rep ); - destroy_reply( rep ); -} - - -static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url ) -{ - struct passport_reply *rep = g_new0( struct passport_reply, 1 ); - char server[512], *dummy; - void *ssl; - - rep->data = data; - rep->func = func; - rep->redirects = 4; - - strncpy( server, url, 512 ); - dummy = strchr( server, '/' ); - if( dummy ) - *dummy = 0; - - ssl = ssl_connect( server, 443, passport_get_id_connected, rep ); - - if( ssl ) - { - rep->header = g_strdup( header_i ); - rep->url = g_strdup( url ); - } - else - { - destroy_reply( rep ); - } + dalogin += strlen( "DALogin=" ); + urlend = strchr( dalogin, ',' ); + if( urlend ) + *urlend = 0; - return( ssl != NULL ); -} - -#define PPG_BUFFERSIZE 4096 -static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond ) -{ - struct passport_reply *rep = data; - char server[512], buffer[PPG_BUFFERSIZE+1], *dummy; - int ret; + /* strip the http(s):// part from the url */ + urlend = strstr( urlend, "://" ); + if( urlend ) + dalogin = urlend + strlen( "://" ); - if( !g_slist_find( msn_connections, rep->data ) ) - { - if( ssl ) ssl_disconnect( ssl ); - destroy_reply( rep ); - return; - } + if( prd_cached == NULL ) + prd_cached = g_strdup( dalogin ); - if( !ssl ) + if( passport_get_id_real( rep->func, rep->data, rep->header ) ) { - rep->func( rep ); destroy_reply( rep ); return; } - memset( buffer, 0, PPG_BUFFERSIZE + 1 ); - - strncpy( server, rep->url, 512 ); - dummy = strchr( server, '/' ); - if( dummy == NULL ) - goto end; - - g_snprintf( buffer, PPG_BUFFERSIZE - 1, "GET %s HTTP/1.0\r\n" - "%s\r\n\r\n", dummy, rep->header ); - - ssl_write( ssl, buffer, strlen( buffer ) ); - memset( buffer, 0, PPG_BUFFERSIZE + 1 ); - - { - char *buffer2 = buffer; - - while( ( ( ret = ssl_read( ssl, buffer2, 512 ) ) > 0 ) && - ( buffer + PPG_BUFFERSIZE - buffer2 - ret - 512 >= 0 ) ) - { - buffer2 += ret; - } - } - - if( *buffer == 0 ) - goto end; - - if( ( dummy = strstr( buffer, "Location:" ) ) ) - { - char *urlend; - - rep->redirects --; - if( rep->redirects == 0 ) - goto end; - - dummy += strlen( "Location:" ); - while( isspace( *dummy ) ) dummy ++; - urlend = dummy; - while( !isspace( *urlend ) ) urlend ++; - *urlend = 0; - if( ( urlend = strstr( dummy, "://" ) ) ) - dummy = urlend + strlen( "://" ); - - g_free( rep->url ); - rep->url = g_strdup( dummy ); - - strncpy( server, dummy, sizeof( server ) - 1 ); - dummy = strchr( server, '/' ); - if( dummy ) *dummy = 0; - - ssl_disconnect( ssl ); - - if( ssl_connect( server, 443, passport_get_id_connected, rep ) ) - { - return; - } - else - { - rep->func( rep ); - destroy_reply( rep ); - return; - } - } - else if( strstr( buffer, "200 OK" ) ) - { - if( ( dummy = strstr( buffer, "from-PP='" ) ) ) - { - char *responseend; - - dummy += strlen( "from-PP='" ); - responseend = strchr( dummy, '\'' ); - if( responseend ) - *responseend = 0; - - rep->result = g_strdup( dummy ); - } - } - -end: - ssl_disconnect( ssl ); +failure: rep->func( rep ); destroy_reply( rep ); } - static void destroy_reply( struct passport_reply *rep ) { - if( rep->result ) g_free( rep->result ); - if( rep->url ) g_free( rep->url ); - if( rep->header ) g_free( rep->header ); - if( rep ) g_free( rep ); + g_free( rep->result ); + g_free( rep->header ); + g_free( rep ); } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 63fef2e9..f7e6ebb6 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -34,14 +34,12 @@ struct passport_reply { + void (*func)( struct passport_reply * ); void *data; char *result; - void (*func)( struct passport_reply * ); - char *url; char *header; - int redirects; }; -int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func ); +int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ); #endif /* __PASSPORT_H__ */ diff --git a/protocols/proxy.c b/protocols/proxy.c index c658a163..1ca35dfe 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -105,8 +105,6 @@ static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpoin gaim_cond |= GAIM_INPUT_READ; if (condition & GAIM_WRITE_COND) gaim_cond |= GAIM_INPUT_WRITE; -// if (condition & GAIM_ERR_COND) -// fprintf( stderr, "ERROR! fd=%d\n", g_io_channel_unix_get_fd( source ) ); closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); diff --git a/protocols/ssl_bogus.c b/protocols/ssl_bogus.c index 1ee0df4c..3766baaa 100644 --- a/protocols/ssl_bogus.c +++ b/protocols/ssl_bogus.c @@ -27,7 +27,7 @@ int ssl_errno; -void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { return( NULL ); } diff --git a/protocols/ssl_client.h b/protocols/ssl_client.h index 719cd0c4..89189db9 100644 --- a/protocols/ssl_client.h +++ b/protocols/ssl_client.h @@ -32,10 +32,11 @@ extern int ssl_errno; -typedef void (*SslInputFunction)(gpointer, void*, GaimInputCondition); +typedef void (*ssl_input_function)(gpointer, void*, GaimInputCondition); -G_MODULE_EXPORT void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ); +G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); G_MODULE_EXPORT int ssl_getfd( void *conn ); +G_MODULE_EXPORT GaimInputCondition ssl_getdirection( void *conn ); diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c index c2eb6906..2e307aab 100644 --- a/protocols/ssl_gnutls.c +++ b/protocols/ssl_gnutls.c @@ -37,7 +37,7 @@ static gboolean initialized = FALSE; struct scd { - SslInputFunction func; + ssl_input_function func; gpointer data; int fd; gboolean established; @@ -50,7 +50,7 @@ struct scd static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); -void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); @@ -116,9 +116,7 @@ static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) { if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) { - conn->inpa = gaim_input_add( conn->fd, - gnutls_record_get_direction( conn->session ) ? - GAIM_INPUT_WRITE : GAIM_INPUT_READ, + conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); } else @@ -144,25 +142,40 @@ static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) int ssl_read( void *conn, char *buf, int len ) { + int st; + if( !((struct scd*)conn)->established ) { ssl_errno = SSL_NOHANDSHAKE; return( -1 ); } - return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) ); + st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len ); + + ssl_errno = SSL_OK; + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + ssl_errno = SSL_AGAIN; + return st; } int ssl_write( void *conn, const char *buf, int len ) { + int st; + if( !((struct scd*)conn)->established ) { ssl_errno = SSL_NOHANDSHAKE; return( -1 ); } - return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) ); + st = gnutls_record_send( ((struct scd*)conn)->session, buf, len ); + + ssl_errno = SSL_OK; + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + ssl_errno = SSL_AGAIN; + + return st; } void ssl_disconnect( void *conn_ ) @@ -183,3 +196,9 @@ int ssl_getfd( void *conn ) { return( ((struct scd*)conn)->fd ); } + +GaimInputCondition ssl_getdirection( void *conn ) +{ + return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? + GAIM_INPUT_WRITE : GAIM_INPUT_READ ); +} diff --git a/protocols/ssl_nss.c b/protocols/ssl_nss.c index d28983fc..dfd32622 100644 --- a/protocols/ssl_nss.c +++ b/protocols/ssl_nss.c @@ -44,7 +44,7 @@ static gboolean initialized = FALSE; struct scd { - SslInputFunction func; + ssl_input_function func; gpointer data; int fd; PRFileDesc *prfd; @@ -90,7 +90,7 @@ static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) } -void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index bf87ab73..5a107fc5 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -40,7 +40,7 @@ static gboolean initialized = FALSE; struct scd { - SslInputFunction func; + ssl_input_function func; gpointer data; int fd; gboolean established; @@ -53,7 +53,7 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) -void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data ) +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); SSL_METHOD *meth; @@ -1,3 +1,6 @@ +#include <errno.h> +#include <fcntl.h> + #ifndef _WIN32 #include <unistd.h> #include <sys/socket.h> @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2001-2004 Wilmer van der Gaast and others * + * Copyright 2001-2005 Wilmer van der Gaast and others * \********************************************************************/ /* URL/mirror stuff - Stolen from Axel */ @@ -29,7 +29,7 @@ int url_set( url_t *url, char *set_url ) { char s[MAX_STRING]; - char *i, *j; + char *i; /* protocol:// */ if( ( i = strstr( set_url, "://" ) ) == NULL ) @@ -39,7 +39,9 @@ int url_set( url_t *url, char *set_url ) } else { - if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) + if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) + url->proto = PROTO_HTTPS; + else if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) url->proto = PROTO_HTTP; else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 ) url->proto = PROTO_SOCKS4; @@ -55,33 +57,14 @@ int url_set( url_t *url, char *set_url ) /* Split */ if( ( i = strchr( s, '/' ) ) == NULL ) { - strcpy( url->dir, "/" ); + strcpy( url->file, "/" ); } else { + strncpy( url->file, i, MAX_STRING ); *i = 0; - g_snprintf( url->dir, MAX_STRING, "/%s", i + 1 ); - if( url->proto == PROTO_HTTP ) - http_encode( url->dir ); } strncpy( url->host, s, MAX_STRING ); - j = strchr( url->dir, '?' ); - if( j != NULL ) - *j = 0; - i = strrchr( url->dir, '/' ); - *i = 0; - if( j != NULL ) - *j = '?'; - if( i == NULL ) - { - strcpy( url->file, url->dir ); - strcpy( url->dir, "/" ); - } - else - { - strcpy( url->file, i + 1 ); - strcat( url->dir, "/" ); - } /* Check for username in host field */ if( strrchr( url->host, '@' ) != NULL ) @@ -95,15 +78,7 @@ int url_set( url_t *url, char *set_url ) /* If not: Fill in defaults */ else { - if( url->proto == PROTO_FTP ) - { - strcpy( url->user, "anonymous" ); - strcpy( url->pass, "-p.artmaps@lintux.cx" ); - } - else - { - *url->user = *url->pass = 0; - } + *url->user = *url->pass = 0; } /* Password? */ @@ -116,13 +91,14 @@ int url_set( url_t *url, char *set_url ) if( ( i = strchr( url->host, ':' ) ) != NULL ) { *i = 0; - sscanf( i + 1, "%i", &url->port ); + sscanf( i + 1, "%d", &url->port ); } - /* Take default port numbers from /etc/services */ else { if( url->proto == PROTO_HTTP ) - url->port = 8080; + url->port = 80; + else if( url->proto == PROTO_HTTPS ) + url->port = 443; else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 ) url->port = 1080; } @@ -25,8 +25,8 @@ #include "bitlbee.h" -#define PROTO_FTP 1 #define PROTO_HTTP 2 +#define PROTO_HTTPS 5 #define PROTO_SOCKS4 3 #define PROTO_SOCKS5 4 #define PROTO_DEFAULT PROTO_HTTP @@ -36,7 +36,6 @@ typedef struct url int proto; int port; char host[MAX_STRING]; - char dir[MAX_STRING]; char file[MAX_STRING]; char user[MAX_STRING]; char pass[MAX_STRING]; |