gwenhywfar
4.3.3
|
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