gwenhywfar  4.99.15beta
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 
127 {
128  GWEN_SYNCIO_TLS *xio;
129 
130  assert(sio);
131  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
132  assert(xio);
133 
134  DBG_WARN(GWEN_LOGDOMAIN, "No checkCertFn set, using GWEN_GUI");
135  return GWEN_Gui_CheckCert(cert, sio, 0);
136 }
137 
138 
139 
141 {
142  GWEN_SYNCIO_TLS *xio;
143 
144  assert(sio);
145  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
146  assert(xio);
147 
148  if (xio->checkCertFn) {
149  /* try my own checkCert function first */
150  return xio->checkCertFn(sio, cert);
151  }
152  else {
153  /* none set, call the check cert function of GWEN_GUI (for older code) */
154  DBG_ERROR(GWEN_LOGDOMAIN, "No checkCertFn set, falling back to GUI (SNH!)");
155  return GWEN_SyncIo_Tls_Internal_CheckCert(sio, cert);
156  }
157 }
158 
159 
160 
162 {
163  GWEN_SYNCIO_TLS *xio;
164 
165  assert(sio);
166  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
167  assert(xio);
168 
169  return xio->localCertFile;
170 }
171 
172 
173 
175 {
176  GWEN_SYNCIO_TLS *xio;
177 
178  assert(sio);
179  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
180  assert(xio);
181 
182  free(xio->localCertFile);
183  if (s)
184  xio->localCertFile=strdup(s);
185  else
186  xio->localCertFile=NULL;
187 }
188 
189 
190 
192 {
193  GWEN_SYNCIO_TLS *xio;
194 
195  assert(sio);
196  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
197  assert(xio);
198 
199  return xio->localKeyFile;
200 }
201 
202 
203 
205 {
206  GWEN_SYNCIO_TLS *xio;
207 
208  assert(sio);
209  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
210  assert(xio);
211 
212  free(xio->localKeyFile);
213  if (s)
214  xio->localKeyFile=strdup(s);
215  else
216  xio->localKeyFile=NULL;
217 }
218 
219 
220 
222 {
223  GWEN_SYNCIO_TLS *xio;
224 
225  assert(sio);
226  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
227  assert(xio);
228 
229  return xio->localTrustFile;
230 }
231 
232 
233 
235 {
236  GWEN_SYNCIO_TLS *xio;
237 
238  assert(sio);
239  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
240  assert(xio);
241 
242  free(xio->localTrustFile);
243  if (s)
244  xio->localTrustFile=strdup(s);
245  else
246  xio->localTrustFile=NULL;
247 }
248 
249 
250 
252 {
253  GWEN_SYNCIO_TLS *xio;
254 
255  assert(sio);
256  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
257  assert(xio);
258 
259  return xio->dhParamFile;
260 }
261 
262 
263 
265 {
266  GWEN_SYNCIO_TLS *xio;
267 
268  assert(sio);
269  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
270  assert(xio);
271 
272  free(xio->dhParamFile);
273  if (s)
274  xio->dhParamFile=strdup(s);
275  else
276  xio->dhParamFile=NULL;
277 }
278 
279 
280 
282 {
283  GWEN_SYNCIO_TLS *xio;
284 
285  assert(sio);
286  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
287  assert(xio);
288 
289  return xio->hostName;
290 }
291 
292 
293 
295 {
296  GWEN_SYNCIO_TLS *xio;
297 
298  assert(sio);
299  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
300  assert(xio);
301 
302  free(xio->hostName);
303  if (s)
304  xio->hostName=strdup(s);
305  else
306  xio->hostName=NULL;
307 }
308 
309 
310 
312 {
313  GWEN_SYNCIO_TLS *xio;
314 
315  assert(sio);
316  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
317  assert(xio);
318 
319  return xio->peerCertDescr;
320 }
321 
322 
323 
324 int GWEN_SyncIo_Tls__readFile(const char *fname, GWEN_BUFFER *buf)
325 {
326  FILE *f;
327 
328  f=fopen(fname, "r");
329  if (f==NULL)
330  return GWEN_ERROR_IO;
331 
332  while (!feof(f)) {
333  int rv;
334 
335  GWEN_Buffer_AllocRoom(buf, 512);
336  rv=fread(GWEN_Buffer_GetPosPointer(buf), 1, 512, f);
337  if (rv==0)
338  break;
339  else if (rv<0) {
340  DBG_INFO(GWEN_LOGDOMAIN, "fread(%s): %s", fname, strerror(errno));
341  fclose(f);
342  return GWEN_ERROR_IO;
343  }
344  else {
345  GWEN_Buffer_IncrementPos(buf, rv);
347  }
348  }
349  fclose(f);
350  return 0;
351 }
352 
353 
354 
355 
356 #if GWEN_TLS_USE_SYSTEM_CERTIFICATES
357 # ifndef OS_WIN32
358 static int GWEN_SyncIo_Tls_AddCaCertFolder(GWEN_SYNCIO *sio, const char *folder)
359 {
360  GWEN_SYNCIO_TLS *xio;
361  int rv;
362  int successfullTustFileCount=0;
363 
364  assert(sio);
365  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
366  assert(xio);
367 
368  if (folder && *folder) {
369  GWEN_STRINGLIST *fileList;
370 
371  fileList=GWEN_StringList_new();
372  rv=GWEN_Directory_GetMatchingFilesRecursively(folder, fileList, "*.crt");
373  if (rv<0) {
375  "Error reading list of certificate files (%d) in folder [%s]",
376  rv, folder);
377  }
378  else {
380 
381  se=GWEN_StringList_FirstEntry(fileList);
382  while (se) {
383  const char *s;
384 
386  if (s && *s) {
387  rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
388  s,
389  GNUTLS_X509_FMT_PEM);
390  if (rv<=0) {
392  "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
393  s, rv, gnutls_strerror(rv));
394  }
395  else {
396  DBG_INFO(GWEN_LOGDOMAIN, "Added %d trusted certs from [%s]", rv, s);
397  successfullTustFileCount++;
398  }
399  }
400 
402  } /* while */
403  }
404  GWEN_StringList_free(fileList);
405  }
406 
407  if (successfullTustFileCount==0) {
408  DBG_ERROR(GWEN_LOGDOMAIN, "No files added from folder [%s]", folder);
409  }
410 
411  return successfullTustFileCount;
412 }
413 # endif
414 #endif
415 
416 
417 
419 {
420  GWEN_SYNCIO_TLS *xio;
421  int rv;
422  uint32_t lflags;
423  const char *custom_ciphers;
424  const char *errPos=NULL;
425 
426  assert(sio);
427  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
428  assert(xio);
429 
430  lflags=GWEN_SyncIo_GetFlags(sio);
431  DBG_INFO(GWEN_LOGDOMAIN, "Preparing SSL (%08x)", lflags);
432 
433  /* init session */
434  if (lflags & GWEN_SYNCIO_FLAGS_PASSIVE) {
435  DBG_INFO(GWEN_LOGDOMAIN, "Init as server");
436  rv=gnutls_init(&xio->session, GNUTLS_SERVER);
437  }
438  else {
439  DBG_INFO(GWEN_LOGDOMAIN, "Init as client");
440  rv=gnutls_init(&xio->session, GNUTLS_CLIENT);
441  }
442  if (rv) {
443  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_init: %d (%s)", rv, gnutls_strerror(rv));
444  return GWEN_ERROR_GENERIC;
445  }
446 
447  /* set cipher priorities */
448  custom_ciphers=getenv("GWEN_TLS_CIPHER_PRIORITIES");
449  /* TODO: make custom ciphers configurable as priority string? */
450  if (custom_ciphers && *custom_ciphers) { /* use cipher list from env var */
451  GWEN_Gui_ProgressLog2(0, GWEN_LoggerLevel_Info, I18N("TLS: SSL cipher priority list: %s"), custom_ciphers);
452  rv=gnutls_priority_set_direct(xio->session, custom_ciphers, &errPos);
453  if (rv!=GNUTLS_E_SUCCESS) {
454  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_priority_set_direct using '%s' failed: %s (%d) [%s]",
455  custom_ciphers, gnutls_strerror(rv), rv, errPos?errPos:"");
456  gnutls_deinit(xio->session);
457  return GWEN_ERROR_GENERIC;
458  }
459  }
460  else { /* use default ciphers from GnuTLS */
461  GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Notice, I18N("Using GnuTLS default ciphers."));
462  rv=gnutls_set_default_priority(xio->session);
463  if (rv!=GNUTLS_E_SUCCESS) {
464  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_set_default_priority failed: %s (%d)", gnutls_strerror(rv), rv);
465  gnutls_deinit(xio->session);
466  return GWEN_ERROR_GENERIC;
467  }
468  }
469 
470  /* protect against too-many-known-ca problem */
471  gnutls_handshake_set_max_packet_length(xio->session, 64*1024);
472 
473  /* let a server request peer certs */
474  if ((lflags & GWEN_SYNCIO_FLAGS_PASSIVE) &&
476  gnutls_certificate_server_set_request(xio->session, GNUTLS_CERT_REQUIRE);
477 
478  /* prepare cert credentials */
479  rv=gnutls_certificate_allocate_credentials(&xio->credentials);
480  if (rv) {
481  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_allocate_credentials: %d (%s)", rv, gnutls_strerror(rv));
482  gnutls_deinit(xio->session);
483  return GWEN_ERROR_GENERIC;
484  }
485 
486  /* possibly set key file and cert file */
487  if (xio->localCertFile && xio->localKeyFile) {
488  rv=gnutls_certificate_set_x509_key_file(xio->credentials,
489  xio->localCertFile,
490  xio->localKeyFile,
491  GNUTLS_X509_FMT_PEM);
492  if (rv<0) {
493  if (rv) {
494  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: %d (%s)", rv, gnutls_strerror(rv));
495  gnutls_certificate_free_credentials(xio->credentials);
496  gnutls_deinit(xio->session);
497  return GWEN_ERROR_GENERIC;
498  }
499  }
500  }
501 
502  /* find default trust file if none is selected */
504 #if GWEN_TLS_USE_SYSTEM_CERTIFICATES
505  /* disable setting of default trust file as discussed on aqbanking-users.
506  * The rationale is that without this file being set gnutls should behave
507  * correctly on each system.
508  * On Linux systems it should use the standard mechanism of the underlying
509  * distribution. On Windows the default CA store should be used (if given
510  * "--with-default-trust-store-file" to "./configure" of GNUTLS).
511  */
512  int trustFileSet=0;
513 
514 
515  if (trustFileSet==0) {
516  /* Adds the system's default trusted CAs in order to verify client or server certificates. */
517  rv=gnutls_certificate_set_x509_system_trust(xio->credentials);
518  if (rv<=0) {
519  DBG_WARN(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_system_trust: %d (%s)", rv, gnutls_strerror(rv));
520  }
521  else {
522  DBG_INFO(GWEN_LOGDOMAIN, "Added %d default trusted certs from system", rv);
523  trustFileSet=1;
524  }
525  }
526 
527  /* try to find OpenSSL certificates */
528 # ifdef OS_WIN32
529  if (trustFileSet==0) {
530  char defaultPath[2*MAX_PATH+1];
531  const char *defaultFile = "ca-bundle.crt";
532  GWEN_STRINGLIST *paths;
533  GWEN_BUFFER *nbuf;
534 
535  if (GWEN_Directory_GetPrefixDirectory(defaultPath, sizeof(defaultPath))) {
536  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: could not get install prefix");
537  return GWEN_ERROR_GENERIC;
538  }
539  if (strcat_s(defaultPath, sizeof(defaultPath), "\\share\\gwenhywfar")) {
540  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: no memory on creating search path");
541  return GWEN_ERROR_GENERIC;
542  }
543 
544  paths=GWEN_StringList_new();
545  GWEN_StringList_AppendString(paths, defaultPath, 0, 0);
546 
547  nbuf=GWEN_Buffer_new(0, 256, 0, 1);
548  rv=GWEN_Directory_FindFileInPaths(paths, defaultFile, nbuf);
549  GWEN_StringList_free(paths);
550  if (rv==0) {
552  "Using default ca-bundle from [%s]",
553  GWEN_Buffer_GetStart(nbuf));
554 
555  rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
556  GWEN_Buffer_GetStart(nbuf),
557  GNUTLS_X509_FMT_PEM);
558  if (rv<=0) {
560  "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
561  GWEN_Buffer_GetStart(nbuf), rv, gnutls_strerror(rv));
562  }
563  else {
565  "Added %d trusted certs from [%s]", rv, GWEN_Buffer_GetStart(nbuf));
566  trustFileSet=1;
567  }
568  }
569  GWEN_Buffer_free(nbuf);
570  }
571 # endif
572 
573 
574 # ifndef OS_WIN32
575  /* try to finde certificate bundle */
576  if (trustFileSet==0) {
577  int i;
578  const char *sCertFile=NULL;
579 
580  for (i=0; ; i++) {
581  sCertFile=SYNCIO_TLS_SYSTEM_CERTFILES[i];
582  if (sCertFile==NULL)
583  break;
585  DBG_INFO(GWEN_LOGDOMAIN, "Found system-wide cert bundle in %s", sCertFile);
586  break;
587  }
588  }
589 
590  if (sCertFile && *sCertFile) {
591  rv=gnutls_certificate_set_x509_trust_file(xio->credentials, sCertFile, GNUTLS_X509_FMT_PEM);
592  if (rv<=0) {
593  DBG_WARN(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_trust_file(%s): %d (%s)", sCertFile, rv, gnutls_strerror(rv));
594  }
595  else {
596  DBG_INFO(GWEN_LOGDOMAIN, "Added %d trusted certs from [%s]", rv, sCertFile);
597  trustFileSet=1;
598  }
599  }
600  else {
601  DBG_ERROR(GWEN_LOGDOMAIN, "No system-wide certificate bundle found.");
602  }
603  }
604 
605  /* try to find ca-certificates (at least available on Debian systems) */
606  if (trustFileSet==0) {
607  rv=GWEN_Directory_GetPath("/usr/share/ca-certificates", GWEN_PATH_FLAGS_NAMEMUSTEXIST);
608  if (rv>=0) {
609  rv=GWEN_SyncIo_Tls_AddCaCertFolder(sio, "/usr/share/ca-certificates");
610  if (rv<=0) {
611  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
612  }
613  else {
614  trustFileSet=1;
615  }
616  }
617  }
618 
619 # endif
620 
621 
622  if (trustFileSet==0) {
623 
624  /* TODO: use gnutls_certificate_set_x509_system_trust() */
625  trustFileSet=1;
626  }
627 
628 
629 
630  if (trustFileSet==0) {
631  DBG_WARN(GWEN_LOGDOMAIN, "No default bundle file found");
632  }
633 #endif
634  }
635 
636  /* possibly set trust file */
637  if (xio->localTrustFile) {
638  rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
639  xio->localTrustFile,
640  GNUTLS_X509_FMT_PEM);
641  if (rv<=0) {
643  "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
644  (xio->localTrustFile)?(xio->localTrustFile):"-none-",
645  rv, gnutls_strerror(rv));
646  gnutls_certificate_free_credentials(xio->credentials);
647  gnutls_deinit(xio->session);
648  return GWEN_ERROR_GENERIC;
649  }
650  else {
652  "Added %d trusted certs", rv);
653  }
654  }
655 
656  /* possibly set DH params */
657  if (xio->dhParamFile) {
658  GWEN_BUFFER *dbuf;
659 
660  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
661  rv=GWEN_SyncIo_Tls__readFile(xio->dhParamFile, dbuf);
662  if (rv) {
663  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
664  GWEN_Buffer_free(dbuf);
665  gnutls_certificate_free_credentials(xio->credentials);
666  gnutls_deinit(xio->session);
667  return rv;
668  }
669  else {
670  gnutls_datum_t d;
671  gnutls_dh_params_t dh_params=NULL;
672 
673  rv=gnutls_dh_params_init(&dh_params);
674  if (rv<0) {
675  GWEN_Buffer_free(dbuf);
676  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_init: %d (%s)", rv, gnutls_strerror(rv));
677  gnutls_certificate_free_credentials(xio->credentials);
678  gnutls_deinit(xio->session);
679  return GWEN_ERROR_GENERIC;
680  }
681 
682  d.size=GWEN_Buffer_GetUsedBytes(dbuf);
683  d.data=(unsigned char *)GWEN_Buffer_GetStart(dbuf);
684 
685  rv=gnutls_dh_params_import_pkcs3(dh_params, &d, GNUTLS_X509_FMT_PEM);
686  if (rv<0) {
687  GWEN_Buffer_free(dbuf);
688  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_import_pkcs3: %d (%s)", rv, gnutls_strerror(rv));
689  gnutls_certificate_free_credentials(xio->credentials);
690  gnutls_deinit(xio->session);
691  return GWEN_ERROR_GENERIC;
692  }
693  GWEN_Buffer_free(dbuf);
694 
695  gnutls_certificate_set_dh_params(xio->credentials, dh_params);
696  }
697  }
698 
699  /* set credentials in TLS session */
700  rv=gnutls_credentials_set(xio->session, GNUTLS_CRD_CERTIFICATE, xio->credentials);
701  if (rv<0) {
702  DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_credentials_set: %d (%s)", rv, gnutls_strerror(rv));
703  gnutls_certificate_free_credentials(xio->credentials);
704  gnutls_deinit(xio->session);
705  return GWEN_ERROR_GENERIC;
706  }
707 
708  /* we use our own push/pull functions */
709  gnutls_transport_set_ptr(xio->session, (gnutls_transport_ptr_t)sio);
710  gnutls_transport_set_push_function(xio->session, GWEN_SyncIo_Tls_Push);
711  gnutls_transport_set_pull_function(xio->session, GWEN_SyncIo_Tls_Pull);
712 #if GNUTLS_VERSION_NUMBER < 0x020c00
713  /* This function must be set to 0 in GNUTLS versions < 2.12.0 because we use
714  * custom push/pull functions.
715  * In GNUTLS 2.12.x this is set to 0 and since version 3 this functions is removed
716  * completely.
717  * So we only call this function now for GNUTLS < 2.12.0.
718  */
719  gnutls_transport_set_lowat(xio->session, 0);
720 #endif
721 
722  xio->prepared=1;
723 
724  return 0;
725 }
726 
727 
728 
730 {
731  GWEN_SYNCIO_TLS *xio;
732 
733  assert(sio);
734  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
735  assert(xio);
736 
737  if (xio->prepared) {
738  gnutls_certificate_free_credentials(xio->credentials);
739  gnutls_deinit(xio->session);
740  xio->prepared=0;
741  }
742 }
743 
744 
745 
747 {
748  GWEN_SYNCIO_TLS *xio;
749  const gnutls_datum_t *cert_list;
750  unsigned int cert_list_size;
751  size_t size;
752  GWEN_SSLCERTDESCR *certDescr;
753  char buffer1[64];
754  time_t t0;
755  int rv;
756  uint32_t lflags;
757  uint32_t errFlags=0;
758  int i;
759  unsigned int status;
760  GWEN_BUFFER *sbuf=NULL;
761 
762  assert(sio);
763  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
764  assert(xio);
765 
766  lflags=GWEN_SyncIo_GetFlags(sio);
767 
768  if (xio->peerCertDescr) {
769  GWEN_SslCertDescr_free(xio->peerCertDescr);
770  xio->peerCertDescr=NULL;
771  }
772  xio->peerCertFlags=0;
773 
774  t0=time(NULL);
775  if (t0<0) {
776  DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
777  errFlags|=GWEN_SSL_CERT_FLAGS_SYSTEM;
778  }
779 
780  /* create new cert description, check cert on the fly */
781  certDescr=GWEN_SslCertDescr_new();
782 
783  /* some general tests */
785  gnutls_certificate_set_verify_flags(xio->credentials,
786  GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
787 
788  rv=gnutls_certificate_verify_peers2(xio->session, &status);
789  if (rv<0) {
790  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
791  GWEN_SslCertDescr_free(certDescr);
793  }
794 
795  if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
796  DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
797 
798  GWEN_SslCertDescr_free(certDescr);
800  }
801 
802  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
803  DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
805  I18N("Signer not found"));
807  }
808 
809  if (status & GNUTLS_CERT_INVALID) {
810  DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
812  I18N("Certificate is not trusted"));
813  errFlags|=GWEN_SSL_CERT_FLAGS_INVALID;
814  }
815 
816  if (status & GNUTLS_CERT_REVOKED) {
817  DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
819  I18N("Certificate has been revoked"));
820  errFlags|=GWEN_SSL_CERT_FLAGS_REVOKED;
821  }
822 
823  cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
824  if (cert_list==NULL || cert_list_size==0) {
825  DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
826  return GWEN_ERROR_NO_DATA;
827  }
828 
829  for (i=0; i<cert_list_size; i++) {
830  gnutls_x509_crt_t cert;
831  time_t t;
832 
833  rv=gnutls_x509_crt_init(&cert);
834  if (rv!=0) {
835  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
836  return GWEN_ERROR_GENERIC;
837  }
838 
839  rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); /* TODO: shouldn't we use the index?? */
840  if (rv!=0) {
841  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
842  gnutls_x509_crt_deinit(cert);
843  return GWEN_ERROR_GENERIC;
844  }
845 
846  if (i==0) {
847  gnutls_datum_t n= {NULL, 0};
848  gnutls_datum_t e= {NULL, 0};
849 
850  /* get public key from cert, if any */
851  rv=gnutls_x509_crt_get_pk_rsa_raw(cert, &n, &e);
852  if (rv!=0) {
853  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_pk_rsa_raw: %d (%s)", rv, gnutls_strerror(rv));
854  }
855  else {
856  GWEN_BUFFER *kbuf;
857 
858  DBG_INFO(GWEN_LOGDOMAIN, "Key stored within certificate, extracting (modlen=%d, explen=%d)",
859  n.size, e.size);
860 
861  kbuf=GWEN_Buffer_new(0, 256, 0, 1);
862 
863  if (n.data && n.size) {
864  /* store public modulus */
865  GWEN_Text_ToHexBuffer((const char *)(n.data), n.size, kbuf, 0, 0, 0);
867  GWEN_Buffer_Reset(kbuf);
868  }
869 
870  if (e.data && e.size) {
871  /* store public exponent */
872  GWEN_Text_ToHexBuffer((const char *)(e.data), e.size, kbuf, 0, 0, 0);
874  GWEN_Buffer_Reset(kbuf);
875  }
876 
877  GWEN_Buffer_free(kbuf);
878  if (n.data)
879  gcry_free(n.data);
880  if (e.data)
881  gcry_free(e.data);
882  }
883 
884  /* get fingerprint (MD5) */
885  size=16;
886  rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
887  if (rv!=0) {
888  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(MD5): %d (%s)", rv, gnutls_strerror(rv));
889  GWEN_SslCertDescr_free(certDescr);
890  gnutls_x509_crt_deinit(cert);
891  return GWEN_ERROR_GENERIC;
892  }
893  else {
894  GWEN_BUFFER *dbuf;
895 
896  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
897  if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
898  size, dbuf, 2, ':', 0)) {
900  "Could not convert fingerprint to hex");
901  }
902  else {
904  }
905  GWEN_Buffer_free(dbuf);
906  }
907 
908  /* get fingerprint (SHA1) */
909  size=sizeof(buffer1);
910  rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buffer1, &size);
911  if (rv!=0) {
912  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(SHA1): %d (%s)", rv, gnutls_strerror(rv));
913  GWEN_SslCertDescr_free(certDescr);
914  gnutls_x509_crt_deinit(cert);
915  return GWEN_ERROR_GENERIC;
916  }
917  else {
918  GWEN_BUFFER *dbuf;
919 
920  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
921  if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
922  size, dbuf, 2, ':', 0)) {
924  "Could not convert fingerprint to hex");
925  }
926  else {
928  }
929  GWEN_Buffer_free(dbuf);
930  }
931 
932  /* get fingerprint (SHA512) */
933  size=sizeof(buffer1);
934  rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA512, buffer1, &size);
935  if (rv!=0) {
936  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint(SHA512): %d (%s)", rv, gnutls_strerror(rv));
937  GWEN_SslCertDescr_free(certDescr);
938  gnutls_x509_crt_deinit(cert);
939  return GWEN_ERROR_GENERIC;
940  }
941  else {
942  GWEN_BUFFER *dbuf;
943 
944  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
945  if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
946  size, dbuf, 2, ':', 0)) {
948  "Could not convert fingerprint to hex");
949  }
950  else {
952  }
953  GWEN_Buffer_free(dbuf);
954  }
955 
956 
957  if (xio->hostName) {
958  DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
959  if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
961  "Certificate was not issued for this host");
963  I18N("Certificate was not issued for this host"));
965  }
966  else {
967  DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
968  }
969  }
970  else {
972  "Hostname is not set, unable to verify the sender");
974  I18N("No hostname to verify the sender!"));
975  }
976 
977  }
978 
979  /* get activation time */
980  t=gnutls_x509_crt_get_activation_time(cert);
981  if (t<0) {
982  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
984  }
985  else {
986  if (t>t0) {
987  DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
989  }
990  if (i==0) {
991  GWEN_TIME *ti;
992 
993  ti=GWEN_Time_fromSeconds(t);
994  if (ti)
995  GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
996  GWEN_Time_free(ti);
997  }
998  }
999 
1000  /* get expiration time */
1001  t=gnutls_x509_crt_get_expiration_time(cert);
1002  if (t<0) {
1003  DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
1004  errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
1005  }
1006  else {
1007  if (t<t0) {
1008  DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
1009  errFlags|=GWEN_SSL_CERT_FLAGS_EXPIRED;
1010  }
1011  if (i==0) {
1012  GWEN_TIME *ti;
1013 
1014  ti=GWEN_Time_fromSeconds(t);
1015  if (ti)
1016  GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
1017  GWEN_Time_free(ti);
1018  }
1019  }
1020 
1021  if (i==0) {
1022  /* get owner information, but only for first cert */
1023  size=sizeof(buffer1)-1;
1024  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
1025  if (rv==0) {
1026  GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
1027  if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
1028  DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
1030  }
1031  }
1032 
1033  size=sizeof(buffer1)-1;
1034  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
1035  if (rv==0)
1036  GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
1037 
1038  size=sizeof(buffer1)-1;
1039  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
1040  if (rv==0)
1041  GWEN_SslCertDescr_SetOrganizationalUnitName(certDescr, buffer1);
1042 
1043  size=sizeof(buffer1)-1;
1044  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
1045  if (rv==0)
1046  GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
1047 
1048  size=sizeof(buffer1)-1;
1049  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
1050  if (rv==0)
1051  GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
1052 
1053  size=sizeof(buffer1)-1;
1054  rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
1055  if (rv==0)
1056  GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
1057  }
1058 
1059  gnutls_x509_crt_deinit(cert);
1060  }
1061 
1062  /* done */
1063  if (errFlags)
1064  GWEN_SslCertDescr_SetIsError(certDescr, 1);
1065  else
1066  errFlags|=GWEN_SSL_CERT_FLAGS_OK;
1067 
1068  sbuf=GWEN_Buffer_new(0, 256, 0, 1);
1069 
1070  if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
1071  if (GWEN_Buffer_GetUsedBytes(sbuf))
1072  GWEN_Buffer_AppendString(sbuf, "; ");
1073  GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
1074  }
1075 
1076  if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
1077  if (GWEN_Buffer_GetUsedBytes(sbuf))
1078  GWEN_Buffer_AppendString(sbuf, "; ");
1079  GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
1080  }
1081 
1082  if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
1083  if (GWEN_Buffer_GetUsedBytes(sbuf))
1084  GWEN_Buffer_AppendString(sbuf, "; ");
1085  GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
1086  }
1087 
1088  if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
1089  if (GWEN_Buffer_GetUsedBytes(sbuf))
1090  GWEN_Buffer_AppendString(sbuf, "; ");
1091  GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
1092  }
1093 
1094  if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
1095  if (GWEN_Buffer_GetUsedBytes(sbuf))
1096  GWEN_Buffer_AppendString(sbuf, "; ");
1097  GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
1098  }
1099 
1100  if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
1101  if (GWEN_Buffer_GetUsedBytes(sbuf))
1102  GWEN_Buffer_AppendString(sbuf, "; ");
1103  GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
1104  }
1105 
1106  if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
1107  if (GWEN_Buffer_GetUsedBytes(sbuf))
1108  GWEN_Buffer_AppendString(sbuf, "; ");
1109  GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
1110  }
1111 
1112  if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
1113  if (GWEN_Buffer_GetUsedBytes(sbuf))
1114  GWEN_Buffer_AppendString(sbuf, "; ");
1115  GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
1116  }
1117 
1118  if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
1119  if (GWEN_Buffer_GetUsedBytes(sbuf))
1120  GWEN_Buffer_AppendString(sbuf, "; ");
1121  GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
1122  }
1123 
1125  GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
1126  GWEN_Buffer_free(sbuf);
1127 
1128 #if 0
1129  if (1) {
1130  GWEN_DB_NODE *dbTest;
1131 
1132  dbTest=GWEN_DB_Group_new("Cert");
1133  GWEN_SslCertDescr_toDb(certDescr, dbTest);
1134  GWEN_DB_Dump(dbTest, 2);
1135  GWEN_DB_Group_free(dbTest);
1136  }
1137 #endif
1138 
1139  xio->peerCertDescr=certDescr;
1140  xio->peerCertFlags=errFlags;
1141 
1142  return 0;
1143 }
1144 
1145 
1146 
1147 ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len)
1148 {
1149  GWEN_SYNCIO *sio;
1150  GWEN_SYNCIO_TLS *xio;
1151  GWEN_SYNCIO *baseIo;
1152  int rv;
1153 
1154  sio=(GWEN_SYNCIO *) p;
1155  assert(sio);
1156  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1157  assert(xio);
1158 
1159  DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
1160  baseIo=GWEN_SyncIo_GetBaseIo(sio);
1161  assert(baseIo);
1162 
1163  rv=GWEN_SyncIo_Read(baseIo, buf, len);
1164  if (rv<0) {
1165  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1166 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
1167  gnutls_transport_set_errno(xio->session, errno);
1168 #endif
1169  return (ssize_t)-1;
1170  }
1171 
1172 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
1173  gnutls_transport_set_errno(xio->session, 0);
1174 #else
1175  errno=0;
1176 #endif
1177  DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", rv);
1178  /*GWEN_Text_DumpString(buf, rv, 2);*/
1179  return rv;
1180 }
1181 
1182 
1183 
1184 ssize_t GWEN_SyncIo_Tls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len)
1185 {
1186  GWEN_SYNCIO *sio;
1187  GWEN_SYNCIO_TLS *xio;
1188  GWEN_SYNCIO *baseIo;
1189  int rv;
1190 
1191  sio=(GWEN_SYNCIO *) p;
1192  assert(sio);
1193  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
1194  assert(xio);
1195 
1196  DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
1197  baseIo=GWEN_SyncIo_GetBaseIo(sio);
1198  assert(baseIo);
1199 
1200  rv=GWEN_SyncIo_Write(baseIo, buf, len);
1201  if (rv<0) {
1202  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1203 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
1204  gnutls_transport_set_errno(xio->session, errno);
1205 #endif
1206  return (ssize_t)-1;
1207  }
1208 
1209 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
1210  gnutls_transport_set_errno(xio->session, 0);
1211 #endif
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");
1324  return GWEN_ERROR_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 
1337  rv=GWEN_SyncIo_Tls_Prepare(sio);
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);
1386  return GWEN_ERROR_SSL_SECURITY;
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);
1402  return GWEN_ERROR_SSL_SECURITY;
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);
1433  return GWEN_ERROR_NOT_CONNECTED;
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);
1481  return GWEN_ERROR_NOT_CONNECTED;
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);
1550  return GWEN_ERROR_NOT_CONNECTED;
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 
void GWEN_SslCertDescr_SetStateOrProvinceName(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SyncIo_Tls_UndoPrepare(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:729
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:989
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:1184
#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
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:234
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:264
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:281
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#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:251
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:191
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:123
int GWEN_SyncIo_Tls_Internal_CheckCert(GWEN_SYNCIO *sio, const GWEN_SSLCERTDESCR *cert)
Definition: syncio_tls.c:126
#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:161
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:86
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:418
#define MAX_PATH
Definition: testlib.c:122
int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *fmt,...)
Definition: gui.c:1001
int GWEN_SyncIo_Tls_CheckCert(GWEN_SYNCIO *sio, const GWEN_SSLCERTDESCR *cert)
Definition: syncio_tls.c:140
#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:311
#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:294
#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:204
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:1462
int GWEN_SyncIo_Tls_GetPeerCert(GWEN_SYNCIO *sio)
Definition: syncio_tls.c:746
ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len)
Definition: syncio_tls.c:1147
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:1416
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:174
#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:1219
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:1526
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:1308
int GWEN_Gui_CheckCert(const GWEN_SSLCERTDESCR *cd, GWEN_SYNCIO *sio, uint32_t guiid)
Definition: gui.c:1262
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:324
#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:221
void GWEN_SslCertDescr_SetFingerPrintSha1(GWEN_SSLCERTDESCR *st, const char *d)
void GWEN_SslCertDescr_SetStatusFlags(GWEN_SSLCERTDESCR *st, uint32_t d)