io_tls.c

Go to the documentation of this file.
00001 /***************************************************************************
00002     copyright   : (C) 2007 by Martin Preuss
00003     email       : martin@libchipcard.de
00004 
00005  ***************************************************************************
00006  *          Please see toplevel file COPYING for license details           *
00007  ***************************************************************************/
00008 
00009 
00010 #ifdef HAVE_CONFIG_H
00011 # include <config.h>
00012 #endif
00013 
00014 
00015 #include "io_tls_p.h"
00016 #include <gwenhywfar/iolayer_be.h>
00017 #include <gwenhywfar/io_codec_be.h>
00018 #include <gwenhywfar/iorequest_be.h>
00019 #include <gwenhywfar/io_socket.h>
00020 
00021 #include "i18n_l.h"
00022 #include <gwenhywfar/gwenhywfar.h>
00023 #include <gwenhywfar/misc.h>
00024 #include <gwenhywfar/debug.h>
00025 #include <gwenhywfar/gui.h>
00026 #include <gwenhywfar/pathmanager.h>
00027 #include <gwenhywfar/directory.h>
00028 
00029 #include <assert.h>
00030 #include <errno.h>
00031 
00032 #include <gnutls/gnutls.h>
00033 #include <gnutls/x509.h>
00034 
00035 
00036 #include <gwenhywfar/text.h> /* debug */
00037 
00038 
00039 /*#define DEBUG_TLS */
00040 
00041 
00042 
00043 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS)
00044 
00045 
00046 #ifndef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00047 /* #warning "gnutls_transport_set_errno is not defined" */
00048 #endif
00049 
00050 
00051 
00052 
00053 GWEN_IO_LAYER *GWEN_Io_LayerTls_new(GWEN_IO_LAYER *baseLayer) {
00054   GWEN_IO_LAYER *io;
00055   GWEN_IO_LAYER_TLS *xio;
00056 
00057   io=GWEN_Io_LayerCodec_new(GWEN_IO_LAYER_TLS_TYPE, baseLayer);
00058   assert(io);
00059   GWEN_NEW_OBJECT(GWEN_IO_LAYER_TLS, xio);
00060   assert(xio);
00061   GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io, xio, GWEN_Io_LayerTls_freeData);
00062 
00063   xio->workOnRequestsFn=GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerTls_WorkOnRequests);
00064   xio->addRequestFn=GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerTls_AddRequest);
00065   xio->delRequestFn=GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerTls_DelRequest);
00066   xio->hasWaitingRequestsFn=GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerTls_HasWaitingRequests);
00067 
00068   GWEN_Io_LayerCodec_SetEncodeFn(io, GWEN_Io_LayerTls_Encode);
00069   GWEN_Io_LayerCodec_SetDecodeFn(io, GWEN_Io_LayerTls_Decode);
00070 
00071   return io;
00072 }
00073 
00074 
00075 
00076 GWENHYWFAR_CB
00077 void GWEN_Io_LayerTls_freeData(void *bp, void *p) {
00078   GWEN_IO_LAYER *io;
00079   GWEN_IO_LAYER_TLS *xio;
00080 
00081   io=(GWEN_IO_LAYER*) bp;
00082   assert(io);
00083   xio=(GWEN_IO_LAYER_TLS*) p;
00084   assert(xio);
00085 
00086   free(xio->dhParamFile);
00087   free(xio->localCertFile);
00088   free(xio->localKeyFile);
00089   free(xio->localTrustFile);
00090   free(xio->hostName);
00091   if (xio->prepared) {
00092     gnutls_deinit(xio->session);
00093     gnutls_certificate_free_credentials(xio->credentials);
00094     xio->prepared=0;
00095   }
00096 
00097   GWEN_SslCertDescr_free(xio->peerCertDescr);
00098 
00099 }
00100 
00101 
00102 
00103 const char *GWEN_Io_LayerTls_GetLocalCertFile(const GWEN_IO_LAYER *io) {
00104   GWEN_IO_LAYER_TLS *xio;
00105 
00106   assert(io);
00107   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00108   assert(xio);
00109 
00110   return xio->localCertFile;
00111 }
00112 
00113 
00114 
00115 void GWEN_Io_LayerTls_SetLocalCertFile(GWEN_IO_LAYER *io, const char *s) {
00116   GWEN_IO_LAYER_TLS *xio;
00117 
00118   assert(io);
00119   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00120   assert(xio);
00121 
00122   free(xio->localCertFile);
00123   if (s) xio->localCertFile=strdup(s);
00124   else xio->localCertFile=NULL;
00125 }
00126 
00127 
00128 
00129 const char *GWEN_Io_LayerTls_GetLocalKeyFile(const GWEN_IO_LAYER *io) {
00130   GWEN_IO_LAYER_TLS *xio;
00131 
00132   assert(io);
00133   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00134   assert(xio);
00135 
00136   return xio->localKeyFile;
00137 }
00138 
00139 
00140 
00141 void GWEN_Io_LayerTls_SetLocalKeyFile(GWEN_IO_LAYER *io, const char *s) {
00142   GWEN_IO_LAYER_TLS *xio;
00143 
00144   assert(io);
00145   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00146   assert(xio);
00147 
00148   free(xio->localKeyFile);
00149   if (s) xio->localKeyFile=strdup(s);
00150   else xio->localKeyFile=NULL;
00151 }
00152 
00153 
00154 
00155 const char *GWEN_Io_LayerTls_GetLocalTrustFile(const GWEN_IO_LAYER *io) {
00156   GWEN_IO_LAYER_TLS *xio;
00157 
00158   assert(io);
00159   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00160   assert(xio);
00161 
00162   return xio->localTrustFile;
00163 }
00164 
00165 
00166 
00167 void GWEN_Io_LayerTls_SetLocalTrustFile(GWEN_IO_LAYER *io, const char *s) {
00168   GWEN_IO_LAYER_TLS *xio;
00169 
00170   assert(io);
00171   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00172   assert(xio);
00173 
00174   free(xio->localTrustFile);
00175   if (s) xio->localTrustFile=strdup(s);
00176   else xio->localTrustFile=NULL;
00177 }
00178 
00179 
00180 
00181 const char *GWEN_Io_LayerTls_GetDhParamFile(const GWEN_IO_LAYER *io) {
00182   GWEN_IO_LAYER_TLS *xio;
00183 
00184   assert(io);
00185   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00186   assert(xio);
00187 
00188   return xio->dhParamFile;
00189 }
00190 
00191 
00192 
00193 void GWEN_Io_LayerTls_SetDhParamFile(GWEN_IO_LAYER *io, const char *s) {
00194   GWEN_IO_LAYER_TLS *xio;
00195 
00196   assert(io);
00197   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00198   assert(xio);
00199 
00200   free(xio->dhParamFile);
00201   if (s) xio->dhParamFile=strdup(s);
00202   else xio->dhParamFile=NULL;
00203 }
00204 
00205 
00206 
00207 const char *GWEN_Io_LayerTls_GetRemoteHostName(const GWEN_IO_LAYER *io) {
00208   GWEN_IO_LAYER_TLS *xio;
00209 
00210   assert(io);
00211   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00212   assert(xio);
00213 
00214   return xio->hostName;
00215 }
00216 
00217 
00218 
00219 void GWEN_Io_LayerTls_SetRemoteHostName(GWEN_IO_LAYER *io, const char *s) {
00220   GWEN_IO_LAYER_TLS *xio;
00221 
00222   assert(io);
00223   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00224   assert(xio);
00225 
00226   free(xio->hostName);
00227   if (s) xio->hostName=strdup(s);
00228   else xio->hostName=NULL;
00229 }
00230 
00231 
00232 
00233 GWEN_SSLCERTDESCR *GWEN_Io_LayerTls_GetPeerCertDescr(const GWEN_IO_LAYER *io) {
00234   GWEN_IO_LAYER_TLS *xio;
00235 
00236   assert(io);
00237   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00238   assert(xio);
00239 
00240   return xio->peerCertDescr;
00241 }
00242 
00243 
00244 
00245 int GWEN_Io_LayerTls__readFile(const char *fname, GWEN_BUFFER *buf) {
00246   FILE *f;
00247 
00248   f=fopen(fname, "r");
00249   if (f==NULL)
00250     return GWEN_ERROR_IO;
00251 
00252   while(!feof(f)) {
00253     int rv;
00254 
00255     GWEN_Buffer_AllocRoom(buf, 512);
00256     rv=fread(GWEN_Buffer_GetPosPointer(buf), 1, 512, f);
00257     if (rv==0)
00258       break;
00259     else if (rv<0) {
00260       DBG_INFO(GWEN_LOGDOMAIN, "fread(%s): %s", fname, strerror(errno));
00261       fclose(f);
00262       return GWEN_ERROR_IO;
00263     }
00264     else {
00265       GWEN_Buffer_IncrementPos(buf, rv);
00266       GWEN_Buffer_AdjustUsedBytes(buf);
00267     }
00268   }
00269   fclose(f);
00270   return 0;
00271 }
00272 
00273 
00274 
00275 int GWEN_Io_LayerTls_Prepare(GWEN_IO_LAYER *io) {
00276   GWEN_IO_LAYER_TLS *xio;
00277   int rv;
00278   uint32_t lflags;
00279 
00280   assert(io);
00281   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00282   assert(xio);
00283 
00284   lflags=GWEN_Io_Layer_GetFlags(io);
00285   DBG_INFO(GWEN_LOGDOMAIN, "Preparing SSL (%08x)", lflags);
00286 
00287   /* init session */
00288   if (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE) {
00289     DBG_INFO(GWEN_LOGDOMAIN, "Init as server");
00290     rv=gnutls_init(&xio->session, GNUTLS_SERVER);
00291   }
00292   else {
00293     DBG_INFO(GWEN_LOGDOMAIN, "Init as client");
00294     rv=gnutls_init(&xio->session, GNUTLS_CLIENT);
00295   }
00296   if (rv) {
00297     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_init: %d (%s)", rv, gnutls_strerror(rv));
00298     return GWEN_ERROR_GENERIC;
00299   }
00300 
00301   /* set default priority */
00302   rv=gnutls_set_default_priority(xio->session);
00303   if (rv) {
00304     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_set_default_priority: %d (%s)", rv, gnutls_strerror(rv));
00305     gnutls_deinit(xio->session);
00306     return GWEN_ERROR_GENERIC;
00307   }
00308 
00309   /* possibly force protocol priority */
00310   if (lflags & GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3) {
00311     const int proto_prio[2] = { GNUTLS_SSL3, 0 };
00312 
00313     rv=gnutls_protocol_set_priority(xio->session, proto_prio);
00314     if (rv) {
00315       DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_protocol_set_priority: %d (%s)", rv, gnutls_strerror(rv));
00316       gnutls_deinit(xio->session);
00317       return GWEN_ERROR_GENERIC;
00318     }
00319   }
00320 
00321   /* let a server request peer certs */
00322   if ((lflags & GWEN_IO_LAYER_FLAGS_PASSIVE) &&
00323       (lflags & GWEN_IO_LAYER_TLS_FLAGS_REQUEST_CERT))
00324     gnutls_certificate_server_set_request(xio->session, GNUTLS_CERT_REQUIRE);
00325 
00326   /* prepare cert credentials */
00327   rv=gnutls_certificate_allocate_credentials(&xio->credentials);
00328   if (rv) {
00329     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_allocate_credentials: %d (%s)", rv, gnutls_strerror(rv));
00330     gnutls_deinit(xio->session);
00331     return GWEN_ERROR_GENERIC;
00332   }
00333 
00334   /* possibly set key file and cert file */
00335   if (xio->localCertFile && xio->localKeyFile) {
00336     rv=gnutls_certificate_set_x509_key_file(xio->credentials,
00337                                             xio->localCertFile,
00338                                             xio->localKeyFile,
00339                                             GNUTLS_X509_FMT_PEM);
00340     if (rv<0) {
00341       if (rv) {
00342         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: %d (%s)", rv, gnutls_strerror(rv));
00343         gnutls_certificate_free_credentials(xio->credentials);
00344         gnutls_deinit(xio->session);
00345         return GWEN_ERROR_GENERIC;
00346       }
00347     }
00348   }
00349 
00350   /* find default trust file if none is selected */
00351   if (lflags & GWEN_IO_LAYER_TLS_FLAGS_ADD_TRUSTED_CAS) {
00352     GWEN_STRINGLIST *paths;
00353 
00354     /* try to find out trust file */
00355     paths=GWEN_PathManager_GetPaths(GWEN_PM_LIBNAME, GWEN_PM_DATADIR);
00356     if (paths) {
00357       GWEN_BUFFER *nbuf;
00358 
00359       nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00360       rv=GWEN_Directory_FindFileInPaths(paths,
00361                                         "ca-bundle.crt",
00362                                         nbuf);
00363       GWEN_StringList_free(paths);
00364       if (rv==0) {
00365         DBG_INFO(GWEN_LOGDOMAIN,
00366                  "Using default ca-bundle from [%s]",
00367                  GWEN_Buffer_GetStart(nbuf));
00368         GWEN_Io_LayerTls_SetLocalTrustFile(io, GWEN_Buffer_GetStart(nbuf));
00369       }
00370       else {
00371         DBG_WARN(GWEN_LOGDOMAIN, "Default bundle file not found");
00372       }
00373       GWEN_Buffer_free(nbuf);
00374     }
00375   }
00376 
00377   /* possibly set trust file */
00378   if (xio->localTrustFile) {
00379     rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
00380                                               xio->localTrustFile,
00381                                               GNUTLS_X509_FMT_PEM);
00382     if (rv<=0) {
00383       DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_trust_file: %d (%s)", rv, gnutls_strerror(rv));
00384       gnutls_certificate_free_credentials(xio->credentials);
00385       gnutls_deinit(xio->session);
00386       return GWEN_ERROR_GENERIC;
00387     }
00388     else {
00389       DBG_INFO(GWEN_LOGDOMAIN,
00390                "Added %d trusted certs", rv);
00391     }
00392   }
00393 
00394   /* possibly set DH params */
00395   if (xio->dhParamFile) {
00396     GWEN_BUFFER *dbuf;
00397 
00398     dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00399     rv=GWEN_Io_LayerTls__readFile(xio->dhParamFile, dbuf);
00400     if (rv) {
00401       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00402       GWEN_Buffer_free(dbuf);
00403       gnutls_certificate_free_credentials(xio->credentials);
00404       gnutls_deinit(xio->session);
00405       return rv;
00406     }
00407     else {
00408       gnutls_datum d;
00409       gnutls_dh_params dh_params=NULL;
00410 
00411       rv=gnutls_dh_params_init(&dh_params);
00412       if (rv<0) {
00413         GWEN_Buffer_free(dbuf);
00414         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_init: %d (%s)", rv, gnutls_strerror(rv));
00415         gnutls_certificate_free_credentials(xio->credentials);
00416         gnutls_deinit(xio->session);
00417         return GWEN_ERROR_GENERIC;
00418       }
00419 
00420       d.size=GWEN_Buffer_GetUsedBytes(dbuf);
00421       d.data=(unsigned char*)GWEN_Buffer_GetStart(dbuf);
00422 
00423       rv=gnutls_dh_params_import_pkcs3(dh_params, &d, GNUTLS_X509_FMT_PEM);
00424       if (rv<0) {
00425         GWEN_Buffer_free(dbuf);
00426         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_import_pkcs3: %d (%s)", rv, gnutls_strerror(rv));
00427         gnutls_certificate_free_credentials(xio->credentials);
00428         gnutls_deinit(xio->session);
00429         return GWEN_ERROR_GENERIC;
00430       }
00431       GWEN_Buffer_free(dbuf);
00432 
00433       gnutls_certificate_set_dh_params(xio->credentials, dh_params);
00434     }
00435   }
00436 
00437   /* set credentials in TLS session */
00438   rv=gnutls_credentials_set(xio->session, GNUTLS_CRD_CERTIFICATE, xio->credentials);
00439   if (rv<0) {
00440     DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_credentials_set: %d (%s)", rv, gnutls_strerror(rv));
00441     gnutls_certificate_free_credentials(xio->credentials);
00442     gnutls_deinit(xio->session);
00443     return GWEN_ERROR_GENERIC;
00444   }
00445 
00446   /* we use our own push/pull functions */
00447   gnutls_transport_set_ptr(xio->session, (gnutls_transport_ptr_t)io);
00448   gnutls_transport_set_push_function(xio->session, GWEN_Io_LayerTls_Push);
00449   gnutls_transport_set_pull_function(xio->session, GWEN_Io_LayerTls_Pull);
00450   gnutls_transport_set_lowat(xio->session, 0);
00451 
00452   xio->prepared=1;
00453 
00454   return 0;
00455 }
00456 
00457 
00458 
00459 int GWEN_Io_LayerTls_GetPeerCert(GWEN_IO_LAYER *io, uint32_t guiid) {
00460   GWEN_IO_LAYER_TLS *xio;
00461   const gnutls_datum_t *cert_list;
00462   unsigned int cert_list_size;
00463   size_t size;
00464   GWEN_SSLCERTDESCR *certDescr;
00465   char buffer1[64];
00466   time_t t0;
00467   int rv;
00468   uint32_t lflags;
00469   uint32_t errFlags=0;
00470   int i;
00471   unsigned int status;
00472   GWEN_BUFFER *sbuf=NULL;
00473 
00474   assert(io);
00475   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00476   assert(xio);
00477 
00478   lflags=GWEN_Io_Layer_GetFlags(io);
00479 
00480   if (xio->peerCertDescr) {
00481     GWEN_SslCertDescr_free(xio->peerCertDescr);
00482     xio->peerCertDescr=NULL;
00483   }
00484   xio->peerCertFlags=0;
00485 
00486   t0=time(NULL);
00487   if (t0<0) {
00488     DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
00489     errFlags|=GWEN_SSL_CERT_FLAGS_SYSTEM;
00490   }
00491 
00492   /* create new cert description, check cert on the fly */
00493   certDescr=GWEN_SslCertDescr_new();
00494 
00495   /* some general tests */
00496   if (lflags & GWEN_IO_LAYER_TLS_FLAGS_ALLOW_V1_CA_CRT)
00497     gnutls_certificate_set_verify_flags(xio->credentials,
00498                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
00499 
00500   rv=gnutls_certificate_verify_peers2(xio->session, &status);
00501   if (rv<0) {
00502     DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
00503     GWEN_SslCertDescr_free(certDescr);
00504     return GWEN_ERROR_SSL_SECURITY;
00505   }
00506 
00507   if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
00508     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
00509 
00510     GWEN_SslCertDescr_free(certDescr);
00511     return GWEN_ERROR_SSL_SECURITY;
00512   }
00513 
00514   if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00515     DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
00516     GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00517                          I18N("Signer not found"));
00518     errFlags|=GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND;
00519   }
00520 
00521   if (status & GNUTLS_CERT_INVALID) {
00522     DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
00523     GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00524                          I18N("Certificate is not trusted"));
00525     errFlags|=GWEN_SSL_CERT_FLAGS_INVALID;
00526   }
00527 
00528   if (status & GNUTLS_CERT_REVOKED) {
00529     DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
00530     GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00531                          I18N("Certificate has been revoked"));
00532     errFlags|=GWEN_SSL_CERT_FLAGS_REVOKED;
00533   }
00534 
00535   cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
00536   if (cert_list==NULL || cert_list_size==0) {
00537     DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
00538     return GWEN_ERROR_NO_DATA;
00539   }
00540 
00541   for (i=0; i<cert_list_size; i++) {
00542     gnutls_x509_crt_t cert;
00543     time_t t;
00544 
00545     rv=gnutls_x509_crt_init(&cert);
00546     if (rv!=0) {
00547       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
00548       return GWEN_ERROR_GENERIC;
00549     }
00550 
00551     rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
00552     if (rv!=0) {
00553       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
00554       gnutls_x509_crt_deinit(cert);
00555       return GWEN_ERROR_GENERIC;
00556     }
00557 
00558     if (i==0) {
00559       /* get fingerprint */
00560       size=16;
00561       rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
00562       if (rv!=0) {
00563         DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint: %d (%s)", rv, gnutls_strerror(rv));
00564         GWEN_SslCertDescr_free(certDescr);
00565         gnutls_x509_crt_deinit(cert);
00566         return GWEN_ERROR_GENERIC;
00567       }
00568       else {
00569         GWEN_BUFFER *dbuf;
00570 
00571         dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00572         if (GWEN_Text_ToHexBuffer(/* GCC4 pointer-signedness fix: */ buffer1,
00573                                   size, dbuf, 2, ':', 0)) {
00574           DBG_ERROR(GWEN_LOGDOMAIN,
00575                     "Could not convert fingerprint to hex");
00576         }
00577         else {
00578           GWEN_SslCertDescr_SetFingerPrint(certDescr, GWEN_Buffer_GetStart(dbuf));
00579         }
00580         GWEN_Buffer_free(dbuf);
00581       }
00582 
00583       if (xio->hostName) {
00584         DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
00585         if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
00586           DBG_WARN(GWEN_LOGDOMAIN,
00587                    "Certificate was not issued for this host");
00588           GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00589                                I18N("Certificate was not issued for this host"));
00590           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00591         }
00592         else {
00593           DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
00594         }
00595       }
00596       else {
00597         DBG_WARN(GWEN_LOGDOMAIN,
00598                  "Hostname is not set, unable to verify the sender");
00599         GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00600                              I18N("No hostname to verify the sender!"));
00601       }
00602 
00603     }
00604 
00605     /* get activation time */
00606     t=gnutls_x509_crt_get_activation_time(cert);
00607     if (t<0) {
00608       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
00609       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00610     }
00611     else {
00612       if (t>t0) {
00613         DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
00614         errFlags|=GWEN_SSL_CERT_FLAGS_NOT_ACTIVE;
00615       }
00616       if (i==0) {
00617         GWEN_TIME *ti;
00618 
00619         ti=GWEN_Time_fromSeconds(t);
00620         if (ti)
00621           GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
00622         GWEN_Time_free(ti);
00623       }
00624     }
00625 
00626     /* get expiration time */
00627     t=gnutls_x509_crt_get_expiration_time(cert);
00628     if (t<0) {
00629       DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
00630       errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00631     }
00632     else {
00633       if (t<t0) {
00634         DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
00635         errFlags|=GWEN_SSL_CERT_FLAGS_EXPIRED;
00636       }
00637       if (i==0) {
00638         GWEN_TIME *ti;
00639 
00640         ti=GWEN_Time_fromSeconds(t);
00641         if (ti)
00642           GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
00643         GWEN_Time_free(ti);
00644       }
00645     }
00646 
00647     if (i==0) {
00648       /* get owner information, but only for first cert */
00649       size=sizeof(buffer1)-1;
00650       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
00651       if (rv==0) {
00652         GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
00653         if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
00654           DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
00655           errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00656         }
00657       }
00658 
00659       size=sizeof(buffer1)-1;
00660       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
00661       if (rv==0)
00662         GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
00663 
00664       size=sizeof(buffer1)-1;
00665       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
00666       if (rv==0)
00667         GWEN_SslCertDescr_SetOrganizationalUnitName(certDescr, buffer1);
00668 
00669       size=sizeof(buffer1)-1;
00670       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
00671       if (rv==0)
00672         GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
00673 
00674       size=sizeof(buffer1)-1;
00675       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
00676       if (rv==0)
00677         GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
00678 
00679       size=sizeof(buffer1)-1;
00680       rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
00681       if (rv==0)
00682         GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
00683     }
00684 
00685     gnutls_x509_crt_deinit(cert);
00686   }
00687 
00688   /* done */
00689   if (errFlags)
00690     GWEN_SslCertDescr_SetIsError(certDescr, 1);
00691   else
00692     errFlags|=GWEN_SSL_CERT_FLAGS_OK;
00693 
00694   sbuf=GWEN_Buffer_new(0, 256, 0, 1);
00695 
00696   if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
00697     if (GWEN_Buffer_GetUsedBytes(sbuf))
00698       GWEN_Buffer_AppendString(sbuf, "; ");
00699     GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
00700   }
00701 
00702   if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
00703     if (GWEN_Buffer_GetUsedBytes(sbuf))
00704       GWEN_Buffer_AppendString(sbuf, "; ");
00705     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
00706   }
00707 
00708   if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
00709     if (GWEN_Buffer_GetUsedBytes(sbuf))
00710       GWEN_Buffer_AppendString(sbuf, "; ");
00711     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
00712   }
00713 
00714   if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
00715     if (GWEN_Buffer_GetUsedBytes(sbuf))
00716       GWEN_Buffer_AppendString(sbuf, "; ");
00717     GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
00718   }
00719 
00720   if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
00721     if (GWEN_Buffer_GetUsedBytes(sbuf))
00722       GWEN_Buffer_AppendString(sbuf, "; ");
00723     GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
00724   }
00725 
00726   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
00727     if (GWEN_Buffer_GetUsedBytes(sbuf))
00728       GWEN_Buffer_AppendString(sbuf, "; ");
00729     GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
00730   }
00731 
00732   if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
00733     if (GWEN_Buffer_GetUsedBytes(sbuf))
00734       GWEN_Buffer_AppendString(sbuf, "; ");
00735     GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
00736   }
00737 
00738   if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
00739     if (GWEN_Buffer_GetUsedBytes(sbuf))
00740       GWEN_Buffer_AppendString(sbuf, "; ");
00741     GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
00742   }
00743 
00744   if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
00745     if (GWEN_Buffer_GetUsedBytes(sbuf))
00746       GWEN_Buffer_AppendString(sbuf, "; ");
00747     GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
00748   }
00749 
00750   GWEN_SslCertDescr_SetStatusText(certDescr, GWEN_Buffer_GetStart(sbuf));
00751   GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
00752   GWEN_Buffer_free(sbuf);
00753 
00754   xio->peerCertDescr=certDescr;
00755   xio->peerCertFlags=errFlags;
00756 
00757   return 0;
00758 }
00759 
00760 
00761 
00762 ssize_t GWEN_Io_LayerTls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len) {
00763   GWEN_IO_LAYER *io;
00764   GWEN_IO_LAYER_TLS *xio;
00765   int rv;
00766 
00767   io=(GWEN_IO_LAYER*) p;
00768   assert(io);
00769   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00770   assert(xio);
00771 
00772   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
00773   rv=GWEN_Io_LayerCodec_EnsureReadOk(io);
00774   if (rv) {
00775     if (rv==GWEN_ERROR_TRY_AGAIN || rv==GWEN_ERROR_IN_PROGRESS) {
00776 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00777       gnutls_transport_set_errno(xio->session, EAGAIN);
00778 #else
00779       errno=EAGAIN;
00780 #endif
00781       return (ssize_t)-1;
00782     }
00783     else {
00784 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00785       gnutls_transport_set_errno(xio->session, EINVAL);
00786 #else
00787       errno=EINVAL;
00788 #endif
00789       return (ssize_t)-1;
00790     }
00791   }
00792   else {
00793     GWEN_RINGBUFFER *rbuf;
00794     uint32_t maxBytes;
00795     const uint8_t *src;
00796 
00797     rbuf=GWEN_Io_LayerCodec_GetReadBuffer(io);
00798     assert(buf);
00799     maxBytes=GWEN_RingBuffer_GetMaxUnsegmentedRead(rbuf);
00800     if (maxBytes>len)
00801       maxBytes=len;
00802     src=(const uint8_t*)GWEN_RingBuffer_GetReadPointer(rbuf);
00803     if (maxBytes) {
00804       memmove(buf, src, maxBytes);
00805       GWEN_RingBuffer_SkipBytesRead(rbuf, maxBytes);
00806     }
00807 
00808 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00809     gnutls_transport_set_errno(xio->session, 0);
00810 #else
00811     errno=0;
00812 #endif
00813     DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", maxBytes);
00814     /*GWEN_Text_DumpString(buf, maxBytes, stderr, 2);*/
00815     return maxBytes;
00816   }
00817 }
00818 
00819 
00820 
00821 ssize_t GWEN_Io_LayerTls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len) {
00822   GWEN_IO_LAYER *io;
00823   GWEN_IO_LAYER_TLS *xio;
00824   int rv;
00825 
00826   io=(GWEN_IO_LAYER*) p;
00827   assert(io);
00828   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00829   assert(xio);
00830 
00831   DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
00832   /*GWEN_Text_DumpString(buf, len, stderr, 2);*/
00833 
00834   rv=GWEN_Io_LayerCodec_CheckWriteOut(io);
00835   if (rv) {
00836     if (rv==GWEN_ERROR_TRY_AGAIN) {
00837       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00838 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00839       gnutls_transport_set_errno(xio->session, EAGAIN);
00840 #else
00841       errno=EAGAIN;
00842 #endif
00843       return (ssize_t)-1;
00844     }
00845     else {
00846       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00847 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00848       gnutls_transport_set_errno(xio->session, EINVAL);
00849 #else
00850       errno=EINVAL;
00851 #endif
00852       return (ssize_t)-1;
00853     }
00854   }
00855   else {
00856     GWEN_RINGBUFFER *rbuf;
00857     uint32_t maxBytes;
00858     uint8_t *dst;
00859     uint32_t guiid=0;
00860 
00861     if (xio->connectRequest)
00862       guiid=GWEN_Io_Request_GetGuiId(xio->connectRequest);
00863     else if (xio->connectRequest)
00864       guiid=GWEN_Io_Request_GetGuiId(xio->disconnectRequest);
00865 
00866     rbuf=GWEN_Io_LayerCodec_GetWriteBuffer(io);
00867     assert(rbuf);
00868     maxBytes=GWEN_RingBuffer_GetMaxUnsegmentedWrite(rbuf);
00869     if (maxBytes>len)
00870       maxBytes=len;
00871     dst=(uint8_t*)GWEN_RingBuffer_GetWritePointer(rbuf);
00872     if (maxBytes) {
00873       memmove(dst, buf, maxBytes);
00874       GWEN_RingBuffer_SkipBytesWrite(rbuf, maxBytes);
00875     }
00876 
00877 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00878     gnutls_transport_set_errno(xio->session, 0);
00879 #else
00880     errno=0;
00881 #endif
00882     DBG_DEBUG(GWEN_LOGDOMAIN, "TLS PUSH: written %d bytes", maxBytes);
00883     return maxBytes;
00884   }
00885 }
00886 
00887 
00888 
00889 int GWEN_Io_LayerTls_Encode(GWEN_IO_LAYER *io, const uint8_t *pBuffer, uint32_t lBuffer) {
00890   GWEN_IO_LAYER_TLS *xio;
00891   ssize_t rv;
00892 
00893   assert(io);
00894   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00895   assert(xio);
00896 
00897   rv=gnutls_record_send(xio->session, pBuffer, lBuffer);
00898   if (rv<0) {
00899     if (rv==GNUTLS_E_AGAIN)
00900       return GWEN_ERROR_TRY_AGAIN;
00901     else if (rv==GNUTLS_E_INTERRUPTED)
00902       return GWEN_ERROR_INTERRUPTED;
00903     else {
00904       DBG_ERROR(GWEN_LOGDOMAIN,
00905                 "gnutls_record_send: %d (%s) [encoding %d bytes]",
00906                 (int)rv, gnutls_strerror(rv), lBuffer);
00907       return GWEN_ERROR_IO;
00908     }
00909   }
00910 #ifdef DEBUG_TLS
00911   else {
00912     DBG_ERROR(0, "Sent this:");
00913     GWEN_Text_DumpString((const char*)pBuffer, rv,
00914                          stderr, 2);
00915   }
00916 #endif
00917   return rv;
00918 }
00919 
00920 
00921 
00922 int GWEN_Io_LayerTls_Decode(GWEN_IO_LAYER *io, uint8_t *pBuffer, uint32_t lBuffer) {
00923   GWEN_IO_LAYER_TLS *xio;
00924   ssize_t rv;
00925 
00926   assert(io);
00927   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00928   assert(xio);
00929 
00930   rv=gnutls_record_recv(xio->session, pBuffer, lBuffer);
00931   if (rv<0) {
00932     if (rv==GNUTLS_E_AGAIN)
00933       return GWEN_ERROR_TRY_AGAIN;
00934     else if (rv==GNUTLS_E_INTERRUPTED)
00935       return GWEN_ERROR_INTERRUPTED;
00936     else {
00937       DBG_ERROR(GWEN_LOGDOMAIN,
00938                 "gnutls_record_recv: %d (%s) [decoding %d bytes]",
00939                 (int)rv, gnutls_strerror(rv), lBuffer);
00940       return GWEN_ERROR_IO;
00941     }
00942   }
00943   else if (rv==0) {
00944     DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
00945     return GWEN_ERROR_EOF;
00946   }
00947 #ifdef DEBUG_TLS
00948   else {
00949     DBG_ERROR(0, "Received this:");
00950     GWEN_Text_DumpString((const char*)pBuffer, rv,
00951                          stderr, 2);
00952   }
00953 #endif
00954 
00955   return rv;
00956 }
00957 
00958 
00959 
00960 int GWEN_Io_LayerTls_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00961   GWEN_IO_LAYER_TLS *xio;
00962   GWEN_IO_LAYER_STATUS st;
00963   uint32_t lflags;
00964 
00965   assert(io);
00966   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00967   assert(xio);
00968 
00969   st=GWEN_Io_Layer_GetStatus(io);
00970   lflags=GWEN_Io_Layer_GetFlags(io);
00971 
00972   switch(GWEN_Io_Request_GetType(r)) {
00973   case GWEN_Io_Request_TypeConnect:
00974     /* check status */
00975     if (st!=GWEN_Io_Layer_StatusUnconnected &&
00976         st!=GWEN_Io_Layer_StatusDisconnected) {
00977       DBG_INFO(GWEN_LOGDOMAIN, "Socket is not open");
00978       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
00979       return GWEN_ERROR_NOT_OPEN;
00980     }
00981 
00982     /* check whether we already have a read request */
00983     if (xio->connectRequest) {
00984       DBG_INFO(GWEN_LOGDOMAIN, "There already is a connect request");
00985       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IN_PROGRESS);
00986       return GWEN_ERROR_IN_PROGRESS;
00987     }
00988     else {
00989       /* prepare structures if necessary */
00990       GWEN_Io_LayerCodec_Reset(io);
00991       if (xio->prepared==0) {
00992         int rv;
00993 
00994         rv=GWEN_Io_LayerTls_Prepare(io);
00995         if (rv) {
00996           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00997           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00998           return rv;
00999         }
01000       }
01001 
01002       /* enqueue request */
01003       xio->connectRequest=r;
01004       GWEN_Io_Request_Attach(xio->connectRequest);
01005       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnecting);
01006     }
01007     break;
01008 
01009   case GWEN_Io_Request_TypeDisconnect:
01010     /* check status */
01011     if (st!=GWEN_Io_Layer_StatusConnected) {
01012       DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
01013       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01014       GWEN_Io_LayerCodec_Reset(io);
01015       return GWEN_ERROR_NOT_OPEN;
01016     }
01017     else {
01018       /* enqueue request */
01019       xio->disconnectRequest=r;
01020       GWEN_Io_Request_Attach(xio->disconnectRequest);
01021       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnecting);
01022     }
01023     break;
01024 
01025   default:
01026     if (xio->addRequestFn)
01027       return xio->addRequestFn(io, r);
01028     else {
01029       DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01030       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01031       return GWEN_ERROR_NOT_SUPPORTED;
01032     }
01033   }
01034 
01035   return 0;
01036 }
01037 
01038 
01039 
01040 int GWEN_Io_LayerTls_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01041   GWEN_IO_LAYER_TLS *xio;
01042 
01043   assert(io);
01044   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01045   assert(xio);
01046 
01047   switch(GWEN_Io_Request_GetType(r)) {
01048   case GWEN_Io_Request_TypeConnect:
01049     if (xio->connectRequest==r) {
01050       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
01051       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01052       GWEN_Io_LayerCodec_AbortRequests(io, GWEN_ERROR_ABORTED);
01053       xio->connectRequest=NULL;
01054       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01055       GWEN_Io_Request_free(r);
01056       if (xio->prepared) {
01057         gnutls_deinit(xio->session);
01058         gnutls_certificate_free_credentials(xio->credentials);
01059         xio->prepared=0;
01060       }
01061     }
01062     else {
01063       /* not my request */
01064       DBG_INFO(GWEN_LOGDOMAIN, "Connect request not registered with this io layer");
01065       return GWEN_ERROR_INVALID;
01066     }
01067     break;
01068 
01069   case GWEN_Io_Request_TypeDisconnect:
01070     if (xio->disconnectRequest==r) {
01071       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
01072 
01073       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01074       if (xio->connectRequest) {
01075         GWEN_IO_REQUEST *r;
01076 
01077         r=xio->connectRequest;
01078         xio->connectRequest=NULL;
01079         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01080         GWEN_Io_Request_free(r);
01081       }
01082     }
01083     else {
01084       /* not my request */
01085       DBG_INFO(GWEN_LOGDOMAIN, "Disconnect request not registered with this io layer");
01086       return GWEN_ERROR_INVALID;
01087     }
01088     break;
01089 
01090   default:
01091     if (xio->delRequestFn)
01092       return xio->delRequestFn(io, r);
01093     else {
01094       DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01095       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01096       return GWEN_ERROR_NOT_SUPPORTED;
01097     }
01098   }
01099 
01100   return 0;
01101 }
01102 
01103 
01104 
01105 int GWEN_Io_LayerTls_HasWaitingRequests(GWEN_IO_LAYER *io) {
01106   GWEN_IO_LAYER_TLS *xio;
01107 
01108   assert(io);
01109   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01110   assert(xio);
01111 
01112   if (xio->connectRequest || xio->disconnectRequest)
01113     return 1;
01114   if (xio->hasWaitingRequestsFn)
01115     return xio->hasWaitingRequestsFn(io);
01116 
01117   return 0;
01118 }
01119 
01120 
01121 
01122 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerTls_WorkOnRequests(GWEN_IO_LAYER *io) {
01123   GWEN_IO_LAYER_TLS *xio;
01124   int doneSomething=0;
01125 
01126   assert(io);
01127   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01128   assert(xio);
01129 
01130   /* work on connect request */
01131   if (xio->connectRequest) {
01132     GWEN_IO_REQUEST *r;
01133     int rv;
01134 
01135     r=xio->connectRequest;
01136     GWEN_Io_LayerCodec_SetCurrentGuiId(io, GWEN_Io_Request_GetGuiId(r));
01137     rv=gnutls_handshake(xio->session);
01138     if (rv<0) {
01139       if (rv!=GNUTLS_E_AGAIN &&
01140           rv!=GNUTLS_E_INTERRUPTED) {
01141         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_handshake: %d (%s) [%s]",
01142                   rv, gnutls_strerror(rv), gnutls_error_is_fatal(rv)?"fatal":"non-fatal");
01143         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01144         xio->connectRequest=NULL;
01145         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL);
01146         GWEN_Io_Request_free(r);
01147         if (xio->prepared) {
01148           gnutls_deinit(xio->session);
01149           gnutls_certificate_free_credentials(xio->credentials);
01150           xio->prepared=0;
01151         }
01152         doneSomething=1;
01153       }
01154     }
01155     else {
01156       /* check certificate */
01157       doneSomething=1;
01158       GWEN_Io_Layer_SubFlags(io, GWEN_IO_LAYER_TLS_FLAGS_SECURE);
01159       rv=GWEN_Io_LayerTls_GetPeerCert(io, GWEN_Io_Request_GetGuiId(r));
01160       if (rv) {
01161         if (GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_TLS_FLAGS_NEED_PEER_CERT) {
01162           DBG_INFO(GWEN_LOGDOMAIN, "No peer certificate when needed, aborting connection");
01163           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01164           xio->connectRequest=NULL;
01165           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL_SECURITY);
01166           GWEN_Io_Request_free(r);
01167           if (xio->prepared) {
01168             gnutls_deinit(xio->session);
01169             gnutls_certificate_free_credentials(xio->credentials);
01170             xio->prepared=0;
01171           }
01172         }
01173         else {
01174           DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (insecure)");
01175           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01176           xio->connectRequest=NULL;
01177           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01178           GWEN_Io_Request_free(r);
01179         }
01180       }
01181       else {
01182         /* present cert to the user */
01183         rv=GWEN_Gui_CheckCert(xio->peerCertDescr, io, GWEN_Io_Request_GetGuiId(r));
01184         if (rv) {
01185           DBG_INFO(GWEN_LOGDOMAIN, "Peer cert not accepted (%d), aborting", rv);
01186           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01187           xio->connectRequest=NULL;
01188           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL_SECURITY);
01189           GWEN_Io_Request_free(r);
01190           if (xio->prepared) {
01191             gnutls_deinit(xio->session);
01192             gnutls_certificate_free_credentials(xio->credentials);
01193             xio->prepared=0;
01194           }
01195         }
01196         else {
01197           DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (secure)");
01198           GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_TLS_FLAGS_SECURE);
01199           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01200           xio->connectRequest=NULL;
01201           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01202           GWEN_Io_Request_free(r);
01203         }
01204       }
01205     }
01206   }
01207   if (xio->disconnectRequest) {
01208     GWEN_IO_REQUEST *r;
01209     int rv;
01210 
01211     r=xio->disconnectRequest;
01212     GWEN_Io_LayerCodec_SetCurrentGuiId(io, GWEN_Io_Request_GetGuiId(r));
01213     rv=gnutls_bye(xio->session, GNUTLS_SHUT_RDWR);
01214     if (rv<0) {
01215       if (rv!=GNUTLS_E_AGAIN &&
01216           rv!=GNUTLS_E_INTERRUPTED) {
01217         DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_bye: %d (%s)", rv, gnutls_strerror(rv));
01218         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01219         xio->disconnectRequest=NULL;
01220         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL);
01221         GWEN_Io_Request_free(r);
01222         GWEN_Io_LayerCodec_Reset(io);
01223         if (xio->prepared) {
01224           gnutls_deinit(xio->session);
01225           gnutls_certificate_free_credentials(xio->credentials);
01226           xio->prepared=0;
01227         }
01228         doneSomething=1;
01229       }
01230     }
01231     else {
01232       DBG_INFO(GWEN_LOGDOMAIN, "SSL disconnected");
01233       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01234       xio->disconnectRequest=NULL;
01235       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01236       GWEN_Io_Request_free(r);
01237       GWEN_Io_LayerCodec_Reset(io);
01238       if (xio->prepared) {
01239         gnutls_deinit(xio->session);
01240         gnutls_certificate_free_credentials(xio->credentials);
01241         xio->prepared=0;
01242       }
01243       doneSomething=1;
01244     }
01245   }
01246 
01247   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01248     GWEN_IO_LAYER *newIo;
01249 
01250     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01251     if (newIo) {
01252       GWEN_IO_LAYER *newNewIo;
01253       uint32_t fl;
01254 
01255       fl=GWEN_Io_Layer_GetFlags(io);
01256       newNewIo=GWEN_Io_LayerTls_new(newIo);
01257       GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01258       GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01259       if (xio->localCertFile)
01260         GWEN_Io_LayerTls_SetLocalCertFile(newNewIo, xio->localCertFile);
01261       if (xio->localKeyFile)
01262         GWEN_Io_LayerTls_SetLocalKeyFile(newNewIo, xio->localKeyFile);
01263       if (xio->localTrustFile)
01264         GWEN_Io_LayerTls_SetLocalTrustFile(newNewIo, xio->localTrustFile);
01265       if (xio->dhParamFile)
01266         GWEN_Io_LayerTls_SetDhParamFile(newNewIo, xio->dhParamFile);
01267 
01268       if ((fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_NAME) ||
01269           (fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_IP)) {
01270         GWEN_IO_LAYER *sp;
01271 
01272         /* try to retrieve the address from socket io layer if there is any */
01273         sp=GWEN_Io_Layer_FindBaseLayerByType(newIo, GWEN_IO_LAYER_SOCKET_TYPE);
01274         if (sp) {
01275           GWEN_INETADDRESS *addr;
01276 
01277           addr=GWEN_Io_LayerSocket_GetPeerAddr(sp);
01278           if (addr) {
01279             char addrBuffer[128];
01280 
01281             if (fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_NAME)
01282               GWEN_InetAddr_GetName(addr, addrBuffer, sizeof(addrBuffer)-1);
01283             else
01284               GWEN_InetAddr_GetAddress(addr, addrBuffer, sizeof(addrBuffer)-1);
01285             addrBuffer[sizeof(addrBuffer)-1]=0;
01286             if (*addrBuffer) {
01287               DBG_INFO(GWEN_LOGDOMAIN, "Setting remote addr to [%s]", addrBuffer);
01288               GWEN_Io_LayerTls_SetRemoteHostName(newNewIo, addrBuffer);
01289             }
01290           }
01291         }
01292       }
01293 
01294       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01295       doneSomething=1;
01296     }
01297   }
01298 
01299   if (xio->workOnRequestsFn &&
01300       xio->workOnRequestsFn(io)!=GWEN_Io_Layer_WorkResultBlocking) {
01301     doneSomething=1;
01302   }
01303 
01304   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01305 }
01306 
01307 
01308 
01309 
01310 
01311 
01312 
01313 
01314 
01315 
01316 
01317 
01318 
01319 
01320 
01321 
01322 
01323 

Generated on Fri Apr 11 01:53:47 2008 for gwenhywfar by  doxygen 1.5.5