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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12.2.1 - (show annotations)
Wed Dec 5 09:56:52 2001 UTC (22 years, 3 months ago) by lefcha
Branch: release-0_7-patches
Changes since 1.12: +19 -11 lines
File MIME type: text/plain
Added server non response timeout variable.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26