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