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