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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.20 - (show annotations)
Mon Jul 29 01:30:51 2002 UTC (21 years, 8 months ago) by lefcha
Branch: MAIN
Changes since 1.19: +28 -18 lines
File MIME type: text/plain
Major bug fix concerning SSL and rcopy/rmove.

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 log_info(LOG_SERVER, serv);
76
77 #ifdef SSL_TLS
78 if (protocol != SSL_DISABLED)
79 if (!ssl_init(sock, protocol)) {
80 if (sock == &sockpri)
81 info("Connected to %s using %s.\n", serv,
82 SSL_get_cipher(*ssl));
83 return 0;
84 } else
85 return ERROR_SSL;
86 else
87 *ssl = NULL;
88 #endif
89
90 if (sock == &sockpri)
91 info("Connected to %s.\n", serv);
92
93 return 0;
94 }
95
96
97 #ifdef SSL_TLS
98 /*
99 * Initialize Secure Socket Layer connection.
100 */
101 int ssl_init(int *sock, unsigned int protocol)
102 {
103 int e;
104 unsigned int i, n = 0;
105 SSL_CTX *ctx;
106 SSL_METHOD *method = NULL;
107 X509 *cert;
108 char *c;
109 EVP_MD *evp;
110 unsigned char digest[EVP_MAX_MD_SIZE];
111 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
112
113 SSL_library_init();
114
115 switch (protocol) {
116 case SSL_SSL_V2:
117 method = SSLv2_client_method();
118 break;
119 case SSL_SSL_V3:
120 method = SSLv3_client_method();
121 break;
122 case SSL_TLS_V1:
123 method = TLSv1_client_method();
124 break;
125 }
126
127 if (!(ctx = SSL_CTX_new(method)))
128 return ERROR_SSL;
129
130 if (!(*ssl = SSL_new(ctx)))
131 return ERROR_SSL;
132
133 SSL_set_fd(*ssl, *sock);
134
135 e = SSL_connect(*ssl);
136
137 if (e < 0) {
138 error("imapfilter: initiating SSL connection; %s",
139 ERR_error_string(e, 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, r, 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 r = 0;
213 s = 1;
214
215 memset(buf, 0, RESPONSE_BUF);
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 if (SSL_pending(*ssl)
231 || ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
232 && FD_ISSET(*sock, &fds)))
233 r = SSL_read(*ssl, buf, RESPONSE_BUF - 1);
234 } else
235 #endif
236 if ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
237 && FD_ISSET(*sock, &fds))
238 r = read(*sock, buf, RESPONSE_BUF - 1);
239
240 fcntl(*sock, F_SETFL, f);
241
242 if (s == -1)
243 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
244 strerror(errno));
245 else if (!s)
246 fatal(ERROR_NETWORK,
247 "imapfilter: timeout period expired while waiting data\n");
248
249 #ifdef SSL_TLS
250 if (*ssl) {
251 if (r < 0)
252 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
253 ERR_error_string(r, NULL));
254 } else
255 #endif
256 if (r == -1)
257 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
258 strerror(errno));
259
260 return 0;
261 }
262
263
264 /*
265 * Write data to socket.
266 */
267 int socket_write(int *sock, char *data)
268 {
269 #ifdef SSL_TLS
270 int e;
271 SSL **ssl = (sock == &sockpri ? &sslpri : &sslaux);
272
273 if (*ssl) {
274 e = SSL_write(*ssl, data, strlen(data));
275 if (e <= 0)
276 fatal(ERROR_NETWORK,
277 "imapfilter: sending data; %s",
278 ERR_error_string(e, NULL));
279 } else
280 #endif
281 if (write(*sock, data, strlen(data)) == -1)
282 fatal(ERROR_NETWORK, "imapfilter: sending data; %s",
283 strerror(errno));
284
285 return 0;
286 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26