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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations)
Tue Jun 18 21:21:58 2002 UTC (21 years, 9 months ago) by lefcha
Branch: MAIN
Changes since 1.17: +28 -27 lines
File MIME type: text/plain
Changes to reflect rcopy/rmove capability.

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 *ssl;
28 #endif
29
30
31 /*
32 * Connect to mail server.
33 */
34 int init_connection(int *sock, char *serv, unsigned short int port,
35 unsigned int protocol)
36 {
37 struct sockaddr_in sa;
38 struct hostent *he;
39
40 #ifndef SSL_TLS
41 if (protocol != SSL_DISABLED) {
42 error("imapfilter: SSL not supported by this build\n");
43 return ERROR_SSL;
44 }
45 #endif
46
47 memset((char *) &sa, 0, sizeof(struct sockaddr_in));
48
49 *sock = socket(PF_INET, SOCK_STREAM, 0);
50
51 if (*sock < 0) {
52 error("imapfilter: create socket; %s\n", strerror(errno));
53 return ERROR_NETWORK;
54 }
55 if (!(he = gethostbyname(serv))) {
56 error("imapfilter: get network host entry of %s; %s\n", serv,
57 strerror(errno));
58 close_connection(sock);
59 return ERROR_NETWORK;
60 }
61 sa.sin_family = AF_INET;
62 sa.sin_port = htons(port);
63 sa.sin_addr = *(struct in_addr *) he->h_addr;
64
65 xstrncpy(serv, he->h_name, SERVER_LEN - 1);
66
67 if (connect(*sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {
68 error("imapfilter: initiating connection to %s; %s\n", serv,
69 strerror(errno));
70 close_connection(sock);
71 return ERROR_NETWORK;
72 }
73 log_info(LOG_SERVER, serv);
74
75 #ifdef SSL_TLS
76 if (protocol != SSL_DISABLED)
77 if (!ssl_init(sock, protocol)) {
78 info("Connected to %s using %s.\n", serv, SSL_get_cipher(ssl));
79 return 0;
80 } else
81 return ERROR_SSL;
82 else
83 ssl = NULL;
84 #endif
85
86 info("Connected to %s.\n", serv);
87
88 return 0;
89 }
90
91
92 #ifdef SSL_TLS
93 /*
94 * Initialize Secure Socket Layer connection.
95 */
96 int ssl_init(int *sock, unsigned int protocol)
97 {
98 int e;
99 unsigned int i, n = 0;
100 SSL_CTX *ctx;
101 SSL_METHOD *method = NULL;
102 X509 *cert;
103 char *c;
104 EVP_MD *evp;
105 unsigned char digest[EVP_MAX_MD_SIZE];
106
107 SSL_library_init();
108
109 switch (protocol) {
110 case SSL_SSL_V2:
111 method = SSLv2_client_method();
112 break;
113 case SSL_SSL_V3:
114 method = SSLv3_client_method();
115 break;
116 case SSL_TLS_V1:
117 method = TLSv1_client_method();
118 break;
119 }
120
121 if (!(ctx = SSL_CTX_new(method)))
122 return ERROR_SSL;
123
124 if (!(ssl = SSL_new(ctx)))
125 return ERROR_SSL;
126
127 SSL_set_fd(ssl, *sock);
128
129 e = SSL_connect(ssl);
130
131 if (e < 0) {
132 error("imapfilter: initiating SSL connection; %s",
133 ERR_error_string(e, NULL));
134 return ERROR_SSL;
135 }
136 /* Get server's certificate. */
137 if (!(cert = SSL_get_peer_certificate(ssl)))
138 return ERROR_SSL;
139
140 if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
141 return ERROR_SSL;
142 verbose("Server certificate subject: %s\n", c);
143 xfree(c);
144
145 if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
146 return ERROR_SSL;
147 verbose("Server certificate issuer: %s\n", c);
148 xfree(c);
149
150 if (!(evp = EVP_md5()))
151 return ERROR_SSL;
152 if (!(X509_digest(cert, evp, digest, &n)))
153 return ERROR_SSL;
154
155 verbose("Server key fingerprint: ");
156 for (i = 0; i < n; i++)
157 verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
158
159 X509_free(cert);
160 SSL_CTX_free(ctx);
161
162 return 0;
163 }
164 #endif
165
166
167 /*
168 * Disconnect from mail server.
169 */
170 int close_connection(int *sock)
171 {
172 #ifdef SSL_TLS
173 if (ssl) {
174 SSL_shutdown(ssl);
175 SSL_free(ssl);
176 }
177 #endif
178
179 if (*sock >= 0 && close(*sock)) {
180 error("imapfilter: closing socket; %s\n", strerror(errno));
181 return ERROR_NETWORK;
182 } else {
183 *sock = -1;
184 return 0;
185 }
186 }
187
188
189 /*
190 * Read data from socket.
191 */
192 int socket_read(int *sock, char *buf)
193 {
194 int f, r, s;
195 fd_set fds;
196 struct timeval tv;
197 struct timeval *tvp = NULL;
198
199 r = 0;
200 s = 1;
201
202 memset(buf, 0, RESPONSE_BUF);
203
204 if (timeout >= 0) {
205 tv.tv_sec = timeout;
206 tv.tv_usec = 0;
207 tvp = &tv;
208 }
209 f = fcntl(*sock, F_GETFL, 0);
210 fcntl(*sock, F_SETFL, f | O_NONBLOCK);
211
212 FD_ZERO(&fds);
213 FD_SET(*sock, &fds);
214
215 #ifdef SSL_TLS
216 if (ssl) {
217 if (SSL_pending(ssl)
218 || ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
219 && FD_ISSET(*sock, &fds)))
220 r = SSL_read(ssl, buf, RESPONSE_BUF - 1);
221 } else
222 #endif
223 if ((s = select(*sock + 1, &fds, NULL, NULL, tvp)) > 0
224 && FD_ISSET(*sock, &fds))
225 r = read(*sock, buf, RESPONSE_BUF - 1);
226
227 fcntl(*sock, F_SETFL, f);
228
229 if (s == -1)
230 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
231 strerror(errno));
232 else if (!s)
233 fatal(ERROR_NETWORK,
234 "imapfilter: timeout period expired while waiting data\n");
235
236 #ifdef SSL_TLS
237 if (ssl) {
238 if (r < 0)
239 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
240 ERR_error_string(r, NULL));
241 } else
242 #endif
243 if (r == -1)
244 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
245 strerror(errno));
246
247 return 0;
248 }
249
250
251 /*
252 * Write data to socket.
253 */
254 int socket_write(int *sock, char *data)
255 {
256 #ifdef SSL_TLS
257 int e;
258
259 if (ssl) {
260 e = SSL_write(ssl, data, strlen(data));
261 if (e <= 0)
262 fatal(ERROR_NETWORK,
263 "imapfilter: sending data; %s",
264 ERR_error_string(e, NULL));
265 } else
266 #endif
267 if (write(*sock, data, strlen(data)) == -1)
268 fatal(ERROR_NETWORK, "imapfilter: sending data; %s",
269 strerror(errno));
270
271 return 0;
272 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26