From 6dac4efa6181e2696ea112c3f1826f529160ceef Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Fri, 30 Jul 2010 21:41:50 +0000 Subject: Can do v6 and reconnect. --- sample-count.fmt | 4 +- sample-devlog.fmt | 4 +- sample-erdgeist.fmt | 4 +- sample-mAsq.fmt | 4 +- sample-oldstyle.fmt | 2 +- sample-xzivi.fmt | 4 +- vchat-client.c | 64 ++++++++++------- vchat-commands.c | 3 +- vchat-config.h | 8 +-- vchat-protocol.c | 193 +++++++++++++++++++++++++++------------------------- vchat-ssl.c | 112 ++++++++---------------------- vchat-ssl.h | 3 +- vchat.h | 2 +- 13 files changed, 186 insertions(+), 221 deletions(-) diff --git a/sample-count.fmt b/sample-count.fmt index d008991..bab9751 100755 --- a/sample-count.fmt +++ b/sample-count.fmt @@ -42,8 +42,8 @@ FS_IDLE = "^8%s" FS_TIME = "^5[%H:%M]-- ^0" FS_TOPICW = "[ Channel %d: %s" FS_NOTOPICW = "[ Channel %d has no topic" -FS_CONSOLE = "%s@%s:%d, use .h to get help" -FS_CONNECTED = "^2# Connected to '^6%s^2', port ^6%d^2 ..." +FS_CONSOLE = "%s@%s:%s, use .h to get help" +FS_CONNECTED = "^2# Connected to '^6%s^2', port ^6%s^2 ..." FS_TOPIC = "^2# Channel ^6%d^2 topic is: '^0%s^2'" FS_NOTOPIC = "^2# Channel ^6%d^2 has no topic" FS_CHGTOPIC = "^2# ^6%s^2 changes topic to: '^0%s^2'" diff --git a/sample-devlog.fmt b/sample-devlog.fmt index e70364d..ac30551 100755 --- a/sample-devlog.fmt +++ b/sample-devlog.fmt @@ -47,8 +47,8 @@ FS_IDLE = "^8%s" FS_TIME = "^2[%H:%M]^0 " FS_TOPICW = "[ Channel %d: %s" FS_NOTOPICW = "[ Channel %d has no topic" -FS_CONSOLE = "%s@%s:%d, use .h to get help" -FS_CONNECTED = "^2# Connected to '^0%s^2', port ^0%d^2 ..." +FS_CONSOLE = "%s@%s:%s, use .h to get help" +FS_CONNECTED = "^2# Connected to '^0%s^2', port ^0%s^2 ..." FS_TOPIC = "^1# Channel ^6%d^2 topic is: '^0%s^2'" FS_NOTOPIC = "^1# Channel ^6%d^2 has no topic" FS_CHGTOPIC = "^1# ^4%s^1 changes topic to: '^0%s^1'" diff --git a/sample-erdgeist.fmt b/sample-erdgeist.fmt index 5fc87e1..7545d3d 100755 --- a/sample-erdgeist.fmt +++ b/sample-erdgeist.fmt @@ -42,8 +42,8 @@ FS_TIME = "^9[%H:%M]^0 " FS_CONSOLETIME = "[%H:%M] " FS_TOPICW = "[ Channel %d: %s" FS_NOTOPICW = "[ Channel %d has no topic" -FS_CONSOLE = "%s@%s:%d, use .h to get help" -FS_CONNECTED = "^2# Connected to '^0%s^2', port ^0%d^2 ..." +FS_CONSOLE = "%s@%s:%s, use .h to get help" +FS_CONNECTED = "^2# Connected to '^0%s^2', port ^0%s^2 ..." FS_TOPIC = "^1# Channel ^6%d^2 topic is: '^0%s^2'" FS_NOTOPIC = "^1# Channel ^6%d^2 has no topic" FS_CHGTOPIC = "^1# ^4%s^1 changes topic to: '^0%s^1'" diff --git a/sample-mAsq.fmt b/sample-mAsq.fmt index 9bed139..af001d7 100755 --- a/sample-mAsq.fmt +++ b/sample-mAsq.fmt @@ -42,8 +42,8 @@ FS_IDLE = "^8%s" FS_TIME = "^5%H:%M^0 " FS_TOPICW = "[ Channel %d: %s" FS_NOTOPICW = "[ Channel %d has no topic" -FS_CONSOLE = "%s@%s:%d, use .h to get help" -FS_CONNECTED = "^2*^0C^2* Connected to '^6%s^2', port ^6%d^2 ..." +FS_CONSOLE = "%s@%s:%s, use .h to get help" +FS_CONNECTED = "^2*^0C^2* Connected to '^6%s^2', port ^6%s^2 ..." FS_TOPIC = "^2*^0T^2* Channel ^6%d^2 topic is: '^0%s^2'" FS_NOTOPIC = "^2*^0T^2* Channel ^6%d^2 has no topic" FS_CHGTOPIC = "^5*^0T^2* ^6%s^2 changes topic to: '^0%s^2'" diff --git a/sample-oldstyle.fmt b/sample-oldstyle.fmt index a1b0eb5..d0d8f17 100755 --- a/sample-oldstyle.fmt +++ b/sample-oldstyle.fmt @@ -43,7 +43,7 @@ FS_TIME = "^0%H:%M " FS_TOPICW = "Channel %d: %s" FS_NOTOPICW = "Channel %d has no topic" FS_CONSOLE = "-=- VChat V0.1 -=- type .h for help -=-" -FS_CONNECTED = "^0* Connected to '%s', port %d ..." +FS_CONNECTED = "^0* Connected to '%s', port %s ..." FS_TOPIC = "^0* Channel %d topic is: '%s'" FS_NOTOPIC = "^0* Channel %d has no topic" FS_CHGTOPIC = "^0* %s changed the channel topic to '%s'" diff --git a/sample-xzivi.fmt b/sample-xzivi.fmt index f839366..dbbf2b4 100755 --- a/sample-xzivi.fmt +++ b/sample-xzivi.fmt @@ -41,8 +41,8 @@ FS_IDLE = "^1^b%s^B" FS_TIME = "^4[%H:%M]^0 " FS_TOPICW = "Channel %d: %s" FS_NOTOPICW = "Channel %d has no topic" -FS_CONSOLE = "%s@%s:%d" -FS_CONNECTED = "# Connected to %s:%d ..." +FS_CONSOLE = "%s@%s:%s" +FS_CONNECTED = "# Connected to %s:%s ..." FS_TOPIC = "# Channel %d topic is: ^6%s" FS_NOTOPIC = "# Channel %d has no topic" FS_CHGTOPIC = "# ^b%s^B changes topic to: ^6%s" diff --git a/vchat-client.c b/vchat-client.c index c80e374..b7f993c 100755 --- a/vchat-client.c +++ b/vchat-client.c @@ -44,6 +44,8 @@ int status = 1; int ownquit = 0; /* we set this, we DONT want to quit */ int wantreconnect = 0; +static int reconnect_delay = 6; +static time_t reconnect_time = 0; /* error string to show after exit */ char errstr[ERRSTRSIZE] = "\0"; @@ -65,7 +67,7 @@ static void parsecfg(char *line) { char *param=line; char *value=NULL; - /* handle quotes value is empty, so wecan use it */ + /* handle quotes value is empty, so we can use it */ value = strchr(line,'#'); if (value) { /* the line contains a cute little quote */ value[0]='\0'; /* ignore the rest of the line */ @@ -414,7 +416,8 @@ void calleverysecond( void ) { quitrequest--; if(outputcountdown && !--outputcountdown) hideout( ); - + if( reconnect_time && ( time( NULL ) > reconnect_time ) ) + status = 0; } /* this function is called in the master loop */ @@ -425,33 +428,33 @@ eventloop (void) fd_set readfds = masterfds; struct timeval tv = { 1, 0}; - switch (select (serverfd + 1, &readfds, NULL, NULL, &tv)) + switch (select (serverfd + 2, &readfds, NULL, NULL, &tv)) { case -1: /* EINTR is most likely a SIGWINCH - ignore for now */ if (errno != EINTR) - { - snprintf (tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno)); + { + snprintf (tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno)); strncpy(errstr,tmpstr,TMPSTRSIZE-2); errstr[TMPSTRSIZE-2] = '\0'; strcat(errstr,"\n"); - writecf (FS_ERR,tmpstr); + writecf (FS_ERR,tmpstr); /* see this as an error condition and bail out */ - status = 0; - } - break; + status = 0; + } + break; case 0: /* time out reached */ calleverysecond(); break; default: /* something to read from user & we're logged in or have a cert? */ - if (FD_ISSET (0, &readfds) && loggedin) - userinput (); + if (FD_ISSET (0, &readfds) ) + userinput (); /* something to read from server? */ - if (FD_ISSET (serverfd, &readfds)) - networkinput (); + if (serverfd!=-1 && FD_ISSET (serverfd, &readfds)) + networkinput (); break; } } @@ -495,7 +498,7 @@ main (int argc, char **argv) #endif switch (pchar) { - case -1 : cmdsunparsed = 0; break; + case -1 : cmdsunparsed = 0; break; case 'C': loadconfig(optarg); break; case 'F': setstroption(CF_FORMFILE,optarg); break; case 'l': setintoption(CF_USESSL,0); break; @@ -528,21 +531,30 @@ main (int argc, char **argv) initui (); while( status ) { + /* add stdin to masterfds */ + FD_ZERO (&masterfds); + FD_SET (0, &masterfds); + /* attempt connection */ - if (!vcconnect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { - snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", - strerror(errno)); - strncpy(errstr,tmpstr,TMPSTRSIZE-2); - errstr[TMPSTRSIZE-2] = '\0'; - strcat(errstr,"\n"); - writecf (FS_ERR,tmpstr); - /* exit condition */ - status = 0; + if (vcconnect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { + snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", strerror(errno)); + strncpy(errstr,tmpstr,TMPSTRSIZE-2); + errstr[TMPSTRSIZE-2] = '\0'; + strcat(errstr,"\n"); + writecf (FS_ERR,tmpstr); + + if( getintoption( CF_AUTORECONN ) ) { + snprintf (tmpstr, TMPSTRSIZE, "reconnecting in %d seconds", reconnect_delay ); + writecf (FS_ERR, tmpstr); + reconnect_delay = ( reconnect_delay * 15 ) / 10; + reconnect_time = time( NULL ) + reconnect_delay; + } else + status = 0; } else { - /* add stdin & server to masterdfs */ - FD_ZERO (&masterfds); - FD_SET (0, &masterfds); + /* add serverfd to masterfds, reset reconnect delay */ FD_SET (serverfd, &masterfds); + reconnect_delay = 6; + reconnect_time = 0; } while (status) diff --git a/vchat-commands.c b/vchat-commands.c index 651878c..0c8ca26 100755 --- a/vchat-commands.c +++ b/vchat-commands.c @@ -393,12 +393,13 @@ command_quit(char *tail) /* send users message to server */ snprintf (tmpstr, TMPSTRSIZE, ".x %s", tail); networkoutput (tmpstr); - + /* show action in channel window */ writechan (tmpstr); /* Inform vchat-client, that the closing connection following is intended */ + status = 0; ownquit = 1; } diff --git a/vchat-config.h b/vchat-config.h index 34866b1..3511c68 100755 --- a/vchat-config.h +++ b/vchat-config.h @@ -23,7 +23,6 @@ #endif /* configuration array with structure as defined in vchat.h */ -extern unsigned int usessl; extern unsigned int ignssl; extern unsigned int usetime; extern unsigned int hscroll; @@ -41,7 +40,7 @@ static volatile configoption configoptions[] = { {CF_FORMFILE, CO_STR, "formatfile", "~/.vchat/formats", NULL, { NULL } }, {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL, { NULL } }, {CF_ENCODING, CO_STR, "encoding", NULL, NULL, { .pstr = &encoding }}, - {CF_USESSL, CO_INT, "usessl", (char *) 1, (char *)-1, { .pint = &usessl } }, + {CF_USESSL, CO_INT, "usessl", (char *) 1, (char *)-1, { NULL } }, {CF_IGNSSL, CO_INT, "ignssl", (char *) 0, (char *)-1, { .pint = &ignssl } }, {CF_USECERT, CO_INT, "usecert", (char *) 1, (char *)-1, { NULL } }, {CF_USETIME, CO_INT, "usetime", (char *) 1, (char *)-1, { .pint = &usetime } }, @@ -100,8 +99,9 @@ static formatstring formatstrings[] = { FE( FS_CONSOLETIME, "[%H:%M] "), FE( FS_TOPICW, "[ Channel %d: %s"), FE( FS_NOTOPICW, "[ Channel %d has no topic"), - FE( FS_CONSOLE, "%s@%s:%d, use .h to get help "), - FE( FS_CONNECTED, "\0012# Connected to '\0016%s\0012', port \0016%d\0012 ..."), + FE( FS_CONSOLE, "%s@%s:%s, use .h to get help "), + FE( FS_CONNECTED, "\0012# Connected to '\0016%s\0012', port \0016%s\0012 ..."), + FE( FS_CANTCONNECT, "\0012# Can not connect to '\0016%s\0012', port \0016%s\0012 ..."), FE( FS_TOPIC, "\0012# Channel \0016%d\0012 topic is: '\0010%s\0012'"), FE( FS_NOTOPIC, "\0012# Channel \0016%d\0012 has no topic"), FE( FS_CHGTOPIC, "\0012# \0016%s\0012 changes topic to: '\0010%s\0012'"), diff --git a/vchat-protocol.c b/vchat-protocol.c index aefe419..700f6c7 100755 --- a/vchat-protocol.c +++ b/vchat-protocol.c @@ -40,18 +40,17 @@ char *vchat_io_version = "$Id$"; /* externally used variables */ int serverfd = -1; -unsigned int usingcert = 1; /* locally global variables */ -/* SSL-connection */ -static BIO *sslconn = NULL; +/* our connection BIO */ +static BIO *server_conn = NULL; /* declaration of local helper functions */ static void usersignon (char *); static void usersignoff (char *); static void usernickchange (char *); static void userjoin (char *); -static void userleave (char *); +static void userleave (char *); static void receivenicks (char *message); static void justloggedin (char *message); static void nickerr (char *message); @@ -64,7 +63,6 @@ static void serverlogin (char *message); static void idleprompt (char *message); static void topicchange (char *message); static void pmnotsent (char *message); -static int getportnum (char *port); /* declaration of server message array */ #include "vchat-messages.h" @@ -72,116 +70,129 @@ static int getportnum (char *port); /* status-variable from vchat-client.c * eventloop is done as long as this is true */ extern int status; - -int usessl = 1; int ignssl = 0; char *encoding; +static int connect_socket( char *server, char *port ) { + struct addrinfo hints, *res, *res0; + int s, error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo( server, port, &hints, &res0 ); + if (error) return -1; + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) continue; + if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + close(s); + s = -1; + continue; + } + break; /* okay we got one */ + } + freeaddrinfo(res0); + return s; +} + /* connects to server */ int vcconnect (char *server, char *port) { - /* used for tilde expansion of cert & key filenames */ - char *tildex = NULL; - - /* vchat connection x509 store */ - vc_x509store_t vc_store; + /* used for tilde expansion of cert & key filenames */ + char *tildex = NULL; - /* SSL-context */ - SSL_CTX *sslctx = NULL; + /* vchat connection x509 store */ + vc_x509store_t vc_store; - /* pointer to tilde-expanded certificate/keyfile-names */ - char *certfile = NULL, *keyfile = NULL; + /* SSL-context */ + SSL_CTX *sslctx = NULL; - SSL_library_init (); - SSL_load_error_strings(); + /* pointer to tilde-expanded certificate/keyfile-names */ + char *certfile = NULL, *keyfile = NULL; - vc_init_x509store(&vc_store); + /* Connect to the server */ + serverfd = connect_socket( server, port ); + if( serverfd < 0 ) { + /* inform user */ + snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); + writechan (tmpstr); + return -1; + } + /* Abstract server IO in openssls BIO */ + server_conn = BIO_new_socket( serverfd, 1 ); + + /* If SSL is requested, get our ssl-BIO running */ + if( server_conn && getintoption(CF_USESSL) ) { + static int sslinit; + if( !sslinit++ ) { + SSL_library_init (); + SSL_load_error_strings(); + } - vc_x509store_setflags(&vc_store, VC_X509S_SSL_VERIFY_PEER); - /* get name of certificate file */ - certfile = getstroption (CF_CERTFILE); + vc_init_x509store(&vc_store); + vc_x509store_setflags(&vc_store, VC_X509S_SSL_VERIFY_PEER); - /* do we have a certificate file? */ - if (certfile) { + /* get name of certificate file */ + certfile = getstroption (CF_CERTFILE); + /* do we have a certificate file? */ + if (certfile) { /* does the filename start with a tilde? expand it! */ if (certfile[0] == '~') - tildex = tilde_expand (certfile); + tildex = tilde_expand (certfile); else - tildex = certfile; - - if (usingcert) { - - vc_x509store_setflags(&vc_store, VC_X509S_USE_CERTIFICATE); - vc_x509store_setcertfile(&vc_store, tildex); + tildex = certfile; - /* get name of key file */ - keyfile = getstroption (CF_KEYFILE); + vc_x509store_setflags(&vc_store, VC_X509S_USE_CERTIFICATE); + vc_x509store_setcertfile(&vc_store, tildex); - /* if we don't have a key file, the key may be in the cert file */ - if (!keyfile) - keyfile = certfile; + /* get name of key file */ + keyfile = getstroption (CF_KEYFILE); - /* does the filename start with a tilde? expand it! */ - if (keyfile[0] == '~') - tildex = tilde_expand (keyfile); - else - tildex = keyfile; - - vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); - vc_x509store_setkeyfile(&vc_store, tildex); - - /* check if OpenSSL thinks key & cert belong together */ - /* result = SSL_CTX_check_private_key (sslctx); THS TODO (-> - * vchat-ssl.c) */ - } - } - - usessl = getintoption(CF_USESSL); - vc_x509store_setignssl(&vc_store, getintoption(CF_IGNSSL)); + /* if we don't have a key file, the key may be in the cert file */ + if (!keyfile) + keyfile = certfile; - sslconn = vc_connect(server, getportnum(port), usessl, &vc_store, &sslctx); + /* does the filename start with a tilde? expand it! */ + if (keyfile[0] == '~') + tildex = tilde_expand (keyfile); + else + tildex = keyfile; - if(sslconn == NULL) { - exitui(); - exit(-1); - } + vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); + vc_x509store_setkeyfile(&vc_store, tildex); + } + vc_x509store_setignssl(&vc_store, getintoption(CF_IGNSSL)); - serverfd = BIO_get_fd(sslconn, 0); + /* upgrade our plain BIO to ssl */ + if( vc_connect_ssl( &server_conn, &vc_store, &sslctx ) ) + BIO_free_all( server_conn ); + } - /* inform user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, getportnum(port)); - writechan (tmpstr); + if( !server_conn ) { + /* inform user */ + snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); + writechan (tmpstr); + return -1; + } - /* dump x509 details here... TODO */ - writecf (FS_DBG,"# SSL Server information: TODO :)"); + /* inform user */ + snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); + writechan (tmpstr); - /* if we didn't fail until now, we've got a connection. */ - return 1; + /* if we didn't fail until now, we've got a connection. */ + return 0; } /* disconnect from server */ void -vcdisconnect () -{ - close (serverfd); +vcdisconnect () { + BIO_free_all( server_conn ); serverfd = -1; } -/* lookup a port number by service string */ -static int getportnum (char *port) -{ - char *endpt = NULL; - struct servent *service = getservbyname(port, "tcp"); - int dport = strtoul( port, &endpt, 10); - - if( service ) - return htons( service->s_port ); - if( (*endpt == 0) && ((char *)port != endpt) ) - return dport; - return -1; -} - /* handle a pm not sent error * format: 412 %s */ static void @@ -358,7 +369,7 @@ justloggedin (char *message) setstroption(CF_NICK,str1); /* show change in console window */ - snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getportnum(getstroption (CF_SERVERPORT))); + snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); consoleline (NULL); /* announce login as servermessage */ @@ -401,7 +412,7 @@ ownnickchange (char *newnick) setstroption(CF_NICK,newnick); /* show change in console window */ - snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getportnum(getstroption (CF_SERVERPORT))); + snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); consoleline (NULL); } @@ -533,7 +544,7 @@ receivenicks (char *message) str2 = strchr (str1, ' '); /* there is another user? terminate this one */ if (str2) { - str2[0] = '\0'; + str2[0] = '\0'; str2++; } @@ -826,7 +837,7 @@ networkinput (void) buf[BUFSIZE-1] = '\0'; /* sanity stop */ /* receive data at offset */ - bytes = BIO_read (sslconn, &buf[bufoff], BUFSIZE-1 - bufoff); + bytes = BIO_read (server_conn, &buf[bufoff], BUFSIZE-1 - bufoff); /* no bytes transferred? raise error message, bail out */ if (bytes < 0) @@ -875,8 +886,8 @@ networkinput (void) } /* move line along .. */ - ltmp = tmp; - } + ltmp = tmp; + } /* buffer exhausted, move partial line to start of buffer and go on .. */ bufoff = (bytes+bufoff) - (ltmp-buf); if (bufoff > 0) @@ -895,10 +906,10 @@ networkoutput (char *msg) #endif /* send data to server */ - if (BIO_write (sslconn, msg, strlen (msg)) != strlen (msg)) + if (BIO_write (server_conn, msg, strlen (msg)) != strlen (msg)) writecf (FS_ERR,"Message sending fuzzy."); /* send line termination to server */ - if (BIO_write (sslconn, "\r\n", 2) != 2) + if (BIO_write (server_conn, "\r\n", 2) != 2) writecf (FS_ERR,"Message sending fuzzy."); } diff --git a/vchat-ssl.c b/vchat-ssl.c index 3c191c2..1a1ff16 100755 --- a/vchat-ssl.c +++ b/vchat-ssl.c @@ -11,7 +11,7 @@ * without even the implied warranty of merchantability or fitness for a * particular purpose. In no event shall the copyright holder be liable for * any direct, indirect, incidental or special damages arising in any way out - * of the use of this software. + * of the use of this software. * */ @@ -111,31 +111,19 @@ SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ) } else if(vc_store->use_key) r=SSL_CTX_use_PrivateKey(ctx, vc_store->use_key); - if(r!=1) + if( r!=1 || !SSL_CTX_check_private_key(ctx)) VC_SETCERT_ERR_EXIT(store, ctx, "Load private key failed"); - } SSL_CTX_set_app_data(ctx, vc_store); return(ctx); } -#define VC_CONNSSL_ERR_EXIT(_cx, cx, cn) do { \ - snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", \ - ERR_error_string (ERR_get_error (), NULL)); \ - writecf(FS_ERR, tmpstr); \ - if(cn) BIO_free_all(cn); \ - if(*cx) SSL_CTX_free(*cx); \ - if(_cx) *cx = 0; \ - return(0); \ - } while(0) - -BIO * vc_connect_ssl(char *host, int port, vc_x509store_t *vc_store, - SSL_CTX **ctx) +int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store, SSL_CTX **ctx) { - BIO *conn = NULL; - int _ctx = 0; - + BIO *ssl_conn = NULL; + int _ctx = 0; + if(*ctx) { CRYPTO_add( &((*ctx)->references), 1, CRYPTO_LOCK_SSL_CTX ); if( vc_store && vc_store != SSL_CTX_get_app_data(*ctx) ) { @@ -147,72 +135,26 @@ BIO * vc_connect_ssl(char *host, int port, vc_x509store_t *vc_store, _ctx = 1; } - if( !(conn = BIO_new_ssl_connect(*ctx)) ) - VC_CONNSSL_ERR_EXIT(_ctx, ctx, conn); - - BIO_set_conn_hostname(conn, host); - BIO_set_conn_int_port(conn, &port); + ssl_conn = BIO_new_ssl(*ctx, 1); + if(_ctx) + SSL_CTX_free(*ctx); - fflush(stdout); - if(BIO_do_connect(conn) <= 0) - VC_CONNSSL_ERR_EXIT(_ctx, ctx, conn); + if( ssl_conn ) { + BIO_push( ssl_conn, *conn ); + *conn = ssl_conn; + fflush(stdout); + if( BIO_do_handshake( *conn ) > 0 ) + return 0; + } - if(_ctx) - SSL_CTX_free(*ctx); + snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); + writecf(FS_ERR, tmpstr); - return(conn); -} - -#define VC_CONN_ERR_EXIT(cn) do { \ - snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", \ - ERR_error_string(ERR_get_error(), NULL)); \ - if(ERR_get_error()) \ - writecf(FS_ERR, tmpstr); \ - if(cn) BIO_free_all(cn); \ - return(NULL); \ - } while(0) - -#define VC_VERIFICATION_ERR_EXIT(cn, err) do { \ - snprintf(tmpstr, TMPSTRSIZE, \ - "[SSL ERROR] certificate verify failed: %s", err); \ - writecf(FS_ERR, tmpstr); \ - if(cn && !ignore_ssl) { BIO_free_all(cn); return(NULL); } \ - } while(0) - -BIO * vc_connect( char *host, int port, int use_ssl, - vc_x509store_t *vc_store, SSL_CTX **ctx) -{ - BIO *conn = NULL; - SSL *ssl = NULL; - - if(use_ssl) { - if( !(conn = vc_connect_ssl(host, port, vc_store, ctx)) ) - VC_CONN_ERR_EXIT(conn); - - - BIO_get_ssl(conn, &ssl); - if(!vc_verify_cert_hostname(SSL_get_peer_certificate(ssl), host)) - VC_VERIFICATION_ERR_EXIT(conn, "Hostname does not match!"); - - return(conn); - } - - *ctx = 0; - - if( !(conn = BIO_new_connect(host)) ) - VC_CONN_ERR_EXIT(conn); - - BIO_set_conn_int_port(conn, &port); - - if(BIO_do_connect(conn) <= 0) - VC_CONN_ERR_EXIT(conn); - - return(conn); + return 1; } int vc_verify_cert_hostname(X509 *cert, char *host) { - int i = 0; int j = 0; int n = 0; @@ -231,39 +173,39 @@ int vc_verify_cert_hostname(X509 *cert, char *host) memset(&name, 0, sizeof(name)); if((extcount = X509_get_ext_count(cert)) > 0) { - + for(i=0; !ok && i < extcount; i++) { - + meth = NULL; ext = X509_get_ext(cert, i); extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); if(!strcasecmp(extstr, "subjectAltName")) { - + if( !(meth = X509V3_EXT_get(ext)) ) break; if( !(meth->d2i) ) break; - + data = ext->value->data; val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0); for( j=0, n=sk_CONF_VALUE_num(val); jname, "DNS") && + if( !strcasecmp(nval->name, "DNS") && !strcasecmp(nval->value, host) ) { ok = 1; break; } - } + } } } } if( !ok && (subj = X509_get_subject_name(cert)) && - X509_NAME_get_text_by_NID(subj, NID_commonName, + X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0 ) { name[sizeof(name)-1] = '\0'; if(!strcasecmp(name, host)) @@ -331,7 +273,7 @@ X509_STORE *vc_x509store_create(vc_x509store_t *vc_store) X509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } - + if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) ) VC_STORE_ERR_EXIT(store); diff --git a/vchat-ssl.h b/vchat-ssl.h index 58e9dec..c745c97 100755 --- a/vchat-ssl.h +++ b/vchat-ssl.h @@ -21,8 +21,7 @@ typedef struct { /* prototypes */ -BIO * vc_connect(char *, int , int, vc_x509store_t *, SSL_CTX **); -BIO * vc_connect_ssl(char *, int, vc_x509store_t *, SSL_CTX **); +int vc_connect_ssl(BIO **conn, vc_x509store_t *, SSL_CTX **); SSL_CTX * vc_create_sslctx( vc_x509store_t *); void vc_init_x509store(vc_x509store_t *); void vc_cleanup_x509store(vc_x509store_t *); diff --git a/vchat.h b/vchat.h index d8054bd..5e2bff9 100755 --- a/vchat.h +++ b/vchat.h @@ -43,7 +43,7 @@ CF_ENCODING, CF_BELLPRIV, CF_AUTORECONN } confopt; /* format strings */ typedef enum { FS_PLAIN, FS_CHAN, FS_PRIV, FS_SERV, FS_GLOB, FS_DBG, FS_ERR, -FS_IDLE, FS_TIME, FS_CONSOLETIME, FS_TOPICW, FS_NOTOPICW, FS_CONSOLE, FS_CONNECTED, +FS_IDLE, FS_TIME, FS_CONSOLETIME, FS_TOPICW, FS_NOTOPICW, FS_CONSOLE, FS_CONNECTED, FS_CANTCONNECT, FS_TOPIC, FS_NOTOPIC, FS_CHGTOPIC, FS_USONLINE, FS_USMATCH, FS_SIGNON, FS_SIGNOFF, FS_JOIN, FS_LEAVE, FS_NICKCHANGE, FS_UNKNOWNMSG, FS_BOGUSMSG, FS_RXPUBURL, FS_MYPUBURL, FS_RXPUBMSG, FS_MYPUBMSG, FS_TXPUBMSG, FS_RXPRIVMSG, FS_TXPRIVMSG, -- cgit v1.2.3