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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Sat Nov 10 19:39:22 2001 UTC (22 years, 5 months ago) by lefcha
Branch: MAIN
CVS Tags: release-0_7
Branch point for: release-0_7-patches
Changes since 1.11: +3 -1 lines
File MIME type: text/plain
Small change.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26