Mercurial > hg
annotate mcabber/connwrap/connwrap.c @ 1566:d64e0b2855fc
Fix display of last character in the input line when Aspell support is enabled
The rightmost character displayed in the input line was always the last
character of the line. (Reported by isbear.)
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 08 Feb 2009 10:08:05 +0100 |
parents | 3067c096cfc4 |
children |
rev | line source |
---|---|
25 | 1 #include "connwrap.h" |
2 | |
302
8ca708a0d550
Remove compilation warnings in connwrap library
Mikael Berthe <mikael@lilotux.net>
parents:
235
diff
changeset
|
3 #include <stdio.h> |
8ca708a0d550
Remove compilation warnings in connwrap library
Mikael Berthe <mikael@lilotux.net>
parents:
235
diff
changeset
|
4 #include <stdlib.h> |
25 | 5 #include <netdb.h> |
6 #include <string.h> | |
7 #include <netinet/in.h> | |
8 #include <errno.h> | |
9 #include <arpa/inet.h> | |
10 #include <fcntl.h> | |
11 #include <sys/time.h> | |
112 | 12 #include <unistd.h> |
25 | 13 |
14 #define PROXY_TIMEOUT 10 | |
15 // HTTP proxy timeout in seconds (for the CONNECT method) | |
16 | |
17 #ifdef HAVE_OPENSSL | |
1253 | 18 # define OPENSSL_NO_KRB5 1 |
19 # include <openssl/ssl.h> | |
20 # include <openssl/err.h> | |
21 # define HAVE_SSL | |
22 # undef HAVE_GNUTLS // Can't use both... | |
23 #elif defined HAVE_GNUTLS | |
24 # include <gnutls/gnutls.h> | |
25 # define HAVE_SSL | |
25 | 26 #endif |
27 | |
28 static int in_http_connect = 0; | |
29 | |
30 #ifdef HAVE_OPENSSL | |
1253 | 31 static SSL_CTX *ctx = NULL; |
32 typedef struct { int fd; SSL *ssl; } sslsock; | |
33 #elif defined HAVE_GNUTLS | |
34 typedef struct { int fd; gnutls_session_t session; } sslsock; | |
35 #endif | |
25 | 36 |
1253 | 37 |
38 #ifdef HAVE_SSL | |
25 | 39 |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
40 /* verify > 0 indicates verify depth as well */ |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
41 static int verify = -1; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
42 static const char *cafile = NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
43 static const char *capath = NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
44 static const char *cipherlist = NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
45 static const char *peer = NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
46 static const char *sslerror = NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
47 |
1253 | 48 #ifdef HAVE_OPENSSL |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
49 static int verify_cb(int preverify_ok, X509_STORE_CTX *cx) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
50 { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
51 X509 *cert; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
52 X509_NAME *nm; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
53 int lastpos; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
54 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
55 if(!preverify_ok) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
56 long err = X509_STORE_CTX_get_error(cx); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
57 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
58 sslerror = X509_verify_cert_error_string(err); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
59 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
60 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
61 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
62 if (peer == NULL) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
63 return 1; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
64 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
65 if ((cert = X509_STORE_CTX_get_current_cert(cx)) == NULL) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
66 sslerror = "internal SSL error"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
67 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
68 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
69 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
70 /* We only want to look at the peername if we're working on the peer |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
71 * certificate. */ |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
72 if (cert != cx->cert) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
73 return 1; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
74 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
75 if ((nm = X509_get_subject_name (cert)) == NULL) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
76 sslerror = "internal SSL error"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
77 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
78 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
79 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
80 for(lastpos = -1; ; ) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
81 X509_NAME_ENTRY *e; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
82 ASN1_STRING *a; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
83 ASN1_STRING *p; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
84 int match; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
85 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
86 lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
87 if (lastpos == -1) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
88 break; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
89 if ((e = X509_NAME_get_entry(nm, lastpos)) == NULL) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
90 sslerror = "internal SSL error"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
91 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
92 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
93 if ((a = X509_NAME_ENTRY_get_data(e)) == NULL) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
94 sslerror = "internal SSL error"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
95 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
96 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
97 if ((p = ASN1_STRING_type_new(ASN1_STRING_type(a))) == NULL) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
98 sslerror = "internal SSL error"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
99 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
100 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
101 (void) ASN1_STRING_set(p, peer, -1); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
102 match = !ASN1_STRING_cmp(a, p); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
103 ASN1_STRING_free(p); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
104 if(match) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
105 return 1; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
106 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
107 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
108 sslerror = "server certificate cn mismatch"; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
109 return 0; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
110 } |
1253 | 111 #endif |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
112 |
1253 | 113 static void init(int fd, sslsock *p) { |
114 #ifdef HAVE_GNUTLS | |
115 gnutls_certificate_credentials_t xcred; | |
116 #endif | |
117 | |
118 #ifdef HAVE_OPENSSL | |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
119 if(ctx) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
120 return; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
121 SSL_library_init(); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
122 SSL_load_error_strings(); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
123 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
124 #ifdef HAVE_SSLEAY |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
125 SSLeay_add_all_algorithms(); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
126 #else |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
127 OpenSSL_add_all_algorithms(); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
128 #endif |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
129 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
130 /* May need to use distinct SSLEAY bindings below... */ |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
131 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
132 ctx = SSL_CTX_new(SSLv23_client_method()); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
133 if(cipherlist) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
134 (void)SSL_CTX_set_cipher_list(ctx, cipherlist); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
135 if(cafile || capath) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
136 (void)SSL_CTX_load_verify_locations(ctx, cafile, capath); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
137 if(verify) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
138 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
139 if(verify > 0) |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
140 SSL_CTX_set_verify_depth(ctx, verify); |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
141 } else |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
142 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); |
1253 | 143 |
144 p->ssl = SSL_new(ctx); | |
145 SSL_set_fd(p->ssl, p->fd = fd); | |
146 | |
147 #elif defined HAVE_GNUTLS | |
148 gnutls_global_init(); | |
149 gnutls_certificate_allocate_credentials(&xcred); | |
150 gnutls_init(&(p->session), GNUTLS_CLIENT); | |
151 gnutls_set_default_priority(p->session); | |
152 gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, xcred); | |
153 p->fd = fd; | |
154 gnutls_transport_set_ptr(p->session,(gnutls_transport_ptr_t)fd); | |
155 #endif | |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
156 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
157 |
1253 | 158 static sslsock *socks = NULL; |
25 | 159 static int sockcount = 0; |
160 | |
161 static sslsock *getsock(int fd) { | |
162 int i; | |
163 | |
164 for(i = 0; i < sockcount; i++) | |
165 if(socks[i].fd == fd) | |
166 return &socks[i]; | |
167 | |
1253 | 168 return NULL; |
25 | 169 } |
170 | |
171 static sslsock *addsock(int fd) { | |
172 sslsock *p; | |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
173 |
1253 | 174 sockcount++; |
175 | |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
176 if (socks) |
1253 | 177 socks = (sslsock *) realloc(socks, sizeof(sslsock)*sockcount); |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
178 else |
1253 | 179 socks = (sslsock *) malloc(sizeof(sslsock)*sockcount); |
25 | 180 |
181 p = &socks[sockcount-1]; | |
182 | |
1253 | 183 init(fd, p); |
25 | 184 |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
185 sslerror = NULL; |
25 | 186 |
187 return p; | |
188 } | |
189 | |
190 static void delsock(int fd) { | |
191 int i, nsockcount; | |
192 sslsock *nsocks; | |
193 | |
194 nsockcount = 0; | |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
195 |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
196 if (sockcount > 1) { |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
197 nsocks = (sslsock *) malloc(sizeof(sslsock)*(sockcount-1)); |
25 | 198 |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
199 for(i = 0; i < sockcount; i++) { |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
200 if(socks[i].fd != fd) { |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
201 nsocks[nsockcount++] = socks[i]; |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
202 } else { |
1253 | 203 #ifdef HAVE_OPENSSL |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
204 SSL_free(socks[i].ssl); |
1253 | 205 #elif defined HAVE_GNUTLS |
206 gnutls_bye(socks[i].session, GNUTLS_SHUT_WR); | |
207 gnutls_deinit(socks[i].session); | |
208 #endif | |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
209 } |
25 | 210 } |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
211 |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
212 } else { |
1253 | 213 #ifdef HAVE_OPENSSL |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
214 if (ctx) |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
215 SSL_CTX_free(ctx); |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
216 ctx = 0; |
1253 | 217 #endif |
218 nsocks = NULL; | |
25 | 219 } |
220 | |
984
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
221 if (socks) |
3225a1ba050d
Fix a potential libconnwrap issue
Mikael Berthe <mikael@lilotux.net>
parents:
955
diff
changeset
|
222 free(socks); |
25 | 223 socks = nsocks; |
224 sockcount = nsockcount; | |
225 } | |
226 | |
1253 | 227 void cw_set_ssl_options(int sslverify, |
228 const char *sslcafile, const char *sslcapath, | |
229 const char *sslciphers, const char *sslpeer) { | |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
230 verify = sslverify; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
231 cafile = sslcafile; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
232 capath = sslcapath; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
233 cipherlist = sslciphers; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
234 peer = sslpeer; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
235 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
236 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
237 const char *cw_get_ssl_error(void) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
238 return sslerror; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
239 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
240 |
1253 | 241 #else // HAVE_SSL |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
242 |
1253 | 243 void cw_set_ssl_options(int sslverify, |
244 const char *sslcafile, const char *sslcapath, | |
245 const char *sslciphers, const char *sslpeer) { } | |
938
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
246 |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
247 const char *cw_get_ssl_error(void) { |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
248 return NULL; |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
249 } |
40175f3dcef7
SSL server certificate verification
Jefferson Ogata <ogata@antibozo.net>
parents:
431
diff
changeset
|
250 |
1253 | 251 #endif // HAVE_SSL |
25 | 252 |
253 static char *bindaddr = 0, *proxyhost = 0, *proxyuser = 0, *proxypass = 0; | |
254 static int proxyport = 3128; | |
255 static int proxy_ssl = 0; | |
256 | |
257 #define SOCKOUT(s) write(sockfd, s, strlen(s)) | |
258 | |
259 int cw_http_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen) { | |
260 int err, pos, fl; | |
261 struct hostent *server; | |
262 struct sockaddr_in paddr; | |
263 char buf[512]; | |
264 fd_set rfds; | |
265 | |
400
e536ab271584
Kill a warning in the connwrap library
Mikael Berthe <mikael@lilotux.net>
parents:
302
diff
changeset
|
266 fl = 0; |
25 | 267 err = 0; |
268 in_http_connect = 1; | |
269 | |
270 if(!(server = gethostbyname(proxyhost))) { | |
271 errno = h_errno; | |
272 err = -1; | |
273 } | |
274 | |
275 if(!err) { | |
276 memset(&paddr, 0, sizeof(paddr)); | |
277 paddr.sin_family = AF_INET; | |
278 memcpy(&paddr.sin_addr.s_addr, *server->h_addr_list, server->h_length); | |
279 paddr.sin_port = htons(proxyport); | |
280 | |
281 fl = fcntl(sockfd, F_GETFL); | |
282 fcntl(sockfd, F_SETFL, fl & ~O_NONBLOCK); | |
283 | |
284 buf[0] = 0; | |
285 | |
1253 | 286 err = cw_connect(sockfd, (struct sockaddr *) &paddr, sizeof(paddr), |
287 proxy_ssl); | |
25 | 288 } |
289 | |
290 errno = ECONNREFUSED; | |
291 | |
292 if(!err) { | |
293 struct sockaddr_in *sin = (struct sockaddr_in *) serv_addr; | |
294 char *ip = inet_ntoa(sin->sin_addr), c; | |
295 struct timeval tv; | |
296 | |
1387 | 297 snprintf(buf, sizeof(buf), "%d", ntohs(sin->sin_port)); |
25 | 298 SOCKOUT("CONNECT "); |
299 SOCKOUT(ip); | |
300 SOCKOUT(":"); | |
301 SOCKOUT(buf); | |
302 SOCKOUT(" HTTP/1.0\r\n"); | |
303 | |
304 if(proxyuser) { | |
305 char *b; | |
306 SOCKOUT("Proxy-Authorization: Basic "); | |
307 | |
427
ac85ce87f539
Fix buffer overflow in cw_setproxy()
Mikael Berthe <mikael@lilotux.net>
parents:
414
diff
changeset
|
308 snprintf(buf, sizeof(buf), "%s:%s", proxyuser, proxypass); |
25 | 309 b = cw_base64_encode(buf); |
310 SOCKOUT(b); | |
311 free(b); | |
312 | |
313 SOCKOUT("\r\n"); | |
314 } | |
315 | |
316 SOCKOUT("\r\n"); | |
317 | |
318 buf[0] = 0; | |
319 | |
320 while(err != -1) { | |
321 FD_ZERO(&rfds); | |
322 FD_SET(sockfd, &rfds); | |
323 | |
324 tv.tv_sec = PROXY_TIMEOUT; | |
325 tv.tv_usec = 0; | |
326 | |
327 err = select(sockfd+1, &rfds, 0, 0, &tv); | |
328 | |
329 if(err < 1) err = -1; | |
330 | |
331 if(err != -1 && FD_ISSET(sockfd, &rfds)) { | |
332 err = read(sockfd, &c, 1); | |
333 if(!err) err = -1; | |
334 | |
335 if(err != -1) { | |
336 pos = strlen(buf); | |
337 buf[pos] = c; | |
338 buf[pos+1] = 0; | |
339 | |
340 if(strlen(buf) > 4) | |
341 if(!strcmp(buf+strlen(buf)-4, "\r\n\r\n")) | |
342 break; | |
343 } | |
344 } | |
345 } | |
346 } | |
347 | |
348 if(err != -1 && strlen(buf)) { | |
349 char *p = strstr(buf, " "); | |
350 | |
351 err = -1; | |
352 | |
353 if(p) | |
354 if(atoi(++p) == 200) | |
355 err = 0; | |
356 | |
357 fcntl(sockfd, F_SETFL, fl); | |
358 if(fl & O_NONBLOCK) { | |
359 errno = EINPROGRESS; | |
360 err = -1; | |
361 } | |
362 } | |
363 | |
364 in_http_connect = 0; | |
365 | |
366 return err; | |
367 } | |
368 | |
1253 | 369 int cw_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, |
370 int ssl) { | |
25 | 371 int rc; |
372 struct sockaddr_in ba; | |
373 | |
374 if(bindaddr) | |
375 if(strlen(bindaddr)) { | |
376 #ifdef HAVE_INET_ATON | |
377 struct in_addr addr; | |
378 rc = inet_aton(bindaddr, &addr); | |
379 ba.sin_addr.s_addr = addr.s_addr; | |
380 #else | |
381 rc = inet_pton(AF_INET, bindaddr, &ba); | |
382 #endif | |
383 | |
384 if(rc) { | |
385 ba.sin_port = 0; | |
386 rc = bind(sockfd, (struct sockaddr *) &ba, sizeof(ba)); | |
387 } else { | |
388 rc = -1; | |
389 } | |
390 | |
391 if(rc) return rc; | |
392 } | |
393 | |
1253 | 394 if(proxyhost && !in_http_connect) |
395 rc = cw_http_connect(sockfd, serv_addr, addrlen); | |
396 else | |
397 rc = connect(sockfd, serv_addr, addrlen); | |
25 | 398 |
399 #ifdef HAVE_OPENSSL | |
400 if(ssl && !rc) { | |
401 sslsock *p = addsock(sockfd); | |
402 if(SSL_connect(p->ssl) != 1) | |
1253 | 403 return -1; // XXX "Can't connect to SSL" |
25 | 404 } |
405 #endif | |
406 | |
407 return rc; | |
408 } | |
409 | |
1253 | 410 int cw_nb_connect(int sockfd, const struct sockaddr *serv_addr, int addrlen, |
411 int ssl, int *state) { | |
25 | 412 int rc = 0; |
413 struct sockaddr_in ba; | |
414 | |
415 if(bindaddr) | |
416 if(strlen(bindaddr)) { | |
417 #ifdef HAVE_INET_ATON | |
418 struct in_addr addr; | |
419 rc = inet_aton(bindaddr, &addr); | |
420 ba.sin_addr.s_addr = addr.s_addr; | |
421 #else | |
422 rc = inet_pton(AF_INET, bindaddr, &ba); | |
423 #endif | |
424 | |
425 if(rc) { | |
426 ba.sin_port = 0; | |
427 rc = bind(sockfd, (struct sockaddr *) &ba, sizeof(ba)); | |
428 } else { | |
429 rc = -1; | |
430 } | |
431 | |
432 if(rc) return rc; | |
433 } | |
434 | |
1253 | 435 #ifdef HAVE_SSL |
25 | 436 if(ssl) { |
1253 | 437 if ( !(*state & CW_CONNECT_WANT_SOMETHING)) { |
25 | 438 rc = cw_connect(sockfd, serv_addr, addrlen, 0); |
1253 | 439 } else { /* check if the socket is connected correctly */ |
25 | 440 int optlen = sizeof(int), optval; |
1253 | 441 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, |
442 (socklen_t*)&optlen) || optval) | |
443 return -1; | |
25 | 444 } |
445 | |
446 if(!rc) { | |
1253 | 447 #ifdef HAVE_GNUTLS |
448 int ret; | |
449 #endif | |
25 | 450 sslsock *p; |
451 if (*state & CW_CONNECT_SSL) | |
452 p = getsock(sockfd); | |
453 else | |
454 p = addsock(sockfd); | |
414
ec86d759ed54
Trailing whitespace cleanup
Mikael Berthe <mikael@lilotux.net>
parents:
409
diff
changeset
|
455 |
1253 | 456 #ifdef HAVE_GNUTLS |
457 do { | |
458 ret = gnutls_handshake(p->session); | |
459 } while ((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)); | |
460 if (ret < 0) { | |
461 gnutls_deinit(p->session); | |
462 gnutls_perror(ret); | |
463 return -1; | |
464 } | |
465 else{ | |
466 *state = 1; | |
467 return 0; | |
468 } | |
469 #elif defined HAVE_OPENSSL | |
25 | 470 rc = SSL_connect(p->ssl); |
471 switch(rc){ | |
472 case 1: | |
473 *state = 0; | |
474 return 0; | |
475 case 0: | |
476 return -1; | |
477 default: | |
478 switch (SSL_get_error(p->ssl, rc)){ | |
479 case SSL_ERROR_WANT_READ: | |
480 *state = CW_CONNECT_SSL | CW_CONNECT_WANT_READ; | |
481 return 0; | |
482 case SSL_ERROR_WANT_WRITE: | |
483 *state = CW_CONNECT_SSL | CW_CONNECT_WANT_WRITE; | |
484 return 0; | |
485 default: | |
486 return -1; | |
487 } | |
488 } | |
1253 | 489 #endif |
490 } else { /* catch EINPROGRESS error from the connect call */ | |
25 | 491 if (errno == EINPROGRESS){ |
492 *state = CW_CONNECT_STARTED | CW_CONNECT_WANT_WRITE; | |
493 return 0; | |
494 } | |
495 } | |
496 | |
497 return rc; | |
498 } | |
499 #endif | |
1253 | 500 if ( !(*state & CW_CONNECT_WANT_SOMETHING)) { |
1266
3bd496b9a9f7
Fix proxy usage when SSL is disabled
Mikael Berthe <mikael@lilotux.net>
parents:
1253
diff
changeset
|
501 rc = cw_connect(sockfd, serv_addr, addrlen, 0); |
1253 | 502 } else { /* check if the socket is connected correctly */ |
25 | 503 int optlen = sizeof(int), optval; |
1253 | 504 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, |
505 (socklen_t*)&optlen) || optval) | |
25 | 506 return -1; |
507 *state = 0; | |
508 return 0; | |
509 } | |
510 if (rc) | |
511 if (errno == EINPROGRESS){ | |
512 *state = CW_CONNECT_STARTED | CW_CONNECT_WANT_WRITE; | |
513 return 0; | |
514 } | |
515 return rc; | |
516 } | |
517 | |
518 int cw_accept(int s, struct sockaddr *addr, int *addrlen, int ssl) { | |
519 #ifdef HAVE_OPENSSL | |
520 int rc; | |
521 | |
522 if(ssl) { | |
235 | 523 rc = accept(s, addr, (socklen_t*)addrlen); |
25 | 524 |
525 if(!rc) { | |
526 sslsock *p = addsock(s); | |
527 if(SSL_accept(p->ssl) != 1) | |
528 return -1; | |
529 } | |
530 return rc; | |
531 } | |
532 #endif | |
235 | 533 return accept(s, addr, (socklen_t*)addrlen); |
25 | 534 } |
535 | |
536 int cw_write(int fd, const void *buf, int count, int ssl) { | |
1253 | 537 #ifdef HAVE_SSL |
25 | 538 sslsock *p; |
539 | |
1253 | 540 if(ssl) { |
541 #ifdef HAVE_GNUTLS | |
542 p = getsock(fd); | |
543 if(p) { | |
544 int ret; | |
545 if((ret = gnutls_record_send( p->session, buf, count) < 0)) | |
546 fprintf(stderr, "Can't write to server"); | |
547 return ret; | |
548 } | |
549 #elif defined HAVE_OPENSSL | |
550 if((p = getsock(fd)) != NULL) | |
551 return SSL_write(p->ssl, buf, count); | |
25 | 552 #endif |
1253 | 553 } |
554 #endif // HAVE_SSL | |
25 | 555 return write(fd, buf, count); |
556 } | |
557 | |
558 int cw_read(int fd, void *buf, int count, int ssl) { | |
1253 | 559 #ifdef HAVE_SSL |
25 | 560 sslsock *p; |
561 | |
1253 | 562 if(ssl) { |
563 #ifdef HAVE_GNUTLS | |
564 p = getsock(fd); | |
565 if(p) { | |
566 int ret; | |
567 do { | |
568 ret = gnutls_record_recv(p->session, buf, count); | |
569 } while (ret < 0 && | |
570 (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)); | |
571 return ret; | |
572 } | |
573 #elif defined HAVE_OPENSSL | |
574 if((p = getsock(fd)) != NULL) | |
575 return SSL_read(p->ssl, buf, count); | |
25 | 576 #endif |
1253 | 577 } |
578 #endif // HAVE_SSL | |
25 | 579 return read(fd, buf, count); |
580 } | |
581 | |
235 | 582 void cw_close(int fd) { |
1253 | 583 #ifdef HAVE_SSL |
25 | 584 delsock(fd); |
585 #endif | |
586 close(fd); | |
587 } | |
588 | |
589 #define FREEVAR(v) if(v) free(v), v = 0; | |
590 | |
591 void cw_setbind(const char *abindaddr) { | |
592 FREEVAR(bindaddr); | |
593 bindaddr = strdup(abindaddr); | |
594 } | |
595 | |
1253 | 596 void cw_setproxy(const char *aproxyhost, int aproxyport, |
597 const char *aproxyuser, const char *aproxypass) { | |
25 | 598 FREEVAR(proxyhost); |
599 FREEVAR(proxyuser); | |
600 FREEVAR(proxypass); | |
601 | |
602 if(aproxyhost && strlen(aproxyhost)) proxyhost = strdup(aproxyhost); | |
603 if(aproxyuser && strlen(aproxyuser)) proxyuser = strdup(aproxyuser); | |
604 if(aproxypass && strlen(aproxypass)) proxypass = strdup(aproxypass); | |
605 proxyport = aproxyport; | |
606 } | |
607 | |
608 char *cw_base64_encode(const char *in) { | |
609 static char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._"; | |
610 | |
611 int j = 0; | |
612 int inlen = strlen(in); | |
613 char *out = (char *) malloc(inlen*4+1), c; | |
614 | |
615 for(out[0] = 0; inlen >= 3; inlen -= 3) { | |
616 strncat(out, &base64digits[ in[j] >> 2 ], 1); | |
617 strncat(out, &base64digits[ ((in[j] << 4) & 0x30) | (in[j+1] >> 4) ], 1); | |
618 strncat(out, &base64digits[ ((in[j+1] << 2) & 0x3c) | (in[j+2] >> 6) ], 1); | |
619 strncat(out, &base64digits[ in[j+2] & 0x3f ], 1); | |
620 j += 3; | |
621 } | |
622 | |
623 if(inlen > 0) { | |
624 unsigned char fragment; | |
625 | |
626 strncat(out, &base64digits[in[j] >> 2], 1); | |
627 fragment = (in[j] << 4) & 0x30; | |
628 | |
629 if(inlen > 1) | |
630 fragment |= in[j+1] >> 4; | |
631 | |
632 strncat(out, &base64digits[fragment], 1); | |
633 | |
634 c = (inlen < 2) ? '-' : base64digits[ (in[j+1] << 2) & 0x3c ]; | |
635 strncat(out, &c, 1); | |
636 c = '-'; | |
637 strncat(out, &c, 1); | |
638 } | |
414
ec86d759ed54
Trailing whitespace cleanup
Mikael Berthe <mikael@lilotux.net>
parents:
409
diff
changeset
|
639 |
25 | 640 return out; |
641 } |