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