diff options
-rwxr-xr-x | Makefile | 15 | ||||
-rwxr-xr-x | vchat-client.c | 46 | ||||
-rwxr-xr-x | vchat-commands.c | 13 | ||||
-rwxr-xr-x | vchat-config.h | 1 | ||||
-rw-r--r-- | vchat-connection.c | 223 | ||||
-rw-r--r-- | vchat-connection.h | 9 | ||||
-rwxr-xr-x | vchat-protocol.c | 186 | ||||
-rwxr-xr-x | vchat-tls.c (renamed from vchat-ssl.c) | 64 | ||||
-rwxr-xr-x | vchat-tls.h (renamed from vchat-ssl.h) | 9 | ||||
-rwxr-xr-x | vchat-ui.c | 16 | ||||
-rwxr-xr-x | vchat.h | 10 |
11 files changed, 331 insertions, 261 deletions
@@ -26,11 +26,13 @@ CFLAGS += $(OLDREADLINE) | |||
26 | ## enable debug code | 26 | ## enable debug code |
27 | #CFLAGS += -DDEBUG | 27 | #CFLAGS += -DDEBUG |
28 | 28 | ||
29 | #LDFLAGS = -L"/usr/local/opt/openssl@1.1/lib" | ||
30 | |||
29 | ## the install prefix best is /usr/local | 31 | ## the install prefix best is /usr/local |
30 | PREFIX=/usr/local | 32 | PREFIX=/usr/local |
31 | 33 | ||
32 | LIBS = -lreadline -lncursesw -lssl -lcrypto | 34 | LIBS = -lssl -lcrypto -lncurses -lreadline |
33 | OBJS = vchat-client.o vchat-ui.o vchat-protocol.o vchat-user.o vchat-commands.o vchat-ssl.o | 35 | OBJS = vchat-client.o vchat-ui.o vchat-protocol.o vchat-user.o vchat-commands.o vchat-tls.o vchat-connection.o |
34 | 36 | ||
35 | 37 | ||
36 | ############################################## | 38 | ############################################## |
@@ -66,7 +68,7 @@ clean: | |||
66 | ############################################## | 68 | ############################################## |
67 | 69 | ||
68 | vchat-client: $(OBJS) | 70 | vchat-client: $(OBJS) |
69 | $(CC) $(CFLAGS) -o vchat-client $(OBJS) $(LIBS) | 71 | $(CC) $(CFLAGS) -o vchat-client $(OBJS) $(LIBS) $(LDFLAGS) |
70 | 72 | ||
71 | vchat-client.o: vchat-client.c vchat-config.h Makefile | 73 | vchat-client.o: vchat-client.c vchat-config.h Makefile |
72 | $(CC) $(CFLAGS) -o vchat-client.o -c vchat-client.c | 74 | $(CC) $(CFLAGS) -o vchat-client.o -c vchat-client.c |
@@ -83,8 +85,11 @@ vchat-user.o: vchat-user.c vchat.h | |||
83 | vchat-commands.o: vchat-commands.c vchat.h vchat-config.h | 85 | vchat-commands.o: vchat-commands.c vchat.h vchat-config.h |
84 | $(CC) $(CFLAGS) -o vchat-commands.o -c vchat-commands.c | 86 | $(CC) $(CFLAGS) -o vchat-commands.o -c vchat-commands.c |
85 | 87 | ||
86 | vchat-ssl.o: vchat-ssl.c vchat-ssl.h | 88 | vchat-tls.o: vchat-tls.c vchat-tls.h |
87 | $(CC) $(CFLAGS) -o vchat-ssl.o -c vchat-ssl.c | 89 | $(CC) $(CFLAGS) -o vchat-tls.o -c vchat-tls.c |
90 | |||
91 | vchat-connection.o: vchat-connection.c vchat-connection.h | ||
92 | $(CC) $(CFLAGS) -o vchat-connection.o -c vchat-connection.c | ||
88 | 93 | ||
89 | #vchat-client.1: vchat-client.sgml | 94 | #vchat-client.1: vchat-client.sgml |
90 | # docbook2man vchat-client.sgml | 95 | # docbook2man vchat-client.sgml |
diff --git a/vchat-client.c b/vchat-client.c index 0e480be..d6a3db3 100755 --- a/vchat-client.c +++ b/vchat-client.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <locale.h> | 29 | #include <locale.h> |
30 | 30 | ||
31 | #include "vchat.h" | 31 | #include "vchat.h" |
32 | #include "vchat-connection.h" | ||
32 | #include "vchat-user.h" | 33 | #include "vchat-user.h" |
33 | 34 | ||
34 | /* version of this module */ | 35 | /* version of this module */ |
@@ -43,7 +44,6 @@ int status = 1; | |||
43 | int ownquit = 0; | 44 | int ownquit = 0; |
44 | /* we set this, we DONT want to quit */ | 45 | /* we set this, we DONT want to quit */ |
45 | int wantreconnect = 0; | 46 | int wantreconnect = 0; |
46 | unsigned int want_tcp_keepalive = 0; | ||
47 | 47 | ||
48 | static int reconnect_delay = 6; | 48 | static int reconnect_delay = 6; |
49 | static time_t reconnect_time = 0; | 49 | static time_t reconnect_time = 0; |
@@ -51,17 +51,10 @@ static time_t reconnect_time = 0; | |||
51 | /* error string to show after exit */ | 51 | /* error string to show after exit */ |
52 | char errstr[ERRSTRSIZE] = "\0"; | 52 | char errstr[ERRSTRSIZE] = "\0"; |
53 | 53 | ||
54 | /* locally global variables */ | ||
55 | /* our list of filedescriptors */ | ||
56 | static fd_set masterfds; | ||
57 | |||
58 | /* declaration of configuration array */ | 54 | /* declaration of configuration array */ |
59 | #include "vchat-config.h" | 55 | #include "vchat-config.h" |
60 | 56 | ||
61 | /* servers filedescriptor from vchat-protocol.c */ | 57 | void setnoption (const char *, char *); |
62 | extern int serverfd; | ||
63 | |||
64 | void setnoption (char *, char *); | ||
65 | 58 | ||
66 | static void parsecfg(char *line) { | 59 | static void parsecfg(char *line) { |
67 | int bytes; | 60 | int bytes; |
@@ -264,7 +257,7 @@ setstroption (confopt option, char *string) | |||
264 | 257 | ||
265 | /* set-named-option, puts string to variable named by name */ | 258 | /* set-named-option, puts string to variable named by name */ |
266 | void | 259 | void |
267 | setnoption (char *name, char *string) | 260 | setnoption (const char *name, char *string) |
268 | { | 261 | { |
269 | int i; | 262 | int i; |
270 | #ifdef DEBUG | 263 | #ifdef DEBUG |
@@ -354,11 +347,8 @@ cleanup (int signal) | |||
354 | exitui (); | 347 | exitui (); |
355 | /* clear userlist */ | 348 | /* clear userlist */ |
356 | ul_clear (); | 349 | ul_clear (); |
357 | /* close server connection */ | 350 | vc_disconnect(); |
358 | if (serverfd > 0) { | 351 | |
359 | close (serverfd); | ||
360 | serverfd = -1; | ||
361 | } | ||
362 | /* inform user if we where killed by signal */ | 352 | /* inform user if we where killed by signal */ |
363 | if (signal > 1) | 353 | if (signal > 1) |
364 | { | 354 | { |
@@ -394,12 +384,9 @@ void calleverysecond( void ) { | |||
394 | void | 384 | void |
395 | eventloop (void) | 385 | eventloop (void) |
396 | { | 386 | { |
397 | /* get fresh copy of filedescriptor list */ | 387 | int poll_result = vc_poll( 1 /* second timeout */ ); |
398 | fd_set readfds = masterfds; | ||
399 | struct timeval tv = { 1, 0}; | ||
400 | 388 | ||
401 | switch (select (serverfd + 2, &readfds, NULL, NULL, &tv)) | 389 | switch (poll_result) { |
402 | { | ||
403 | case -1: | 390 | case -1: |
404 | /* EINTR is most likely a SIGWINCH - ignore for now */ | 391 | /* EINTR is most likely a SIGWINCH - ignore for now */ |
405 | if (errno != EINTR) | 392 | if (errno != EINTR) |
@@ -411,19 +398,19 @@ eventloop (void) | |||
411 | writecf (FS_ERR,tmpstr); | 398 | writecf (FS_ERR,tmpstr); |
412 | /* see this as an error condition and bail out */ | 399 | /* see this as an error condition and bail out */ |
413 | status = 0; | 400 | status = 0; |
414 | } | 401 | } |
415 | break; | 402 | break; |
416 | case 0: | 403 | case 0: |
417 | /* time out reached */ | 404 | /* time out reached */ |
418 | calleverysecond(); | 405 | calleverysecond(); |
419 | break; | 406 | break; |
420 | default: | 407 | default: |
421 | /* something to read from user & we're logged in or have a cert? */ | 408 | /* something to read from user & we're logged in or have a cert? */ |
422 | if (FD_ISSET (0, &readfds) ) | 409 | if (poll_result & 1) |
423 | userinput (); | 410 | userinput (); |
424 | 411 | ||
425 | /* something to read from server? */ | 412 | /* something to read from server? */ |
426 | if (serverfd!=-1 && FD_ISSET (serverfd, &readfds)) | 413 | if (poll_result & 2) |
427 | networkinput (); | 414 | networkinput (); |
428 | break; | 415 | break; |
429 | } | 416 | } |
@@ -511,12 +498,8 @@ main (int argc, char **argv) | |||
511 | initui (); | 498 | initui (); |
512 | 499 | ||
513 | while( status ) { | 500 | while( status ) { |
514 | /* add stdin to masterfds */ | ||
515 | FD_ZERO (&masterfds); | ||
516 | FD_SET (0, &masterfds); | ||
517 | |||
518 | /* attempt connection */ | 501 | /* attempt connection */ |
519 | if (vcconnect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { | 502 | if (vc_connect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { |
520 | snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", strerror(errno)); | 503 | snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", strerror(errno)); |
521 | strncpy(errstr,tmpstr,TMPSTRSIZE-2); | 504 | strncpy(errstr,tmpstr,TMPSTRSIZE-2); |
522 | errstr[TMPSTRSIZE-2] = '\0'; | 505 | errstr[TMPSTRSIZE-2] = '\0'; |
@@ -531,8 +514,7 @@ main (int argc, char **argv) | |||
531 | } else | 514 | } else |
532 | status = 0; | 515 | status = 0; |
533 | } else { | 516 | } else { |
534 | /* add serverfd to masterfds, reset reconnect delay */ | 517 | /* reset reconnect delay */ |
535 | FD_SET (serverfd, &masterfds); | ||
536 | reconnect_delay = 6; | 518 | reconnect_delay = 6; |
537 | reconnect_time = 0; | 519 | reconnect_time = 0; |
538 | } | 520 | } |
@@ -541,7 +523,7 @@ main (int argc, char **argv) | |||
541 | eventloop (); | 523 | eventloop (); |
542 | 524 | ||
543 | /* sanely close connection to server */ | 525 | /* sanely close connection to server */ |
544 | vcdisconnect (); | 526 | vc_disconnect (); |
545 | 527 | ||
546 | if( !ownquit && ( getintoption( CF_AUTORECONN ) || wantreconnect ) ) | 528 | if( !ownquit && ( getintoption( CF_AUTORECONN ) || wantreconnect ) ) |
547 | status = 1; | 529 | status = 1; |
diff --git a/vchat-commands.c b/vchat-commands.c index 06c9010..dc46b9c 100755 --- a/vchat-commands.c +++ b/vchat-commands.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | /* local includes */ | 26 | /* local includes */ |
27 | #include "vchat.h" | 27 | #include "vchat.h" |
28 | #include "vchat-connection.h" | ||
28 | #include "vchat-help.h" | 29 | #include "vchat-help.h" |
29 | #include "vchat-user.h" | 30 | #include "vchat-user.h" |
30 | 31 | ||
@@ -146,7 +147,7 @@ dothink( char *tail, char nice ) | |||
146 | 147 | ||
147 | /* send users message to server */ | 148 | /* send users message to server */ |
148 | snprintf (tmpstr, TMPSTRSIZE, ".%c %s", nice, tail); | 149 | snprintf (tmpstr, TMPSTRSIZE, ".%c %s", nice, tail); |
149 | networkoutput (tmpstr); | 150 | vc_sendmessage (tmpstr); |
150 | 151 | ||
151 | /* show action in channel window */ | 152 | /* show action in channel window */ |
152 | snprintf (tmpstr, TMPSTRSIZE, nice == 'O' ? getformatstr(FS_TXPUBNTHOUGHT) : getformatstr(FS_TXPUBTHOUGHT), tail); | 153 | snprintf (tmpstr, TMPSTRSIZE, nice == 'O' ? getformatstr(FS_TXPUBNTHOUGHT) : getformatstr(FS_TXPUBTHOUGHT), tail); |
@@ -163,7 +164,7 @@ doaction( char *tail ) | |||
163 | if( *tail ) { | 164 | if( *tail ) { |
164 | /* send users message to server */ | 165 | /* send users message to server */ |
165 | snprintf (tmpstr, TMPSTRSIZE, ".a %s", tail); | 166 | snprintf (tmpstr, TMPSTRSIZE, ".a %s", tail); |
166 | networkoutput (tmpstr); | 167 | vc_sendmessage (tmpstr); |
167 | 168 | ||
168 | /* show action in channel window */ | 169 | /* show action in channel window */ |
169 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBACTION), own_nick_get(), tail); | 170 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBACTION), own_nick_get(), tail); |
@@ -194,7 +195,7 @@ privatemessagetx ( char *tail ) { | |||
194 | 195 | ||
195 | /* form message and send to server */ | 196 | /* form message and send to server */ |
196 | snprintf (tmpstr, TMPSTRSIZE, ".m %s %s", tail, mesg); | 197 | snprintf (tmpstr, TMPSTRSIZE, ".m %s %s", tail, mesg); |
197 | networkoutput (tmpstr); | 198 | vc_sendmessage (tmpstr); |
198 | 199 | ||
199 | /* show message in private window */ | 200 | /* show message in private window */ |
200 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPRIVMSG), tail, mesg); | 201 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPRIVMSG), tail, mesg); |
@@ -254,7 +255,7 @@ handleline (char *line) | |||
254 | /* generic server command, send to server, show to user */ | 255 | /* generic server command, send to server, show to user */ |
255 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_COMMAND), line); | 256 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_COMMAND), line); |
256 | writechan (tmpstr); | 257 | writechan (tmpstr); |
257 | networkoutput (line); | 258 | vc_sendmessage (line); |
258 | break; | 259 | break; |
259 | } | 260 | } |
260 | break; | 261 | break; |
@@ -274,7 +275,7 @@ output_default(char *line ) { | |||
274 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBMSG), own_nick_get(), line); | 275 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBMSG), own_nick_get(), line); |
275 | 276 | ||
276 | /* send original line to server */ | 277 | /* send original line to server */ |
277 | networkoutput (line); | 278 | vc_sendmessage (line); |
278 | 279 | ||
279 | /* output message to channel window */ | 280 | /* output message to channel window */ |
280 | writechan (tmpstr); | 281 | writechan (tmpstr); |
@@ -430,7 +431,7 @@ command_quit(char *tail) | |||
430 | { | 431 | { |
431 | /* send users message to server */ | 432 | /* send users message to server */ |
432 | snprintf (tmpstr, TMPSTRSIZE, ".x %s", tail); | 433 | snprintf (tmpstr, TMPSTRSIZE, ".x %s", tail); |
433 | networkoutput (tmpstr); | 434 | vc_sendmessage (tmpstr); |
434 | 435 | ||
435 | /* show action in channel window */ | 436 | /* show action in channel window */ |
436 | writechan (tmpstr); | 437 | writechan (tmpstr); |
diff --git a/vchat-config.h b/vchat-config.h index f7123d7..954a029 100755 --- a/vchat-config.h +++ b/vchat-config.h | |||
@@ -36,6 +36,7 @@ static volatile configoption configoptions[] = { | |||
36 | {CF_CONFIGFILE, CO_STR, "conffile", "~/.vchat/config", NULL, { NULL } }, | 36 | {CF_CONFIGFILE, CO_STR, "conffile", "~/.vchat/config", NULL, { NULL } }, |
37 | {CF_CERTFILE, CO_STR, "certfile", "~/.vchat/cert", NULL, { NULL } }, | 37 | {CF_CERTFILE, CO_STR, "certfile", "~/.vchat/cert", NULL, { NULL } }, |
38 | {CF_KEYFILE, CO_STR, "keyfile", "~/.vchat/key", NULL, { NULL } }, | 38 | {CF_KEYFILE, CO_STR, "keyfile", "~/.vchat/key", NULL, { NULL } }, |
39 | {CF_CAFILE, CO_STR, "cafile", "~/.vchat/ca", NULL, { NULL } }, | ||
39 | {CF_FORMFILE, CO_STR, "formatfile", "~/.vchat/formats", NULL, { NULL } }, | 40 | {CF_FORMFILE, CO_STR, "formatfile", "~/.vchat/formats", NULL, { NULL } }, |
40 | {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL, { NULL } }, | 41 | {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL, { NULL } }, |
41 | {CF_FINGERPRINT, CO_STR, "fingerprint","~/.vchat/fingerprint", NULL, { NULL } }, | 42 | {CF_FINGERPRINT, CO_STR, "fingerprint","~/.vchat/fingerprint", NULL, { NULL } }, |
diff --git a/vchat-connection.c b/vchat-connection.c new file mode 100644 index 0000000..e3d79e9 --- /dev/null +++ b/vchat-connection.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * vchat-client - alpha version | ||
3 | * vchat-connection.c - handling of server connection and tls library dispatch | ||
4 | * | ||
5 | * Copyright (C) 2022 Dirk Engling <erdgeist@erdgeist.org> | ||
6 | * | ||
7 | * This program is free software. It can be redistributed and/or modified, | ||
8 | * provided that this copyright notice is kept intact. This program is | ||
9 | * distributed in the hope that it will be useful, but without any warranty; | ||
10 | * without even the implied warranty of merchantability or fitness for a | ||
11 | * particular purpose. In no event shall the copyright holder be liable for | ||
12 | * any direct, indirect, incidental or special damages arising in any way out | ||
13 | * of the use of this software. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <stdlib.h> | ||
18 | #include <stddef.h> | ||
19 | #include <string.h> | ||
20 | #include <stdio.h> | ||
21 | #include <unistd.h> | ||
22 | #include <netdb.h> | ||
23 | #include <errno.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/socket.h> | ||
26 | #include <netinet/in.h> | ||
27 | |||
28 | /* For tilde_expand */ | ||
29 | #include <readline/readline.h> | ||
30 | |||
31 | #include "vchat.h" | ||
32 | #include "vchat-connection.h" | ||
33 | #include "vchat-tls.h" | ||
34 | |||
35 | static int serverfd = -1; | ||
36 | unsigned int want_tcp_keepalive = 0; | ||
37 | |||
38 | /* Generic tcp connector, blocking */ | ||
39 | static int connect_tcp_socket( const char *server, const char *port ) { | ||
40 | struct addrinfo hints, *res, *res0; | ||
41 | int s, error; | ||
42 | |||
43 | memset(&hints, 0, sizeof(hints)); | ||
44 | hints.ai_family = PF_UNSPEC; | ||
45 | hints.ai_socktype = SOCK_STREAM; | ||
46 | error = getaddrinfo( server, port, &hints, &res0 ); | ||
47 | if (error) return -1; | ||
48 | s = -1; | ||
49 | for (res = res0; res; res = res->ai_next) { | ||
50 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
51 | if (s < 0) continue; | ||
52 | if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { | ||
53 | close(s); | ||
54 | s = -1; | ||
55 | continue; | ||
56 | } | ||
57 | break; /* okay we got one */ | ||
58 | } | ||
59 | freeaddrinfo(res0); | ||
60 | |||
61 | if (want_tcp_keepalive) { | ||
62 | int one=1; | ||
63 | setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)); | ||
64 | } | ||
65 | return s; | ||
66 | } | ||
67 | |||
68 | /* Return a tilde expanded path in a malloced buffer or NULL */ | ||
69 | static char *get_tilde_expanded(confopt opt) { | ||
70 | char *str = getstroption (opt); | ||
71 | if (!str) | ||
72 | return str; | ||
73 | if (str[0] == '~') | ||
74 | return tilde_expand (str); | ||
75 | return strdup(str); | ||
76 | } | ||
77 | |||
78 | /* connects to server */ | ||
79 | int | ||
80 | vc_connect (const char *server, const char *port) | ||
81 | { | ||
82 | /* vchat connection x509 store */ | ||
83 | vc_x509store_t *vc_store; | ||
84 | |||
85 | /* pointer to tilde-expanded certificate/keyfile-names */ | ||
86 | char *certfile = NULL; | ||
87 | |||
88 | /* Connect to the server */ | ||
89 | serverfd = connect_tcp_socket( server, port ); | ||
90 | if( serverfd < 0 ) { | ||
91 | /* inform user */ | ||
92 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | ||
93 | writechan (tmpstr); | ||
94 | return -1; | ||
95 | } | ||
96 | |||
97 | if (!getintoption(CF_USESSL)) | ||
98 | return 0; | ||
99 | |||
100 | /* If SSL is requested, get our ssl-BIO running */ | ||
101 | vc_store = vc_init_x509store(); | ||
102 | if( !vc_store ) { | ||
103 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), "Out of memory" ); | ||
104 | writechan (tmpstr); | ||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | /* get name of certificate file */ | ||
109 | certfile = get_tilde_expanded (CF_CERTFILE); | ||
110 | /* do we have a certificate file? */ | ||
111 | if (certfile) { | ||
112 | /* get name of key file */ | ||
113 | char *keyfile = get_tilde_expanded (CF_KEYFILE); | ||
114 | |||
115 | vc_x509store_setflags(vc_store, VC_X509S_USE_CERTIFICATE); | ||
116 | vc_x509store_setcertfile(vc_store, certfile); | ||
117 | |||
118 | vc_x509store_set_pkeycb(vc_store, (vc_askpass_cb_t)passprompt); | ||
119 | /* if we don't have a key file, the key may be in the cert file */ | ||
120 | vc_x509store_setkeyfile(vc_store, keyfile ? keyfile : certfile); | ||
121 | |||
122 | free(keyfile); | ||
123 | free(certfile); | ||
124 | } | ||
125 | |||
126 | if (getintoption(CF_VERIFYSSL)) { | ||
127 | /* get name of key file */ | ||
128 | char *cafile = get_tilde_expanded (CF_CAFILE); | ||
129 | if (cafile) { | ||
130 | vc_x509store_setflags(vc_store, VC_X509S_NODEF_CAFILE); | ||
131 | vc_x509store_setcafile(vc_store, cafile); | ||
132 | } | ||
133 | vc_x509store_setflags(vc_store, VC_X509S_SSL_VERIFY_PEER); | ||
134 | free(cafile); | ||
135 | } | ||
136 | |||
137 | /* upgrade our plain BIO to ssl */ | ||
138 | int result = vc_tls_connect( serverfd, vc_store ); | ||
139 | vc_cleanup_x509store(vc_store); | ||
140 | |||
141 | if (result) { | ||
142 | close(serverfd); | ||
143 | serverfd = -1; | ||
144 | errno = EIO; | ||
145 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | ||
146 | writechan (tmpstr); | ||
147 | return -1; | ||
148 | } | ||
149 | |||
150 | /* inform user */ | ||
151 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); | ||
152 | writechan (tmpstr); | ||
153 | |||
154 | #ifdef DEBUG | ||
155 | dumpfile = fopen( "dumpfile", "a"); | ||
156 | #endif | ||
157 | |||
158 | /* if we didn't fail until now, we've got a connection. */ | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /* Poll for activity on the socket or stdin */ | ||
163 | int vc_poll (int timeout_seconds) { | ||
164 | fd_set readfds; | ||
165 | FD_ZERO (&readfds); | ||
166 | FD_SET (0, &readfds); | ||
167 | if (serverfd != -1) | ||
168 | FD_SET (serverfd, &readfds); | ||
169 | struct timeval tv = { timeout_seconds, 0}; | ||
170 | int result = select (serverfd + 2, &readfds, NULL, NULL, &tv); | ||
171 | if (result <= 0) | ||
172 | return result; | ||
173 | result = FD_ISSET (0, &readfds) ? 1 : 0; | ||
174 | if (serverfd != -1) | ||
175 | result += FD_ISSET (serverfd, &readfds) ? 2 : 0; | ||
176 | return result; | ||
177 | } | ||
178 | |||
179 | /* disconnect from server */ | ||
180 | void | ||
181 | vc_disconnect () { | ||
182 | if (serverfd > 0) { | ||
183 | close(serverfd); | ||
184 | serverfd = -1; | ||
185 | } | ||
186 | vc_tls_cleanup(); | ||
187 | loggedin = 0; | ||
188 | } | ||
189 | |||
190 | void | ||
191 | vc_sendmessage (const char *msg) | ||
192 | { | ||
193 | #ifdef DEBUG | ||
194 | /* debugging? log network output! */ | ||
195 | fprintf (dumpfile, ">| %s (%zd)\n", msg, strlen(msg)); | ||
196 | #endif | ||
197 | |||
198 | if (getintoption(CF_USESSL)) { | ||
199 | /* send data to server */ | ||
200 | if (vc_tls_sendmessage (msg, strlen (msg)) != strlen (msg)) | ||
201 | writecf (FS_ERR,"Message sending fuzzy."); | ||
202 | |||
203 | /* send line termination to server */ | ||
204 | if (vc_tls_sendmessage ("\r\n", 2) != 2) | ||
205 | writecf (FS_ERR,"Message sending fuzzy."); | ||
206 | } else { | ||
207 | /* send data to server */ | ||
208 | if (write (serverfd, msg, strlen (msg)) != strlen (msg)) | ||
209 | writecf (FS_ERR,"Message sending fuzzy."); | ||
210 | |||
211 | /* send line termination to server */ | ||
212 | if (write (serverfd, "\r\n", 2) != 2) | ||
213 | writecf (FS_ERR,"Message sending fuzzy."); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | ssize_t | ||
218 | vc_receivemessage (char *buffer, size_t size) { | ||
219 | if (getintoption(CF_USESSL)) | ||
220 | return vc_tls_receivemessage (buffer, size); | ||
221 | else | ||
222 | return read(serverfd, buffer, size); | ||
223 | } | ||
diff --git a/vchat-connection.h b/vchat-connection.h new file mode 100644 index 0000000..140e467 --- /dev/null +++ b/vchat-connection.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <stdint.h> | ||
4 | |||
5 | int vc_connect(const char *host, const char *port); | ||
6 | void vc_sendmessage(const char *message); | ||
7 | ssize_t vc_receivemessage(char *buffer, size_t size); | ||
8 | int vc_poll(); | ||
9 | void vc_disconnect(); | ||
diff --git a/vchat-protocol.c b/vchat-protocol.c index 0073956..b7d654e 100755 --- a/vchat-protocol.c +++ b/vchat-protocol.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * vchat-client - alpha version | 2 | * vchat-client - alpha version |
3 | * vchat-protocol.c - handling of server connection & messages | 3 | * vchat-protocol.c - handling of server messages |
4 | * | 4 | * |
5 | * Copyright (C) 2001 Andreas Kotes <count@flatline.de> | 5 | * Copyright (C) 2001 Andreas Kotes <count@flatline.de> |
6 | * | 6 | * |
@@ -15,38 +15,26 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | /* general includes */ | 17 | /* general includes */ |
18 | #include <unistd.h> | 18 | #include <stdlib.h> |
19 | #include <errno.h> | ||
20 | #include <stdio.h> | 19 | #include <stdio.h> |
21 | #include <netdb.h> | ||
22 | #include <string.h> | 20 | #include <string.h> |
23 | #include <sys/types.h> | 21 | #include <errno.h> |
24 | #include <sys/socket.h> | ||
25 | #include <netinet/in.h> | ||
26 | #include <readline/readline.h> | 22 | #include <readline/readline.h> |
27 | #include <locale.h> | 23 | #include <locale.h> |
28 | #include <langinfo.h> | 24 | #include <langinfo.h> |
29 | 25 | ||
30 | // TO BE GONE | 26 | #ifdef DEBUG |
31 | #include <openssl/bio.h> | ||
32 | |||
33 | FILE * dumpfile; | 27 | FILE * dumpfile; |
28 | #endif | ||
34 | 29 | ||
35 | /* local includes */ | 30 | /* local includes */ |
36 | #include "vchat.h" | 31 | #include "vchat.h" |
37 | #include "vchat-user.h" | 32 | #include "vchat-user.h" |
38 | #include "vchat-ssl.h" | 33 | #include "vchat-connection.h" |
39 | 34 | ||
40 | /* version of this module */ | 35 | /* version of this module */ |
41 | const char *vchat_io_version = "vchat-protocol.c $Id$"; | 36 | const char *vchat_io_version = "vchat-protocol.c $Id$"; |
42 | 37 | ||
43 | /* externally used variables */ | ||
44 | int serverfd = -1; | ||
45 | |||
46 | /* locally global variables */ | ||
47 | /* our connection BIO */ | ||
48 | static BIO *server_conn = NULL; | ||
49 | |||
50 | /* declaration of local helper functions */ | 38 | /* declaration of local helper functions */ |
51 | static void usersignon (char *); | 39 | static void usersignon (char *); |
52 | static void usersignoff (char *); | 40 | static void usersignoff (char *); |
@@ -74,137 +62,6 @@ static void pmnotsent (char *message); | |||
74 | extern int status; | 62 | extern int status; |
75 | char *encoding; | 63 | char *encoding; |
76 | 64 | ||
77 | static int connect_socket( char *server, char *port ) { | ||
78 | struct addrinfo hints, *res, *res0; | ||
79 | int s, error; | ||
80 | |||
81 | memset(&hints, 0, sizeof(hints)); | ||
82 | hints.ai_family = PF_UNSPEC; | ||
83 | hints.ai_socktype = SOCK_STREAM; | ||
84 | error = getaddrinfo( server, port, &hints, &res0 ); | ||
85 | if (error) return -1; | ||
86 | s = -1; | ||
87 | for (res = res0; res; res = res->ai_next) { | ||
88 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
89 | if (s < 0) continue; | ||
90 | if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { | ||
91 | close(s); | ||
92 | s = -1; | ||
93 | continue; | ||
94 | } | ||
95 | break; /* okay we got one */ | ||
96 | } | ||
97 | freeaddrinfo(res0); | ||
98 | |||
99 | if (want_tcp_keepalive) { /* global from vchat-client.c */ | ||
100 | int one=1; | ||
101 | setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)); | ||
102 | } | ||
103 | return s; | ||
104 | } | ||
105 | |||
106 | /* connects to server */ | ||
107 | int | ||
108 | vcconnect (char *server, char *port) | ||
109 | { | ||
110 | /* used for tilde expansion of cert & key filenames */ | ||
111 | char *tildex = NULL; | ||
112 | |||
113 | /* vchat connection x509 store */ | ||
114 | vc_x509store_t *vc_store; | ||
115 | |||
116 | /* pointer to tilde-expanded certificate/keyfile-names */ | ||
117 | char *certfile = NULL, *keyfile = NULL; | ||
118 | |||
119 | /* Connect to the server */ | ||
120 | serverfd = connect_socket( server, port ); | ||
121 | if( serverfd < 0 ) { | ||
122 | /* inform user */ | ||
123 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | ||
124 | writechan (tmpstr); | ||
125 | return -1; | ||
126 | } | ||
127 | /* Abstract server IO in openssls BIO */ | ||
128 | server_conn = BIO_new_socket( serverfd, 1 ); | ||
129 | |||
130 | /* If SSL is requested, get our ssl-BIO running */ | ||
131 | if( server_conn && getintoption(CF_USESSL) ) { | ||
132 | vc_store = vc_init_x509store(); | ||
133 | if( !vc_store ) { | ||
134 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), "Out of memory" ); | ||
135 | writechan (tmpstr); | ||
136 | return -1; | ||
137 | } | ||
138 | |||
139 | vc_x509store_setflags(vc_store, VC_X509S_SSL_VERIFY_PEER); | ||
140 | |||
141 | /* get name of certificate file */ | ||
142 | certfile = getstroption (CF_CERTFILE); | ||
143 | /* do we have a certificate file? */ | ||
144 | if (certfile) { | ||
145 | /* does the filename start with a tilde? expand it! */ | ||
146 | if (certfile[0] == '~') | ||
147 | tildex = tilde_expand (certfile); | ||
148 | else | ||
149 | tildex = certfile; | ||
150 | |||
151 | vc_x509store_setflags(vc_store, VC_X509S_USE_CERTIFICATE); | ||
152 | vc_x509store_setcertfile(vc_store, tildex); | ||
153 | |||
154 | /* get name of key file */ | ||
155 | keyfile = getstroption (CF_KEYFILE); | ||
156 | |||
157 | /* if we don't have a key file, the key may be in the cert file */ | ||
158 | if (!keyfile) | ||
159 | keyfile = certfile; | ||
160 | |||
161 | /* does the filename start with a tilde? expand it! */ | ||
162 | if (keyfile[0] == '~') | ||
163 | tildex = tilde_expand (keyfile); | ||
164 | else | ||
165 | tildex = keyfile; | ||
166 | |||
167 | vc_x509store_set_pkeycb(vc_store, (vc_askpass_cb_t)passprompt); | ||
168 | vc_x509store_setkeyfile(vc_store, tildex); | ||
169 | } | ||
170 | |||
171 | /* upgrade our plain BIO to ssl */ | ||
172 | if( vc_connect_ssl( &server_conn, vc_store ) ) { | ||
173 | BIO_free_all( server_conn ); | ||
174 | server_conn = NULL; | ||
175 | errno = EIO; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | if( !server_conn ) { | ||
180 | /* inform user */ | ||
181 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | ||
182 | writechan (tmpstr); | ||
183 | return -1; | ||
184 | } | ||
185 | |||
186 | /* inform user */ | ||
187 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); | ||
188 | writechan (tmpstr); | ||
189 | |||
190 | dumpfile = fopen( "dumpfile", "a"); | ||
191 | |||
192 | /* if we didn't fail until now, we've got a connection. */ | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* disconnect from server */ | ||
197 | void | ||
198 | vcdisconnect () { | ||
199 | BIO_free_all( server_conn ); | ||
200 | server_conn = 0; | ||
201 | if (serverfd>0) { | ||
202 | close(serverfd); | ||
203 | serverfd = -1; | ||
204 | } | ||
205 | loggedin = 0; | ||
206 | } | ||
207 | |||
208 | /* handle a pm not sent error | 65 | /* handle a pm not sent error |
209 | * format: 412 %s */ | 66 | * format: 412 %s */ |
210 | static void | 67 | static void |
@@ -264,7 +121,7 @@ serverlogin (char *message) | |||
264 | { | 121 | { |
265 | int utf8=!strcmp(nl_langinfo(CODESET), "UTF-8"); | 122 | int utf8=!strcmp(nl_langinfo(CODESET), "UTF-8"); |
266 | if (utf8) | 123 | if (utf8) |
267 | networkoutput(".e utf8"); | 124 | vc_sendmessage(".e utf8"); |
268 | } | 125 | } |
269 | 126 | ||
270 | /* parse and handle an idle message | 127 | /* parse and handle an idle message |
@@ -401,9 +258,9 @@ justloggedin (char *message) | |||
401 | void | 258 | void |
402 | ownjoin (int channel) | 259 | ownjoin (int channel) |
403 | { | 260 | { |
404 | networkoutput(".t"); | 261 | vc_sendmessage(".t"); |
405 | snprintf(tmpstr, TMPSTRSIZE, ".S %d",channel); | 262 | snprintf(tmpstr, TMPSTRSIZE, ".S %d",channel); |
406 | networkoutput(tmpstr); | 263 | vc_sendmessage(tmpstr); |
407 | } | 264 | } |
408 | 265 | ||
409 | /* this user changes his nick */ | 266 | /* this user changes his nick */ |
@@ -443,7 +300,7 @@ nickerr (char *message) | |||
443 | 300 | ||
444 | /* form login message and send it to server */ | 301 | /* form login message and send it to server */ |
445 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); | 302 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); |
446 | networkoutput (tmpstr); | 303 | vc_sendmessage (tmpstr); |
447 | } | 304 | } |
448 | } | 305 | } |
449 | 306 | ||
@@ -476,7 +333,7 @@ login (char *message) { | |||
476 | 333 | ||
477 | /* form login message and send it to server */ | 334 | /* form login message and send it to server */ |
478 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); | 335 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); |
479 | networkoutput (tmpstr); | 336 | vc_sendmessage (tmpstr); |
480 | } | 337 | } |
481 | 338 | ||
482 | /* parse and handle anon login request | 339 | /* parse and handle anon login request |
@@ -496,7 +353,7 @@ anonlogin (char *message) | |||
496 | 353 | ||
497 | /* form login message and send it to server */ | 354 | /* form login message and send it to server */ |
498 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); | 355 | snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); |
499 | networkoutput (tmpstr); | 356 | vc_sendmessage (tmpstr); |
500 | } | 357 | } |
501 | 358 | ||
502 | /* parse and handle list of nicks (from '.S') | 359 | /* parse and handle list of nicks (from '.S') |
@@ -849,7 +706,7 @@ networkinput (void) | |||
849 | buf[BUFSIZE-1] = '\0'; /* sanity stop */ | 706 | buf[BUFSIZE-1] = '\0'; /* sanity stop */ |
850 | 707 | ||
851 | /* receive data at offset */ | 708 | /* receive data at offset */ |
852 | bytes = BIO_read (server_conn, &buf[bufoff], BUFSIZE-1 - bufoff); | 709 | bytes = vc_receivemessage(&buf[bufoff], BUFSIZE-1 - bufoff); |
853 | 710 | ||
854 | /* no bytes transferred? raise error message, bail out */ | 711 | /* no bytes transferred? raise error message, bail out */ |
855 | if (bytes < 0) | 712 | if (bytes < 0) |
@@ -908,20 +765,3 @@ networkinput (void) | |||
908 | bufoff = 0; | 765 | bufoff = 0; |
909 | } | 766 | } |
910 | } | 767 | } |
911 | |||
912 | void | ||
913 | networkoutput (char *msg) | ||
914 | { | ||
915 | #ifdef DEBUG | ||
916 | /* debugging? log network output! */ | ||
917 | fprintf (dumpfile, ">| %s (%zd)\n", msg, strlen(msg)); | ||
918 | #endif | ||
919 | |||
920 | /* send data to server */ | ||
921 | if (BIO_write (server_conn, msg, strlen (msg)) != strlen (msg)) | ||
922 | writecf (FS_ERR,"Message sending fuzzy."); | ||
923 | |||
924 | /* send line termination to server */ | ||
925 | if (BIO_write (server_conn, "\r\n", 2) != 2) | ||
926 | writecf (FS_ERR,"Message sending fuzzy."); | ||
927 | } | ||
diff --git a/vchat-ssl.c b/vchat-tls.c index adef70d..a6e5e2d 100755 --- a/vchat-ssl.c +++ b/vchat-tls.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * vchat-client - alpha version | 2 | * vchat-client - alpha version |
3 | * vchat-ssl.c - handling of SSL connection and X509 certificate | 3 | * vchat-tls.c - handling of SSL connection and X509 certificate |
4 | * verification | 4 | * verification |
5 | * | 5 | * |
6 | * Copyright (C) 2007 Thorsten Schroeder <ths@berlin.ccc.de> | 6 | * Copyright (C) 2007 Thorsten Schroeder <ths@berlin.ccc.de> |
@@ -31,9 +31,12 @@ | |||
31 | #include <readline/readline.h> | 31 | #include <readline/readline.h> |
32 | 32 | ||
33 | #include "vchat.h" | 33 | #include "vchat.h" |
34 | #include "vchat-ssl.h" | 34 | #include "vchat-tls.h" |
35 | 35 | ||
36 | const char *vchat_ssl_version = "vchat-ssl.c $Id$"; | 36 | const char *vchat_ssl_version = "vchat-tlsl.c $Id$"; |
37 | |||
38 | /* connection BIO for openssl */ | ||
39 | static BIO *server_conn = NULL; | ||
37 | 40 | ||
38 | typedef int (*vc_x509verify_cb_t)(int, X509_STORE_CTX *); | 41 | typedef int (*vc_x509verify_cb_t)(int, X509_STORE_CTX *); |
39 | struct vc_x509store_t { | 42 | struct vc_x509store_t { |
@@ -51,12 +54,10 @@ struct vc_x509store_t { | |||
51 | int flags; | 54 | int flags; |
52 | }; | 55 | }; |
53 | 56 | ||
54 | static void vc_cleanup_x509store(vc_x509store_t *); // Should not be static but is unused | ||
55 | static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ); | 57 | static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ); |
56 | static int vc_verify_callback(int, X509_STORE_CTX *); | 58 | static int vc_verify_callback(int, X509_STORE_CTX *); |
57 | static X509_STORE * vc_x509store_create(vc_x509store_t *); | 59 | static X509_STORE * vc_x509store_create(vc_x509store_t *); |
58 | static void vc_x509store_clearflags(vc_x509store_t *, int); | 60 | static void vc_x509store_clearflags(vc_x509store_t *, int); |
59 | static void vc_x509store_setcafile(vc_x509store_t *, char *); | ||
60 | static void vc_x509store_setcapath(vc_x509store_t *, char *); | 61 | static void vc_x509store_setcapath(vc_x509store_t *, char *); |
61 | static void vc_x509store_setcrlfile(vc_x509store_t *, char *); | 62 | static void vc_x509store_setcrlfile(vc_x509store_t *, char *); |
62 | static void vc_x509store_addcert(vc_x509store_t *, X509 *); | 63 | static void vc_x509store_addcert(vc_x509store_t *, X509 *); |
@@ -90,7 +91,7 @@ static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ) | |||
90 | vc_x509verify_cb_t verify_callback = NULL; | 91 | vc_x509verify_cb_t verify_callback = NULL; |
91 | 92 | ||
92 | /* Explicitly use TLSv1 (or maybe later) */ | 93 | /* Explicitly use TLSv1 (or maybe later) */ |
93 | if( !(ctx = SSL_CTX_new(SSLv23_client_method())) ) | 94 | if( !(ctx = SSL_CTX_new(TLS_client_method())) ) |
94 | VC_CTX_ERR_EXIT(store, ctx); | 95 | VC_CTX_ERR_EXIT(store, ctx); |
95 | 96 | ||
96 | if( !(store = vc_x509store_create(vc_store)) ) | 97 | if( !(store = vc_x509store_create(vc_store)) ) |
@@ -152,7 +153,7 @@ static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ) | |||
152 | return(ctx); | 153 | return(ctx); |
153 | } | 154 | } |
154 | 155 | ||
155 | int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | 156 | int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) |
156 | { | 157 | { |
157 | SSL_CTX * ctx = vc_create_sslctx(vc_store); | 158 | SSL_CTX * ctx = vc_create_sslctx(vc_store); |
158 | X509 *peercert = NULL; | 159 | X509 *peercert = NULL; |
@@ -160,6 +161,8 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | |||
160 | const SSL *sslp = NULL; | 161 | const SSL *sslp = NULL; |
161 | const SSL_CIPHER * cipher = NULL; | 162 | const SSL_CIPHER * cipher = NULL; |
162 | 163 | ||
164 | server_conn = BIO_new_socket( serverfd, 1 ); | ||
165 | |||
163 | /* To display and check server fingerprint */ | 166 | /* To display and check server fingerprint */ |
164 | char fingerprint[EVP_MAX_MD_SIZE*4]; | 167 | char fingerprint[EVP_MAX_MD_SIZE*4]; |
165 | unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; | 168 | unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; |
@@ -171,7 +174,7 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | |||
171 | long result, j; | 174 | long result, j; |
172 | 175 | ||
173 | if( !ctx ) | 176 | if( !ctx ) |
174 | return 1; | 177 | goto all_errors; |
175 | 178 | ||
176 | ssl_conn = BIO_new_ssl(ctx, 1); | 179 | ssl_conn = BIO_new_ssl(ctx, 1); |
177 | SSL_CTX_free(ctx); | 180 | SSL_CTX_free(ctx); |
@@ -179,18 +182,20 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | |||
179 | if( !ssl_conn ) | 182 | if( !ssl_conn ) |
180 | goto ssl_error; | 183 | goto ssl_error; |
181 | 184 | ||
182 | BIO_push( ssl_conn, *conn ); | 185 | BIO_push( ssl_conn, server_conn ); |
183 | *conn = ssl_conn; | 186 | server_conn = ssl_conn; |
184 | fflush(stdout); | 187 | fflush(stdout); |
185 | 188 | ||
186 | if( BIO_do_handshake( *conn ) <= 0 ) | 189 | if( BIO_do_handshake( server_conn ) <= 0 ) |
187 | goto ssl_error; | 190 | goto ssl_error; |
188 | 191 | ||
189 | /* Show information about cipher used */ | 192 | /* Show information about cipher used */ |
190 | /* Get cipher object */ | 193 | /* Get cipher object */ |
191 | BIO_get_ssl(ssl_conn, &sslp); | 194 | BIO_get_ssl(ssl_conn, &sslp); |
192 | if (sslp) | 195 | if (!sslp) |
193 | cipher = SSL_get_current_cipher(sslp); | 196 | goto ssl_error; |
197 | |||
198 | cipher = SSL_get_current_cipher(sslp); | ||
194 | if (cipher) { | 199 | if (cipher) { |
195 | char cipher_desc[TMPSTRSIZE]; | 200 | char cipher_desc[TMPSTRSIZE]; |
196 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); | 201 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); |
@@ -201,9 +206,6 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | |||
201 | } | 206 | } |
202 | 207 | ||
203 | /* Accept being connected, _if_ verification passed */ | 208 | /* Accept being connected, _if_ verification passed */ |
204 | if (!sslp) | ||
205 | goto ssl_error; | ||
206 | |||
207 | peercert = SSL_get_peer_certificate(sslp); | 209 | peercert = SSL_get_peer_certificate(sslp); |
208 | if (!peercert) | 210 | if (!peercert) |
209 | goto ssl_error; | 211 | goto ssl_error; |
@@ -282,7 +284,9 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store ) | |||
282 | ssl_error: | 284 | ssl_error: |
283 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); | 285 | snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); |
284 | writecf(FS_ERR, tmpstr); | 286 | writecf(FS_ERR, tmpstr); |
285 | 287 | all_errors: | |
288 | BIO_free_all( server_conn ); | ||
289 | server_conn = NULL; | ||
286 | return 1; | 290 | return 1; |
287 | } | 291 | } |
288 | 292 | ||
@@ -414,18 +418,6 @@ void vc_x509store_setcertfile(vc_x509store_t *store, char *file) | |||
414 | store->use_certfile = ( file ? strdup(file) : 0 ); | 418 | store->use_certfile = ( file ? strdup(file) : 0 ); |
415 | } | 419 | } |
416 | 420 | ||
417 | #if 0 | ||
418 | int vc_tls_read() | ||
419 | { | ||
420 | |||
421 | } | ||
422 | |||
423 | int vc_tls_read() | ||
424 | { | ||
425 | |||
426 | } | ||
427 | #endif | ||
428 | |||
429 | vc_x509store_t *vc_init_x509store() | 421 | vc_x509store_t *vc_init_x509store() |
430 | { | 422 | { |
431 | vc_x509store_t *s = malloc(sizeof(vc_x509store_t)); | 423 | vc_x509store_t *s = malloc(sizeof(vc_x509store_t)); |
@@ -464,6 +456,20 @@ void vc_cleanup_x509store(vc_x509store_t *s) | |||
464 | sk_X509_free(s->certs); | 456 | sk_X509_free(s->certs); |
465 | sk_X509_CRL_free(s->crls); | 457 | sk_X509_CRL_free(s->crls); |
466 | sk_X509_free(s->use_certs); | 458 | sk_X509_free(s->use_certs); |
459 | free(s); | ||
460 | } | ||
461 | |||
462 | ssize_t vc_tls_sendmessage(const void *buf, size_t size) { | ||
463 | return BIO_write(server_conn, buf, size); | ||
464 | } | ||
465 | |||
466 | ssize_t vc_tls_receivemessage(void *buf, size_t size) { | ||
467 | return BIO_read (server_conn, buf, size); | ||
468 | } | ||
469 | |||
470 | void vc_tls_cleanup() { | ||
471 | BIO_free_all( server_conn ); | ||
472 | server_conn = NULL; | ||
467 | } | 473 | } |
468 | 474 | ||
469 | const char *vchat_ssl_version_external = "OpenSSL implementation; version unknown"; | 475 | const char *vchat_ssl_version_external = "OpenSSL implementation; version unknown"; |
diff --git a/vchat-ssl.h b/vchat-tls.h index 8dc1bfc..8d33ebd 100755 --- a/vchat-ssl.h +++ b/vchat-tls.h | |||
@@ -1,3 +1,4 @@ | |||
1 | #pragma once | ||
1 | 2 | ||
2 | /* prototypes */ | 3 | /* prototypes */ |
3 | 4 | ||
@@ -10,7 +11,13 @@ void vc_x509store_set_pkeycb(vc_x509store_t *, vc_askpass_cb_t); | |||
10 | void vc_x509store_setflags(vc_x509store_t *, int); | 11 | void vc_x509store_setflags(vc_x509store_t *, int); |
11 | void vc_x509store_setkeyfile(vc_x509store_t *, char *); | 12 | void vc_x509store_setkeyfile(vc_x509store_t *, char *); |
12 | void vc_x509store_setcertfile(vc_x509store_t *, char *); | 13 | void vc_x509store_setcertfile(vc_x509store_t *, char *); |
13 | int vc_connect_ssl(BIO **conn, vc_x509store_t * ); | 14 | void vc_x509store_setcafile(vc_x509store_t *, char *); |
15 | void vc_cleanup_x509store(vc_x509store_t *s); | ||
16 | |||
17 | int vc_tls_connect(int serverfd, vc_x509store_t * ); | ||
18 | ssize_t vc_tls_sendmessage(const void *buf, size_t size); | ||
19 | ssize_t vc_tls_receivemessage(void *buf, size_t size); | ||
20 | void vc_tls_cleanup(); | ||
14 | 21 | ||
15 | #define VC_X509S_NODEF_CAFILE 0x01 | 22 | #define VC_X509S_NODEF_CAFILE 0x01 |
16 | #define VC_X509S_NODEF_CAPATH 0x02 | 23 | #define VC_X509S_NODEF_CAPATH 0x02 |
@@ -492,7 +492,7 @@ writescr ( WINDOW *win, struct sb_entry *entry ) { | |||
492 | /* store original attributes */ | 492 | /* store original attributes */ |
493 | WATTR_GET( win, orgattr); | 493 | WATTR_GET( win, orgattr); |
494 | attrbuffer[ 0 ] = orgattr; | 494 | attrbuffer[ 0 ] = orgattr; |
495 | 495 | ||
496 | /* copy time string */ | 496 | /* copy time string */ |
497 | for( i = 0; i < timelen; i++ ) | 497 | for( i = 0; i < timelen; i++ ) |
498 | if( tmp[ i ] == 1 ) { | 498 | if( tmp[ i ] == 1 ) { |
@@ -871,13 +871,13 @@ gettextwidth (const char *textbuffer) | |||
871 | do switch( *(textbuffer++) ) { | 871 | do switch( *(textbuffer++) ) { |
872 | case 1: | 872 | case 1: |
873 | if (!*(textbuffer++)) return width; | 873 | if (!*(textbuffer++)) return width; |
874 | break; | 874 | break; |
875 | case 0: | 875 | case 0: |
876 | return width; | 876 | return width; |
877 | break; | 877 | break; |
878 | default: | 878 | default: |
879 | width++; | 879 | width++; |
880 | break; | 880 | break; |
881 | } while( 1 ); | 881 | } while( 1 ); |
882 | } | 882 | } |
883 | 883 | ||
@@ -920,20 +920,20 @@ getsbeheight (struct sb_entry *entry, const int xwidth, int needstime ) | |||
920 | break; | 920 | break; |
921 | case 1: | 921 | case 1: |
922 | if (!*textbuffer++) return lines; | 922 | if (!*textbuffer++) return lines; |
923 | break; | 923 | break; |
924 | case 0: | 924 | case 0: |
925 | return lines; | 925 | return lines; |
926 | break; | 926 | break; |
927 | case 2: | 927 | case 2: |
928 | textbuffer=entry->what; | 928 | textbuffer=entry->what; |
929 | break; | 929 | break; |
930 | default: | 930 | default: |
931 | if( curx++ == xwidth ) { | 931 | if( curx++ == xwidth ) { |
932 | curx = 0; lines++; | 932 | curx = 0; lines++; |
933 | } | 933 | } |
934 | break; | 934 | break; |
935 | } while( 1 ); | 935 | } while( 1 ); |
936 | 936 | ||
937 | } | 937 | } |
938 | 938 | ||
939 | /* Check, which kind of filter we have to apply: | 939 | /* Check, which kind of filter we have to apply: |
@@ -30,7 +30,7 @@ typedef struct servermessage servermessage; | |||
30 | /* configuration types and variable numbers */ | 30 | /* configuration types and variable numbers */ |
31 | typedef enum { CO_NIL, CO_STR, CO_INT } conftype; | 31 | typedef enum { CO_NIL, CO_STR, CO_INT } conftype; |
32 | typedef enum { CF_NIL, CF_NICK, CF_FROM, CF_SERVERHOST, CF_SERVERPORT, | 32 | typedef enum { CF_NIL, CF_NICK, CF_FROM, CF_SERVERHOST, CF_SERVERPORT, |
33 | CF_CIPHERSUITE, CF_CONFIGFILE, CF_CERTFILE, CF_KEYFILE, CF_FORMFILE, | 33 | CF_CIPHERSUITE, CF_CONFIGFILE, CF_CERTFILE, CF_KEYFILE, CF_CAFILE, CF_FORMFILE, |
34 | CF_LOGINSCRIPT, CF_FINGERPRINT, CF_PINFINGER, CF_USESSL, CF_IGNSSL, CF_VERIFYSSL, CF_USECERT, | 34 | CF_LOGINSCRIPT, CF_FINGERPRINT, CF_PINFINGER, CF_USESSL, CF_IGNSSL, CF_VERIFYSSL, CF_USECERT, |
35 | CF_PRIVHEIGHT, CF_PRIVCOLLAPS, CF_HSCROLL, CF_CHANNEL, CF_USETIME, CF_USETOPIC, | 35 | CF_PRIVHEIGHT, CF_PRIVCOLLAPS, CF_HSCROLL, CF_CHANNEL, CF_USETIME, CF_USETOPIC, |
36 | CF_SCROLLBPRIV, CF_SCROLLBACK, CF_SCROLLBPRIVT, CF_SCROLLBACKT, CF_ENCODING, | 36 | CF_SCROLLBPRIV, CF_SCROLLBACK, CF_SCROLLBPRIVT, CF_SCROLLBACKT, CF_ENCODING, |
@@ -86,7 +86,7 @@ void loadcfg (char *file,int complain,void (*lineparser) (char *)); | |||
86 | void loadformats (char *file); | 86 | void loadformats (char *file); |
87 | void cleanup(int signal); | 87 | void cleanup(int signal); |
88 | 88 | ||
89 | /* configuration helper funktions from vchat-client.c */ | 89 | /* configuration helper functions from vchat-client.c */ |
90 | char *getformatstr (formtstr id); | 90 | char *getformatstr (formtstr id); |
91 | char *getstroption (confopt option); | 91 | char *getstroption (confopt option); |
92 | void setstroption (confopt option, char *string); | 92 | void setstroption (confopt option, char *string); |
@@ -143,10 +143,6 @@ void handlequery ( char *line ); | |||
143 | /* vchat-protocol.c */ | 143 | /* vchat-protocol.c */ |
144 | extern const char *vchat_io_version; | 144 | extern const char *vchat_io_version; |
145 | 145 | ||
146 | /* connect/disconnect */ | ||
147 | int vcconnect (char *server, char *port); | ||
148 | void vcdisconnect (); | ||
149 | |||
150 | /* network I/O */ | 146 | /* network I/O */ |
151 | void networkinput (void); | 147 | void networkinput (void); |
152 | void networkoutput (char *); | 148 | void networkoutput (char *); |
@@ -173,7 +169,7 @@ typedef struct { | |||
173 | char *help; | 169 | char *help; |
174 | } commandentry; | 170 | } commandentry; |
175 | 171 | ||
176 | /* vchat-ssl.c */ | 172 | /* vchat-tls.c */ |
177 | extern const char *vchat_ssl_version; | 173 | extern const char *vchat_ssl_version; |
178 | extern const char *vchat_ssl_version_external; | 174 | extern const char *vchat_ssl_version_external; |
179 | void vchat_ssl_get_version_external(); | 175 | void vchat_ssl_get_version_external(); |