gwenhywfar  4.3.1
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 #if GNUTLS_VERSION_NUMBER < 0x030003
00473   gnutls_transport_set_lowat(xio->session, 0);
00474 #endif
00475 
00476   xio->prepared=1;
00477 
00478   return 0;
00479 }
00480 
00481 
00482 
00483 void GWEN_SyncIo_Tls_UndoPrepare(GWEN_SYNCIO *sio) {
00484   GWEN_SYNCIO_TLS *xio;
00485 
00486   assert(sio);
00487   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00488   assert(xio);
00489 
00490   if (xio->prepared) {
00491     gnutls_certificate_free_credentials(xio->credentials);
00492     gnutls_deinit(xio->session);
00493     xio->prepared=0;
00494   }
00495 }
00496 
00497 
00498 
00499 int GWEN_SyncIo_Tls_GetPeerCert(GWEN_SYNCIO *sio) {
00500   GWEN_SYNCIO_TLS *xio;
00501   const gnutls_datum_t *cert_list;
00502   unsigned int cert_list_size;
00503   size_t size;
00504   GWEN_SSLCERTDESCR *certDescr;
00505   char buffer1[64];
00506   time_t t0;
00507   int rv;
00508   uint32_t lflags;
00509   uint32_t errFlags=0;
00510   int i;
00511   unsigned int status;
00512   GWEN_BUFFER *sbuf=NULL;
00513 
00514   assert(sio);
00515   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00516   assert(xio);
00517 
00518   lflags=GWEN_SyncIo_GetFlags(sio);
00519 
00520   if (xio->peerCertDescr) {
00521     GWEN_SslCertDescr_free(xio->peerCertDescr);
00522     xio->peerCertDescr=NULL;
00523   }
00524   xio->peerCertFlags=0;
00525 
00526   t0=time(NULL);
00527   if (t0<0) {
00528     DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
00529     errFlags|=GWEN_SSL_CERT_FLAGS_SYSTEM;
00530   }
00531 
00532   /* create new cert description, check cert on the fly */
00533   certDescr=GWEN_SslCertDescr_new();
00534 
00535   /* some general tests */
00536   if (lflags & GWEN_SYNCIO_TLS_FLAGS_ALLOW_V1_CA_CRT)
00537     gnutls_certificate_set_verify_flags(xio->credentials,
00538                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
00539 
00540   rv=gnutls_certificate_verify_peers2(xio->session, &status);
00541   if (rv<0) {
00542     DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
00543     GWEN_SslCertDescr_free(certDescr);
00544     return GWEN_ERROR_SSL_SECURITY;
00545   }
00546 
00547   if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
00548     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
00549 
00550     GWEN_SslCertDescr_free(certDescr);
00551     return GWEN_ERROR_SSL_SECURITY;
00552   }
00553 
00554   if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00555     DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
00556     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00557                          I18N("Signer not found"));
00558     errFlags|=GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND;
00559   }
00560 
00561   if (status & GNUTLS_CERT_INVALID) {
00562     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
00563     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00564                          I18N("Certificate is not trusted"));
00565     errFlags|=GWEN_SSL_CERT_FLAGS_INVALID;
00566   }
00567 
00568   if (status & GNUTLS_CERT_REVOKED) {
00569     DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
00570     GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00571                          I18N("Certificate has been revoked"));
00572     errFlags|=GWEN_SSL_CERT_FLAGS_REVOKED;
00573   }
00574 
00575   cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
00576   if (cert_list==NULL || cert_list_size==0) {
00577     DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
00578     return GWEN_ERROR_NO_DATA;
00579   }
00580 
00581   for (i=0; i<cert_list_size; i++) {
00582     gnutls_x509_crt_t cert;
00583     time_t t;
00584 
00585     rv=gnutls_x509_crt_init(&cert);
00586     if (rv!=0) {
00587       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
00588       return GWEN_ERROR_GENERIC;
00589     }
00590 
00591     rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
00592     if (rv!=0) {
00593       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
00594       gnutls_x509_crt_deinit(cert);
00595       return GWEN_ERROR_GENERIC;
00596     }
00597 
00598     if (i==0) {
00599       /* get fingerprint */
00600       size=16;
00601       rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
00602       if (rv!=0) {
00603         DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint: %d (%s)", rv, gnutls_strerror(rv));
00604         GWEN_SslCertDescr_free(certDescr);
00605         gnutls_x509_crt_deinit(cert);
00606         return GWEN_ERROR_GENERIC;
00607       }
00608       else {
00609         GWEN_BUFFER *dbuf;
00610 
00611         dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00612         if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
00613                                   size, dbuf, 2, ':', 0)) {
00614           DBG_ERROR(GWEN_LOGDOMAIN,
00615                     "Could not convert fingerprint to hex");
00616         }
00617         else {
00618           GWEN_SslCertDescr_SetFingerPrint(certDescr, GWEN_Buffer_GetStart(dbuf));
00619         }
00620         GWEN_Buffer_free(dbuf);
00621       }
00622 
00623       if (xio->hostName) {
00624         DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
00625         if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
00626           DBG_WARN(GWEN_LOGDOMAIN,
00627                    "Certificate was not issued for this host");
00628           GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00629                                I18N("Certificate was not issued for this host"));
00630           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00631         }
00632         else {
00633           DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
00634         }
00635       }
00636       else {
00637         DBG_WARN(GWEN_LOGDOMAIN,
00638                  "Hostname is not set, unable to verify the sender");
00639         GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Warning,
00640                              I18N("No hostname to verify the sender!"));
00641       }
00642 
00643     }
00644 
00645     /* get activation time */
00646     t=gnutls_x509_crt_get_activation_time(cert);
00647     if (t<0) {
00648       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
00649       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00650     }
00651     else {
00652       if (t>t0) {
00653         DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
00654         errFlags|=GWEN_SSL_CERT_FLAGS_NOT_ACTIVE;
00655       }
00656       if (i==0) {
00657         GWEN_TIME *ti;
00658 
00659         ti=GWEN_Time_fromSeconds(t);
00660         if (ti)
00661           GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
00662         GWEN_Time_free(ti);
00663       }
00664     }
00665 
00666     /* get expiration time */
00667     t=gnutls_x509_crt_get_expiration_time(cert);
00668     if (t<0) {
00669       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
00670       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00671     }
00672     else {
00673       if (t<t0) {
00674         DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
00675         errFlags|=GWEN_SSL_CERT_FLAGS_EXPIRED;
00676       }
00677       if (i==0) {
00678         GWEN_TIME *ti;
00679 
00680         ti=GWEN_Time_fromSeconds(t);
00681         if (ti)
00682           GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
00683         GWEN_Time_free(ti);
00684       }
00685     }
00686 
00687     if (i==0) {
00688       /* get owner information, but only for first cert */
00689       size=sizeof(buffer1)-1;
00690       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
00691       if (rv==0) {
00692         GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
00693         if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
00694           DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
00695           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00696         }
00697       }
00698 
00699       size=sizeof(buffer1)-1;
00700       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
00701       if (rv==0)
00702         GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
00703 
00704       size=sizeof(buffer1)-1;
00705       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
00706       if (rv==0)
00707         GWEN_SslCertDescr_SetOrganizationalUnitName(certDescr, buffer1);
00708 
00709       size=sizeof(buffer1)-1;
00710       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
00711       if (rv==0)
00712         GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
00713 
00714       size=sizeof(buffer1)-1;
00715       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
00716       if (rv==0)
00717         GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
00718 
00719       size=sizeof(buffer1)-1;
00720       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
00721       if (rv==0)
00722         GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
00723     }
00724 
00725     gnutls_x509_crt_deinit(cert);
00726   }
00727 
00728   /* done */
00729   if (errFlags)
00730     GWEN_SslCertDescr_SetIsError(certDescr, 1);
00731   else
00732     errFlags|=GWEN_SSL_CERT_FLAGS_OK;
00733 
00734   sbuf=GWEN_Buffer_new(0, 256, 0, 1);
00735 
00736   if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
00737     if (GWEN_Buffer_GetUsedBytes(sbuf))
00738       GWEN_Buffer_AppendString(sbuf, "; ");
00739     GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
00740   }
00741 
00742   if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
00743     if (GWEN_Buffer_GetUsedBytes(sbuf))
00744       GWEN_Buffer_AppendString(sbuf, "; ");
00745     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
00746   }
00747 
00748   if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
00749     if (GWEN_Buffer_GetUsedBytes(sbuf))
00750       GWEN_Buffer_AppendString(sbuf, "; ");
00751     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
00752   }
00753 
00754   if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
00755     if (GWEN_Buffer_GetUsedBytes(sbuf))
00756       GWEN_Buffer_AppendString(sbuf, "; ");
00757     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
00758   }
00759 
00760   if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
00761     if (GWEN_Buffer_GetUsedBytes(sbuf))
00762       GWEN_Buffer_AppendString(sbuf, "; ");
00763     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
00764   }
00765 
00766   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
00767     if (GWEN_Buffer_GetUsedBytes(sbuf))
00768       GWEN_Buffer_AppendString(sbuf, "; ");
00769     GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
00770   }
00771 
00772   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
00773     if (GWEN_Buffer_GetUsedBytes(sbuf))
00774       GWEN_Buffer_AppendString(sbuf, "; ");
00775     GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
00776   }
00777 
00778   if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
00779     if (GWEN_Buffer_GetUsedBytes(sbuf))
00780       GWEN_Buffer_AppendString(sbuf, "; ");
00781     GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
00782   }
00783 
00784   if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
00785     if (GWEN_Buffer_GetUsedBytes(sbuf))
00786       GWEN_Buffer_AppendString(sbuf, "; ");
00787     GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
00788   }
00789 
00790   GWEN_SslCertDescr_SetStatusText(certDescr, GWEN_Buffer_GetStart(sbuf));
00791   GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
00792   GWEN_Buffer_free(sbuf);
00793 
00794   xio->peerCertDescr=certDescr;
00795   xio->peerCertFlags=errFlags;
00796 
00797   return 0;
00798 }
00799 
00800 
00801 
00802 ssize_t GWEN_SyncIo_Tls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len) {
00803   GWEN_SYNCIO *sio;
00804   GWEN_SYNCIO_TLS *xio;
00805   GWEN_SYNCIO *baseIo;
00806   int rv;
00807 
00808   sio=(GWEN_SYNCIO*) p;
00809   assert(sio);
00810   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00811   assert(xio);
00812 
00813   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
00814   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00815   assert(baseIo);
00816 
00817   rv=GWEN_SyncIo_Read(baseIo, buf, len);
00818   if (rv<0) {
00819     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00820 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00821     gnutls_transport_set_errno(xio->session, errno);
00822 #endif
00823     return (ssize_t)-1;
00824   }
00825 
00826 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00827   gnutls_transport_set_errno(xio->session, 0);
00828 #else
00829   errno=0;
00830 #endif
00831   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", rv);
00832   /*GWEN_Text_DumpString(buf, rv, 2);*/
00833   return rv;
00834 }
00835 
00836 
00837 
00838 ssize_t GWEN_SyncIo_Tls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len) {
00839   GWEN_SYNCIO *sio;
00840   GWEN_SYNCIO_TLS *xio;
00841   GWEN_SYNCIO *baseIo;
00842   int rv;
00843 
00844   sio=(GWEN_SYNCIO*) p;
00845   assert(sio);
00846   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00847   assert(xio);
00848 
00849   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
00850   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00851   assert(baseIo);
00852 
00853   rv=GWEN_SyncIo_Write(baseIo, buf, len);
00854   if (rv<0) {
00855     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00856 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00857     gnutls_transport_set_errno(xio->session, errno);
00858 #endif
00859     return (ssize_t)-1;
00860   }
00861 
00862 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00863   gnutls_transport_set_errno(xio->session, 0);
00864 #endif
00865   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: returning %d bytes", rv);
00866   /*GWEN_Text_DumpString(buf, rv, 2);*/
00867   return rv;
00868 }
00869 
00870 
00871 
00872 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Connect(GWEN_SYNCIO *sio) {
00873   GWEN_SYNCIO_TLS *xio;
00874   GWEN_SYNCIO *baseIo;
00875   int rv;
00876 
00877   assert(sio);
00878   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00879   assert(xio);
00880 
00881   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00882   assert(baseIo);
00883 
00884   if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_FLAGS_PASSIVE) {
00885     if (GWEN_SyncIo_GetStatus(baseIo)!=GWEN_SyncIo_Status_Connected) {
00886       DBG_ERROR(GWEN_LOGDOMAIN, "Base layer is not connected");
00887       return GWEN_ERROR_NOT_CONNECTED;
00888     }
00889   }
00890   else {
00891     DBG_INFO(GWEN_LOGDOMAIN, "Connecting base layer");
00892     rv=GWEN_SyncIo_Connect(baseIo);
00893     if (rv<0) {
00894       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00895       return rv;
00896     }
00897     DBG_INFO(GWEN_LOGDOMAIN, "Base layer connected");
00898   }
00899 
00900   rv=GWEN_SyncIo_Tls_Prepare(sio);
00901   if (rv<0) {
00902     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00903     GWEN_SyncIo_Disconnect(baseIo);
00904     return rv;
00905   }
00906 
00907   do {
00908     rv=gnutls_handshake(xio->session);
00909   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
00910 
00911   if (rv) {
00912     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_handshake: %d (%s) [%s]",
00913               rv, gnutls_strerror(rv), gnutls_error_is_fatal(rv)?"fatal":"non-fatal");
00914     if (rv==GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
00915       GWEN_Gui_ProgressLog(0,
00916                            GWEN_LoggerLevel_Error,
00917                            I18N("A TLS handshake error occurred. "
00918                                 "If you are using AqBanking you should "
00919                                 "consider enabling the option "
00920                                 "\"force SSLv3\" in the user settings "
00921                                 "dialog."));
00922     }
00923     else {
00924       GWEN_Gui_ProgressLog2(0,
00925                             GWEN_LoggerLevel_Error,
00926                             I18N("TLS Handshake Error: %d (%s)"),
00927                             rv,
00928                             gnutls_strerror(rv));
00929     }
00930     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00931     GWEN_SyncIo_Tls_UndoPrepare(sio);
00932     GWEN_SyncIo_Disconnect(baseIo);
00933     return GWEN_ERROR_SSL;
00934   }
00935   else {
00936     /* check certificate */
00937     GWEN_SyncIo_SubFlags(sio, GWEN_SYNCIO_TLS_FLAGS_SECURE);
00938     rv=GWEN_SyncIo_Tls_GetPeerCert(sio);
00939     if (rv<0) {
00940       if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_TLS_FLAGS_NEED_PEER_CERT) {
00941         DBG_ERROR(GWEN_LOGDOMAIN, "No peer certificate when needed, aborting connection");
00942         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00943         GWEN_SyncIo_Tls_UndoPrepare(sio);
00944         GWEN_SyncIo_Disconnect(baseIo);
00945         return GWEN_ERROR_SSL_SECURITY;
00946       }
00947       else {
00948         DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (insecure)");
00949         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00950         return 0;
00951       }
00952     }
00953     else {
00954       /* present cert to the user */
00955       rv=GWEN_Gui_CheckCert(xio->peerCertDescr, sio, 0);
00956       if (rv<0) {
00957         DBG_ERROR(GWEN_LOGDOMAIN, "Peer cert not accepted (%d), aborting", rv);
00958         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00959         GWEN_SyncIo_Tls_UndoPrepare(sio);
00960         GWEN_SyncIo_Disconnect(baseIo);
00961         return GWEN_ERROR_SSL_SECURITY;
00962       }
00963       else {
00964         DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (secure)");
00965         GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_TLS_FLAGS_SECURE);
00966         GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00967         return 0;
00968       }
00969     }
00970   }
00971 }
00972 
00973 
00974 
00975 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Disconnect(GWEN_SYNCIO *sio) {
00976   GWEN_SYNCIO_TLS *xio;
00977   GWEN_SYNCIO *baseIo;
00978   int rv;
00979 
00980   assert(sio);
00981   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
00982   assert(xio);
00983 
00984   baseIo=GWEN_SyncIo_GetBaseIo(sio);
00985   assert(baseIo);
00986 
00987   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
00988     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
00989     GWEN_SyncIo_Tls_UndoPrepare(sio);
00990     GWEN_SyncIo_Disconnect(baseIo);
00991     return GWEN_ERROR_NOT_CONNECTED;
00992   }
00993 
00994   do {
00995     rv=gnutls_bye(xio->session, GNUTLS_SHUT_RDWR);
00996   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
00997 
00998   if (rv) {
00999     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_bye: %d (%s)", rv, gnutls_strerror(rv));
01000     GWEN_Gui_ProgressLog2(0,
01001                           GWEN_LoggerLevel_Info,
01002                           I18N("Error on gnutls_bye: %d (%s)"),
01003                           rv,
01004                           gnutls_strerror(rv));
01005     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01006     GWEN_SyncIo_Tls_UndoPrepare(sio);
01007     GWEN_SyncIo_Disconnect(baseIo);
01008     return GWEN_ERROR_SSL;
01009   }
01010 
01011   GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01012   GWEN_SyncIo_Tls_UndoPrepare(sio);
01013   GWEN_SyncIo_Disconnect(baseIo);
01014   return 0;
01015 }
01016 
01017 
01018 
01019 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Read(GWEN_SYNCIO *sio,
01020                                        uint8_t *buffer,
01021                                        uint32_t size) {
01022   GWEN_SYNCIO_TLS *xio;
01023   GWEN_SYNCIO *baseIo;
01024   int rv;
01025 
01026   assert(sio);
01027   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
01028   assert(xio);
01029 
01030   baseIo=GWEN_SyncIo_GetBaseIo(sio);
01031   assert(baseIo);
01032 
01033   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
01034     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
01035     GWEN_SyncIo_Tls_UndoPrepare(sio);
01036     GWEN_SyncIo_Disconnect(baseIo);
01037     return GWEN_ERROR_NOT_CONNECTED;
01038   }
01039 
01040   do {
01041     rv=gnutls_record_recv(xio->session, buffer, size);
01042   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
01043 
01044   if (rv<0) {
01045     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_recv: %d (%s)", rv, gnutls_strerror(rv));
01046 #if 0
01047     GWEN_Gui_ProgressLog2(0,
01048                           GWEN_LoggerLevel_Error,
01049                           I18N("Error on gnutls_record_recv: %d (%s)"),
01050                           rv,
01051                           gnutls_strerror(rv));
01052 #endif
01053     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01054     GWEN_SyncIo_Tls_UndoPrepare(sio);
01055     GWEN_SyncIo_Disconnect(baseIo);
01056     return GWEN_ERROR_SSL;
01057   }
01058 
01059 #ifdef GWEN_TLS_DEBUG
01060   DBG_ERROR(0, "Received this:");
01061   GWEN_Text_DumpString((const char*) buffer, rv, 2);
01062 #endif
01063 
01064   return rv;
01065 }
01066 
01067 
01068 
01069 int GWENHYWFAR_CB GWEN_SyncIo_Tls_Write(GWEN_SYNCIO *sio,
01070                                         const uint8_t *buffer,
01071                                         uint32_t size) {
01072   GWEN_SYNCIO_TLS *xio;
01073   GWEN_SYNCIO *baseIo;
01074   int rv;
01075 
01076   assert(sio);
01077   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_TLS, sio);
01078   assert(xio);
01079 
01080 #ifdef GWEN_TLS_DEBUG
01081   DBG_ERROR(0, "Sending this:");
01082   GWEN_Text_DumpString((const char*) buffer, size, 2);
01083 #endif
01084 
01085   baseIo=GWEN_SyncIo_GetBaseIo(sio);
01086   assert(baseIo);
01087 
01088   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
01089     DBG_INFO(GWEN_LOGDOMAIN, "Not connected");
01090     GWEN_SyncIo_Tls_UndoPrepare(sio);
01091     GWEN_SyncIo_Disconnect(baseIo);
01092     return GWEN_ERROR_NOT_CONNECTED;
01093   }
01094 
01095   do {
01096     rv=gnutls_record_send(xio->session, buffer, size);
01097   } while (rv==GNUTLS_E_AGAIN && rv==GNUTLS_E_INTERRUPTED);
01098 
01099   if (rv<0) {
01100     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_record_send: %d (%s)", rv, gnutls_strerror(rv));
01101     GWEN_Gui_ProgressLog2(0,
01102                           GWEN_LoggerLevel_Error,
01103                           I18N("Error on gnutls_record_send: %d (%s)"),
01104                           rv,
01105                           gnutls_strerror(rv));
01106     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
01107     GWEN_SyncIo_Tls_UndoPrepare(sio);
01108     GWEN_SyncIo_Disconnect(baseIo);
01109     return GWEN_ERROR_SSL;
01110   }
01111 
01112   return rv;
01113 }
01114 
01115 
01116 
01117 
01118 
01119 
01120