/[imapfilter]/imapfilter/socket.c
ViewVC logotype

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.19.2.6 - (show annotations)
Fri Mar 28 16:57:52 2003 UTC (21 years ago) by lefcha
Branch: release-0_8-patches
Changes since 1.19.2.5: +3 -4 lines
File MIME type: text/plain
Correct bug with long headers along with action list and logger.

1 #include <string.h>
2 #include <errno.h>
3 #include <unistd.h>
4 #include <sys/time.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <netdb.h>
9 #include <fcntl.h>
10
11 #include "config.h"
12 #include "imapfilter.h"
13
14 #ifdef SSL_TLS
15 #include <openssl/ssl.h>
16 #include <openssl/err.h>
17 #include <openssl/x509.h>
18 #endif
19
20
21 long timeout = -1; /* Server non-response timeout in seconds. */
22
23 int sockpri = -1; /* Main socket used mostly. */
24 int sockaux = -1; /* Auxiliary socked used when another
25 connection is needed. */
26 #ifdef SSL_TLS
27 static SSL *sslpri = NULL;
28 static SSL *sslaux = NULL;
29 #endif
30
31
32 /*
33 * Connect to mail server.
34 */
35 int init_connection(int *sock, char *serv, unsigned short int port,
36 unsigned int protocol)
37 {
38 struct sockaddr_in sa;
39 struct hostent *he;
40 #ifdef SSL_TLS
41 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
42 #else
43 if (protocol != SSL_DISABLED) {
44 error("imapfilter: SSL not supported by this build\n");
45 return ERROR_SSL;
46 }
47 #endif
48
49 memset((char *)&sa, 0, sizeof(struct sockaddr_in));
50
51 *sock = socket(PF_INET, SOCK_STREAM, 0);
52
53 if (*sock < 0) {
54 error("imapfilter: create socket; %s\n", strerror(errno));
55 return ERROR_NETWORK;
56 }
57 if (!(he = gethostbyname(serv))) {
58 error("imapfilter: get network host entry of %s; %s\n", serv,
59 strerror(errno));
60 close_connection(sock);
61 return ERROR_NETWORK;
62 }
63 sa.sin_family = AF_INET;
64 sa.sin_port = htons(port);
65 sa.sin_addr = *(struct in_addr *) he->h_addr;
66
67 xstrncpy(serv, he->h_name, SERVER_LEN - 1);
68
69 if (connect(*sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {
70 error("imapfilter: initiating connection to %s; %s\n", serv,
71 strerror(errno));
72 close_connection(sock);
73 return ERROR_NETWORK;
74 }
75
76 #ifdef SSL_TLS
77 if (protocol != SSL_DISABLED)
78 if (!ssl_init(sock, protocol)) {
79 if (sock == &sockpri)
80 info("Connected to %s using %s.\n", serv,
81 SSL_get_cipher(*ssl));
82 return 0;
83 } else
84 return ERROR_SSL;
85 else
86 *ssl = NULL;
87 #endif
88
89 if (sock == &sockpri)
90 info("Connected to %s.\n", serv);
91
92 return 0;
93 }
94
95
96 #ifdef SSL_TLS
97 /*
98 * Initialize Secure Socket Layer connection.
99 */
100 int ssl_init(int *sock, unsigned int protocol)
101 {
102 int e;
103 unsigned int i, n = 0;
104 SSL_CTX *ctx;
105 SSL_METHOD *method = NULL;
106 X509 *cert;
107 char *c;
108 const EVP_MD *evp;
109 unsigned char digest[EVP_MAX_MD_SIZE];
110 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
111
112 SSL_library_init();
113
114 switch (protocol) {
115 case SSL_SSL_V2:
116 method = SSLv2_client_method();
117 break;
118 case SSL_SSL_V3:
119 method = SSLv3_client_method();
120 break;
121 case SSL_TLS_V1:
122 method = TLSv1_client_method();
123 break;
124 }
125
126 if (!(ctx = SSL_CTX_new(method)))
127 return ERROR_SSL;
128
129 if (!(*ssl = SSL_new(ctx)))
130 return ERROR_SSL;
131
132 SSL_set_fd(*ssl, *sock);
133
134 e = SSL_connect(*ssl);
135
136 if (e <= 0) {
137 SSL_get_error(*ssl, e);
138 error("imapfilter: initiating SSL connection; %s",
139 ERR_error_string(ERR_get_error(), NULL));
140 return ERROR_SSL;
141 }
142 /* Get server's certificate. */
143 if (!(cert = SSL_get_peer_certificate(*ssl)))
144 return ERROR_SSL;
145
146 if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
147 return ERROR_SSL;
148 verbose("Server certificate subject: %s\n", c);
149 xfree(c);
150
151 if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
152 return ERROR_SSL;
153 verbose("Server certificate issuer: %s\n", c);
154 xfree(c);
155
156 if (!(evp = EVP_md5()))
157 return ERROR_SSL;
158 if (!(X509_digest(cert, evp, digest, &n)))
159 return ERROR_SSL;
160
161 verbose("Server key fingerprint: ");
162 for (i = 0; i < n; i++)
163 verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
164
165 X509_free(cert);
166 SSL_CTX_free(ctx);
167
168 return 0;
169 }
170
171 #endif
172
173
174 /*
175 * Disconnect from mail server.
176 */
177 int close_connection(int *sock)
178 {
179 #ifdef SSL_TLS
180 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
181
182 if (*ssl) {
183 SSL_shutdown(*ssl);
184 SSL_free(*ssl);
185 *ssl = NULL;
186 }
187 #endif
188
189 if (*sock >= 0 && close(*sock)) {
190 error("imapfilter: closing socket; %s\n", strerror(errno));
191 return ERROR_NETWORK;
192 } else {
193 *sock = -1;
194 return 0;
195 }
196 }
197
198
199 /*
200 * Read data from socket.
201 */
202 int socket_read(int *sock, char *buf)
203 {
204 int f, e, s;
205 fd_set fds;
206 struct timeval tv;
207 struct timeval *tvp = NULL;
208 #ifdef SSL_TLS
209 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
210 #endif
211
212 e = 0;
213 s = 1;
214
215 memset(buf, 0, RESPONSE_BUF + 1);
216
217 if (timeout >= 0) {
218 tv.tv_sec = timeout;
219 tv.tv_usec = 0;
220 tvp = &tv;
221 }
222 f = fcntl(*sock, F_GETFL, 0);
223 fcntl(*sock, F_SETFL, f | O_NONBLOCK);
224
225 FD_ZERO(&fds);
226 FD_SET(*sock, &fds);
227
228 #ifdef SSL_TLS
229 if (*ssl) {
230
231 for (;;) {
232 if (SSL_pending(*ssl) ||
233 ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0 &&
234 FD_ISSET(*sock, &fds)))
235 e = SSL_read(*ssl, buf, RESPONSE_BUF);
236
237 if (e > 0)
238 break;
239
240 switch (SSL_get_error(*ssl, e)) {
241 case SSL_ERROR_WANT_READ:
242 case SSL_ERROR_WANT_WRITE:
243 continue;
244 case SSL_ERROR_ZERO_RETURN:
245 return ERROR_NETWORK;
246 case SSL_ERROR_SYSCALL:
247 case SSL_ERROR_SSL:
248 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
249 ERR_error_string(ERR_get_error(), NULL));
250 default:
251 fatal(ERROR_NETWORK,
252 "imapfilter: undefined ssl error while reading data\n");
253 }
254 }
255 } else
256 #endif
257 {
258 if ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0 &&
259 FD_ISSET(*sock, &fds))
260 e = read(*sock, buf, RESPONSE_BUF);
261
262 if (e == -1)
263 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
264 strerror(errno));
265 else if (e == 0)
266 return ERROR_NETWORK;
267 }
268
269 fcntl(*sock, F_SETFL, f);
270
271 if (s == -1)
272 fatal(ERROR_NETWORK, "imapfilter: waiting to read from socket; %s\n",
273 strerror(errno));
274 else if (!s)
275 fatal(ERROR_NETWORK,
276 "imapfilter: timeout period expired while waiting to read "
277 "data\n");
278
279 return 0;
280 }
281
282
283 /*
284 * Write data to socket.
285 */
286 int socket_write(int *sock, char *data)
287 {
288 int f, e, s;
289 fd_set fds;
290 struct timeval tv;
291 struct timeval *tvp = NULL;
292 #ifdef SSL_TLS
293 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
294 #endif
295
296 e = 0;
297 s = 1;
298
299 if (timeout >= 0) {
300 tv.tv_sec = timeout;
301 tv.tv_usec = 0;
302 tvp = &tv;
303 }
304 f = fcntl(*sock, F_GETFL, 0);
305 fcntl(*sock, F_SETFL, f | O_NONBLOCK);
306
307 FD_ZERO(&fds);
308 FD_SET(*sock, &fds);
309
310 #ifdef SSL_TLS
311 if (*ssl) {
312 for (;;) {
313 if ((s = select(*sock + 1, NULL, &fds, NULL, tvp) > 0 &&
314 FD_ISSET(*sock, &fds)))
315 e = SSL_write(*ssl, data, strlen(data));
316
317 if (e > 0)
318 break;
319
320 switch (SSL_get_error(*ssl, e)) {
321 case SSL_ERROR_WANT_READ:
322 case SSL_ERROR_WANT_WRITE:
323 continue;
324 case SSL_ERROR_ZERO_RETURN:
325 return ERROR_NETWORK;
326 case SSL_ERROR_SYSCALL:
327 case SSL_ERROR_SSL:
328 fatal(ERROR_NETWORK, "imapfilter: writing data; %s",
329 ERR_error_string(ERR_get_error(), NULL));
330 default:
331 fatal(ERROR_NETWORK,
332 "imapfilter: undefined ssl error while writing data\n");
333 }
334 }
335 } else
336 #endif
337 {
338 if ((s = select(*sock + 1, NULL, &fds, NULL, tvp)) > 0 &&
339 FD_ISSET(*sock, &fds))
340 e = write(*sock, data, strlen(data));
341
342 if (e == -1)
343 fatal(ERROR_NETWORK, "imapfilter: writing data; %s",
344 strerror(errno));
345 }
346
347 fcntl(*sock, F_SETFL, f);
348
349 if (s == -1)
350 fatal(ERROR_NETWORK, "imapfilter: waiting to write to socket; %s\n",
351 strerror(errno));
352 else if (!s)
353 fatal(ERROR_NETWORK,
354 "imapfilter: timeout period expired while waiting to write "
355 "data\n");
356
357 return 0;
358 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26