diff options
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 | } |