diff options
| author | erdgeist <> | 2010-07-30 21:41:50 +0000 |
|---|---|---|
| committer | erdgeist <> | 2010-07-30 21:41:50 +0000 |
| commit | 6dac4efa6181e2696ea112c3f1826f529160ceef (patch) | |
| tree | 0f081ca75b0f35d727314c78c4b0f33fdf93af25 /vchat-protocol.c | |
| parent | a4b65f17eb73100a3fd4ec1f4de7cee56aa5131b (diff) | |
Can do v6 and reconnect.
Diffstat (limited to 'vchat-protocol.c')
| -rwxr-xr-x | vchat-protocol.c | 193 |
1 files changed, 102 insertions, 91 deletions
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$"; | |||
| 40 | 40 | ||
| 41 | /* externally used variables */ | 41 | /* externally used variables */ |
| 42 | int serverfd = -1; | 42 | int serverfd = -1; |
| 43 | unsigned int usingcert = 1; | ||
| 44 | 43 | ||
| 45 | /* locally global variables */ | 44 | /* locally global variables */ |
| 46 | /* SSL-connection */ | 45 | /* our connection BIO */ |
| 47 | static BIO *sslconn = NULL; | 46 | static BIO *server_conn = NULL; |
| 48 | 47 | ||
| 49 | /* declaration of local helper functions */ | 48 | /* declaration of local helper functions */ |
| 50 | static void usersignon (char *); | 49 | static void usersignon (char *); |
| 51 | static void usersignoff (char *); | 50 | static void usersignoff (char *); |
| 52 | static void usernickchange (char *); | 51 | static void usernickchange (char *); |
| 53 | static void userjoin (char *); | 52 | static void userjoin (char *); |
| 54 | static void userleave (char *); | 53 | static void userleave (char *); |
| 55 | static void receivenicks (char *message); | 54 | static void receivenicks (char *message); |
| 56 | static void justloggedin (char *message); | 55 | static void justloggedin (char *message); |
| 57 | static void nickerr (char *message); | 56 | static void nickerr (char *message); |
| @@ -64,7 +63,6 @@ static void serverlogin (char *message); | |||
| 64 | static void idleprompt (char *message); | 63 | static void idleprompt (char *message); |
| 65 | static void topicchange (char *message); | 64 | static void topicchange (char *message); |
| 66 | static void pmnotsent (char *message); | 65 | static void pmnotsent (char *message); |
| 67 | static int getportnum (char *port); | ||
| 68 | 66 | ||
| 69 | /* declaration of server message array */ | 67 | /* declaration of server message array */ |
| 70 | #include "vchat-messages.h" | 68 | #include "vchat-messages.h" |
| @@ -72,116 +70,129 @@ static int getportnum (char *port); | |||
| 72 | /* status-variable from vchat-client.c | 70 | /* status-variable from vchat-client.c |
| 73 | * eventloop is done as long as this is true */ | 71 | * eventloop is done as long as this is true */ |
| 74 | extern int status; | 72 | extern int status; |
| 75 | |||
| 76 | int usessl = 1; | ||
| 77 | int ignssl = 0; | 73 | int ignssl = 0; |
| 78 | char *encoding; | 74 | char *encoding; |
| 79 | 75 | ||
| 76 | static int connect_socket( char *server, char *port ) { | ||
| 77 | struct addrinfo hints, *res, *res0; | ||
| 78 | int s, error; | ||
| 79 | |||
| 80 | memset(&hints, 0, sizeof(hints)); | ||
| 81 | hints.ai_family = PF_UNSPEC; | ||
| 82 | hints.ai_socktype = SOCK_STREAM; | ||
| 83 | error = getaddrinfo( server, port, &hints, &res0 ); | ||
| 84 | if (error) return -1; | ||
| 85 | s = -1; | ||
| 86 | for (res = res0; res; res = res->ai_next) { | ||
| 87 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
| 88 | if (s < 0) continue; | ||
| 89 | if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { | ||
| 90 | close(s); | ||
| 91 | s = -1; | ||
| 92 | continue; | ||
| 93 | } | ||
| 94 | break; /* okay we got one */ | ||
| 95 | } | ||
| 96 | freeaddrinfo(res0); | ||
| 97 | return s; | ||
| 98 | } | ||
| 99 | |||
| 80 | /* connects to server */ | 100 | /* connects to server */ |
| 81 | int | 101 | int |
| 82 | vcconnect (char *server, char *port) | 102 | vcconnect (char *server, char *port) |
| 83 | { | 103 | { |
| 84 | /* used for tilde expansion of cert & key filenames */ | 104 | /* used for tilde expansion of cert & key filenames */ |
| 85 | char *tildex = NULL; | 105 | char *tildex = NULL; |
| 86 | |||
| 87 | /* vchat connection x509 store */ | ||
| 88 | vc_x509store_t vc_store; | ||
| 89 | 106 | ||
| 90 | /* SSL-context */ | 107 | /* vchat connection x509 store */ |
| 91 | SSL_CTX *sslctx = NULL; | 108 | vc_x509store_t vc_store; |
| 92 | 109 | ||
| 93 | /* pointer to tilde-expanded certificate/keyfile-names */ | 110 | /* SSL-context */ |
| 94 | char *certfile = NULL, *keyfile = NULL; | 111 | SSL_CTX *sslctx = NULL; |
| 95 | 112 | ||
| 96 | SSL_library_init (); | 113 | /* pointer to tilde-expanded certificate/keyfile-names */ |
| 97 | SSL_load_error_strings(); | 114 | char *certfile = NULL, *keyfile = NULL; |
| 98 | 115 | ||
| 99 | vc_init_x509store(&vc_store); | 116 | /* Connect to the server */ |
| 117 | serverfd = connect_socket( server, port ); | ||
| 118 | if( serverfd < 0 ) { | ||
| 119 | /* inform user */ | ||
| 120 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | ||
| 121 | writechan (tmpstr); | ||
| 122 | return -1; | ||
| 123 | } | ||
| 124 | /* Abstract server IO in openssls BIO */ | ||
| 125 | server_conn = BIO_new_socket( serverfd, 1 ); | ||
| 126 | |||
| 127 | /* If SSL is requested, get our ssl-BIO running */ | ||
| 128 | if( server_conn && getintoption(CF_USESSL) ) { | ||
| 129 | static int sslinit; | ||
| 130 | if( !sslinit++ ) { | ||
| 131 | SSL_library_init (); | ||
| 132 | SSL_load_error_strings(); | ||
| 133 | } | ||
| 100 | 134 | ||
| 101 | vc_x509store_setflags(&vc_store, VC_X509S_SSL_VERIFY_PEER); | 135 | vc_init_x509store(&vc_store); |
| 102 | /* get name of certificate file */ | 136 | vc_x509store_setflags(&vc_store, VC_X509S_SSL_VERIFY_PEER); |
| 103 | certfile = getstroption (CF_CERTFILE); | ||
| 104 | 137 | ||
| 105 | /* do we have a certificate file? */ | 138 | /* get name of certificate file */ |
| 106 | if (certfile) { | 139 | certfile = getstroption (CF_CERTFILE); |
| 140 | /* do we have a certificate file? */ | ||
| 141 | if (certfile) { | ||
| 107 | /* does the filename start with a tilde? expand it! */ | 142 | /* does the filename start with a tilde? expand it! */ |
| 108 | if (certfile[0] == '~') | 143 | if (certfile[0] == '~') |
| 109 | tildex = tilde_expand (certfile); | 144 | tildex = tilde_expand (certfile); |
| 110 | else | 145 | else |
| 111 | tildex = certfile; | 146 | tildex = certfile; |
| 112 | |||
| 113 | if (usingcert) { | ||
| 114 | |||
| 115 | vc_x509store_setflags(&vc_store, VC_X509S_USE_CERTIFICATE); | ||
| 116 | vc_x509store_setcertfile(&vc_store, tildex); | ||
| 117 | 147 | ||
| 118 | /* get name of key file */ | 148 | vc_x509store_setflags(&vc_store, VC_X509S_USE_CERTIFICATE); |
| 119 | keyfile = getstroption (CF_KEYFILE); | 149 | vc_x509store_setcertfile(&vc_store, tildex); |
| 120 | 150 | ||
| 121 | /* if we don't have a key file, the key may be in the cert file */ | 151 | /* get name of key file */ |
| 122 | if (!keyfile) | 152 | keyfile = getstroption (CF_KEYFILE); |
| 123 | keyfile = certfile; | ||
| 124 | 153 | ||
| 125 | /* does the filename start with a tilde? expand it! */ | 154 | /* if we don't have a key file, the key may be in the cert file */ |
| 126 | if (keyfile[0] == '~') | 155 | if (!keyfile) |
| 127 | tildex = tilde_expand (keyfile); | 156 | keyfile = certfile; |
| 128 | else | ||
| 129 | tildex = keyfile; | ||
| 130 | |||
| 131 | vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); | ||
| 132 | vc_x509store_setkeyfile(&vc_store, tildex); | ||
| 133 | |||
| 134 | /* check if OpenSSL thinks key & cert belong together */ | ||
| 135 | /* result = SSL_CTX_check_private_key (sslctx); THS TODO (-> | ||
| 136 | * vchat-ssl.c) */ | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | usessl = getintoption(CF_USESSL); | ||
| 141 | vc_x509store_setignssl(&vc_store, getintoption(CF_IGNSSL)); | ||
| 142 | 157 | ||
| 143 | sslconn = vc_connect(server, getportnum(port), usessl, &vc_store, &sslctx); | 158 | /* does the filename start with a tilde? expand it! */ |
| 159 | if (keyfile[0] == '~') | ||
| 160 | tildex = tilde_expand (keyfile); | ||
| 161 | else | ||
| 162 | tildex = keyfile; | ||
| 144 | 163 | ||
| 145 | if(sslconn == NULL) { | 164 | vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); |
| 146 | exitui(); | 165 | vc_x509store_setkeyfile(&vc_store, tildex); |
| 147 | exit(-1); | 166 | } |
| 148 | } | 167 | vc_x509store_setignssl(&vc_store, getintoption(CF_IGNSSL)); |
| 149 | 168 | ||
| 150 | serverfd = BIO_get_fd(sslconn, 0); | 169 | /* upgrade our plain BIO to ssl */ |
| 170 | if( vc_connect_ssl( &server_conn, &vc_store, &sslctx ) ) | ||
| 171 | BIO_free_all( server_conn ); | ||
| 172 | } | ||
| 151 | 173 | ||
| 152 | /* inform user */ | 174 | if( !server_conn ) { |
| 153 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, getportnum(port)); | 175 | /* inform user */ |
| 154 | writechan (tmpstr); | 176 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); |
| 177 | writechan (tmpstr); | ||
| 178 | return -1; | ||
| 179 | } | ||
| 155 | 180 | ||
| 156 | /* dump x509 details here... TODO */ | 181 | /* inform user */ |
| 157 | writecf (FS_DBG,"# SSL Server information: TODO :)"); | 182 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); |
| 183 | writechan (tmpstr); | ||
| 158 | 184 | ||
| 159 | /* if we didn't fail until now, we've got a connection. */ | 185 | /* if we didn't fail until now, we've got a connection. */ |
| 160 | return 1; | 186 | return 0; |
| 161 | } | 187 | } |
| 162 | 188 | ||
| 163 | /* disconnect from server */ | 189 | /* disconnect from server */ |
| 164 | void | 190 | void |
| 165 | vcdisconnect () | 191 | vcdisconnect () { |
| 166 | { | 192 | BIO_free_all( server_conn ); |
| 167 | close (serverfd); | ||
| 168 | serverfd = -1; | 193 | serverfd = -1; |
| 169 | } | 194 | } |
| 170 | 195 | ||
| 171 | /* lookup a port number by service string */ | ||
| 172 | static int getportnum (char *port) | ||
| 173 | { | ||
| 174 | char *endpt = NULL; | ||
| 175 | struct servent *service = getservbyname(port, "tcp"); | ||
| 176 | int dport = strtoul( port, &endpt, 10); | ||
| 177 | |||
| 178 | if( service ) | ||
| 179 | return htons( service->s_port ); | ||
| 180 | if( (*endpt == 0) && ((char *)port != endpt) ) | ||
| 181 | return dport; | ||
| 182 | return -1; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* handle a pm not sent error | 196 | /* handle a pm not sent error |
| 186 | * format: 412 %s */ | 197 | * format: 412 %s */ |
| 187 | static void | 198 | static void |
| @@ -358,7 +369,7 @@ justloggedin (char *message) | |||
| 358 | setstroption(CF_NICK,str1); | 369 | setstroption(CF_NICK,str1); |
| 359 | 370 | ||
| 360 | /* show change in console window */ | 371 | /* show change in console window */ |
| 361 | snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getportnum(getstroption (CF_SERVERPORT))); | 372 | snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); |
| 362 | consoleline (NULL); | 373 | consoleline (NULL); |
| 363 | 374 | ||
| 364 | /* announce login as servermessage */ | 375 | /* announce login as servermessage */ |
| @@ -401,7 +412,7 @@ ownnickchange (char *newnick) | |||
| 401 | setstroption(CF_NICK,newnick); | 412 | setstroption(CF_NICK,newnick); |
| 402 | 413 | ||
| 403 | /* show change in console window */ | 414 | /* show change in console window */ |
| 404 | snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getportnum(getstroption (CF_SERVERPORT))); | 415 | snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), nick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); |
| 405 | consoleline (NULL); | 416 | consoleline (NULL); |
| 406 | } | 417 | } |
| 407 | 418 | ||
| @@ -533,7 +544,7 @@ receivenicks (char *message) | |||
| 533 | str2 = strchr (str1, ' '); | 544 | str2 = strchr (str1, ' '); |
| 534 | /* there is another user? terminate this one */ | 545 | /* there is another user? terminate this one */ |
| 535 | if (str2) { | 546 | if (str2) { |
| 536 | str2[0] = '\0'; | 547 | str2[0] = '\0'; |
| 537 | str2++; | 548 | str2++; |
| 538 | } | 549 | } |
| 539 | 550 | ||
| @@ -826,7 +837,7 @@ networkinput (void) | |||
| 826 | buf[BUFSIZE-1] = '\0'; /* sanity stop */ | 837 | buf[BUFSIZE-1] = '\0'; /* sanity stop */ |
| 827 | 838 | ||
| 828 | /* receive data at offset */ | 839 | /* receive data at offset */ |
| 829 | bytes = BIO_read (sslconn, &buf[bufoff], BUFSIZE-1 - bufoff); | 840 | bytes = BIO_read (server_conn, &buf[bufoff], BUFSIZE-1 - bufoff); |
| 830 | 841 | ||
| 831 | /* no bytes transferred? raise error message, bail out */ | 842 | /* no bytes transferred? raise error message, bail out */ |
| 832 | if (bytes < 0) | 843 | if (bytes < 0) |
| @@ -875,8 +886,8 @@ networkinput (void) | |||
| 875 | } | 886 | } |
| 876 | 887 | ||
| 877 | /* move line along .. */ | 888 | /* move line along .. */ |
| 878 | ltmp = tmp; | 889 | ltmp = tmp; |
| 879 | } | 890 | } |
| 880 | /* buffer exhausted, move partial line to start of buffer and go on .. */ | 891 | /* buffer exhausted, move partial line to start of buffer and go on .. */ |
| 881 | bufoff = (bytes+bufoff) - (ltmp-buf); | 892 | bufoff = (bytes+bufoff) - (ltmp-buf); |
| 882 | if (bufoff > 0) | 893 | if (bufoff > 0) |
| @@ -895,10 +906,10 @@ networkoutput (char *msg) | |||
| 895 | #endif | 906 | #endif |
| 896 | 907 | ||
| 897 | /* send data to server */ | 908 | /* send data to server */ |
| 898 | if (BIO_write (sslconn, msg, strlen (msg)) != strlen (msg)) | 909 | if (BIO_write (server_conn, msg, strlen (msg)) != strlen (msg)) |
| 899 | writecf (FS_ERR,"Message sending fuzzy."); | 910 | writecf (FS_ERR,"Message sending fuzzy."); |
| 900 | 911 | ||
| 901 | /* send line termination to server */ | 912 | /* send line termination to server */ |
| 902 | if (BIO_write (sslconn, "\r\n", 2) != 2) | 913 | if (BIO_write (server_conn, "\r\n", 2) != 2) |
| 903 | writecf (FS_ERR,"Message sending fuzzy."); | 914 | writecf (FS_ERR,"Message sending fuzzy."); |
| 904 | } | 915 | } |
