gwenhywfar 4.0.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 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