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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (show annotations)
Fri Feb 8 22:15:43 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.16: +7 -4 lines
File MIME type: text/plain
Allow ssl appear in config file, but fail with error message.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26