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

Annotation of /imapfilter/socket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide 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 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 lefcha 1.11 int init_connection(char *serv, unsigned short int port)
31 lefcha 1.1 #else
32 lefcha 1.11 int init_connection(char *serv, unsigned short int port, unsigned int protocol)
33 lefcha 1.1 #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 lefcha 1.12
47 lefcha 1.1 if (!(he = gethostbyname(serv))) {
48 lefcha 1.12 error("imapfilter: get network host entry of %s; %s\n", serv,
49     strerror(errno));
50 lefcha 1.1 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 lefcha 1.9 xstrncpy(serv, he->h_name, SERVER_LEN - 1);
58    
59 lefcha 1.1 if (connect(sock, (struct sockaddr *) & sa, sizeof(struct sockaddr))) {
60 lefcha 1.9 error("imapfilter: initiating connection to %s; %s\n", serv, strerror(errno));
61 lefcha 1.1 close_connection();
62     return ERROR_NETWORK;
63     }
64     log_info(LOG_SERVER, serv);
65 lefcha 1.2
66 lefcha 1.1 #ifdef SSL_TLS
67 lefcha 1.11 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 lefcha 1.1 ssl = NULL;
75     #endif
76    
77 lefcha 1.8 info("Connected to %s.\n", serv);
78 lefcha 1.10
79 lefcha 1.1 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 lefcha 1.7 unsigned int i, n = 0;
91 lefcha 1.1 SSL_CTX *ctx;
92     SSL_METHOD *method = NULL;
93 lefcha 1.3 X509 *cert;
94     char *c;
95     EVP_MD *evp;
96     unsigned char digest[EVP_MAX_MD_SIZE];
97 lefcha 1.2
98 lefcha 1.1 SSL_library_init();
99 lefcha 1.2
100 lefcha 1.1 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 lefcha 1.2
112 lefcha 1.1 if (!(ctx = SSL_CTX_new(method)))
113     return ERROR_SSL;
114 lefcha 1.2
115 lefcha 1.1 if (!(ssl = SSL_new(ctx)))
116     return ERROR_SSL;
117 lefcha 1.2
118 lefcha 1.1 SSL_set_fd(ssl, sock);
119    
120     e = SSL_connect(ssl);
121 lefcha 1.2
122 lefcha 1.1 if (e <= 0) {
123     error("imapfilter: initiating SSL connection; %s",
124     ERR_error_string(e, NULL));
125     return ERROR_SSL;
126     }
127 lefcha 1.3 /* 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 lefcha 1.7 if (!(X509_digest(cert, evp, digest, &n)))
144 lefcha 1.3 return ERROR_SSL;
145    
146     verbose("Server key fingerprint: ");
147 lefcha 1.7 for (i = 0; i < n; i++)
148     verbose(i != n - 1 ? "%02X:" : "%02X\n", digest[i]);
149 lefcha 1.3
150     X509_free(cert);
151 lefcha 1.1 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 lefcha 1.6 int flags, r, s;
184 lefcha 1.1 fd_set fds;
185     struct timeval tv;
186 lefcha 1.7
187 lefcha 1.8 r = 0;
188     s = 1;
189 lefcha 1.1
190 lefcha 1.5 memset(buf, 0, RESPONSE_BUF);
191 lefcha 1.1
192 lefcha 1.8 tv.tv_sec = 60;
193 lefcha 1.1 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 lefcha 1.6 if (ssl) {
203 lefcha 1.8 if (SSL_pending(ssl)
204     || ((s = select(sock + 1, &fds, NULL, NULL, &tv)) > 0
205     && FD_ISSET(sock, &fds)))
206 lefcha 1.6 r = SSL_read(ssl, buf, RESPONSE_BUF - 1);
207     } else
208 lefcha 1.1 #endif
209 lefcha 1.6 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 lefcha 1.2
215 lefcha 1.8 if (s == -1)
216 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: waiting input from socket; %s\n",
217     strerror(errno));
218 lefcha 1.8 else if (!s)
219     fatal(ERROR_NETWORK,
220     "imapfilter: timeout period expired while waiting data\n");
221 lefcha 1.1
222     #ifdef SSL_TLS
223 lefcha 1.6 if (ssl) {
224 lefcha 1.8 if (r < 0)
225 lefcha 1.6 fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
226     ERR_error_string(r, NULL));
227     } else
228 lefcha 1.1 #endif
229 lefcha 1.6 if (r == -1)
230     fatal(ERROR_NETWORK, "imapfilter: reading data; %s",
231     strerror(errno));
232 lefcha 1.1
233 lefcha 1.6 return 0;
234 lefcha 1.1 }
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 lefcha 1.2
257 lefcha 1.1 return 0;
258     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26