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 rv=gnutls_protocol_set_priority(xio->session, proto_prio);
00314 if (rv) {
00315 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_protocol_set_priority: %d (%s)", rv, gnutls_strerror(rv));
00316 gnutls_deinit(xio->session);
00317 return GWEN_ERROR_GENERIC;
00318 }
00319 }
00320
00321
00322 if ((lflags & GWEN_IO_LAYER_FLAGS_PASSIVE) &&
00323 (lflags & GWEN_IO_LAYER_TLS_FLAGS_REQUEST_CERT))
00324 gnutls_certificate_server_set_request(xio->session, GNUTLS_CERT_REQUIRE);
00325
00326
00327 rv=gnutls_certificate_allocate_credentials(&xio->credentials);
00328 if (rv) {
00329 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_allocate_credentials: %d (%s)", rv, gnutls_strerror(rv));
00330 gnutls_deinit(xio->session);
00331 return GWEN_ERROR_GENERIC;
00332 }
00333
00334
00335 if (xio->localCertFile && xio->localKeyFile) {
00336 rv=gnutls_certificate_set_x509_key_file(xio->credentials,
00337 xio->localCertFile,
00338 xio->localKeyFile,
00339 GNUTLS_X509_FMT_PEM);
00340 if (rv<0) {
00341 if (rv) {
00342 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_key_file: %d (%s)", rv, gnutls_strerror(rv));
00343 gnutls_certificate_free_credentials(xio->credentials);
00344 gnutls_deinit(xio->session);
00345 return GWEN_ERROR_GENERIC;
00346 }
00347 }
00348 }
00349
00350
00351 if (lflags & GWEN_IO_LAYER_TLS_FLAGS_ADD_TRUSTED_CAS) {
00352 GWEN_STRINGLIST *paths;
00353
00354
00355 paths=GWEN_PathManager_GetPaths(GWEN_PM_LIBNAME, GWEN_PM_DATADIR);
00356 if (paths) {
00357 GWEN_BUFFER *nbuf;
00358
00359 nbuf=GWEN_Buffer_new(0, 256, 0, 1);
00360 rv=GWEN_Directory_FindFileInPaths(paths,
00361 "ca-bundle.crt",
00362 nbuf);
00363 GWEN_StringList_free(paths);
00364 if (rv==0) {
00365 DBG_INFO(GWEN_LOGDOMAIN,
00366 "Using default ca-bundle from [%s]",
00367 GWEN_Buffer_GetStart(nbuf));
00368 GWEN_Io_LayerTls_SetLocalTrustFile(io, GWEN_Buffer_GetStart(nbuf));
00369 }
00370 else {
00371 DBG_WARN(GWEN_LOGDOMAIN, "Default bundle file not found");
00372 }
00373 GWEN_Buffer_free(nbuf);
00374 }
00375 }
00376
00377
00378 if (xio->localTrustFile) {
00379 rv=gnutls_certificate_set_x509_trust_file(xio->credentials,
00380 xio->localTrustFile,
00381 GNUTLS_X509_FMT_PEM);
00382 if (rv<=0) {
00383 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_certificate_set_x509_trust_file: %d (%s)", rv, gnutls_strerror(rv));
00384 gnutls_certificate_free_credentials(xio->credentials);
00385 gnutls_deinit(xio->session);
00386 return GWEN_ERROR_GENERIC;
00387 }
00388 else {
00389 DBG_INFO(GWEN_LOGDOMAIN,
00390 "Added %d trusted certs", rv);
00391 }
00392 }
00393
00394
00395 if (xio->dhParamFile) {
00396 GWEN_BUFFER *dbuf;
00397
00398 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00399 rv=GWEN_Io_LayerTls__readFile(xio->dhParamFile, dbuf);
00400 if (rv) {
00401 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00402 GWEN_Buffer_free(dbuf);
00403 gnutls_certificate_free_credentials(xio->credentials);
00404 gnutls_deinit(xio->session);
00405 return rv;
00406 }
00407 else {
00408 gnutls_datum d;
00409 gnutls_dh_params dh_params=NULL;
00410
00411 rv=gnutls_dh_params_init(&dh_params);
00412 if (rv<0) {
00413 GWEN_Buffer_free(dbuf);
00414 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_init: %d (%s)", rv, gnutls_strerror(rv));
00415 gnutls_certificate_free_credentials(xio->credentials);
00416 gnutls_deinit(xio->session);
00417 return GWEN_ERROR_GENERIC;
00418 }
00419
00420 d.size=GWEN_Buffer_GetUsedBytes(dbuf);
00421 d.data=(unsigned char*)GWEN_Buffer_GetStart(dbuf);
00422
00423 rv=gnutls_dh_params_import_pkcs3(dh_params, &d, GNUTLS_X509_FMT_PEM);
00424 if (rv<0) {
00425 GWEN_Buffer_free(dbuf);
00426 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_dh_params_import_pkcs3: %d (%s)", rv, gnutls_strerror(rv));
00427 gnutls_certificate_free_credentials(xio->credentials);
00428 gnutls_deinit(xio->session);
00429 return GWEN_ERROR_GENERIC;
00430 }
00431 GWEN_Buffer_free(dbuf);
00432
00433 gnutls_certificate_set_dh_params(xio->credentials, dh_params);
00434 }
00435 }
00436
00437
00438 rv=gnutls_credentials_set(xio->session, GNUTLS_CRD_CERTIFICATE, xio->credentials);
00439 if (rv<0) {
00440 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_credentials_set: %d (%s)", rv, gnutls_strerror(rv));
00441 gnutls_certificate_free_credentials(xio->credentials);
00442 gnutls_deinit(xio->session);
00443 return GWEN_ERROR_GENERIC;
00444 }
00445
00446
00447 gnutls_transport_set_ptr(xio->session, (gnutls_transport_ptr_t)io);
00448 gnutls_transport_set_push_function(xio->session, GWEN_Io_LayerTls_Push);
00449 gnutls_transport_set_pull_function(xio->session, GWEN_Io_LayerTls_Pull);
00450 gnutls_transport_set_lowat(xio->session, 0);
00451
00452 xio->prepared=1;
00453
00454 return 0;
00455 }
00456
00457
00458
00459 int GWEN_Io_LayerTls_GetPeerCert(GWEN_IO_LAYER *io, uint32_t guiid) {
00460 GWEN_IO_LAYER_TLS *xio;
00461 const gnutls_datum_t *cert_list;
00462 unsigned int cert_list_size;
00463 size_t size;
00464 GWEN_SSLCERTDESCR *certDescr;
00465 char buffer1[64];
00466 time_t t0;
00467 int rv;
00468 uint32_t lflags;
00469 uint32_t errFlags=0;
00470 int i;
00471 unsigned int status;
00472 GWEN_BUFFER *sbuf=NULL;
00473
00474 assert(io);
00475 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00476 assert(xio);
00477
00478 lflags=GWEN_Io_Layer_GetFlags(io);
00479
00480 if (xio->peerCertDescr) {
00481 GWEN_SslCertDescr_free(xio->peerCertDescr);
00482 xio->peerCertDescr=NULL;
00483 }
00484 xio->peerCertFlags=0;
00485
00486 t0=time(NULL);
00487 if (t0<0) {
00488 DBG_WARN(GWEN_LOGDOMAIN, "Could not get system time");
00489 errFlags|=GWEN_SSL_CERT_FLAGS_SYSTEM;
00490 }
00491
00492
00493 certDescr=GWEN_SslCertDescr_new();
00494
00495
00496 if (lflags & GWEN_IO_LAYER_TLS_FLAGS_ALLOW_V1_CA_CRT)
00497 gnutls_certificate_set_verify_flags(xio->credentials,
00498 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
00499
00500 rv=gnutls_certificate_verify_peers2(xio->session, &status);
00501 if (rv<0) {
00502 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_certificate_verify_peers2: %d (%s)", rv, gnutls_strerror(rv));
00503 GWEN_SslCertDescr_free(certDescr);
00504 return GWEN_ERROR_SSL_SECURITY;
00505 }
00506
00507 if (gnutls_certificate_type_get(xio->session)!=GNUTLS_CRT_X509) {
00508 DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not X.509");
00509
00510 GWEN_SslCertDescr_free(certDescr);
00511 return GWEN_ERROR_SSL_SECURITY;
00512 }
00513
00514 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
00515 DBG_INFO(GWEN_LOGDOMAIN, "Signer not found");
00516 GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00517 I18N("Signer not found"));
00518 errFlags|=GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND;
00519 }
00520
00521 if (status & GNUTLS_CERT_INVALID) {
00522 DBG_INFO(GWEN_LOGDOMAIN, "Certificate is not trusted");
00523 GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00524 I18N("Certificate is not trusted"));
00525 errFlags|=GWEN_SSL_CERT_FLAGS_INVALID;
00526 }
00527
00528 if (status & GNUTLS_CERT_REVOKED) {
00529 DBG_INFO(GWEN_LOGDOMAIN, "Certificate has been revoked");
00530 GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00531 I18N("Certificate has been revoked"));
00532 errFlags|=GWEN_SSL_CERT_FLAGS_REVOKED;
00533 }
00534
00535 cert_list=gnutls_certificate_get_peers(xio->session, &cert_list_size);
00536 if (cert_list==NULL || cert_list_size==0) {
00537 DBG_INFO(GWEN_LOGDOMAIN, "No peer certificates found");
00538 return GWEN_ERROR_NO_DATA;
00539 }
00540
00541 for (i=0; i<cert_list_size; i++) {
00542 gnutls_x509_crt_t cert;
00543 time_t t;
00544
00545 rv=gnutls_x509_crt_init(&cert);
00546 if (rv!=0) {
00547 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_init: %d (%s)", rv, gnutls_strerror(rv));
00548 return GWEN_ERROR_GENERIC;
00549 }
00550
00551 rv=gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
00552 if (rv!=0) {
00553 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_import: %d (%s)", rv, gnutls_strerror(rv));
00554 gnutls_x509_crt_deinit(cert);
00555 return GWEN_ERROR_GENERIC;
00556 }
00557
00558 if (i==0) {
00559
00560 size=16;
00561 rv=gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, buffer1, &size);
00562 if (rv!=0) {
00563 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_fingerprint: %d (%s)", rv, gnutls_strerror(rv));
00564 GWEN_SslCertDescr_free(certDescr);
00565 gnutls_x509_crt_deinit(cert);
00566 return GWEN_ERROR_GENERIC;
00567 }
00568 else {
00569 GWEN_BUFFER *dbuf;
00570
00571 dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00572 if (GWEN_Text_ToHexBuffer( buffer1,
00573 size, dbuf, 2, ':', 0)) {
00574 DBG_ERROR(GWEN_LOGDOMAIN,
00575 "Could not convert fingerprint to hex");
00576 }
00577 else {
00578 GWEN_SslCertDescr_SetFingerPrint(certDescr, GWEN_Buffer_GetStart(dbuf));
00579 }
00580 GWEN_Buffer_free(dbuf);
00581 }
00582
00583 if (xio->hostName) {
00584 DBG_INFO(GWEN_LOGDOMAIN, "Checking hostname [%s]", xio->hostName);
00585 if (!gnutls_x509_crt_check_hostname(cert, xio->hostName)) {
00586 DBG_WARN(GWEN_LOGDOMAIN,
00587 "Certificate was not issued for this host");
00588 GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00589 I18N("Certificate was not issued for this host"));
00590 errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00591 }
00592 else {
00593 DBG_INFO(GWEN_LOGDOMAIN, "Cert is for this server");
00594 }
00595 }
00596 else {
00597 DBG_WARN(GWEN_LOGDOMAIN,
00598 "Hostname is not set, unable to verify the sender");
00599 GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Warning,
00600 I18N("No hostname to verify the sender!"));
00601 }
00602
00603 }
00604
00605
00606 t=gnutls_x509_crt_get_activation_time(cert);
00607 if (t<0) {
00608 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_activation_time: %d (%s)", rv, gnutls_strerror(rv));
00609 errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00610 }
00611 else {
00612 if (t>t0) {
00613 DBG_INFO(GWEN_LOGDOMAIN, "Cert is not yet active");
00614 errFlags|=GWEN_SSL_CERT_FLAGS_NOT_ACTIVE;
00615 }
00616 if (i==0) {
00617 GWEN_TIME *ti;
00618
00619 ti=GWEN_Time_fromSeconds(t);
00620 if (ti)
00621 GWEN_SslCertDescr_SetNotBefore(certDescr, ti);
00622 GWEN_Time_free(ti);
00623 }
00624 }
00625
00626
00627 t=gnutls_x509_crt_get_expiration_time(cert);
00628 if (t<0) {
00629 DBG_INFO(GWEN_LOGDOMAIN, "gnutls_x509_crt_get_expiration_time: %d (%s)", rv, gnutls_strerror(rv));
00630 errFlags|=GWEN_SSL_CERT_FLAGS_BAD_DATA;
00631 }
00632 else {
00633 if (t<t0) {
00634 DBG_INFO(GWEN_LOGDOMAIN, "Cert has expired");
00635 errFlags|=GWEN_SSL_CERT_FLAGS_EXPIRED;
00636 }
00637 if (i==0) {
00638 GWEN_TIME *ti;
00639
00640 ti=GWEN_Time_fromSeconds(t);
00641 if (ti)
00642 GWEN_SslCertDescr_SetNotAfter(certDescr, ti);
00643 GWEN_Time_free(ti);
00644 }
00645 }
00646
00647 if (i==0) {
00648
00649 size=sizeof(buffer1)-1;
00650 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buffer1, &size);
00651 if (rv==0) {
00652 GWEN_SslCertDescr_SetCommonName(certDescr, buffer1);
00653 if (xio->hostName && strcasecmp(xio->hostName, buffer1)!=0) {
00654 DBG_INFO(GWEN_LOGDOMAIN, "Owner of certificate does not match hostname");
00655 errFlags|=GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME;
00656 }
00657 }
00658
00659 size=sizeof(buffer1)-1;
00660 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, buffer1, &size);
00661 if (rv==0)
00662 GWEN_SslCertDescr_SetOrganizationName(certDescr, buffer1);
00663
00664 size=sizeof(buffer1)-1;
00665 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0, buffer1, &size);
00666 if (rv==0)
00667 GWEN_SslCertDescr_SetOrganizationalUnitName(certDescr, buffer1);
00668
00669 size=sizeof(buffer1)-1;
00670 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, buffer1, &size);
00671 if (rv==0)
00672 GWEN_SslCertDescr_SetLocalityName(certDescr, buffer1);
00673
00674 size=sizeof(buffer1)-1;
00675 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0, buffer1, &size);
00676 if (rv==0)
00677 GWEN_SslCertDescr_SetStateOrProvinceName(certDescr, buffer1);
00678
00679 size=sizeof(buffer1)-1;
00680 rv=gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, buffer1, &size);
00681 if (rv==0)
00682 GWEN_SslCertDescr_SetCountryName(certDescr, buffer1);
00683 }
00684
00685 gnutls_x509_crt_deinit(cert);
00686 }
00687
00688
00689 if (errFlags)
00690 GWEN_SslCertDescr_SetIsError(certDescr, 1);
00691 else
00692 errFlags|=GWEN_SSL_CERT_FLAGS_OK;
00693
00694 sbuf=GWEN_Buffer_new(0, 256, 0, 1);
00695
00696 if (errFlags & GWEN_SSL_CERT_FLAGS_SIGNER_NOT_FOUND) {
00697 if (GWEN_Buffer_GetUsedBytes(sbuf))
00698 GWEN_Buffer_AppendString(sbuf, "; ");
00699 GWEN_Buffer_AppendString(sbuf, I18N("Signer not found"));
00700 }
00701
00702 if (errFlags & GWEN_SSL_CERT_FLAGS_INVALID) {
00703 if (GWEN_Buffer_GetUsedBytes(sbuf))
00704 GWEN_Buffer_AppendString(sbuf, "; ");
00705 GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not trusted"));
00706 }
00707
00708 if (errFlags & GWEN_SSL_CERT_FLAGS_REVOKED) {
00709 if (GWEN_Buffer_GetUsedBytes(sbuf))
00710 GWEN_Buffer_AppendString(sbuf, "; ");
00711 GWEN_Buffer_AppendString(sbuf, I18N("Certificate has been revoked"));
00712 }
00713
00714 if (errFlags & GWEN_SSL_CERT_FLAGS_EXPIRED) {
00715 if (GWEN_Buffer_GetUsedBytes(sbuf))
00716 GWEN_Buffer_AppendString(sbuf, "; ");
00717 GWEN_Buffer_AppendString(sbuf, I18N("Certificate has expired"));
00718 }
00719
00720 if (errFlags & GWEN_SSL_CERT_FLAGS_NOT_ACTIVE) {
00721 if (GWEN_Buffer_GetUsedBytes(sbuf))
00722 GWEN_Buffer_AppendString(sbuf, "; ");
00723 GWEN_Buffer_AppendString(sbuf, I18N("Certificate is not active yet"));
00724 }
00725
00726 if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_HOSTNAME) {
00727 if (GWEN_Buffer_GetUsedBytes(sbuf))
00728 GWEN_Buffer_AppendString(sbuf, "; ");
00729 GWEN_Buffer_AppendString(sbuf, I18N("Certificate owner does not match hostname"));
00730 }
00731
00732 if (errFlags & GWEN_SSL_CERT_FLAGS_BAD_DATA) {
00733 if (GWEN_Buffer_GetUsedBytes(sbuf))
00734 GWEN_Buffer_AppendString(sbuf, "; ");
00735 GWEN_Buffer_AppendString(sbuf, I18N("Certificate contains invalid information"));
00736 }
00737
00738 if (errFlags & GWEN_SSL_CERT_FLAGS_SYSTEM) {
00739 if (GWEN_Buffer_GetUsedBytes(sbuf))
00740 GWEN_Buffer_AppendString(sbuf, "; ");
00741 GWEN_Buffer_AppendString(sbuf, I18N("A system error occurred while checking the certificate"));
00742 }
00743
00744 if (errFlags & GWEN_SSL_CERT_FLAGS_OK) {
00745 if (GWEN_Buffer_GetUsedBytes(sbuf))
00746 GWEN_Buffer_AppendString(sbuf, "; ");
00747 GWEN_Buffer_AppendString(sbuf, I18N("The certificate is valid"));
00748 }
00749
00750 GWEN_SslCertDescr_SetStatusText(certDescr, GWEN_Buffer_GetStart(sbuf));
00751 GWEN_SslCertDescr_SetStatusFlags(certDescr, errFlags);
00752 GWEN_Buffer_free(sbuf);
00753
00754 xio->peerCertDescr=certDescr;
00755 xio->peerCertFlags=errFlags;
00756
00757 return 0;
00758 }
00759
00760
00761
00762 ssize_t GWEN_Io_LayerTls_Pull(gnutls_transport_ptr_t p, void *buf, size_t len) {
00763 GWEN_IO_LAYER *io;
00764 GWEN_IO_LAYER_TLS *xio;
00765 int rv;
00766
00767 io=(GWEN_IO_LAYER*) p;
00768 assert(io);
00769 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00770 assert(xio);
00771
00772 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: %d bytes", (int)len);
00773 rv=GWEN_Io_LayerCodec_EnsureReadOk(io);
00774 if (rv) {
00775 if (rv==GWEN_ERROR_TRY_AGAIN || rv==GWEN_ERROR_IN_PROGRESS) {
00776 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00777 gnutls_transport_set_errno(xio->session, EAGAIN);
00778 #else
00779 errno=EAGAIN;
00780 #endif
00781 return (ssize_t)-1;
00782 }
00783 else {
00784 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00785 gnutls_transport_set_errno(xio->session, EINVAL);
00786 #else
00787 errno=EINVAL;
00788 #endif
00789 return (ssize_t)-1;
00790 }
00791 }
00792 else {
00793 GWEN_RINGBUFFER *rbuf;
00794 uint32_t maxBytes;
00795 const uint8_t *src;
00796
00797 rbuf=GWEN_Io_LayerCodec_GetReadBuffer(io);
00798 assert(buf);
00799 maxBytes=GWEN_RingBuffer_GetMaxUnsegmentedRead(rbuf);
00800 if (maxBytes>len)
00801 maxBytes=len;
00802 src=(const uint8_t*)GWEN_RingBuffer_GetReadPointer(rbuf);
00803 if (maxBytes) {
00804 memmove(buf, src, maxBytes);
00805 GWEN_RingBuffer_SkipBytesRead(rbuf, maxBytes);
00806 }
00807
00808 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00809 gnutls_transport_set_errno(xio->session, 0);
00810 #else
00811 errno=0;
00812 #endif
00813 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PULL: returning %d bytes", maxBytes);
00814
00815 return maxBytes;
00816 }
00817 }
00818
00819
00820
00821 ssize_t GWEN_Io_LayerTls_Push(gnutls_transport_ptr_t p, const void *buf, size_t len) {
00822 GWEN_IO_LAYER *io;
00823 GWEN_IO_LAYER_TLS *xio;
00824 int rv;
00825
00826 io=(GWEN_IO_LAYER*) p;
00827 assert(io);
00828 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00829 assert(xio);
00830
00831 DBG_VERBOUS(GWEN_LOGDOMAIN, "TLS PUSH: %d bytes", (int)len);
00832
00833
00834 rv=GWEN_Io_LayerCodec_CheckWriteOut(io);
00835 if (rv) {
00836 if (rv==GWEN_ERROR_TRY_AGAIN) {
00837 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00838 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00839 gnutls_transport_set_errno(xio->session, EAGAIN);
00840 #else
00841 errno=EAGAIN;
00842 #endif
00843 return (ssize_t)-1;
00844 }
00845 else {
00846 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00847 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00848 gnutls_transport_set_errno(xio->session, EINVAL);
00849 #else
00850 errno=EINVAL;
00851 #endif
00852 return (ssize_t)-1;
00853 }
00854 }
00855 else {
00856 GWEN_RINGBUFFER *rbuf;
00857 uint32_t maxBytes;
00858 uint8_t *dst;
00859 uint32_t guiid=0;
00860
00861 if (xio->connectRequest)
00862 guiid=GWEN_Io_Request_GetGuiId(xio->connectRequest);
00863 else if (xio->connectRequest)
00864 guiid=GWEN_Io_Request_GetGuiId(xio->disconnectRequest);
00865
00866 rbuf=GWEN_Io_LayerCodec_GetWriteBuffer(io);
00867 assert(rbuf);
00868 maxBytes=GWEN_RingBuffer_GetMaxUnsegmentedWrite(rbuf);
00869 if (maxBytes>len)
00870 maxBytes=len;
00871 dst=(uint8_t*)GWEN_RingBuffer_GetWritePointer(rbuf);
00872 if (maxBytes) {
00873 memmove(dst, buf, maxBytes);
00874 GWEN_RingBuffer_SkipBytesWrite(rbuf, maxBytes);
00875 }
00876
00877 #ifdef HAVE_GNUTLS_TRANSPORT_SET_ERRNO
00878 gnutls_transport_set_errno(xio->session, 0);
00879 #else
00880 errno=0;
00881 #endif
00882 DBG_DEBUG(GWEN_LOGDOMAIN, "TLS PUSH: written %d bytes", maxBytes);
00883 return maxBytes;
00884 }
00885 }
00886
00887
00888
00889 int GWEN_Io_LayerTls_Encode(GWEN_IO_LAYER *io, const uint8_t *pBuffer, uint32_t lBuffer) {
00890 GWEN_IO_LAYER_TLS *xio;
00891 ssize_t rv;
00892
00893 assert(io);
00894 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00895 assert(xio);
00896
00897 rv=gnutls_record_send(xio->session, pBuffer, lBuffer);
00898 if (rv<0) {
00899 if (rv==GNUTLS_E_AGAIN)
00900 return GWEN_ERROR_TRY_AGAIN;
00901 else if (rv==GNUTLS_E_INTERRUPTED)
00902 return GWEN_ERROR_INTERRUPTED;
00903 else {
00904 DBG_ERROR(GWEN_LOGDOMAIN,
00905 "gnutls_record_send: %d (%s) [encoding %d bytes]",
00906 (int)rv, gnutls_strerror(rv), lBuffer);
00907 return GWEN_ERROR_IO;
00908 }
00909 }
00910 #ifdef DEBUG_TLS
00911 else {
00912 DBG_ERROR(0, "Sent this:");
00913 GWEN_Text_DumpString((const char*)pBuffer, rv,
00914 stderr, 2);
00915 }
00916 #endif
00917 return rv;
00918 }
00919
00920
00921
00922 int GWEN_Io_LayerTls_Decode(GWEN_IO_LAYER *io, uint8_t *pBuffer, uint32_t lBuffer) {
00923 GWEN_IO_LAYER_TLS *xio;
00924 ssize_t rv;
00925
00926 assert(io);
00927 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00928 assert(xio);
00929
00930 rv=gnutls_record_recv(xio->session, pBuffer, lBuffer);
00931 if (rv<0) {
00932 if (rv==GNUTLS_E_AGAIN)
00933 return GWEN_ERROR_TRY_AGAIN;
00934 else if (rv==GNUTLS_E_INTERRUPTED)
00935 return GWEN_ERROR_INTERRUPTED;
00936 else {
00937 DBG_ERROR(GWEN_LOGDOMAIN,
00938 "gnutls_record_recv: %d (%s) [decoding %d bytes]",
00939 (int)rv, gnutls_strerror(rv), lBuffer);
00940 return GWEN_ERROR_IO;
00941 }
00942 }
00943 else if (rv==0) {
00944 DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
00945 return GWEN_ERROR_EOF;
00946 }
00947 #ifdef DEBUG_TLS
00948 else {
00949 DBG_ERROR(0, "Received this:");
00950 GWEN_Text_DumpString((const char*)pBuffer, rv,
00951 stderr, 2);
00952 }
00953 #endif
00954
00955 return rv;
00956 }
00957
00958
00959
00960 int GWEN_Io_LayerTls_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00961 GWEN_IO_LAYER_TLS *xio;
00962 GWEN_IO_LAYER_STATUS st;
00963 uint32_t lflags;
00964
00965 assert(io);
00966 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
00967 assert(xio);
00968
00969 st=GWEN_Io_Layer_GetStatus(io);
00970 lflags=GWEN_Io_Layer_GetFlags(io);
00971
00972 switch(GWEN_Io_Request_GetType(r)) {
00973 case GWEN_Io_Request_TypeConnect:
00974
00975 if (st!=GWEN_Io_Layer_StatusUnconnected &&
00976 st!=GWEN_Io_Layer_StatusDisconnected) {
00977 DBG_INFO(GWEN_LOGDOMAIN, "Socket is not open");
00978 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
00979 return GWEN_ERROR_NOT_OPEN;
00980 }
00981
00982
00983 if (xio->connectRequest) {
00984 DBG_INFO(GWEN_LOGDOMAIN, "There already is a connect request");
00985 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IN_PROGRESS);
00986 return GWEN_ERROR_IN_PROGRESS;
00987 }
00988 else {
00989
00990 GWEN_Io_LayerCodec_Reset(io);
00991 if (xio->prepared==0) {
00992 int rv;
00993
00994 rv=GWEN_Io_LayerTls_Prepare(io);
00995 if (rv) {
00996 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00997 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00998 return rv;
00999 }
01000 }
01001
01002
01003 xio->connectRequest=r;
01004 GWEN_Io_Request_Attach(xio->connectRequest);
01005 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnecting);
01006 }
01007 break;
01008
01009 case GWEN_Io_Request_TypeDisconnect:
01010
01011 if (st!=GWEN_Io_Layer_StatusConnected) {
01012 DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
01013 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01014 GWEN_Io_LayerCodec_Reset(io);
01015 return GWEN_ERROR_NOT_OPEN;
01016 }
01017 else {
01018
01019 xio->disconnectRequest=r;
01020 GWEN_Io_Request_Attach(xio->disconnectRequest);
01021 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnecting);
01022 }
01023 break;
01024
01025 default:
01026 if (xio->addRequestFn)
01027 return xio->addRequestFn(io, r);
01028 else {
01029 DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01030 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01031 return GWEN_ERROR_NOT_SUPPORTED;
01032 }
01033 }
01034
01035 return 0;
01036 }
01037
01038
01039
01040 int GWEN_Io_LayerTls_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01041 GWEN_IO_LAYER_TLS *xio;
01042
01043 assert(io);
01044 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01045 assert(xio);
01046
01047 switch(GWEN_Io_Request_GetType(r)) {
01048 case GWEN_Io_Request_TypeConnect:
01049 if (xio->connectRequest==r) {
01050 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
01051 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01052 GWEN_Io_LayerCodec_AbortRequests(io, GWEN_ERROR_ABORTED);
01053 xio->connectRequest=NULL;
01054 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01055 GWEN_Io_Request_free(r);
01056 if (xio->prepared) {
01057 gnutls_deinit(xio->session);
01058 gnutls_certificate_free_credentials(xio->credentials);
01059 xio->prepared=0;
01060 }
01061 }
01062 else {
01063
01064 DBG_INFO(GWEN_LOGDOMAIN, "Connect request not registered with this io layer");
01065 return GWEN_ERROR_INVALID;
01066 }
01067 break;
01068
01069 case GWEN_Io_Request_TypeDisconnect:
01070 if (xio->disconnectRequest==r) {
01071 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
01072
01073 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01074 if (xio->connectRequest) {
01075 GWEN_IO_REQUEST *r;
01076
01077 r=xio->connectRequest;
01078 xio->connectRequest=NULL;
01079 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01080 GWEN_Io_Request_free(r);
01081 }
01082 }
01083 else {
01084
01085 DBG_INFO(GWEN_LOGDOMAIN, "Disconnect request not registered with this io layer");
01086 return GWEN_ERROR_INVALID;
01087 }
01088 break;
01089
01090 default:
01091 if (xio->delRequestFn)
01092 return xio->delRequestFn(io, r);
01093 else {
01094 DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01095 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01096 return GWEN_ERROR_NOT_SUPPORTED;
01097 }
01098 }
01099
01100 return 0;
01101 }
01102
01103
01104
01105 int GWEN_Io_LayerTls_HasWaitingRequests(GWEN_IO_LAYER *io) {
01106 GWEN_IO_LAYER_TLS *xio;
01107
01108 assert(io);
01109 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01110 assert(xio);
01111
01112 if (xio->connectRequest || xio->disconnectRequest)
01113 return 1;
01114 if (xio->hasWaitingRequestsFn)
01115 return xio->hasWaitingRequestsFn(io);
01116
01117 return 0;
01118 }
01119
01120
01121
01122 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerTls_WorkOnRequests(GWEN_IO_LAYER *io) {
01123 GWEN_IO_LAYER_TLS *xio;
01124 int doneSomething=0;
01125
01126 assert(io);
01127 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_TLS, io);
01128 assert(xio);
01129
01130
01131 if (xio->connectRequest) {
01132 GWEN_IO_REQUEST *r;
01133 int rv;
01134
01135 r=xio->connectRequest;
01136 GWEN_Io_LayerCodec_SetCurrentGuiId(io, GWEN_Io_Request_GetGuiId(r));
01137 rv=gnutls_handshake(xio->session);
01138 if (rv<0) {
01139 if (rv!=GNUTLS_E_AGAIN &&
01140 rv!=GNUTLS_E_INTERRUPTED) {
01141 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_handshake: %d (%s) [%s]",
01142 rv, gnutls_strerror(rv), gnutls_error_is_fatal(rv)?"fatal":"non-fatal");
01143 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01144 xio->connectRequest=NULL;
01145 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL);
01146 GWEN_Io_Request_free(r);
01147 if (xio->prepared) {
01148 gnutls_deinit(xio->session);
01149 gnutls_certificate_free_credentials(xio->credentials);
01150 xio->prepared=0;
01151 }
01152 doneSomething=1;
01153 }
01154 }
01155 else {
01156
01157 doneSomething=1;
01158 GWEN_Io_Layer_SubFlags(io, GWEN_IO_LAYER_TLS_FLAGS_SECURE);
01159 rv=GWEN_Io_LayerTls_GetPeerCert(io, GWEN_Io_Request_GetGuiId(r));
01160 if (rv) {
01161 if (GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_TLS_FLAGS_NEED_PEER_CERT) {
01162 DBG_INFO(GWEN_LOGDOMAIN, "No peer certificate when needed, aborting connection");
01163 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01164 xio->connectRequest=NULL;
01165 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL_SECURITY);
01166 GWEN_Io_Request_free(r);
01167 if (xio->prepared) {
01168 gnutls_deinit(xio->session);
01169 gnutls_certificate_free_credentials(xio->credentials);
01170 xio->prepared=0;
01171 }
01172 }
01173 else {
01174 DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (insecure)");
01175 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01176 xio->connectRequest=NULL;
01177 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01178 GWEN_Io_Request_free(r);
01179 }
01180 }
01181 else {
01182
01183 rv=GWEN_Gui_CheckCert(xio->peerCertDescr, io, GWEN_Io_Request_GetGuiId(r));
01184 if (rv) {
01185 DBG_INFO(GWEN_LOGDOMAIN, "Peer cert not accepted (%d), aborting", rv);
01186 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01187 xio->connectRequest=NULL;
01188 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL_SECURITY);
01189 GWEN_Io_Request_free(r);
01190 if (xio->prepared) {
01191 gnutls_deinit(xio->session);
01192 gnutls_certificate_free_credentials(xio->credentials);
01193 xio->prepared=0;
01194 }
01195 }
01196 else {
01197 DBG_INFO(GWEN_LOGDOMAIN, "SSL connected (secure)");
01198 GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_TLS_FLAGS_SECURE);
01199 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01200 xio->connectRequest=NULL;
01201 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01202 GWEN_Io_Request_free(r);
01203 }
01204 }
01205 }
01206 }
01207 if (xio->disconnectRequest) {
01208 GWEN_IO_REQUEST *r;
01209 int rv;
01210
01211 r=xio->disconnectRequest;
01212 GWEN_Io_LayerCodec_SetCurrentGuiId(io, GWEN_Io_Request_GetGuiId(r));
01213 rv=gnutls_bye(xio->session, GNUTLS_SHUT_RDWR);
01214 if (rv<0) {
01215 if (rv!=GNUTLS_E_AGAIN &&
01216 rv!=GNUTLS_E_INTERRUPTED) {
01217 DBG_ERROR(GWEN_LOGDOMAIN, "gnutls_bye: %d (%s)", rv, gnutls_strerror(rv));
01218 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01219 xio->disconnectRequest=NULL;
01220 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_SSL);
01221 GWEN_Io_Request_free(r);
01222 GWEN_Io_LayerCodec_Reset(io);
01223 if (xio->prepared) {
01224 gnutls_deinit(xio->session);
01225 gnutls_certificate_free_credentials(xio->credentials);
01226 xio->prepared=0;
01227 }
01228 doneSomething=1;
01229 }
01230 }
01231 else {
01232 DBG_INFO(GWEN_LOGDOMAIN, "SSL disconnected");
01233 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01234 xio->disconnectRequest=NULL;
01235 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01236 GWEN_Io_Request_free(r);
01237 GWEN_Io_LayerCodec_Reset(io);
01238 if (xio->prepared) {
01239 gnutls_deinit(xio->session);
01240 gnutls_certificate_free_credentials(xio->credentials);
01241 xio->prepared=0;
01242 }
01243 doneSomething=1;
01244 }
01245 }
01246
01247 if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01248 GWEN_IO_LAYER *newIo;
01249
01250 newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01251 if (newIo) {
01252 GWEN_IO_LAYER *newNewIo;
01253 uint32_t fl;
01254
01255 fl=GWEN_Io_Layer_GetFlags(io);
01256 newNewIo=GWEN_Io_LayerTls_new(newIo);
01257 GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01258 GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01259 if (xio->localCertFile)
01260 GWEN_Io_LayerTls_SetLocalCertFile(newNewIo, xio->localCertFile);
01261 if (xio->localKeyFile)
01262 GWEN_Io_LayerTls_SetLocalKeyFile(newNewIo, xio->localKeyFile);
01263 if (xio->localTrustFile)
01264 GWEN_Io_LayerTls_SetLocalTrustFile(newNewIo, xio->localTrustFile);
01265 if (xio->dhParamFile)
01266 GWEN_Io_LayerTls_SetDhParamFile(newNewIo, xio->dhParamFile);
01267
01268 if ((fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_NAME) ||
01269 (fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_IP)) {
01270 GWEN_IO_LAYER *sp;
01271
01272
01273 sp=GWEN_Io_Layer_FindBaseLayerByType(newIo, GWEN_IO_LAYER_SOCKET_TYPE);
01274 if (sp) {
01275 GWEN_INETADDRESS *addr;
01276
01277 addr=GWEN_Io_LayerSocket_GetPeerAddr(sp);
01278 if (addr) {
01279 char addrBuffer[128];
01280
01281 if (fl & GWEN_IO_LAYER_TLS_FLAGS_SET_PASSV_HOST_NAME)
01282 GWEN_InetAddr_GetName(addr, addrBuffer, sizeof(addrBuffer)-1);
01283 else
01284 GWEN_InetAddr_GetAddress(addr, addrBuffer, sizeof(addrBuffer)-1);
01285 addrBuffer[sizeof(addrBuffer)-1]=0;
01286 if (*addrBuffer) {
01287 DBG_INFO(GWEN_LOGDOMAIN, "Setting remote addr to [%s]", addrBuffer);
01288 GWEN_Io_LayerTls_SetRemoteHostName(newNewIo, addrBuffer);
01289 }
01290 }
01291 }
01292 }
01293
01294 GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01295 doneSomething=1;
01296 }
01297 }
01298
01299 if (xio->workOnRequestsFn &&
01300 xio->workOnRequestsFn(io)!=GWEN_Io_Layer_WorkResultBlocking) {
01301 doneSomething=1;
01302 }
01303
01304 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01305 }
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323