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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Fri Nov 9 16:55:15 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.7: +18 -14 lines
File MIME type: text/plain
A fix about select() timeout period.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26