gwenhywfar 4.0.3

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