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

Contents of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations)
Tue Nov 6 17:41:27 2001 UTC (22 years, 4 months ago) by lefcha
Branch: MAIN
Changes since 1.3: +6 -3 lines
File MIME type: text/plain
Dynamically allocate response buffer.

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 strncpy(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 ssl_init(protocol);
66 info("Connected to %s using %s.\n", serv, SSL_get_cipher(ssl));
67 } else {
68 ssl = NULL;
69 #endif
70 info("Connected to %s.\n", serv);
71 #ifdef SSL_TLS
72 }
73 #endif
74
75
76 return 0;
77 }
78
79
80 #ifdef SSL_TLS
81 /*
82 * Initialize Secure Socket Layer connection.
83 */
84 int ssl_init(unsigned int protocol)
85 {
86 int e;
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 int s, i;
94
95 SSL_library_init();
96
97 switch (protocol) {
98 case SSL_SSL_V2:
99 method = SSLv2_client_method();
100 break;
101 case SSL_SSL_V3:
102 method = SSLv3_client_method();
103 break;
104 case SSL_TLS_V1:
105 method = TLSv1_client_method();
106 break;
107 }
108
109 if (!(ctx = SSL_CTX_new(method)))
110 return ERROR_SSL;
111
112 if (!(ssl = SSL_new(ctx)))
113 return ERROR_SSL;
114
115 SSL_set_fd(ssl, sock);
116
117 e = SSL_connect(ssl);
118
119 if (e <= 0) {
120 error("imapfilter: initiating SSL connection; %s",
121 ERR_error_string(e, NULL));
122 return ERROR_SSL;
123 }
124 /* Get server's certificate. */
125 if (!(cert = SSL_get_peer_certificate(ssl)))
126 return ERROR_SSL;
127
128 if (!(c = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)))
129 return ERROR_SSL;
130 verbose("Server certificate subject: %s\n", c);
131 free(c);
132
133 if (!(c = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)))
134 return ERROR_SSL;
135 verbose("Server certificate issuer: %s\n", c);
136 free(c);
137
138 if (!(evp = EVP_md5()))
139 return ERROR_SSL;
140 if (!(X509_digest(cert, evp, digest, &s)))
141 return ERROR_SSL;
142
143 verbose("Server key fingerprint: ");
144 for (i = 0; i < s; i++)
145 verbose(i != s - 1 ? "%02X:" : "%02X\n", digest[i]);
146
147 X509_free(cert);
148 SSL_CTX_free(ctx);
149
150 return 0;
151 }
152 #endif
153
154
155 /*
156 * Disconnect from mail server.
157 */
158 int close_connection(void)
159 {
160 #ifdef SSL_TLS
161 if (ssl) {
162 SSL_shutdown(ssl);
163 SSL_free(ssl);
164 }
165 #endif
166
167 if (close(sock)) {
168 error("imapfilter: closing socket; %s\n", strerror(errno));
169 return ERROR_NETWORK;
170 } else
171 return 0;
172 }
173
174
175 /*
176 * Read data from socket.
177 */
178 int socket_read(char *buf)
179 {
180 char b[SOCKET_READ_BUF + 1];
181 int flags, e;
182 fd_set fds;
183 struct timeval tv;
184
185 memset(b, 0, SOCKET_READ_BUF + 1);
186
187 tv.tv_sec = 20;
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 if ((select(sock + 1, &fds, NULL, NULL, &tv) > 0)
197 && FD_ISSET(sock, &fds)) {
198
199 #ifdef SSL_TLS
200 if (ssl)
201 e = SSL_read(ssl, b, SOCKET_READ_BUF);
202 else
203 #endif
204 e = read(sock, b, SOCKET_READ_BUF);
205
206 strncat(buf, b, SOCKET_READ_BUF);
207
208 fcntl(sock, F_SETFL, flags);
209
210 #ifdef SSL_TLS
211 if (ssl) {
212 if (e <= 0)
213 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
214 ERR_error_string(e, NULL));
215 } else
216 #endif
217 if (e == -1)
218 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
219 strerror(errno));
220
221 return 0;
222 }
223 fcntl(sock, F_SETFL, flags);
224
225 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
226 strerror(errno));
227
228 return ERROR_NETWORK; /* NEVER REACHED. */
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