summaryrefslogtreecommitdiff
path: root/vchat-protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-protocol.c')
-rwxr-xr-xvchat-protocol.c193
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 */
42int serverfd = -1; 42int serverfd = -1;
43unsigned int usingcert = 1;
44 43
45/* locally global variables */ 44/* locally global variables */
46/* SSL-connection */ 45/* our connection BIO */
47static BIO *sslconn = NULL; 46static BIO *server_conn = NULL;
48 47
49/* declaration of local helper functions */ 48/* declaration of local helper functions */
50static void usersignon (char *); 49static void usersignon (char *);
51static void usersignoff (char *); 50static void usersignoff (char *);
52static void usernickchange (char *); 51static void usernickchange (char *);
53static void userjoin (char *); 52static void userjoin (char *);
54static void userleave (char *); 53static void userleave (char *);
55static void receivenicks (char *message); 54static void receivenicks (char *message);
56static void justloggedin (char *message); 55static void justloggedin (char *message);
57static void nickerr (char *message); 56static void nickerr (char *message);
@@ -64,7 +63,6 @@ static void serverlogin (char *message);
64static void idleprompt (char *message); 63static void idleprompt (char *message);
65static void topicchange (char *message); 64static void topicchange (char *message);
66static void pmnotsent (char *message); 65static void pmnotsent (char *message);
67static 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 */
74extern int status; 72extern int status;
75
76int usessl = 1;
77int ignssl = 0; 73int ignssl = 0;
78char *encoding; 74char *encoding;
79 75
76static 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 */
81int 101int
82vcconnect (char *server, char *port) 102vcconnect (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 */
164void 190void
165vcdisconnect () 191vcdisconnect () {
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 */
172static 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 */
187static void 198static 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}