"Fossies" - the Fresh Open Source Software Archive 
Member "tlswrap-1.04/tls.c" (25 Nov 2006, 14513 Bytes) of package /linux/privat/old/tlswrap-1.04.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "tls.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * Copyright (c) 2002-2006 Tomas Svensson <ts@codepix.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #ifdef WIN32
33 #include <Winsock2.h>
34 #define snprintf _snprintf
35 #define strcasecmp _stricmp
36 #else
37 #include <unistd.h>
38 #include <syslog.h>
39 #include <arpa/ftp.h>
40 #include <sys/time.h>
41 #include <netinet/in.h>
42 #include <pwd.h>
43 #endif
44 #include <ctype.h>
45 #include <openssl/ssl.h>
46 #include <openssl/rand.h>
47 #include <openssl/err.h>
48 #include <openssl/x509v3.h>
49 #include <fcntl.h>
50
51 #include "tlswrap.h"
52 #include "tls.h"
53 #include "misc.h"
54
55 extern int debug;
56 /* extern int sec_mode;
57
58 int global_user_cert;
59 X509_STORE *ca_store; */
60
61 void tls_init(char *egd_sock) {
62
63 if (!SSL_library_init())
64 sys_err("OpenSSL initialization failed");
65
66 SSL_load_error_strings(); /* load readable error messages */
67 /*
68 if (!(tls_ctx = SSL_CTX_new(SSLv23_method()))) {
69 printf("SSL_CTX_new() %s\r\n",(char *)ERR_error_string(ERR_get_error(), NULL));
70 exit(1);
71 }*/
72 if (debug)
73 printf("egd_sock is %s\n", egd_sock);
74 #ifdef HAVE_RAND_STATUS
75 if (RAND_status() != 1) {
76 if ( RAND_egd(egd_sock) == -1 ) {
77 fprintf(stderr, "egd_sock is %s\n", egd_sock);
78 sys_err("RAND_egd failed\n");
79 }
80 if (RAND_status() != 1)
81 sys_err("ssl_init: System without /dev/urandom, PRNG seeding must be done manually.\r\n");
82 }
83 #endif
84 /*
85 SSL_CTX_set_options(tls_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
86 SSL_CTX_set_default_verify_paths(tls_ctx);
87 */
88 // global_user_cert = 0;
89
90 /*
91 if (sec_mode > 0) {
92 if (SSL_CTX_use_certificate_chain_file(tls_ctx, "usercert.pem") == 1) {
93 if (SSL_CTX_use_PrivateKey_file(tls_ctx, "usercert.pem", SSL_FILETYPE_PEM) != 1)
94 sys_err("Unable to load private key from file.");
95 else
96 global_user_cert = 1;
97 if (debug)
98 printf("Global user certificate chain loaded.\n");
99 } else {
100 if (debug)
101 printf("No global user certificate loaded.\n");
102 }
103 */
104
105 /*
106 if (cafile[0] != '\0') { // CA verifications.
107 if (SSL_CTX_load_verify_locations(tls_ctx, cafile, NULL) != 1)
108 sys_err("could not load certificates from CA file.");
109 else if (debug)
110 printf("Loaded CA file.\n");
111 ca_store = SSL_CTX_get_cert_store(tls_ctx);
112 } else
113 ca_store = NULL;
114
115 SSL_CTX_set_cert_store(tls_ctx, NULL);
116 SSL_CTX_free(tls_ctx);
117 */
118 if (debug)
119 printf("TLS initialization successful.\n");
120
121 }
122
123 void
124 tls_auth(struct user_data *ud, int data, char *ucertspath, char *cafile)
125 {
126 SSL *ssl;
127 char fn[NI_MAXHOST];
128
129 #ifdef WIN32
130 char sep = '\\';
131 #else
132 char sep = '/';
133 #endif
134
135 if (!data) {
136 if ((ud->ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) {
137 printf("SSL_CTX_new() %s\n",(char *)ERR_error_string(ERR_get_error(), NULL));
138 exit(1);
139 }
140 if (cafile[0] != '\0') { // CA verifications.
141 if (SSL_CTX_load_verify_locations(ud->ssl_ctx, cafile, NULL) != 1)
142 sys_err("could not load certificates from CA file.");
143 else if (debug)
144 printf("Loaded CA file.\n");
145 }
146 SSL_CTX_set_options(ud->ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
147 SSL_CTX_set_default_verify_paths(ud->ssl_ctx);
148
149 if (ucertspath[0] != '\0') { /* Try to load user certificate chain */
150 if (ucertspath[strlen(ucertspath)] == sep)
151 snprintf(fn, sizeof(fn), "%s%s.pem",ucertspath, ud->serv_dns.hostname);
152 else
153 snprintf(fn, sizeof(fn), "%s%c%s.pem",ucertspath, sep, ud->serv_dns.hostname);
154 if (SSL_CTX_use_certificate_chain_file(ud->ssl_ctx, fn) != 1) {
155 if (debug)
156 printf("failed to load %s\n", fn);
157 } else {
158 if (debug)
159 printf("loaded %s\n", fn);
160 }
161 }
162 }
163
164 ssl = SSL_new(ud->ssl_ctx);
165
166 if (ssl == NULL) {
167 printf("SSL_new() %s\r\n",(char *)ERR_error_string(ERR_get_error(), NULL));
168 exit(1);
169 }
170
171 if (data)
172 ud->ssl_data = ssl;
173 else
174 ud->ssl_ctrl = ssl;
175 if (debug)
176 printf("tls_auth: ciphers: %s\n", cfg_tlsciphers);
177
178 SSL_set_cipher_list(ssl, cfg_tlsciphers);
179
180 /* if (sec_mode >= 3)
181 SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); */
182
183 if (data) {
184 if (SSL_set_fd(ssl, ud->serv_data_fd) != 1)
185 printf("SSL_set_fd_error\n");
186 if (ud->ssl_sess) { /* There is a cached SSL session */
187 SSL_set_session(ssl, ud->ssl_sess);
188 SSL_SESSION_free(ud->ssl_sess);
189 ud->ssl_sess = NULL;
190 }
191 } else {
192 if (SSL_set_fd(ssl, ud->serv_fd) != 1)
193 printf("SSL_set_fd_error\n");
194 }
195
196 SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
197 tls_auth_cont(ud, data);
198 }
199
200 int tls_cert(struct user_data *ud, int data) /* save new key or verify saved key */
201 {
202 X509 *x509_peer, *x509_stored;
203 FILE *fp;
204 char filename[1024];
205 int cert_ok;
206
207 cert_ok = 0;
208 x509_stored = NULL;
209
210 if (debug)
211 printf("tls_cert\n");
212
213 if ((x509_peer = SSL_get_peer_certificate((data) ? ud->ssl_data : ud->ssl_ctrl)) == NULL)
214 return 0; /* SSL_get_peer* can only be NULL on 'anonymous DH connections' so shouldn't happen. */
215
216 snprintf(filename, sizeof(filename), "%s-%s.pem", (data && !ud->epsv) ? ud->serv_data_host : ud->serv_dns.hostname,
217 (data) ? "data" : "ctrl");
218 if ( (fp = fopen(filename, "r")) == NULL) { /* key doesn't exist, store it */
219 if (debug)
220 printf("key %s doesn't exist, store it\n", filename);
221 if (ud->sec_level == 2) { /* don't add new certs */
222 X509_free(x509_peer);
223 return 0;
224 }
225 if ( (fp = fopen(filename, "w")) == NULL) {
226 X509_free(x509_peer);
227 sys_err(filename);
228 } else {
229 PEM_write_X509(fp, x509_peer);
230 cert_ok = 1;
231 }
232 } else { /* KEY already exists, verify it */
233 if (debug)
234 printf("key %s exists, verifying it\n", filename);
235 if((x509_stored = PEM_read_X509(fp, NULL, 0, NULL)) == NULL)
236 sys_err("can't read certificate");
237 if (X509_cmp(x509_peer, x509_stored) == 0)
238 cert_ok = 1;
239 else {
240 if (debug)
241 printf("X509_cmp failed\n");
242 }
243
244 if (debug && cert_ok)
245 printf("verified cert ok\n");
246 }
247
248 fclose(fp);
249
250 X509_free(x509_peer);
251 if (x509_stored != NULL)
252 X509_free(x509_stored);
253 return cert_ok;
254 }
255
256 long tls_cert2(struct user_data *ud, int data) /* save new key or verify saved key */
257 {
258 X509 *x509_peer;
259 X509_NAME *x509_subj;
260 X509_EXTENSION *x509_ext;
261 X509V3_EXT_METHOD *x509_meth;
262 int ok, extcount, i, j;
263 char *extstr;
264 SSL *ssl;
265 #if (OPENSSL_VERSION_NUMBER > 0x00908000L)
266 unsigned char const *data1;
267 #else
268 unsigned char *data1;
269 #endif
270 char data2[256];
271 STACK_OF(CONF_VALUE) *val;
272 CONF_VALUE *nval;
273 void *ext_str = NULL;
274 int subjectaltname;
275
276 ok = subjectaltname = 0;
277 ssl = (data) ? ud->ssl_data : ud->ssl_ctrl;
278
279 if (debug)
280 printf("tls_cert2\n");
281
282 if ((x509_peer = SSL_get_peer_certificate(ssl)) == NULL)
283 return X509_V_ERR_APPLICATION_VERIFICATION; /* SSL_get_peer* can only be NULL on 'anonymous DH connections' so shouldn't happen. */
284
285 if (ud->sec_level == 3) {
286 X509_free(x509_peer);
287 return SSL_get_verify_result(ssl);
288 }
289
290 if ((extcount = X509_get_ext_count(x509_peer)) > 0) {
291 if (debug) printf("extcount = %d\n", extcount);
292 for (i = 0; i < extcount; i++) {
293 x509_ext = X509_get_ext(x509_peer, i);
294 extstr = (char*)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(x509_ext)));
295 if (debug) printf("extstr = %s\n", extstr);
296 if (!strcmp(extstr, "subjectAltName")) {
297 subjectaltname = 1;
298 if (!(x509_meth = X509V3_EXT_get(x509_ext)))
299 break;
300 data1 = x509_ext->value->data;
301 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
302 if (x509_meth->it)
303 ext_str = ASN1_item_d2i(NULL, &data1, x509_ext->value->length, ASN1_ITEM_ptr(x509_meth->it));
304 else
305 ext_str = x509_meth->d2i(NULL, &data1, x509_ext->value->length);
306 #else
307 ext_str = x509_meth->d2i(NULL, &data1, x509_ext->value->length);
308 #endif
309 val = x509_meth->i2v(x509_meth, ext_str, NULL);
310 for (j = 0; j < sk_CONF_VALUE_num(val); j++) {
311 nval = sk_CONF_VALUE_value(val, j);
312 if (debug)
313 printf("X509 extension : %s - %s\n", nval->name, nval->value);
314 if (!strcmp(nval->name, "DNS") && !strcasecmp(nval->value, ud->serv_host)) {
315 ok = 1;
316 break;
317 } else if (!strcmp(nval->name, "IP Address") &&
318 ( (data == 0 && !strcmp(nval->value, ud->serv_dns.hostname)) ||
319 (data == 1 && !strcmp(nval->value, ud->serv_data_host)) ) ) {
320 ok = 1;
321 break;
322 }
323 }
324 }
325 if (ok) break;
326 }
327 }
328
329 if (!ok && (x509_subj = X509_get_subject_name(x509_peer)) && X509_NAME_get_text_by_NID(x509_subj, NID_commonName, data2, sizeof(data2)) > 0) {
330 data2[255] = 0;
331 if ((strcasecmp(data2, ud->serv_host) != 0) || subjectaltname) {
332 X509_free(x509_peer);
333 return X509_V_ERR_APPLICATION_VERIFICATION;
334 }
335 }
336 X509_free(x509_peer);
337 return SSL_get_verify_result(ssl);
338 }
339
340 void
341 tls_auth_cont(struct user_data *ud, int data)
342 {
343 int status, sslerr, cert_ok;
344 SSL_CIPHER *cipher;
345 char cipher_info[128];
346 SSL *ssl;
347
348 if (debug)
349 printf("tls_auth_cont\n");
350 ssl = (data) ? ud->ssl_data : ud->ssl_ctrl;
351
352 if (ssl == NULL) printf("SSL == NULL!\n");
353
354 status = SSL_connect(ssl);
355 sslerr = SSL_get_error(ssl, status);
356 if (data)
357 ud->ssl_data_fd_mode = TLS_NONE;
358 else
359 ud->ssl_ctrl_fd_mode = TLS_NONE;
360
361 /* if ((data) && (status == 1)) {
362 status = -1; sslerr = 1; } */
363
364 if (status == 1) { /* The TLS/SSL handshake was successfully completed */
365 cipher = SSL_get_current_cipher(ssl);
366 SSL_CIPHER_description(cipher, cipher_info, sizeof(cipher_info));
367 if (debug)
368 printf("cipher %s, sec_level %d\n", cipher_info, ud->sec_level);
369 cert_ok = (ud->sec_level == 1 || ud->sec_level == 2) ? tls_cert(ud, data) : (ud->sec_level >= 3) ? tls_cert2(ud, data) == X509_V_OK : 1;
370 if (debug)
371 printf("cert_ok = %d, data = %d\n", cert_ok, data);
372
373 if (data) {
374 ud->tls_status |= TLS_DATA;
375 ud->data_connected = CONN_DATA_OK;
376 } else {
377 ud->serv_status = SERV_TLS_OK;
378 ud->tls_status |= TLS_CTRL;
379 print_to_serv(ud, "PBSZ 0\r\n");
380 if (debug)
381 printf("printed pbsz\n");
382 }
383 if (!cert_ok) {
384 if (!data) {
385 ud->serv_status = SERV_FLOW;
386 print_to_ud(ud, "530 TLSWrap certificate verification failed, disconnecting.\r\n");
387 print_to_serv(ud, "QUIT\r\n");
388 } else {
389 print_to_ud(ud, "425 TLSWrap data certificate verification failed.\r\n");
390 SSL_clear(ud->ssl_data); /* Prevent reuse */
391 data_close(ud);
392 }
393 if (debug)
394 printf("printed that certificate verification failed.\n");
395 //user_close(ud);
396 }
397 } else {
398 switch (sslerr) {
399 case SSL_ERROR_WANT_READ:
400 if (debug)
401 printf("setting TLS_READ\n");
402 if (data)
403 ud->ssl_data_fd_mode = TLS_READ;
404 else
405 ud->ssl_ctrl_fd_mode = TLS_READ;
406 break;
407 case SSL_ERROR_WANT_WRITE:
408 if (debug)
409 printf("setting TLS_WRITE\n");
410 if (data)
411 ud->ssl_data_fd_mode = TLS_WRITE;
412 else
413 ud->ssl_ctrl_fd_mode = TLS_WRITE;
414 break;
415 case SSL_ERROR_SSL:
416 case SSL_ERROR_SYSCALL: // assorted I/O error
417 if (debug)
418 printf("tls_auth_cont got SSL_ERROR_SSL or SSL_ERROR_SYSCALL\n");
419 if (!data) {
420 ud->serv_status = SERV_NONE;
421 print_to_ud(ud, "530 TLSWrap SSL/TLS connection to server failed.\r\n");
422 ud->connected = CONN_NO;
423 } else {
424 /* ud->serv_data_close = CLOSE_READ;
425 ud->user_data_close = CLOSE_READ; */
426 print_to_ud(ud, "230 TLSWrap SSL/TLS DATA connection to server failed.\r\n");
427 SSL_clear(ssl);
428 data_close(ud);
429 }
430 break;
431 default:
432 if (debug)
433 printf("tls_auth_cont failed (%d)\n", sslerr);
434 if (sslerr)
435 perror("tls_auth_cont");
436 if (data) {
437 SSL_clear(ud->ssl_data);
438 data_close(ud);
439 }
440 }
441 }
442 }
443
444 int
445 tls_write(struct user_data *ud, const void *buf, int num, int data)
446 {
447 SSL *ssl;
448 int status, sslerr;
449
450 ssl = (data) ? ud->ssl_data : ud->ssl_ctrl;
451
452 status = SSL_write(ssl, buf, num);
453 sslerr = SSL_get_error(ssl, status);
454
455 if (status == -1) {
456 if (data)
457 ud->ssl_data_func = TLS_WRITE;
458 else
459 ud->ssl_ctrl_func = TLS_WRITE;
460 switch (sslerr) {
461 case SSL_ERROR_WANT_READ:
462 if (data)
463 ud->ssl_data_fd_mode = TLS_READ;
464 else
465 ud->ssl_ctrl_fd_mode = TLS_READ;
466 break;
467 case SSL_ERROR_WANT_WRITE:
468 if (data)
469 ud->ssl_data_fd_mode = TLS_WRITE;
470 else
471 ud->ssl_ctrl_fd_mode = TLS_WRITE;
472 break;
473 default:
474 if (debug)
475 printf("tls_write_error\n");
476 return -1;
477 }
478 } else {
479 if (data)
480 ud->ssl_data_fd_mode = TLS_NONE;
481 else
482 ud->ssl_ctrl_fd_mode = TLS_NONE;
483 }
484
485 return status;
486 }
487
488 int
489 tls_read(struct user_data *ud, void *buf, int num, int data)
490 {
491 SSL *ssl;
492 int status, sslerr;
493
494 ssl = (data) ? ud->ssl_data : ud->ssl_ctrl;
495
496 status = SSL_read(ssl, buf, num);
497 sslerr = SSL_get_error(ssl, status);
498
499 if (status == -1) {
500 if (data)
501 ud->ssl_data_func = TLS_READ;
502 else
503 ud->ssl_ctrl_func = TLS_READ;
504 switch (sslerr) {
505 case SSL_ERROR_WANT_READ:
506 if (data)
507 ud->ssl_data_fd_mode = TLS_READ;
508 else
509 ud->ssl_ctrl_fd_mode = TLS_READ;
510 break;
511 case SSL_ERROR_WANT_WRITE:
512 if (data)
513 ud->ssl_data_fd_mode = TLS_WRITE;
514 else
515 ud->ssl_ctrl_fd_mode = TLS_WRITE;
516 break;
517 default:
518 if (debug)
519 printf("tls_read_error\n");
520 return -2;
521 }
522 } else {
523 if (data)
524 ud->ssl_data_fd_mode = TLS_NONE;
525 else
526 ud->ssl_ctrl_fd_mode = TLS_NONE;
527 }
528
529 return status;
530 }