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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 lefcha 1.1 #include <string.h>
2     #include <errno.h>
3     #include <unistd.h>
4 lefcha 1.10 #include <sys/time.h>
5 lefcha 1.1 #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 lefcha 1.3 #include <openssl/x509.h>
18 lefcha 1.1
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 lefcha 1.9 xstrncpy(serv, he->h_name, SERVER_LEN - 1);
56    
57 lefcha 1.1 if (connect(sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {
58 lefcha 1.9 error("imapfilter: initiating connection to %s; %s\n", serv, strerror(errno));
59 lefcha 1.1 close_connection();
60     return ERROR_NETWORK;
61     }
62     log_info(LOG_SERVER, serv);
63 lefcha 1.2
64 lefcha 1.1 #ifdef SSL_TLS
65 lefcha 1.9 if (protocol != SSL_DISABLED && !ssl_init(protocol)) {
66     info("Connected to %s using %s.\n", serv, SSL_get_cipher(ssl));
67     return 0;
68 lefcha 1.8 } else
69 lefcha 1.1 ssl = NULL;
70     #endif
71    
72 lefcha 1.8 info("Connected to %s.\n", serv);
73 lefcha 1.10
74 lefcha 1.1 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 lefcha 1.7 unsigned int i, n = 0;
86 lefcha 1.1 SSL_CTX *ctx;
87     SSL_METHOD *method = NULL;
88 lefcha 1.3 X509 *cert;
89     char *c;
90     EVP_MD *evp;
91     unsigned char digest[EVP_MAX_MD_SIZE];
92 lefcha 1.2
93 lefcha 1.1 SSL_library_init();
94 lefcha 1.2
95 lefcha 1.1 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 lefcha 1.2
107 lefcha 1.1 if (!(ctx = SSL_CTX_new(method)))
108     return ERROR_SSL;
109 lefcha 1.2
110 lefcha 1.1 if (!(ssl = SSL_new(ctx)))
111     return ERROR_SSL;
112 lefcha 1.2
113 lefcha 1.1 SSL_set_fd(ssl, sock);
114    
115     e = SSL_connect(ssl);
116 lefcha 1.2
117 lefcha 1.1 if (e <= 0) {
118     error("imapfilter: initiating SSL connection; %s",
119     ERR_error_string(e, NULL));
120     return ERROR_SSL;
121     }
122 lefcha 1.3 /* 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 lefcha 1.7 if (!(X509_digest(cert, evp, digest, &n)))
139 lefcha 1.3 return ERROR_SSL;
140    
141     verbose("Server key fingerprint: ");
142 lefcha 1.7 for (i = 0; i < n; i++)
143     verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
144 lefcha 1.3
145     X509_free(cert);
146 lefcha 1.1 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 lefcha 1.6 int flags, r, s;
179 lefcha 1.1 fd_set fds;
180     struct timeval tv;
181 lefcha 1.7
182 lefcha 1.8 r = 0;
183     s = 1;
184 lefcha 1.1
185 lefcha 1.5 memset(buf, 0, RESPONSE_BUF);
186 lefcha 1.1
187 lefcha 1.8 tv.tv_sec = 60;
188 lefcha 1.1 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 lefcha 1.6 if (ssl) {
198 lefcha 1.8 if (SSL_pending(ssl)
199     || ((s = select(sock + 1, &fds, NULL, NULL, &tv)) > 0
200     && FD_ISSET(sock, &fds)))
201 lefcha 1.6 r = SSL_read(ssl, buf, RESPONSE_BUF - 1);
202     } else
203 lefcha 1.1 #endif
204 lefcha 1.6 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 lefcha 1.2
210 lefcha 1.8 if (s == -1)
211 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
212     strerror(errno));
213 lefcha 1.8 else if (!s)
214     fatal(ERROR_NETWORK,
215     "imapfilter: timeout period expired while waiting data\n");
216 lefcha 1.1
217     #ifdef SSL_TLS
218 lefcha 1.6 if (ssl) {
219 lefcha 1.8 if (r < 0)
220 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
221     ERR_error_string(r, NULL));
222     } else
223 lefcha 1.1 #endif
224 lefcha 1.6 if (r == -1)
225     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
226     strerror(errno));
227 lefcha 1.1
228 lefcha 1.6 return 0;
229 lefcha 1.1 }
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 lefcha 1.2
252 lefcha 1.1 return 0;
253     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26