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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Fri Nov 9 23:38:25 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
Changes since 1.9: +2 -3 lines
File MIME type: text/plain
Missing header file.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26