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