gwenhywfar 5.10.1
syncio_tls.c
Go to the documentation of this file.
1/***************************************************************************
2 begin : Wed Apr 28 2010
3 copyright : (C) 2010, 2016 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 * *
23 ***************************************************************************/
24
25#ifdef HAVE_CONFIG_H
26# include <config.h>
27#endif
28
29#define DISABLE_DEBUGLOG
30
31/*#define GWEN_TLS_DEBUG*/
32
33/* #define GWEN_TLS_USE_OLD_CODE */
34
35#include "syncio_tls_p.h"
36#include "i18n_l.h"
37
38#include <gwenhywfar/misc.h>
39#include <gwenhywfar/debug.h>
40#include <gwenhywfar/gui.h>
41#include <gwenhywfar/gui.h>
42#include <gwenhywfar/pathmanager.h>
43#include <gwenhywfar/directory.h>
44#include <gwenhywfar/gwenhywfar.h>
45#include <gwenhywfar/text.h>
46
47#include <assert.h>
48#include <errno.h>
49#include <string.h>
50#include <stdlib.h>
51
52#include <gnutls/gnutls.h>
53#include <gnutls/x509.h>
54#include <gcrypt.h>
55
56
57
58GWEN_INHERIT(GWEN_SYNCIO, GWEN_SYNCIO_TLS)
59
60
61#ifndef OS_WIN32
63 "/etc/ssl/certs/ca-certificates.crt",
64 "/etc/ssl/ca-bundle.pem",
65 NULL
66};
67#endif
68
69
70
71
73{
74 GWEN_SYNCIO *sio;
75 GWEN_SYNCIO_TLS *xio;
76
77 assert(baseIo);
79 GWEN_NEW_OBJECT(GWEN_SYNCIO_TLS, xio);
81
82 /* preset data */
84
85 /* set virtual functions */
90
91 return sio;
92}
93
94
95
97{
98 GWEN_SYNCIO_TLS *xio;
99
100 xio=(GWEN_SYNCIO_TLS *) p;
101 free(xio->localCertFile);
102 free(xio->localKeyFile);
103 free(xio->localTrustFile);
104 free(xio->dhParamFile);
105 free(xio->hostName);
106 GWEN_SslCertDescr_free(xio->peerCertDescr);
107 GWEN_FREE_OBJECT(xio);
108}
109
110
111
113{
114 GWEN_SYNCIO_TLS *xio;
116
117 assert(sio);
118 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
119 assert(xio);
120
121 oldF=xio->checkCertFn;
122 xio->checkCertFn=f;
123 return oldF;
124}
125
126
127
129 const GWEN_SSLCERTDESCR *cert)
130{
131 GWEN_SYNCIO_TLS *xio;
132
133 assert(sio);
134 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
135 assert(xio);
136
137 DBG_WARN(GWEN_LOGDOMAIN, "No checkCertFn set, using GWEN_GUI");
138 return GWEN_Gui_CheckCert(cert, sio, 0);
139}
140
141
142
144{
145 GWEN_SYNCIO_TLS *xio;
146
147 assert(sio);
148 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
149 assert(xio);
150
151 if (xio->checkCertFn) {
152 /* try my own checkCert function first */
153 return xio->checkCertFn(sio, cert);
154 }
155 else {
156 /* none set, call the check cert function of GWEN_GUI (for older code) */
157 DBG_ERROR(GWEN_LOGDOMAIN, "No checkCertFn set, falling back to GUI (SNH!)");
158 return GWEN_SyncIo_Tls_Internal_CheckCert(sio, cert);
159 }
160}
161
162
163
165{
166 GWEN_SYNCIO_TLS *xio;
167
168 assert(sio);
169 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
170 assert(xio);
171
172 return xio->localCertFile;
173}
174
175
176
178{
179 GWEN_SYNCIO_TLS *xio;
180
181 assert(sio);
182 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
183 assert(xio);
184
185 free(xio->localCertFile);
186 if (s)
187 xio->localCertFile=strdup(s);
188 else
189 xio->localCertFile=NULL;
190}
191
192
193
195{
196 GWEN_SYNCIO_TLS *xio;
197
198 assert(sio);
199 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
200 assert(xio);
201
202 return xio->localKeyFile;
203}
204
205
206
208{
209 GWEN_SYNCIO_TLS *xio;
210
211 assert(sio);
212 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
213 assert(xio);
214
215 free(xio->localKeyFile);
216 if (s)
217 xio->localKeyFile=strdup(s);
218 else
219 xio->localKeyFile=NULL;
220}
221
222
223
225{
226 GWEN_SYNCIO_TLS *xio;
227
228 assert(sio);
229 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
230 assert(xio);
231
232 return xio->localTrustFile;
233}
234
235
236
238{
239 GWEN_SYNCIO_TLS *xio;
240
241 assert(sio);
242 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
243 assert(xio);
244
245 free(xio->localTrustFile);
246 if (s)
247 xio->localTrustFile=strdup(s);
248 else
249 xio->localTrustFile=NULL;
250}
251
252
253
255{
256 GWEN_SYNCIO_TLS *xio;
257
258 assert(sio);
259 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
260 assert(xio);
261
262 return xio->dhParamFile;
263}
264
265
266
268{
269 GWEN_SYNCIO_TLS *xio;
270
271 assert(sio);
272 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
273 assert(xio);
274
275 free(xio->dhParamFile);
276 if (s)
277 xio->dhParamFile=strdup(s);
278 else
279 xio->dhParamFile=NULL;
280}
281
282
283
285{
286 GWEN_SYNCIO_TLS *xio;
287
288 assert(sio);
289 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
290 assert(xio);
291
292 return xio->hostName;
293}
294
295
296
298{
299 GWEN_SYNCIO_TLS *xio;
300
301 assert(sio);
302 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
303 assert(xio);
304
305 free(xio->hostName);
306 if (s)
307 xio->hostName=strdup(s);
308 else
309 xio->hostName=NULL;
310}
311
312
313
315{
316 GWEN_SYNCIO_TLS *xio;
317
318 assert(sio);
319 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
320 assert(xio);
321
322 return xio->peerCertDescr;
323}
324
325
326
327int GWEN_SyncIo_Tls__readFile(const char *fname, GWEN_BUFFER *buf)
328{
329 FILE *f;
330
331 f=fopen(fname, "r");
332 if (f==NULL)
333 return GWEN_ERROR_IO;
334
335 while (!feof(f)) {
336 int rv;
337
338 GWEN_Buffer_AllocRoom(buf, 512);
339 rv=fread(GWEN_Buffer_GetPosPointer(buf), 1, 512, f);
340 if (rv==0)
341 break;
342 else if (rv<0) {
343 DBG_INFO(GWEN_LOGDOMAIN, "fread(%s): %s", fname, strerror(errno));
344 fclose(f);
345 return GWEN_ERROR_IO;
346 }
347 else {
350 }
351 }
352 fclose(f);
353 return 0;
354}
355
356
357
358
359#if GWEN_TLS_USE_SYSTEM_CERTIFICATES
360# ifndef OS_WIN32
361static int GWEN_SyncIo_Tls_AddCaCertFolder(GWEN_SYNCIO *sio, const char *folder)
362{
363 GWEN_SYNCIO_TLS *xio;
364 int rv;
365 int successfullTustFileCount=0;
366
367 assert(sio);
368 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
369 assert(xio);
370
371 if (folder && *folder) {
372 GWEN_STRINGLIST *fileList;
373
374 fileList=GWEN_StringList_new();
375 rv=GWEN_Directory_GetMatchingFilesRecursively(folder, fileList, "*.crt");
376 if (rv<0) {
378 "Error reading list of certificate files (%d) in folder [%s]",
379 rv, folder);
380 }
381 else {
383
384 se=GWEN_StringList_FirstEntry(fileList);
385 while (se) {
386 const char *s;
387
389 if (s && *s) {
390 rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
391 s,
392 GNUTLS_X509_FMT_PEM);
393 if (rv<=0) {
395 "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
396 s, rv, gnutls_strerror(rv));
397 }
398 else {
399 DBG_INFO(GWEN_LOGDOMAIN, "Added %d trusted certs from [%s]", rv, s);
400 successfullTustFileCount++;
401 }
402 }
403
405 } /* while */
406 }
407 GWEN_StringList_free(fileList);
408 }
409
410 if (successfullTustFileCount==0) {
411 DBG_ERROR(GWEN_LOGDOMAIN, "No files added from folder [%s]", folder);
412 }
413
414 return successfullTustFileCount;
415}
416# endif
417#endif
418
419
420
422{
423 GWEN_SYNCIO_TLS *xio;
424 int rv;
425 uint32_t lflags;
426 const char *custom_ciphers;
427 const char *errPos=NULL;
428
429 assert(sio);
430 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
431 assert(xio);
432
433 lflags=GWEN_SyncIo_GetFlags(sio);
434 DBG_INFO(GWEN_LOGDOMAIN, "Preparing SSL (%08x)", lflags);
435
436 /* init session */
437 if (lflags & GWEN_SYNCIO_FLAGS_PASSIVE) {
438 DBG_INFO(GWEN_LOGDOMAIN, "Init as server");
439 rv=gnutls_init(&xio->session, GNUTLS_SERVER);
440 }
441 else {
442 DBG_INFO(GWEN_LOGDOMAIN, "Init as client");
443 rv=gnutls_init(&xio->session, GNUTLS_CLIENT);
444 }
445 if (rv) {
446 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_init: %d (%s)", rv, gnutls_strerror(rv));
447 return GWEN_ERROR_GENERIC;
448 }
449
450 /* set cipher priorities */
451 custom_ciphers=getenv("GWEN_TLS_CIPHER_PRIORITIES");
452 /* TODO: make custom ciphers configurable as priority string? */
453 if (custom_ciphers && *custom_ciphers) { /* use cipher list from env var */
454 GWEN_Gui_ProgressLog2(0, GWEN_LoggerLevel_Info, I18N("TLS: SSL cipher priority list: %s"), custom_ciphers);
455 rv=gnutls_priority_set_direct(xio->session, custom_ciphers, &errPos);
456 if (rv!=GNUTLS_E_SUCCESS) {
457 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_priority_set_direct using '%s' failed: %s (%d) [%s]",
458 custom_ciphers, gnutls_strerror(rv), rv, errPos?errPos:"");
459 gnutls_deinit(xio->session);
460 return GWEN_ERROR_GENERIC;
461 }
462 }
463 else { /* use default ciphers from GnuTLS */
464 GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Notice, I18N("Using GnuTLS default ciphers."));
465 rv=gnutls_set_default_priority(xio->session);
466 if (rv!=GNUTLS_E_SUCCESS) {
467 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_set_default_priority failed: %s (%d)", gnutls_strerror(rv), rv);
468 gnutls_deinit(xio->session);
469 return GWEN_ERROR_GENERIC;
470 }
471 }
472
473 /* protect against too-many-known-ca problem */
474 gnutls_handshake_set_max_packet_length(xio->session, 64*1024);
475
476 /* let a server request peer certs */
477 if ((lflags & GWEN_SYNCIO_FLAGS_PASSIVE) &&
479 gnutls_certificate_server_set_request(xio->session, GNUTLS_CERT_REQUIRE);
480
481 /* prepare cert credentials */
482 rv=gnutls_certificate_allocate_credentials(&xio->credentials);
483 if (rv) {
484 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_allocate_credentials: %d (%s)", rv, gnutls_strerror(rv));
485 gnutls_deinit(xio->session);
486 return GWEN_ERROR_GENERIC;
487 }
488
489 /* possibly set key file and cert file */
490 if (xio->localCertFile && xio->localKeyFile) {
491 rv=gnutls_certificate_set_x509_key_file(xio->credentials,
492 xio->localCertFile,
493 xio->localKeyFile,
494 GNUTLS_X509_FMT_PEM);
495 if (rv<0) {
496 if (rv) {
497 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: %d (%s)", rv, gnutls_strerror(rv));
498 gnutls_certificate_free_credentials(xio->credentials);
499 gnutls_deinit(xio->session);
500 return GWEN_ERROR_GENERIC;
501 }
502 }
503 }
504
505 /* find default trust file if none is selected */
507 int trustFileSet=0;
508
509#if GWEN_TLS_USE_SYSTEM_CERTIFICATES
510 /* disable setting of default trust file as discussed on aqbanking-users.
511 * The rationale is that without this file being set gnutls should behave
512 * correctly on each system.
513 * On Linux systems it should use the standard mechanism of the underlying
514 * distribution. On Windows the default CA store should be used (if given
515 * "--with-default-trust-store-file" to "./configure" of GNUTLS).
516 */
517 if (trustFileSet==0) {
518 /* Adds the system's default trusted CAs in order to verify client or server certificates. */
519 rv=gnutls_certificate_set_x509_system_trust(xio->credentials);
520 if (rv<=0) {
521 DBG_WARN(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_system_trust: %d (%s)", rv, gnutls_strerror(rv));
522 }
523 else {
524 DBG_INFO(GWEN_LOGDOMAIN, "Added %d default trusted certs from system", rv);
525 trustFileSet=1;
526 }
527 }
528#endif
529
530 /* try to find OpenSSL certificates */
531# ifdef OS_WIN32
532 if (trustFileSet==0) {
533 char defaultPath[2*MAX_PATH+1];
534 const char *defaultFile = "ca-bundle.crt";
535 GWEN_STRINGLIST *paths;
536 GWEN_BUFFER *nbuf;
537
538 if (GWEN_Directory_GetPrefixDirectory(defaultPath, sizeof(defaultPath))) {
539 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: could not get install prefix");
540 return GWEN_ERROR_GENERIC;
541 }
542 if (strcat_s(defaultPath, sizeof(defaultPath), "\\share\\gwenhywfar")) {
543 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: no memory on creating search path");
544 return GWEN_ERROR_GENERIC;
545 }
546
547 paths=GWEN_StringList_new();
548 GWEN_StringList_AppendString(paths, defaultPath, 0, 0);
549
550 nbuf=GWEN_Buffer_new(0, 256, 0, 1);
551 rv=GWEN_Directory_FindFileInPaths(paths, defaultFile, nbuf);
553 if (rv==0) {
555 "Using default ca-bundle from [%s]",
557
558 rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
560 GNUTLS_X509_FMT_PEM);
561 if (rv<=0) {
563 "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
564 GWEN_Buffer_GetStart(nbuf), rv, gnutls_strerror(rv));
565 }
566 else {
568 "Added %d trusted certs from [%s]", rv, GWEN_Buffer_GetStart(nbuf));
569 trustFileSet=1;
570 }
571 }
572 GWEN_Buffer_free(nbuf);
573 }
574# endif
575
576
577# ifndef OS_WIN32
578 /* try to finde certificate bundle */
579 if (trustFileSet==0) {
580 int i;
581 const char *sCertFile=NULL;
582
583 for (i=0; ; i++) {
584 sCertFile=SYNCIO_TLS_SYSTEM_CERTFILES[i];
585 if (sCertFile==NULL)
586 break;
588 DBG_INFO(GWEN_LOGDOMAIN, "Found system-wide cert bundle in %s", sCertFile);
589 break;
590 }
591 }
592
593 if (sCertFile && *sCertFile) {
594 rv=gnutls_certificate_set_x509_trust_file(xio->credentials, sCertFile, GNUTLS_X509_FMT_PEM);
595 if (rv<=0) {
596 DBG_WARN(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_trust_file(%s): %d (%s)", sCertFile, rv, gnutls_strerror(rv));
597 }
598 else {
599 DBG_INFO(GWEN_LOGDOMAIN, "Added %d trusted certs from [%s]", rv, sCertFile);
600 trustFileSet=1;
601 }
602 }
603 else {
604 DBG_ERROR(GWEN_LOGDOMAIN, "No system-wide certificate bundle found.");
605 }
606 }
607
608 /* try to find ca-certificates (at least available on Debian systems) */
609 if (trustFileSet==0) {
610 rv=GWEN_Directory_GetPath("/usr/share/ca-certificates", GWEN_PATH_FLAGS_NAMEMUSTEXIST);
611 if (rv>=0) {
612 rv=GWEN_SyncIo_Tls_AddCaCertFolder(sio, "/usr/share/ca-certificates");
613 if (rv<=0) {
614 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
615 }
616 else {
617 trustFileSet=1;
618 }
619 }
620 }
621
622# endif
623
624
625 if (trustFileSet==0) {
626
627 /* TODO: use gnutls_certificate_set_x509_system_trust() */
628 trustFileSet=1;
629 }
630
631
632
633 if (trustFileSet==0) {
634 DBG_WARN(GWEN_LOGDOMAIN, "No default bundle file found");
635 }
636 }
637
638 /* possibly set trust file */
639 if (xio->localTrustFile) {
640 rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
641 xio->localTrustFile,
642 GNUTLS_X509_FMT_PEM);
643 if (rv<=0) {
645 "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
646 (xio->localTrustFile)?(xio->localTrustFile):"-none-",
647 rv, gnutls_strerror(rv));
648 gnutls_certificate_free_credentials(xio->credentials);
649 gnutls_deinit(xio->session);
650 return GWEN_ERROR_GENERIC;
651 }
652 else {
654 "Added %d trusted certs", rv);
655 }
656 }
657
658 /* possibly set DH params */
659 if (xio->dhParamFile) {
660 GWEN_BUFFER *dbuf;
661
662 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
663 rv=GWEN_SyncIo_Tls__readFile(xio->dhParamFile, dbuf);
664 if (rv) {
665 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
666 GWEN_Buffer_free(dbuf);
667 gnutls_certificate_free_credentials(xio->credentials);
668 gnutls_deinit(xio->session);
669 return rv;
670 }
671 else {
672 gnutls_datum_t d;
673 gnutls_dh_params_t dh_params=NULL;
674
675 rv=gnutls_dh_params_init(&dh_params);
676 if (rv<0) {
677 GWEN_Buffer_free(dbuf);
678 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_init: %d (%s)", rv, gnutls_strerror(rv));
679 gnutls_certificate_free_credentials(xio->credentials);
680 gnutls_deinit(xio->session);
681 return GWEN_ERROR_GENERIC;
682 }
683
684 d.size=GWEN_Buffer_GetUsedBytes(dbuf);
685 d.data=(unsigned char *)GWEN_Buffer_GetStart(dbuf);
686
687 rv=gnutls_dh_params_import_pkcs3(dh_params, &d, GNUTLS_X509_FMT_PEM);
688 if (rv<0) {
689 GWEN_Buffer_free(dbuf);
690 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_import_pkcs3: %d (%s)", rv, gnutls_strerror(rv));
691 gnutls_certificate_free_credentials(xio->credentials);
692 gnutls_deinit(xio->session);
693 return GWEN_ERROR_GENERIC;
694 }
695 GWEN_Buffer_free(dbuf);
696
697 gnutls_certificate_set_dh_params(xio->credentials, dh_params);
698 }
699 }
700
701 /* set credentials in TLS session */
702 rv=gnutls_credentials_set(xio->session, GNUTLS_CRD_CERTIFICATE, xio->credentials);
703 if (rv<0) {
704 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_credentials_set: %d (%s)", rv, gnutls_strerror(rv));
705 gnutls_certificate_free_credentials(xio->credentials);
706 gnutls_deinit(xio->session);
707 return GWEN_ERROR_GENERIC;
708 }
709
710 /* if hostname set try to set it */
711 if (xio->hostName) {
712 rv=gnutls_server_name_set(xio->session, GNUTLS_NAME_DNS, xio->hostName, strlen(xio->hostName));
713 if (rv!=GNUTLS_E_SUCCESS) {
714 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_server_name_set: %d (%s), ignoring", rv, gnutls_strerror(rv));
715 }
716 }
717
718 /* we use our own push/pull functions */
719 gnutls_transport_set_ptr(xio->session, (gnutls_transport_ptr_t)sio);
720 gnutls_transport_set_push_function(xio->session, GWEN_SyncIo_Tls_Push);
721 gnutls_transport_set_pull_function(xio->session, GWEN_SyncIo_Tls_Pull);
722#if GNUTLS_VERSION_NUMBER < 0x020c00
723 /* This function must be set to 0 in GNUTLS versions < 2.12.0 because we use
724 * custom push/pull functions.
725 * In GNUTLS 2.12.x this is set to 0 and since version 3 this functions is removed
726 * completely.
727 * So we only call this function now for GNUTLS < 2.12.0.
728 */
729 gnutls_transport_set_lowat(xio->session, 0);
730#endif
731
732 xio->prepared=1;
733
734 return 0;
735}
736
737
738
740{
741 GWEN_SYNCIO_TLS *xio;
742
743 assert(sio);
744 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
745 assert(xio);
746
747 if (xio->prepared) {
748 gnutls_certificate_free_credentials(xio->credentials);
749 gnutls_deinit(xio->session);
750 xio->prepared=0;
751 }
752}
753
754
755
757{
758 GWEN_SYNCIO_TLS *xio;
759 const gnutls_datum_t *cert_list;
760 unsigned int cert_list_size;
761 size_t size;
762 GWEN_SSLCERTDESCR *certDescr;
763 char buffer1[64];
764 time_t t0;
765 int rv;
766 uint32_t lflags;
767 uint32_t errFlags=0;
768 int i;
769 unsigned int status;
770 GWEN_BUFFER *sbuf=NULL;
771
772 assert(sio);
773 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
774 assert(xio);
775
776 lflags=GWEN_SyncIo_GetFlags(sio);
777
778 if (xio->peerCertDescr) {
779 GWEN_SslCertDescr_free(xio->peerCertDescr);
780 xio->peerCertDescr=NULL;
781 }
782 xio->peerCertFlags=0;
783
784 t0=time(NULL);
785 if (t0<0) {
786 DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
788 }
789
790 /* create new cert description, check cert on the fly */
791 certDescr=GWEN_SslCertDescr_new();
792
793 /* some general tests */
795 gnutls_certificate_set_verify_flags(xio->credentials,
796 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
797
798 rv=gnutls_certificate_verify_peers2(xio->session, &status);
799 if (rv<0) {
800 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
801 GWEN_SslCertDescr_free(certDescr);
803 }
804
805 if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
806 DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
807
808 GWEN_SslCertDescr_free(certDescr);
810 }
811
812 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
813 DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
815 I18N("Signer not found"));
817 }
818
819 if (status & GNUTLS_CERT_INVALID) {
820 DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
822 I18N("Certificate is not trusted"));
824 }
825
826 if (status & GNUTLS_CERT_REVOKED) {
827 DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
829 I18N("Certificate has been revoked"));
831 }
832
833 cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
834 if (cert_list==NULL || cert_list_size==0) {
835 DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
836 return GWEN_ERROR_NO_DATA;
837 }
838
839 for (i=0; i<(int) cert_list_size; i++) {
840 gnutls_x509_crt_t cert;
841 time_t t;
842
843 rv=gnutls_x509_crt_init(&cert);
844 if (rv!=0) {
845 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
846 return GWEN_ERROR_GENERIC;
847 }
848
849 rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); /* TODO: shouldn't we use the index?? */
850 if (rv!=0) {
851 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
852 gnutls_x509_crt_deinit(cert);
853 return GWEN_ERROR_GENERIC;
854 }
855
856 if (i==0) {
857 gnutls_datum_t n= {NULL, 0};
858 gnutls_datum_t e= {NULL, 0};
859
860 /* get public key from cert, if any */
861 rv=gnutls_x509_crt_get_pk_rsa_raw(cert, &n, &e);
862 if (rv!=0) {
863 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_pk_rsa_raw: %d (%s)", rv, gnutls_strerror(rv));
864 }
865 else {
866 GWEN_BUFFER *kbuf;
867
868 DBG_INFO(GWEN_LOGDOMAIN, "Key stored within certificate, extracting (modlen=%d, explen=%d)",
869 n.size, e.size);
870
871 kbuf=GWEN_Buffer_new(0, 256, 0, 1);
872
873 if (n.data && n.size) {
874 /* store public modulus */
875 GWEN_Text_ToHexBuffer((const char *)(n.data), n.size, kbuf, 0, 0, 0);
877 GWEN_Buffer_Reset(kbuf);
878 }
879
880 if (e.data && e.size) {
881 /* store public exponent */
882 GWEN_Text_ToHexBuffer((const char *)(e.data), e.size, kbuf, 0, 0, 0);
884 GWEN_Buffer_Reset(kbuf);
885 }
886
887 GWEN_Buffer_free(kbuf);
888 if (n.data)
889 gcry_free(n.data);
890 if (e.data)
891 gcry_free(e.data);
892 }
893
894 /* get fingerprint (MD5) */
895 size=16;
896 rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
897 if (rv!=0) {
898 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(MD5): %d (%s)", rv, gnutls_strerror(rv));
899 GWEN_SslCertDescr_free(certDescr);
900 gnutls_x509_crt_deinit(cert);
901 return GWEN_ERROR_GENERIC;
902 }
903 else {
904 GWEN_BUFFER *dbuf;
905
906 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
907 if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
908 size, dbuf, 2, ':', 0)) {
910 "Could not convert fingerprint to hex");
911 }
912 else {
914 }
915 GWEN_Buffer_free(dbuf);
916 }
917
918 /* get fingerprint (SHA1) */
919 size=sizeof(buffer1);
920 rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer1, &size);
921 if (rv!=0) {
922 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(SHA1): %d (%s)", rv, gnutls_strerror(rv));
923 GWEN_SslCertDescr_free(certDescr);
924 gnutls_x509_crt_deinit(cert);
925 return GWEN_ERROR_GENERIC;
926 }
927 else {
928 GWEN_BUFFER *dbuf;
929
930 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
931 if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
932 size, dbuf, 2, ':', 0)) {
934 "Could not convert fingerprint to hex");
935 }
936 else {
938 }
939 GWEN_Buffer_free(dbuf);
940 }
941
942 /* get fingerprint (SHA512) */
943 size=sizeof(buffer1);
944 rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA512, buffer1, &size);
945 if (rv!=0) {
946 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(SHA512): %d (%s)", rv, gnutls_strerror(rv));
947 GWEN_SslCertDescr_free(certDescr);
948 gnutls_x509_crt_deinit(cert);
949 return GWEN_ERROR_GENERIC;
950 }
951 else {
952 GWEN_BUFFER *dbuf;
953
954 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
955 if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
956 size, dbuf, 2, ':', 0)) {
958 "Could not convert fingerprint to hex");
959 }
960 else {
962 }
963 GWEN_Buffer_free(dbuf);
964 }
965
966
967 if (xio->hostName) {
968 DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
969 if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
971 "Certificate was not issued for this host");
973 I18N("Certificate was not issued for this host"));
975 }
976 else {
977 DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
978 }
979 }
980 else {
982 "Hostname is not set, unable to verify the sender");
984 I18N("No hostname to verify the sender!"));
985 }
986
987 }
988
989 /* get activation time */
990 t=gnutls_x509_crt_get_activation_time(cert);
991 if (t<0) {
992 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
994 }
995 else {
996 if (t>t0) {
997 DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
999 }
1000 if (i==0) {
1001 GWEN_TIME *ti;
1002
1004 if (ti)
1005 GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
1006 GWEN_Time_free(ti);
1007 }
1008 }
1009
1010 /* get expiration time */
1011 t=gnutls_x509_crt_get_expiration_time(cert);
1012 if (t<0) {
1013 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
1015 }
1016 else {
1017 if (t<t0) {
1018 DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
1020 }
1021 if (i==0) {
1022 GWEN_TIME *ti;
1023
1025 if (ti)
1026 GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
1027 GWEN_Time_free(ti);
1028 }
1029 }
1030
1031 if (i==0) {
1032 /* get owner information, but only for first cert */
1033 size=sizeof(buffer1)-1;
1034 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
1035 if (rv==0) {
1036 GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
1037 if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
1038 DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
1040 }
1041 }
1042
1043 size=sizeof(buffer1)-1;
1044 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
1045 if (rv==0)
1046 GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
1047
1048 size=sizeof(buffer1)-1;
1049 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
1050 if (rv==0)
1052
1053 size=sizeof(buffer1)-1;
1054 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
1055 if (rv==0)
1056 GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
1057
1058 size=sizeof(buffer1)-1;
1059 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
1060 if (rv==0)
1061 GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
1062
1063 size=sizeof(buffer1)-1;
1064 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
1065 if (rv==0)
1066 GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
1067 }
1068
1069 gnutls_x509_crt_deinit(cert);
1070 }
1071
1072 /* done */
1073 if (errFlags)
1074 GWEN_SslCertDescr_SetIsError(certDescr, 1);
1075 else
1076 errFlags|=GWEN_SSL_CERT_FLAGS_OK;
1077
1078 sbuf=GWEN_Buffer_new(0, 256, 0, 1);
1079
1080 if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
1081 if (GWEN_Buffer_GetUsedBytes(sbuf))
1082 GWEN_Buffer_AppendString(sbuf, "; ");
1083 GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
1084 }
1085
1086 if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
1087 if (GWEN_Buffer_GetUsedBytes(sbuf))
1088 GWEN_Buffer_AppendString(sbuf, "; ");
1089 GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
1090 }
1091
1092 if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
1093 if (GWEN_Buffer_GetUsedBytes(sbuf))
1094 GWEN_Buffer_AppendString(sbuf, "; ");
1095 GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
1096 }
1097
1098 if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
1099 if (GWEN_Buffer_GetUsedBytes(sbuf))
1100 GWEN_Buffer_AppendString(sbuf, "; ");
1101 GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
1102 }
1103
1104 if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
1105 if (GWEN_Buffer_GetUsedBytes(sbuf))
1106 GWEN_Buffer_AppendString(sbuf, "; ");
1107 GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
1108 }
1109
1110 if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
1111 if (GWEN_Buffer_GetUsedBytes(sbuf))
1112 GWEN_Buffer_AppendString(sbuf, "; ");
1113 GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
1114 }
1115
1116 if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
1117 if (GWEN_Buffer_GetUsedBytes(sbuf))
1118 GWEN_Buffer_AppendString(sbuf, "; ");
1119 GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
1120 }
1121
1122 if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
1123 if (GWEN_Buffer_GetUsedBytes(sbuf))
1124 GWEN_Buffer_AppendString(sbuf, "; ");
1125 GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
1126 }
1127
1128 if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
1129 if (GWEN_Buffer_GetUsedBytes(sbuf))
1130 GWEN_Buffer_AppendString(sbuf, "; ");
1131 GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
1132 }
1133
1135 GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
1136 GWEN_Buffer_free(sbuf);
1137
1138#if 0
1139 if (1) {
1140 GWEN_DB_NODE *dbTest;
1141
1142 dbTest=GWEN_DB_Group_new("Cert");
1143 GWEN_SslCertDescr_toDb(certDescr, dbTest);
1144 GWEN_DB_Dump(dbTest, 2);
1145 GWEN_DB_Group_free(dbTest);
1146 }
1147#endif
1148
1149 xio->peerCertDescr=certDescr;
1150 xio->peerCertFlags=errFlags;
1151
1152 return 0;
1153}
1154
1155
1156
1157ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len)
1158{
1159 GWEN_SYNCIO *sio;
1160 GWEN_SYNCIO_TLS *xio;
1161 GWEN_SYNCIO *baseIo;
1162 int rv;
1163
1164 sio=(GWEN_SYNCIO *) p;
1165 assert(sio);
1166 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1167 assert(xio);
1168
1169 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
1170 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1171 assert(baseIo);
1172
1173 rv=GWEN_SyncIo_Read(baseIo, buf, len);
1174 if (rv<0) {
1175 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1176 gnutls_transport_set_errno(xio->session, errno);
1177 return (ssize_t)-1;
1178 }
1179
1180 gnutls_transport_set_errno(xio->session, 0);
1181 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", rv);
1182 /*GWEN_Text_DumpString(buf, rv, 2);*/
1183 return rv;
1184}
1185
1186
1187
1188ssize_t GWEN_SyncIo_Tls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len)
1189{
1190 GWEN_SYNCIO *sio;
1191 GWEN_SYNCIO_TLS *xio;
1192 GWEN_SYNCIO *baseIo;
1193 int rv;
1194
1195 sio=(GWEN_SYNCIO *) p;
1196 assert(sio);
1197 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1198 assert(xio);
1199
1200 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
1201 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1202 assert(baseIo);
1203
1204 rv=GWEN_SyncIo_Write(baseIo, buf, len);
1205 if (rv<0) {
1206 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1207 gnutls_transport_set_errno(xio->session, errno);
1208 return (ssize_t)-1;
1209 }
1210
1211 gnutls_transport_set_errno(xio->session, 0);
1212 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: returning %d bytes", rv);
1213 /*GWEN_Text_DumpString(buf, rv, 2);*/
1214 return rv;
1215}
1216
1217
1218
1220{
1221 GWEN_SYNCIO_TLS *xio;
1222 const char *s;
1223 gnutls_kx_algorithm_t kx;
1224 GWEN_BUFFER *cbuf;
1225 GWEN_BUFFER *sbuf;
1226
1227 assert(sio);
1228 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1229 assert(xio);
1230
1231 cbuf=GWEN_Buffer_new(0, 256, 0, 1);
1232 sbuf=GWEN_Buffer_new(0, 256, 0, 1);
1233
1234 /* protocol */
1235 s=gnutls_protocol_get_name(gnutls_protocol_get_version(xio->session));
1236 if (s && *s) {
1237 if (GWEN_Buffer_GetUsedBytes(cbuf))
1238 GWEN_Buffer_AppendString(cbuf, " ");
1239 GWEN_Buffer_AppendString(cbuf, "Protocol: ");
1240 GWEN_Buffer_AppendString(cbuf, s);
1241
1242 GWEN_Buffer_AppendString(sbuf, s);
1243 }
1244 GWEN_Buffer_AppendString(sbuf, ":");
1245
1246 /* key exchange algorithm */
1247 kx=gnutls_kx_get(xio->session);
1248 s=gnutls_kx_get_name(kx);
1249 if (s && *s) {
1250 if (GWEN_Buffer_GetUsedBytes(cbuf))
1251 GWEN_Buffer_AppendString(cbuf, " ");
1252 GWEN_Buffer_AppendString(cbuf, "Key exchange algorithm: ");
1253 GWEN_Buffer_AppendString(cbuf, s);
1254 GWEN_Buffer_AppendString(sbuf, s);
1255 }
1256 GWEN_Buffer_AppendString(sbuf, "-");
1257
1258 /* cipher */
1259 s=gnutls_cipher_get_name(gnutls_cipher_get(xio->session));
1260 if (s && *s) {
1261 if (GWEN_Buffer_GetUsedBytes(cbuf))
1262 GWEN_Buffer_AppendString(cbuf, " ");
1263 GWEN_Buffer_AppendString(cbuf, "cipher algorithm: ");
1264 GWEN_Buffer_AppendString(cbuf, s);
1265 GWEN_Buffer_AppendString(sbuf, s);
1266 }
1267 GWEN_Buffer_AppendString(sbuf, ":");
1268
1269 /* MAC algorithm */
1270 s=gnutls_mac_get_name(gnutls_mac_get(xio->session));
1271 if (s && *s) {
1272 if (GWEN_Buffer_GetUsedBytes(cbuf))
1273 GWEN_Buffer_AppendString(cbuf, " ");
1274 GWEN_Buffer_AppendString(cbuf, "MAC algorithm: ");
1275 GWEN_Buffer_AppendString(cbuf, s);
1276 GWEN_Buffer_AppendString(sbuf, s);
1277 }
1278
1279
1281 GWEN_Gui_ProgressLog2(0, GWEN_LoggerLevel_Info, I18N("TLS: SSL-Ciphers negotiated: %s"), GWEN_Buffer_GetStart(sbuf));
1282 GWEN_Buffer_free(cbuf);
1283 GWEN_Buffer_free(sbuf);
1284
1285 /* possibly show warning */
1286 switch (gnutls_cipher_get(xio->session)) {
1287 case GNUTLS_CIPHER_ARCFOUR_128:
1288 case GNUTLS_CIPHER_3DES_CBC:
1289 case GNUTLS_CIPHER_AES_128_CBC:
1290 case GNUTLS_CIPHER_ARCFOUR_40:
1291 case GNUTLS_CIPHER_CAMELLIA_128_CBC:
1292 GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Error, I18N("TLS: Warning - The server has chosen unsafe SSL-Ciphers!"));
1293 break;
1294 case GNUTLS_CIPHER_AES_256_CBC:
1295 case GNUTLS_CIPHER_CAMELLIA_256_CBC:
1296 case GNUTLS_CIPHER_RC2_40_CBC:
1297 case GNUTLS_CIPHER_DES_CBC:
1298#ifdef GNUTLS_CIPHER_AES_192_CBC
1299 case GNUTLS_CIPHER_AES_192_CBC: /* new in gnutls-2.9.8, so i.e. not available in gnutls-2.8.x */
1300#endif
1301 default:
1302 break;
1303 }
1304}
1305
1306
1307
1309{
1310 GWEN_SYNCIO_TLS *xio;
1311 GWEN_SYNCIO *baseIo;
1312 int rv;
1313
1314 assert(sio);
1315 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1316 assert(xio);
1317
1318 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1319 assert(baseIo);
1320
1323 DBG_ERROR(GWEN_LOGDOMAIN, "Base layer is not connected");
1325 }
1326 }
1327 else {
1328 DBG_INFO(GWEN_LOGDOMAIN, "Connecting base layer");
1329 rv=GWEN_SyncIo_Connect(baseIo);
1330 if (rv<0) {
1331 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1332 return rv;
1333 }
1334 DBG_INFO(GWEN_LOGDOMAIN, "Base layer connected");
1335 }
1336
1338 if (rv<0) {
1339 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1340 GWEN_SyncIo_Disconnect(baseIo);
1341 return rv;
1342 }
1343
1344 do {
1345 rv=gnutls_handshake(xio->session);
1346 }
1347 while (rv==GNUTLS_E_AGAIN || rv==GNUTLS_E_INTERRUPTED);
1348
1349 if (rv) {
1350 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_handshake: %d (%s) [%s]",
1351 rv, gnutls_strerror(rv), gnutls_error_is_fatal(rv)?"fatal":"non-fatal");
1352 if (rv==GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
1355 I18N("A TLS handshake error occurred. "
1356 "If you are using AqBanking you should "
1357 "consider enabling the option "
1358 "\"force SSLv3\" in the user settings "
1359 "dialog."));
1360 }
1361 else {
1364 I18N("TLS Handshake Error: %d (%s)"),
1365 rv,
1366 gnutls_strerror(rv));
1367 }
1370 GWEN_SyncIo_Disconnect(baseIo);
1371 return GWEN_ERROR_SSL;
1372 }
1373 else {
1374 /* show session info */
1376
1377 /* check certificate */
1380 if (rv<0) {
1382 DBG_ERROR(GWEN_LOGDOMAIN, "No peer certificate when needed, aborting connection");
1385 GWEN_SyncIo_Disconnect(baseIo);
1387 }
1388 else {
1389 DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (insecure)");
1391 return 0;
1392 }
1393 }
1394 else {
1395 /* present cert to the user */
1396 rv=GWEN_SyncIo_Tls_CheckCert(sio, xio->peerCertDescr);
1397 if (rv<0) {
1398 DBG_ERROR(GWEN_LOGDOMAIN, "Peer cert not accepted (%d), aborting", rv);
1401 GWEN_SyncIo_Disconnect(baseIo);
1403 }
1404 else {
1405 DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (secure)");
1408 return 0;
1409 }
1410 }
1411 }
1412}
1413
1414
1415
1417{
1418 GWEN_SYNCIO_TLS *xio;
1419 GWEN_SYNCIO *baseIo;
1420 int rv;
1421
1422 assert(sio);
1423 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1424 assert(xio);
1425
1426 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1427 assert(baseIo);
1428
1430 DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
1432 GWEN_SyncIo_Disconnect(baseIo);
1434 }
1435
1436 do {
1437 rv=gnutls_bye(xio->session, GNUTLS_SHUT_RDWR);
1438 }
1439 while (rv==GNUTLS_E_AGAIN || rv==GNUTLS_E_INTERRUPTED);
1440
1441 if (rv) {
1442 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_bye: %d (%s)", rv, gnutls_strerror(rv));
1445 I18N("Error on gnutls_bye: %d (%s)"),
1446 rv,
1447 gnutls_strerror(rv));
1450 GWEN_SyncIo_Disconnect(baseIo);
1451 return GWEN_ERROR_SSL;
1452 }
1453
1456 GWEN_SyncIo_Disconnect(baseIo);
1457 return 0;
1458}
1459
1460
1461
1463 uint8_t *buffer,
1464 uint32_t size)
1465{
1466 GWEN_SYNCIO_TLS *xio;
1467 GWEN_SYNCIO *baseIo;
1468 int rv;
1469
1470 assert(sio);
1471 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1472 assert(xio);
1473
1474 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1475 assert(baseIo);
1476
1478 DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
1480 GWEN_SyncIo_Disconnect(baseIo);
1482 }
1483
1484 do {
1485 rv=gnutls_record_recv(xio->session, buffer, size);
1486 }
1487 while (rv==GNUTLS_E_AGAIN || rv==GNUTLS_E_INTERRUPTED);
1488
1489 if (rv<0) {
1490 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_recv: %d (%s)", rv, gnutls_strerror(rv));
1491#if 0
1494 I18N("Error on gnutls_record_recv: %d (%s)"),
1495 rv,
1496 gnutls_strerror(rv));
1497#endif
1500 GWEN_SyncIo_Disconnect(baseIo);
1501#ifdef GNUTLS_E_PREMATURE_TERMINATION
1502 if (rv==GNUTLS_E_PREMATURE_TERMINATION) {
1504 DBG_ERROR(GWEN_LOGDOMAIN, "Detected premature disconnect by server (violates specs!), ignoring.");
1505 return 0; /* report EOF */
1506 }
1507 else {
1508 DBG_ERROR(GWEN_LOGDOMAIN, "Detected premature disconnect by server (violates specs!)");
1510 }
1511 }
1512#endif
1513 return GWEN_ERROR_SSL;
1514 }
1515
1516#ifdef GWEN_TLS_DEBUG
1517 DBG_ERROR(0, "Received this:");
1518 GWEN_Text_DumpString((const char *) buffer, rv, 2);
1519#endif
1520
1521 return rv;
1522}
1523
1524
1525
1527 const uint8_t *buffer,
1528 uint32_t size)
1529{
1530 GWEN_SYNCIO_TLS *xio;
1531 GWEN_SYNCIO *baseIo;
1532 int rv;
1533
1534 assert(sio);
1535 xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1536 assert(xio);
1537
1538#ifdef GWEN_TLS_DEBUG
1539 DBG_ERROR(0, "Sending this:");
1540 GWEN_Text_DumpString((const char *) buffer, size, 2);
1541#endif
1542
1543 baseIo=GWEN_SyncIo_GetBaseIo(sio);
1544 assert(baseIo);
1545
1547 DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
1549 GWEN_SyncIo_Disconnect(baseIo);
1551 }
1552
1553 do {
1554 rv=gnutls_record_send(xio->session, buffer, size);
1555 }
1556 while (rv==GNUTLS_E_AGAIN || rv==GNUTLS_E_INTERRUPTED);
1557
1558 if (rv<0) {
1559 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_send: %d (%s)", rv, gnutls_strerror(rv));
1562 I18N("Error on gnutls_record_send: %d (%s)"),
1563 rv,
1564 gnutls_strerror(rv));
1567 GWEN_SyncIo_Disconnect(baseIo);
1568 return GWEN_ERROR_SSL;
1569 }
1570
1571 return rv;
1572}
1573
1574
1575
1576
1577
1578
1579
#define NULL
Definition: binreloc.c:300
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:285
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:173
void GWEN_DB_Dump(GWEN_DB_NODE *n, int insert)
Definition: db.c:1420
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:421
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:125
#define DBG_NOTICE(dbg_logger, format, args...)
Definition: debug.h:152
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWENHYWFAR_API int GWEN_Directory_GetPrefixDirectory(char *buffer, unsigned int size)
GWENHYWFAR_API int GWEN_Directory_GetMatchingFilesRecursively(const char *folder, GWEN_STRINGLIST *sl, const char *mask)
GWENHYWFAR_API int GWEN_Directory_FindFileInPaths(const GWEN_STRINGLIST *paths, const char *filePath, GWEN_BUFFER *fbuf)
GWENHYWFAR_API int GWEN_Directory_GetPath(const char *path, unsigned int flags)
#define I18N(m)
Definition: error.c:42
#define GWEN_ERROR_SSL
Definition: error.h:105
#define GWEN_ERROR_SSL_SECURITY
Definition: error.h:129
#define GWEN_ERROR_NOT_CONNECTED
Definition: error.h:120
#define GWEN_ERROR_IO
Definition: error.h:123
#define GWEN_ERROR_SSL_PREMATURE_CLOSE
Definition: error.h:133
#define GWEN_ERROR_GENERIC
Definition: error.h:62
#define GWEN_ERROR_NO_DATA
Definition: error.h:94
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
GWENHYWFAR_API int GWEN_Gui_CheckCert(const GWEN_SSLCERTDESCR *cert, GWEN_SYNCIO *sio, uint32_t guiid)
Definition: gui_cert.c:30
GWENHYWFAR_API int GWEN_Gui_ProgressLog(uint32_t id, GWEN_LOGGER_LEVEL level, const char *text)
Definition: gui_virtual.c:444
GWENHYWFAR_API int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *text,...)
Definition: gui_virtual.c:458
#define GWEN_UNUSED
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
struct GWEN_TIME GWEN_TIME
Definition: gwentime.h:43
GWENHYWFAR_API void GWEN_Time_free(GWEN_TIME *t)
Definition: gwentime_all.c:462
GWENHYWFAR_API GWEN_TIME * GWEN_Time_fromSeconds(uint32_t s)
Definition: gwentime_all.c:77
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition: inherit.h:292
#define GWEN_INHERIT(bt, t)
Definition: inherit.h:264
#define GWEN_INHERIT_GETDATA(bt, t, element)
Definition: inherit.h:271
#define GWEN_LOGDOMAIN
Definition: logger.h:35
@ GWEN_LoggerLevel_Warning
Definition: logger.h:69
@ GWEN_LoggerLevel_Notice
Definition: logger.h:70
@ GWEN_LoggerLevel_Info
Definition: logger.h:71
@ GWEN_LoggerLevel_Error
Definition: logger.h:68
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
#define GWEN_PATH_FLAGS_VARIABLE
Definition: path.h:111
#define GWEN_PATH_FLAGS_NAMEMUSTEXIST
Definition: path.h:84
void GWEN_SslCertDescr_SetIsError(GWEN_SSLCERTDESCR *st, int d)
void GWEN_SslCertDescr_SetFingerPrintSha1(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetOrganizationName(GWEN_SSLCERTDESCR *st, const char *d)
GWEN_SSLCERTDESCR * GWEN_SslCertDescr_new(void)
void GWEN_SslCertDescr_SetNotAfter(GWEN_SSLCERTDESCR *st, const GWEN_TIME *d)
void GWEN_SslCertDescr_SetFingerPrint(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetPubKeyExponent(GWEN_SSLCERTDESCR *st, const char *d)
int GWEN_SslCertDescr_toDb(const GWEN_SSLCERTDESCR *st, GWEN_DB_NODE *db)
void GWEN_SslCertDescr_SetStatusFlags(GWEN_SSLCERTDESCR *st, uint32_t d)
void GWEN_SslCertDescr_SetCommonName(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetLocalityName(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetOrganizationalUnitName(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetNotBefore(GWEN_SSLCERTDESCR *st, const GWEN_TIME *d)
void GWEN_SslCertDescr_free(GWEN_SSLCERTDESCR *st)
void GWEN_SslCertDescr_SetCountryName(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetFingerPrintSha512(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetPubKeyModulus(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetStatusText(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetStateOrProvinceName(GWEN_SSLCERTDESCR *st, const char *d)
struct GWEN_SSLCERTDESCR GWEN_SSLCERTDESCR
#define GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME
#define GWEN_SSL_CERT_FLAGS_OK
#define GWEN_SSL_CERT_FLAGS_NOT_ACTIVE
#define GWEN_SSL_CERT_FLAGS_REVOKED
#define GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND
#define GWEN_SSL_CERT_FLAGS_EXPIRED
#define GWEN_SSL_CERT_FLAGS_SYSTEM
#define GWEN_SSL_CERT_FLAGS_BAD_DATA
#define GWEN_SSL_CERT_FLAGS_INVALID
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:62
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:406
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:398
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:245
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:390
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:50
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:53
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:56
uint32_t GWEN_SyncIo_GetFlags(const GWEN_SYNCIO *sio)
Definition: syncio.c:161
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition: syncio.c:97
void GWEN_SyncIo_AddFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:179
GWEN_SYNCIO * GWEN_SyncIo_new(const char *typeName, GWEN_SYNCIO *baseIo)
Definition: syncio.c:51
int GWEN_SyncIo_Write(GWEN_SYNCIO *sio, const uint8_t *buffer, uint32_t size)
Definition: syncio.c:147
GWEN_SYNCIO_READ_FN GWEN_SyncIo_SetReadFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_READ_FN fn)
Definition: syncio.c:291
GWEN_SYNCIO * GWEN_SyncIo_GetBaseIo(const GWEN_SYNCIO *sio)
Definition: syncio.c:224
GWEN_SYNCIO_DISCONNECT_FN GWEN_SyncIo_SetDisconnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_DISCONNECT_FN fn)
Definition: syncio.c:265
void GWEN_SyncIo_SubFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:188
GWEN_SYNCIO_WRITE_FN GWEN_SyncIo_SetWriteFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_WRITE_FN fn)
Definition: syncio.c:304
GWEN_SYNCIO_STATUS GWEN_SyncIo_GetStatus(const GWEN_SYNCIO *sio)
Definition: syncio.c:197
int GWEN_SyncIo_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
Definition: syncio.c:133
GWEN_SYNCIO_CONNECT_FN GWEN_SyncIo_SetConnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_CONNECT_FN fn)
Definition: syncio.c:252
void GWEN_SyncIo_SetStatus(GWEN_SYNCIO *sio, GWEN_SYNCIO_STATUS st)
Definition: syncio.c:206
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:109
#define GWEN_SYNCIO_FLAGS_PASSIVE
Definition: syncio.h:57
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
@ GWEN_SyncIo_Status_Connected
Definition: syncio.h:49
@ GWEN_SyncIo_Status_Disconnected
Definition: syncio.h:48
int GWEN_SyncIo_Tls_CheckCert(GWEN_SYNCIO *sio, const GWEN_SSLCERTDESCR *cert)
Definition: syncio_tls.c:143
GWEN_SIO_TLS_CHECKCERT_FN GWEN_SyncIo_Tls_SetCheckCertFn(GWEN_SYNCIO *sio, GWEN_SIO_TLS_CHECKCERT_FN f)
Definition: syncio_tls.c:112
GWEN_SSLCERTDESCR * GWEN_SyncIo_Tls_GetPeerCertDescr(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:314
int GWEN_SyncIo_Tls_GetPeerCert(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:756
void GWEN_SyncIo_Tls_UndoPrepare(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:739
int GWENHYWFAR_CB GWEN_SyncIo_Tls_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
Definition: syncio_tls.c:1462
const char * GWEN_SyncIo_Tls_GetLocalTrustFile(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:224
ssize_t GWEN_SyncIo_Tls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len)
Definition: syncio_tls.c:1188
GWEN_SYNCIO * GWEN_SyncIo_Tls_new(GWEN_SYNCIO *baseIo)
Definition: syncio_tls.c:72
void GWENHYWFAR_CB GWEN_SyncIo_Tls_FreeData(GWEN_UNUSED void *bp, void *p)
Definition: syncio_tls.c:96
const char * GWEN_SyncIo_Tls_GetLocalKeyFile(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:194
void GWEN_SyncIo_Tls_SetLocalTrustFile(GWEN_SYNCIO *sio, const char *s)
Definition: syncio_tls.c:237
void GWEN_SyncIo_Tls_SetLocalCertFile(GWEN_SYNCIO *sio, const char *s)
Definition: syncio_tls.c:177
ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len)
Definition: syncio_tls.c:1157
void GWEN_SyncIo_Tls_ShowCipherInfo(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:1219
void GWEN_SyncIo_Tls_SetDhParamFile(GWEN_SYNCIO *sio, const char *s)
Definition: syncio_tls.c:267
const char * GWEN_SyncIo_Tls_GetLocalCertFile(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:164
void GWEN_SyncIo_Tls_SetLocalKeyFile(GWEN_SYNCIO *sio, const char *s)
Definition: syncio_tls.c:207
void GWEN_SyncIo_Tls_SetRemoteHostName(GWEN_SYNCIO *sio, const char *s)
Definition: syncio_tls.c:297
const char * SYNCIO_TLS_SYSTEM_CERTFILES[]
Definition: syncio_tls.c:62
GWENHYWFAR_CB int GWEN_SyncIo_Tls_Internal_CheckCert(GWEN_SYNCIO *sio, const GWEN_SSLCERTDESCR *cert)
Definition: syncio_tls.c:128
int GWEN_SyncIo_Tls__readFile(const char *fname, GWEN_BUFFER *buf)
Definition: syncio_tls.c:327
const char * GWEN_SyncIo_Tls_GetRemoteHostName(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:284
int GWEN_SyncIo_Tls_Prepare(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:421
int GWENHYWFAR_CB GWEN_SyncIo_Tls_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:1416
int GWENHYWFAR_CB GWEN_SyncIo_Tls_Connect(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:1308
int GWENHYWFAR_CB GWEN_SyncIo_Tls_Write(GWEN_SYNCIO *sio, const uint8_t *buffer, uint32_t size)
Definition: syncio_tls.c:1526
const char * GWEN_SyncIo_Tls_GetDhParamFile(const GWEN_SYNCIO *sio)
Definition: syncio_tls.c:254
#define GWEN_SYNCIO_TLS_FLAGS_REQUEST_CERT
Definition: syncio_tls.h:36
#define GWEN_SYNCIO_TLS_TYPE
Definition: syncio_tls.h:33
#define GWEN_SYNCIO_TLS_FLAGS_ALLOW_V1_CA_CRT
Definition: syncio_tls.h:38
#define GWEN_SYNCIO_TLS_FLAGS_IGN_PREMATURE_CLOSE
Definition: syncio_tls.h:45
#define GWEN_SYNCIO_TLS_FLAGS_NEED_PEER_CERT
Definition: syncio_tls.h:39
#define GWEN_SYNCIO_TLS_FLAGS_ADD_TRUSTED_CAS
Definition: syncio_tls.h:40
#define GWEN_SYNCIO_TLS_FLAGS_SECURE
Definition: syncio_tls.h:47
int GWENHYWFAR_CB(* GWEN_SIO_TLS_CHECKCERT_FN)(GWEN_SYNCIO *sio, const GWEN_SSLCERTDESCR *cert)
Definition: syncio_tls.h:84
#define MAX_PATH
Definition: testlib.c:124
int GWEN_Text_ToHexBuffer(const char *src, unsigned l, GWEN_BUFFER *buf, unsigned int groupsize, char delimiter, int skipLeadingZeroes)
Definition: text.c:777
void GWEN_Text_DumpString(const char *s, unsigned int l, unsigned int insert)
Definition: text.c:1283