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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (show annotations)
Sat Nov 10 15:33:01 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
Changes since 1.10: +9 -6 lines
File MIME type: text/plain
To next server if SSL problem occured.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26