gwenhywfar 4.1.0
syncio_tls.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Wed Apr 28 2010
00003  copyright   : (C) 2010 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #define DISABLE_DEBUGLOG
00030 
00031 /*#define GWEN_TLS_DEBUG*/
00032 
00033 
00034 #include "syncio_tls_p.h"
00035 #include "i18n_l.h"
00036 
00037 #include <gwenhywfar/misc.h>
00038 #include <gwenhywfar/debug.h>
00039 #include <gwenhywfar/gui.h>
00040 #include <gwenhywfar/gui.h>
00041 #include <gwenhywfar/pathmanager.h>
00042 #include <gwenhywfar/directory.h>
00043 #include <gwenhywfar/gwenhywfar.h>
00044 #include <gwenhywfar/text.h>
00045 
00046 #include <assert.h>
00047 #include <errno.h>
00048 #include <string.h>
00049 
00050 #include <gnutls/gnutls.h>
00051 #include <gnutls/x509.h>
00052 
00053 
00054 
00055 GWEN_INHERIT(GWEN_SYNCIO, GWEN_SYNCIO_TLS)
00056 
00057 
00058 GWEN_SYNCIO *GWEN_SyncIo_Tls_new(GWEN_SYNCIO *baseIo) {
00059   GWEN_SYNCIO *sio;
00060   GWEN_SYNCIO_TLS *xio;
00061 
00062   assert(baseIo);
00063   sio=GWEN_SyncIo_new(GWEN_SYNCIO_TLS_TYPE, baseIo);
00064   GWEN_NEW_OBJECT(GWEN_SYNCIO_TLS, xio);
00065   GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio, xio, GWEN_SyncIo_Tls_FreeData);
00066 
00067   GWEN_SyncIo_SetConnectFn(sio, GWEN_SyncIo_Tls_Connect);
00068   GWEN_SyncIo_SetDisconnectFn(sio, GWEN_SyncIo_Tls_Disconnect);
00069   GWEN_SyncIo_SetReadFn(sio, GWEN_SyncIo_Tls_Read);
00070   GWEN_SyncIo_SetWriteFn(sio, GWEN_SyncIo_Tls_Write);
00071 
00072   return sio;
00073 }
00074 
00075 
00076 
00077 void GWENHYWFAR_CB GWEN_SyncIo_Tls_FreeData(void *bp, void *p) {
00078   GWEN_SYNCIO_TLS *xio;
00079 
00080   xio=(GWEN_SYNCIO_TLS*) p;
00081   GWEN_FREE_OBJECT(xio);
00082 }
00083 
00084 
00085 
00086 const char *GWEN_SyncIo_Tls_GetLocalCertFile(const GWEN_SYNCIO *sio) {
00087   GWEN_SYNCIO_TLS *xio;
00088 
00089   assert(sio);
00090   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00091   assert(xio);
00092 
00093   return xio->localCertFile;
00094 }
00095 
00096 
00097 
00098 void GWEN_SyncIo_Tls_SetLocalCertFile(GWEN_SYNCIO *sio, const char *s) {
00099   GWEN_SYNCIO_TLS *xio;
00100 
00101   assert(sio);
00102   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00103   assert(xio);
00104 
00105   free(xio->localCertFile);
00106   if (s) xio->localCertFile=strdup(s);
00107   else xio->localCertFile=NULL;
00108 }
00109 
00110 
00111 
00112 const char *GWEN_SyncIo_Tls_GetLocalKeyFile(const GWEN_SYNCIO *sio) {
00113   GWEN_SYNCIO_TLS *xio;
00114 
00115   assert(sio);
00116   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00117   assert(xio);
00118 
00119   return xio->localKeyFile;
00120 }
00121 
00122 
00123 
00124 void GWEN_SyncIo_Tls_SetLocalKeyFile(GWEN_SYNCIO *sio, const char *s) {
00125   GWEN_SYNCIO_TLS *xio;
00126 
00127   assert(sio);
00128   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00129   assert(xio);
00130 
00131   free(xio->localKeyFile);
00132   if (s) xio->localKeyFile=strdup(s);
00133   else xio->localKeyFile=NULL;
00134 }
00135 
00136 
00137 
00138 const char *GWEN_SyncIo_Tls_GetLocalTrustFile(const GWEN_SYNCIO *sio) {
00139   GWEN_SYNCIO_TLS *xio;
00140 
00141   assert(sio);
00142   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00143   assert(xio);
00144 
00145   return xio->localTrustFile;
00146 }
00147 
00148 
00149 
00150 void GWEN_SyncIo_Tls_SetLocalTrustFile(GWEN_SYNCIO *sio, const char *s) {
00151   GWEN_SYNCIO_TLS *xio;
00152 
00153   assert(sio);
00154   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00155   assert(xio);
00156 
00157   free(xio->localTrustFile);
00158   if (s) xio->localTrustFile=strdup(s);
00159   else xio->localTrustFile=NULL;
00160 }
00161 
00162 
00163 
00164 const char *GWEN_SyncIo_Tls_GetDhParamFile(const GWEN_SYNCIO *sio) {
00165   GWEN_SYNCIO_TLS *xio;
00166 
00167   assert(sio);
00168   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00169   assert(xio);
00170 
00171   return xio->dhParamFile;
00172 }
00173 
00174 
00175 
00176 void GWEN_SyncIo_Tls_SetDhParamFile(GWEN_SYNCIO *sio, const char *s) {
00177   GWEN_SYNCIO_TLS *xio;
00178 
00179   assert(sio);
00180   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00181   assert(xio);
00182 
00183   free(xio->dhParamFile);
00184   if (s) xio->dhParamFile=strdup(s);
00185   else xio->dhParamFile=NULL;
00186 }
00187 
00188 
00189 
00190 const char *GWEN_SyncIo_Tls_GetRemoteHostName(const GWEN_SYNCIO *sio) {
00191   GWEN_SYNCIO_TLS *xio;
00192 
00193   assert(sio);
00194   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00195   assert(xio);
00196 
00197   return xio->hostName;
00198 }
00199 
00200 
00201 
00202 void GWEN_SyncIo_Tls_SetRemoteHostName(GWEN_SYNCIO *sio, const char *s) {
00203   GWEN_SYNCIO_TLS *xio;
00204 
00205   assert(sio);
00206   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00207   assert(xio);
00208 
00209   free(xio->hostName);
00210   if (s) xio->hostName=strdup(s);
00211   else xio->hostName=NULL;
00212 }
00213 
00214 
00215 
00216 GWEN_SSLCERTDESCR *GWEN_SyncIo_Tls_GetPeerCertDescr(const GWEN_SYNCIO *sio) {
00217   GWEN_SYNCIO_TLS *xio;
00218 
00219   assert(sio);
00220   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00221   assert(xio);
00222 
00223   return xio->peerCertDescr;
00224 }
00225 
00226 
00227 
00228 int GWEN_SyncIo_Tls__readFile(const char *fname, GWEN_BUFFER *buf) {
00229   FILE *f;
00230 
00231   f=fopen(fname, "r");
00232   if (f==NULL)
00233     return GWEN_ERROR_IO;
00234 
00235   while(!feof(f)) {
00236     int rv;
00237 
00238     GWEN_Buffer_AllocRoom(buf, 512);
00239     rv=fread(GWEN_Buffer_GetPosPointer(buf), 1, 512, f);
00240     if (rv==0)
00241       break;
00242     else if (rv<0) {
00243       DBG_INFO(GWEN_LOGDOMAIN, "fread(%s): %s", fname, strerror(errno));
00244       fclose(f);
00245       return GWEN_ERROR_IO;
00246     }
00247     else {
00248       GWEN_Buffer_IncrementPos(buf, rv);
00249       GWEN_Buffer_AdjustUsedBytes(buf);
00250     }
00251   }
00252   fclose(f);
00253   return 0;
00254 }
00255 
00256 
00257 
00258 int GWEN_SyncIo_Tls_Prepare(GWEN_SYNCIO *sio) {
00259   GWEN_SYNCIO_TLS *xio;
00260   int rv;
00261   uint32_t lflags;
00262 
00263   assert(sio);
00264   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00265   assert(xio);
00266 
00267   lflags=GWEN_SyncIo_GetFlags(sio);
00268   DBG_INFO(GWEN_LOGDOMAIN, "Preparing SSL (%08x)", lflags);
00269 
00270   /* init session */
00271   if (lflags & GWEN_SYNCIO_FLAGS_PASSIVE) {
00272     DBG_INFO(GWEN_LOGDOMAIN, "Init as server");
00273     rv=gnutls_init(&xio->session, GNUTLS_SERVER);
00274   }
00275   else {
00276     DBG_INFO(GWEN_LOGDOMAIN, "Init as client");
00277     rv=gnutls_init(&xio->session, GNUTLS_CLIENT);
00278   }
00279   if (rv) {
00280     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_init: %d (%s)", rv, gnutls_strerror(rv));
00281     return GWEN_ERROR_GENERIC;
00282   }
00283 
00284   /* set default priority */
00285   rv=gnutls_set_default_priority(xio->session);
00286   if (rv) {
00287     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_set_default_priority: %d (%s)", rv, gnutls_strerror(rv));
00288     gnutls_deinit(xio->session);
00289     return GWEN_ERROR_GENERIC;
00290   }
00291 
00292   /* possibly force protocol priority */
00293   if (lflags & GWEN_SYNCIO_TLS_FLAGS_FORCE_SSL_V3) {
00294     const int proto_prio[2] = { GNUTLS_SSL3, 0 };
00295 
00296     DBG_INFO(GWEN_LOGDOMAIN, "Forcing SSL v3");
00297     rv=gnutls_protocol_set_priority(xio->session, proto_prio);
00298     if (rv) {
00299       DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_protocol_set_priority: %d (%s)", rv, gnutls_strerror(rv));
00300       gnutls_deinit(xio->session);
00301       return GWEN_ERROR_GENERIC;
00302     }
00303   }
00304 
00305   /* protect against too-many-known-ca problem */
00306   gnutls_handshake_set_max_packet_length(xio->session, 64*1024);
00307 
00308   /* let a server request peer certs */
00309   if ((lflags & GWEN_SYNCIO_FLAGS_PASSIVE) &&
00310       (lflags & GWEN_SYNCIO_TLS_FLAGS_REQUEST_CERT))
00311     gnutls_certificate_server_set_request(xio->session, GNUTLS_CERT_REQUIRE);
00312 
00313   /* prepare cert credentials */
00314   rv=gnutls_certificate_allocate_credentials(&xio->credentials);
00315   if (rv) {
00316     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_allocate_credentials: %d (%s)", rv, gnutls_strerror(rv));
00317     gnutls_deinit(xio->session);
00318     return GWEN_ERROR_GENERIC;
00319   }
00320 
00321   /* possibly set key file and cert file */
00322   if (xio->localCertFile && xio->localKeyFile) {
00323     rv=gnutls_certificate_set_x509_key_file(xio->credentials,
00324                                             xio->localCertFile,
00325                                             xio->localKeyFile,
00326                                             GNUTLS_X509_FMT_PEM);
00327     if (rv<0) {
00328       if (rv) {
00329         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: %d (%s)", rv, gnutls_strerror(rv));
00330         gnutls_certificate_free_credentials(xio->credentials);
00331         gnutls_deinit(xio->session);
00332         return GWEN_ERROR_GENERIC;
00333       }
00334     }
00335   }
00336 
00337   /* find default trust file if none is selected */
00338   if (lflags & GWEN_SYNCIO_TLS_FLAGS_ADD_TRUSTED_CAS) {
00339     int trustFileSet=0;
00340 
00341 #if 0
00342 # ifndef OS_WIN32
00343     /* try to find OpenSSL cert file */
00344     if (trustFileSet==0) {
00345       GWEN_STRINGLIST *paths;
00346       GWEN_BUFFER *nbuf;
00347 
00348       paths=GWEN_StringList_new();
00349       GWEN_StringList_AppendString(paths, "/etc/ssl/certs", 0, 0);
00350 
00351       nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00352       rv=GWEN_Directory_FindFileInPaths(paths,
00353                                         "ca-certificates.crt",
00354                                         nbuf);
00355       GWEN_StringList_free(paths);
00356       if (rv==0) {
00357         DBG_INFO(GWEN_LOGDOMAIN,
00358                  "Using default ca-bundle from [%s]",
00359                  GWEN_Buffer_GetStart(nbuf));
00360         GWEN_SyncIo_Tls_SetLocalTrustFile(sio, GWEN_Buffer_GetStart(nbuf));
00361         trustFileSet=1;
00362       }
00363     }
00364 # endif
00365 #endif
00366 
00367     if (trustFileSet==0) {
00368       GWEN_STRINGLIST *paths;
00369 
00370       /* try to find our trust file */
00371       paths=GWEN_PathManager_GetPaths(GWEN_PM_LIBNAME, GWEN_PM_DATADIR);
00372       if (paths) {
00373         GWEN_BUFFER *nbuf;
00374 
00375         nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00376         rv=GWEN_Directory_FindFileInPaths(paths,
00377                                           "ca-bundle.crt",
00378                                           nbuf);
00379         GWEN_StringList_free(paths);
00380         if (rv==0) {
00381           DBG_INFO(GWEN_LOGDOMAIN,
00382                    "Using default ca-bundle from [%s]",
00383                    GWEN_Buffer_GetStart(nbuf));
00384           GWEN_SyncIo_Tls_SetLocalTrustFile(sio, GWEN_Buffer_GetStart(nbuf));
00385           trustFileSet=1;
00386         }
00387         GWEN_Buffer_free(nbuf);
00388       }
00389     }
00390 
00391     if (trustFileSet==0) {
00392       DBG_WARN(GWEN_LOGDOMAIN, "No default bundle file found");
00393     }
00394   }
00395 
00396   /* possibly set trust file */
00397   if (xio->localTrustFile) {
00398     rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
00399                                               xio->localTrustFile,
00400                                               GNUTLS_X509_FMT_PEM);
00401     if (rv<=0) {
00402       DBG_ERROR(GWEN_LOGDOMAIN,
00403                 "gnutls_certificate_set_x509_trust_file(%s): %d (%s)",
00404                 (xio->localTrustFile)?(xio->localTrustFile):"-none-",
00405                 rv, gnutls_strerror(rv));
00406       gnutls_certificate_free_credentials(xio->credentials);
00407       gnutls_deinit(xio->session);
00408       return GWEN_ERROR_GENERIC;
00409     }
00410     else {
00411       DBG_INFO(GWEN_LOGDOMAIN,
00412                "Added %d trusted certs", rv);
00413     }
00414   }
00415 
00416   /* possibly set DH params */
00417   if (xio->dhParamFile) {
00418     GWEN_BUFFER *dbuf;
00419 
00420     dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00421     rv=GWEN_SyncIo_Tls__readFile(xio->dhParamFile, dbuf);
00422     if (rv) {
00423       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00424       GWEN_Buffer_free(dbuf);
00425       gnutls_certificate_free_credentials(xio->credentials);
00426       gnutls_deinit(xio->session);
00427       return rv;
00428     }
00429     else {
00430       gnutls_datum d;
00431       gnutls_dh_params dh_params=NULL;
00432 
00433       rv=gnutls_dh_params_init(&dh_params);
00434       if (rv<0) {
00435         GWEN_Buffer_free(dbuf);
00436         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_init: %d (%s)", rv, gnutls_strerror(rv));
00437         gnutls_certificate_free_credentials(xio->credentials);
00438         gnutls_deinit(xio->session);
00439         return GWEN_ERROR_GENERIC;
00440       }
00441 
00442       d.size=GWEN_Buffer_GetUsedBytes(dbuf);
00443       d.data=(unsigned char*)GWEN_Buffer_GetStart(dbuf);
00444 
00445       rv=gnutls_dh_params_import_pkcs3(dh_params, &d, GNUTLS_X509_FMT_PEM);
00446       if (rv<0) {
00447         GWEN_Buffer_free(dbuf);
00448         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_import_pkcs3: %d (%s)", rv, gnutls_strerror(rv));
00449         gnutls_certificate_free_credentials(xio->credentials);
00450         gnutls_deinit(xio->session);
00451         return GWEN_ERROR_GENERIC;
00452       }
00453       GWEN_Buffer_free(dbuf);
00454 
00455       gnutls_certificate_set_dh_params(xio->credentials, dh_params);
00456     }
00457   }
00458 
00459   /* set credentials in TLS session */
00460   rv=gnutls_credentials_set(xio->session, GNUTLS_CRD_CERTIFICATE, xio->credentials);
00461   if (rv<0) {
00462     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_credentials_set: %d (%s)", rv, gnutls_strerror(rv));
00463     gnutls_certificate_free_credentials(xio->credentials);
00464     gnutls_deinit(xio->session);
00465     return GWEN_ERROR_GENERIC;
00466   }
00467 
00468   /* we use our own push/pull functions */
00469   gnutls_transport_set_ptr(xio->session, (gnutls_transport_ptr_t)sio);
00470   gnutls_transport_set_push_function(xio->session, GWEN_SyncIo_Tls_Push);
00471   gnutls_transport_set_pull_function(xio->session, GWEN_SyncIo_Tls_Pull);
00472   gnutls_transport_set_lowat(xio->session, 0);
00473 
00474   xio->prepared=1;
00475 
00476   return 0;
00477 }
00478 
00479 
00480 
00481 void GWEN_SyncIo_Tls_UndoPrepare(GWEN_SYNCIO *sio) {
00482   GWEN_SYNCIO_TLS *xio;
00483 
00484   assert(sio);
00485   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00486   assert(xio);
00487 
00488   if (xio->prepared) {
00489     gnutls_certificate_free_credentials(xio->credentials);
00490     gnutls_deinit(xio->session);
00491     xio->prepared=0;
00492   }
00493 }
00494 
00495 
00496 
00497 int GWEN_SyncIo_Tls_GetPeerCert(GWEN_SYNCIO *sio) {
00498   GWEN_SYNCIO_TLS *xio;
00499   const gnutls_datum_t *cert_list;
00500   unsigned int cert_list_size;
00501   size_t size;
00502   GWEN_SSLCERTDESCR *certDescr;
00503   char buffer1[64];
00504   time_t t0;
00505   int rv;
00506   uint32_t lflags;
00507   uint32_t errFlags=0;
00508   int i;
00509   unsigned int status;
00510   GWEN_BUFFER *sbuf=NULL;
00511 
00512   assert(sio);
00513   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00514   assert(xio);
00515 
00516   lflags=GWEN_SyncIo_GetFlags(sio);
00517 
00518   if (xio->peerCertDescr) {
00519     GWEN_SslCertDescr_free(xio->peerCertDescr);
00520     xio->peerCertDescr=NULL;
00521   }
00522   xio->peerCertFlags=0;
00523 
00524   t0=time(NULL);
00525   if (t0<0) {
00526     DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
00527     errFlags|=GWEN_SSL_CERT_FLAGS_SYSTEM;
00528   }
00529 
00530   /* create new cert description, check cert on the fly */
00531   certDescr=GWEN_SslCertDescr_new();
00532 
00533   /* some general tests */
00534   if (lflags & GWEN_SYNCIO_TLS_FLAGS_ALLOW_V1_CA_CRT)
00535     gnutls_certificate_set_verify_flags(xio->credentials,
00536                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
00537 
00538   rv=gnutls_certificate_verify_peers2(xio->session, &status);
00539   if (rv<0) {
00540     DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
00541     GWEN_SslCertDescr_free(certDescr);
00542     return GWEN_ERROR_SSL_SECURITY;
00543   }
00544 
00545   if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
00546     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
00547 
00548     GWEN_SslCertDescr_free(certDescr);
00549     return GWEN_ERROR_SSL_SECURITY;
00550   }
00551 
00552   if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00553     DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
00554     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00555                          I18N("Signer not found"));
00556     errFlags|=GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND;
00557   }
00558 
00559   if (status & GNUTLS_CERT_INVALID) {
00560     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
00561     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00562                          I18N("Certificate is not trusted"));
00563     errFlags|=GWEN_SSL_CERT_FLAGS_INVALID;
00564   }
00565 
00566   if (status & GNUTLS_CERT_REVOKED) {
00567     DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
00568     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00569                          I18N("Certificate has been revoked"));
00570     errFlags|=GWEN_SSL_CERT_FLAGS_REVOKED;
00571   }
00572 
00573   cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
00574   if (cert_list==NULL || cert_list_size==0) {
00575     DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
00576     return GWEN_ERROR_NO_DATA;
00577   }
00578 
00579   for (i=0; i<cert_list_size; i++) {
00580     gnutls_x509_crt_t cert;
00581     time_t t;
00582 
00583     rv=gnutls_x509_crt_init(&cert);
00584     if (rv!=0) {
00585       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
00586       return GWEN_ERROR_GENERIC;
00587     }
00588 
00589     rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
00590     if (rv!=0) {
00591       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
00592       gnutls_x509_crt_deinit(cert);
00593       return GWEN_ERROR_GENERIC;
00594     }
00595 
00596     if (i==0) {
00597       /* get fingerprint */
00598       size=16;
00599       rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
00600       if (rv!=0) {
00601         DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint: %d (%s)", rv, gnutls_strerror(rv));
00602         GWEN_SslCertDescr_free(certDescr);
00603         gnutls_x509_crt_deinit(cert);
00604         return GWEN_ERROR_GENERIC;
00605       }
00606       else {
00607         GWEN_BUFFER *dbuf;
00608 
00609         dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00610         if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
00611                                   size, dbuf, 2, ':', 0)) {
00612           DBG_ERROR(GWEN_LOGDOMAIN,
00613                     "Could not convert fingerprint to hex");
00614         }
00615         else {
00616           GWEN_SslCertDescr_SetFingerPrint(certDescr, GWEN_Buffer_GetStart(dbuf));
00617         }
00618         GWEN_Buffer_free(dbuf);
00619       }
00620 
00621       if (xio->hostName) {
00622         DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
00623         if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
00624           DBG_WARN(GWEN_LOGDOMAIN,
00625                    "Certificate was not issued for this host");
00626           GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00627                                I18N("Certificate was not issued for this host"));
00628           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00629         }
00630         else {
00631           DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
00632         }
00633       }
00634       else {
00635         DBG_WARN(GWEN_LOGDOMAIN,
00636                  "Hostname is not set, unable to verify the sender");
00637         GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00638                              I18N("No hostname to verify the sender!"));
00639       }
00640 
00641     }
00642 
00643     /* get activation time */
00644     t=gnutls_x509_crt_get_activation_time(cert);
00645     if (t<0) {
00646       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
00647       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00648     }
00649     else {
00650       if (t>t0) {
00651         DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
00652         errFlags|=GWEN_SSL_CERT_FLAGS_NOT_ACTIVE;
00653       }
00654       if (i==0) {
00655         GWEN_TIME *ti;
00656 
00657         ti=GWEN_Time_fromSeconds(t);
00658         if (ti)
00659           GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
00660         GWEN_Time_free(ti);
00661       }
00662     }
00663 
00664     /* get expiration time */
00665     t=gnutls_x509_crt_get_expiration_time(cert);
00666     if (t<0) {
00667       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
00668       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00669     }
00670     else {
00671       if (t<t0) {
00672         DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
00673         errFlags|=GWEN_SSL_CERT_FLAGS_EXPIRED;
00674       }
00675       if (i==0) {
00676         GWEN_TIME *ti;
00677 
00678         ti=GWEN_Time_fromSeconds(t);
00679         if (ti)
00680           GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
00681         GWEN_Time_free(ti);
00682       }
00683     }
00684 
00685     if (i==0) {
00686       /* get owner information, but only for first cert */
00687       size=sizeof(buffer1)-1;
00688       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
00689       if (rv==0) {
00690         GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
00691         if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
00692           DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
00693           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00694         }
00695       }
00696 
00697       size=sizeof(buffer1)-1;
00698       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
00699       if (rv==0)
00700         GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
00701 
00702       size=sizeof(buffer1)-1;
00703       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
00704       if (rv==0)
00705         GWEN_SslCertDescr_SetOrganizationalUnitName(certDescr, buffer1);
00706 
00707       size=sizeof(buffer1)-1;
00708       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
00709       if (rv==0)
00710         GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
00711 
00712       size=sizeof(buffer1)-1;
00713       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
00714       if (rv==0)
00715         GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
00716 
00717       size=sizeof(buffer1)-1;
00718       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
00719       if (rv==0)
00720         GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
00721     }
00722 
00723     gnutls_x509_crt_deinit(cert);
00724   }
00725 
00726   /* done */
00727   if (errFlags)
00728     GWEN_SslCertDescr_SetIsError(certDescr, 1);
00729   else
00730     errFlags|=GWEN_SSL_CERT_FLAGS_OK;
00731 
00732   sbuf=GWEN_Buffer_new(0, 256, 0, 1);
00733 
00734   if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
00735     if (GWEN_Buffer_GetUsedBytes(sbuf))
00736       GWEN_Buffer_AppendString(sbuf, "; ");
00737     GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
00738   }
00739 
00740   if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
00741     if (GWEN_Buffer_GetUsedBytes(sbuf))
00742       GWEN_Buffer_AppendString(sbuf, "; ");
00743     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
00744   }
00745 
00746   if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
00747     if (GWEN_Buffer_GetUsedBytes(sbuf))
00748       GWEN_Buffer_AppendString(sbuf, "; ");
00749     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
00750   }
00751 
00752   if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
00753     if (GWEN_Buffer_GetUsedBytes(sbuf))
00754       GWEN_Buffer_AppendString(sbuf, "; ");
00755     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
00756   }
00757 
00758   if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
00759     if (GWEN_Buffer_GetUsedBytes(sbuf))
00760       GWEN_Buffer_AppendString(sbuf, "; ");
00761     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
00762   }
00763 
00764   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
00765     if (GWEN_Buffer_GetUsedBytes(sbuf))
00766       GWEN_Buffer_AppendString(sbuf, "; ");
00767     GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
00768   }
00769 
00770   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
00771     if (GWEN_Buffer_GetUsedBytes(sbuf))
00772       GWEN_Buffer_AppendString(sbuf, "; ");
00773     GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
00774   }
00775 
00776   if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
00777     if (GWEN_Buffer_GetUsedBytes(sbuf))
00778       GWEN_Buffer_AppendString(sbuf, "; ");
00779     GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
00780   }
00781 
00782   if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
00783     if (GWEN_Buffer_GetUsedBytes(sbuf))
00784       GWEN_Buffer_AppendString(sbuf, "; ");
00785     GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
00786   }
00787 
00788   GWEN_SslCertDescr_SetStatusText(certDescr, GWEN_Buffer_GetStart(sbuf));
00789   GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
00790   GWEN_Buffer_free(sbuf);
00791 
00792   xio->peerCertDescr=certDescr;
00793   xio->peerCertFlags=errFlags;
00794 
00795   return 0;
00796 }
00797 
00798 
00799 
00800 ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len) {
00801   GWEN_SYNCIO *sio;
00802   GWEN_SYNCIO_TLS *xio;
00803   GWEN_SYNCIO *baseIo;
00804   int rv;
00805 
00806   sio=(GWEN_SYNCIO*) p;
00807   assert(sio);
00808   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00809   assert(xio);
00810 
00811   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
00812   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00813   assert(baseIo);
00814 
00815   rv=GWEN_SyncIo_Read(baseIo, buf, len);
00816   if (rv<0) {
00817     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00818 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00819     gnutls_transport_set_errno(xio->session, errno);
00820 #endif
00821     return (ssize_t)-1;
00822   }
00823 
00824 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00825   gnutls_transport_set_errno(xio->session, 0);
00826 #else
00827   errno=0;
00828 #endif
00829   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", rv);
00830   /*GWEN_Text_DumpString(buf, rv, 2);*/
00831   return rv;
00832 }
00833 
00834 
00835 
00836 ssize_t GWEN_SyncIo_Tls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len) {
00837   GWEN_SYNCIO *sio;
00838   GWEN_SYNCIO_TLS *xio;
00839   GWEN_SYNCIO *baseIo;
00840   int rv;
00841 
00842   sio=(GWEN_SYNCIO*) p;
00843   assert(sio);
00844   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00845   assert(xio);
00846 
00847   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
00848   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00849   assert(baseIo);
00850 
00851   rv=GWEN_SyncIo_Write(baseIo, buf, len);
00852   if (rv<0) {
00853     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00854 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00855     gnutls_transport_set_errno(xio->session, errno);
00856 #endif
00857     return (ssize_t)-1;
00858   }
00859 
00860 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00861   gnutls_transport_set_errno(xio->session, 0);
00862 #endif
00863   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: returning %d bytes", rv);
00864   /*GWEN_Text_DumpString(buf, rv, 2);*/
00865   return rv;
00866 }
00867 
00868 
00869 
00870 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Connect(GWEN_SYNCIO *sio) {
00871   GWEN_SYNCIO_TLS *xio;
00872   GWEN_SYNCIO *baseIo;
00873   int rv;
00874 
00875   assert(sio);
00876   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00877   assert(xio);
00878 
00879   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00880   assert(baseIo);
00881 
00882   if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_FLAGS_PASSIVE) {
00883     if (GWEN_SyncIo_GetStatus(baseIo)!=GWEN_SyncIo_Status_Connected) {
00884       DBG_ERROR(GWEN_LOGDOMAIN, "Base layer is not connected");
00885       return GWEN_ERROR_NOT_CONNECTED;
00886     }
00887   }
00888   else {
00889     DBG_INFO(GWEN_LOGDOMAIN, "Connecting base layer");
00890     rv=GWEN_SyncIo_Connect(baseIo);
00891     if (rv<0) {
00892       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00893       return rv;
00894     }
00895     DBG_INFO(GWEN_LOGDOMAIN, "Base layer connected");
00896   }
00897 
00898   rv=GWEN_SyncIo_Tls_Prepare(sio);
00899   if (rv<0) {
00900     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00901     GWEN_SyncIo_Disconnect(baseIo);
00902     return rv;
00903   }
00904 
00905   do {
00906     rv=gnutls_handshake(xio->session);
00907   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
00908 
00909   if (rv) {
00910     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_handshake: %d (%s) [%s]",
00911               rv, gnutls_strerror(rv), gnutls_error_is_fatal(rv)?"fatal":"non-fatal");
00912     if (rv==GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
00913       GWEN_Gui_ProgressLog(0,
00914                            GWEN_LoggerLevel_Error,
00915                            I18N("A TLS handshake error occurred. "
00916                                 "If you are using AqBanking you should "
00917                                 "consider enabling the option "
00918                                 "\"force SSLv3\" in the user settings "
00919                                 "dialog."));
00920     }
00921     else {
00922       GWEN_Gui_ProgressLog2(0,
00923                             GWEN_LoggerLevel_Error,
00924                             I18N("TLS Handshake Error: %d (%s)"),
00925                             rv,
00926                             gnutls_strerror(rv));
00927     }
00928     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00929     GWEN_SyncIo_Tls_UndoPrepare(sio);
00930     GWEN_SyncIo_Disconnect(baseIo);
00931     return GWEN_ERROR_SSL;
00932   }
00933   else {
00934     /* check certificate */
00935     GWEN_SyncIo_SubFlags(sio, GWEN_SYNCIO_TLS_FLAGS_SECURE);
00936     rv=GWEN_SyncIo_Tls_GetPeerCert(sio);
00937     if (rv<0) {
00938       if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_TLS_FLAGS_NEED_PEER_CERT) {
00939         DBG_ERROR(GWEN_LOGDOMAIN, "No peer certificate when needed, aborting connection");
00940         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00941         GWEN_SyncIo_Tls_UndoPrepare(sio);
00942         GWEN_SyncIo_Disconnect(baseIo);
00943         return GWEN_ERROR_SSL_SECURITY;
00944       }
00945       else {
00946         DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (insecure)");
00947         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00948         return 0;
00949       }
00950     }
00951     else {
00952       /* present cert to the user */
00953       rv=GWEN_Gui_CheckCert(xio->peerCertDescr, sio, 0);
00954       if (rv<0) {
00955         DBG_ERROR(GWEN_LOGDOMAIN, "Peer cert not accepted (%d), aborting", rv);
00956         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00957         GWEN_SyncIo_Tls_UndoPrepare(sio);
00958         GWEN_SyncIo_Disconnect(baseIo);
00959         return GWEN_ERROR_SSL_SECURITY;
00960       }
00961       else {
00962         DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (secure)");
00963         GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_TLS_FLAGS_SECURE);
00964         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00965         return 0;
00966       }
00967     }
00968   }
00969 }
00970 
00971 
00972 
00973 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Disconnect(GWEN_SYNCIO *sio) {
00974   GWEN_SYNCIO_TLS *xio;
00975   GWEN_SYNCIO *baseIo;
00976   int rv;
00977 
00978   assert(sio);
00979   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00980   assert(xio);
00981 
00982   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00983   assert(baseIo);
00984 
00985   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
00986     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
00987     GWEN_SyncIo_Tls_UndoPrepare(sio);
00988     GWEN_SyncIo_Disconnect(baseIo);
00989     return GWEN_ERROR_NOT_CONNECTED;
00990   }
00991 
00992   do {
00993     rv=gnutls_bye(xio->session, GNUTLS_SHUT_RDWR);
00994   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
00995 
00996   if (rv) {
00997     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_bye: %d (%s)", rv, gnutls_strerror(rv));
00998     GWEN_Gui_ProgressLog2(0,
00999                           GWEN_LoggerLevel_Info,
01000                           I18N("Error on gnutls_bye: %d (%s)"),
01001                           rv,
01002                           gnutls_strerror(rv));
01003     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01004     GWEN_SyncIo_Tls_UndoPrepare(sio);
01005     GWEN_SyncIo_Disconnect(baseIo);
01006     return GWEN_ERROR_SSL;
01007   }
01008 
01009   GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01010   GWEN_SyncIo_Tls_UndoPrepare(sio);
01011   GWEN_SyncIo_Disconnect(baseIo);
01012   return 0;
01013 }
01014 
01015 
01016 
01017 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Read(GWEN_SYNCIO *sio,
01018                                        uint8_t *buffer,
01019                                        uint32_t size) {
01020   GWEN_SYNCIO_TLS *xio;
01021   GWEN_SYNCIO *baseIo;
01022   int rv;
01023 
01024   assert(sio);
01025   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
01026   assert(xio);
01027 
01028   baseIo=GWEN_SyncIo_GetBaseIo(sio);
01029   assert(baseIo);
01030 
01031   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
01032     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
01033     GWEN_SyncIo_Tls_UndoPrepare(sio);
01034     GWEN_SyncIo_Disconnect(baseIo);
01035     return GWEN_ERROR_NOT_CONNECTED;
01036   }
01037 
01038   do {
01039     rv=gnutls_record_recv(xio->session, buffer, size);
01040   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
01041 
01042   if (rv<0) {
01043     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_recv: %d (%s)", rv, gnutls_strerror(rv));
01044 #if 0
01045     GWEN_Gui_ProgressLog2(0,
01046                           GWEN_LoggerLevel_Error,
01047                           I18N("Error on gnutls_record_recv: %d (%s)"),
01048                           rv,
01049                           gnutls_strerror(rv));
01050 #endif
01051     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01052     GWEN_SyncIo_Tls_UndoPrepare(sio);
01053     GWEN_SyncIo_Disconnect(baseIo);
01054     return GWEN_ERROR_SSL;
01055   }
01056 
01057 #ifdef GWEN_TLS_DEBUG
01058   DBG_ERROR(0, "Received this:");
01059   GWEN_Text_DumpString((const char*) buffer, rv, 2);
01060 #endif
01061 
01062   return rv;
01063 }
01064 
01065 
01066 
01067 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Write(GWEN_SYNCIO *sio,
01068                                         const uint8_t *buffer,
01069                                         uint32_t size) {
01070   GWEN_SYNCIO_TLS *xio;
01071   GWEN_SYNCIO *baseIo;
01072   int rv;
01073 
01074   assert(sio);
01075   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
01076   assert(xio);
01077 
01078 #ifdef GWEN_TLS_DEBUG
01079   DBG_ERROR(0, "Sending this:");
01080   GWEN_Text_DumpString((const char*) buffer, size, 2);
01081 #endif
01082 
01083   baseIo=GWEN_SyncIo_GetBaseIo(sio);
01084   assert(baseIo);
01085 
01086   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
01087     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
01088     GWEN_SyncIo_Tls_UndoPrepare(sio);
01089     GWEN_SyncIo_Disconnect(baseIo);
01090     return GWEN_ERROR_NOT_CONNECTED;
01091   }
01092 
01093   do {
01094     rv=gnutls_record_send(xio->session, buffer, size);
01095   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
01096 
01097   if (rv<0) {
01098     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_send: %d (%s)", rv, gnutls_strerror(rv));
01099     GWEN_Gui_ProgressLog2(0,
01100                           GWEN_LoggerLevel_Error,
01101                           I18N("Error on gnutls_record_send: %d (%s)"),
01102                           rv,
01103                           gnutls_strerror(rv));
01104     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01105     GWEN_SyncIo_Tls_UndoPrepare(sio);
01106     GWEN_SyncIo_Disconnect(baseIo);
01107     return GWEN_ERROR_SSL;
01108   }
01109 
01110   return rv;
01111 }
01112 
01113 
01114 
01115 
01116 
01117 
01118