Changeset 542:0b6cee362f5d in freeDiameter for freeDiameter/config.c
- Timestamp:
- Sep 13, 2010, 6:39:22 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/config.c
r447 r542 269 269 } 270 270 271 272 /* Verify that our certificate is valid -- otherwise remote peers will reject it */ 273 { 274 int ret = 0, i; 275 276 gnutls_datum_t certfile; 277 size_t alloc = 0; 278 279 gnutls_x509_crt_t * certs = NULL; 280 unsigned int cert_max = 0; 281 282 gnutls_x509_crt_t * CA_list; 283 int CA_list_length; 284 285 gnutls_x509_crl_t * CRL_list; 286 int CRL_list_length; 287 288 unsigned int verify; 289 time_t now; 290 291 memset(&certfile, 0, sizeof(certfile)); 292 293 /* Read the certificate file */ 294 FILE *stream = fopen (fd_g_config->cnf_sec_data.cert_file, "rb"); 295 if (!stream) { 296 int err = errno; 297 TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err)); 298 return err; 299 } 300 do { 301 uint8_t * realloced = NULL; 302 size_t read = 0; 303 304 if (alloc < certfile.size + BUFSIZ + 1) { 305 alloc += alloc / 2 + BUFSIZ + 1; 306 CHECK_MALLOC_DO( realloced = realloc(certfile.data, alloc), 307 { 308 free(certfile.data); 309 return ENOMEM; 310 } ) 311 certfile.data = realloced; 312 } 313 314 read = fread( certfile.data + certfile.size, 1, alloc - certfile.size - 1, stream ); 315 certfile.size += read; 316 317 if (ferror(stream)) { 318 int err = errno; 319 TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s\n", fd_g_config->cnf_sec_data.cert_file, strerror(err)); 320 return err; 321 } 322 } while (!feof(stream)); 323 certfile.data[certfile.size] = '\0'; 324 fclose(stream); 325 326 /* Import the certificate(s) */ 327 GNUTLS_TRACE( ret = gnutls_x509_crt_list_import(NULL, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) ); 328 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { 329 CHECK_GNUTLS_DO(ret, return EINVAL); 330 } 331 332 CHECK_MALLOC( certs = calloc(cert_max, sizeof(gnutls_x509_crt_t)) ); 333 CHECK_GNUTLS_DO( gnutls_x509_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM, 0), 334 { 335 TRACE_DEBUG(INFO, "Failed to import the data from file '%s'", fd_g_config->cnf_sec_data.cert_file); 336 free(certfile.data); 337 return EINVAL; 338 } ); 339 free(certfile.data); 340 341 ASSERT(cert_max >= 1); 342 343 /* Now, verify the list against the local CA and CRL */ 344 GNUTLS_TRACE( gnutls_certificate_get_x509_cas (fd_g_config->cnf_sec_data.credentials, &CA_list, (unsigned int *) &CA_list_length) ); 345 GNUTLS_TRACE( gnutls_certificate_get_x509_crls (fd_g_config->cnf_sec_data.credentials, &CRL_list, (unsigned int *) &CRL_list_length) ); 346 CHECK_GNUTLS_DO( gnutls_x509_crt_list_verify(certs, cert_max, CA_list, CA_list_length, CRL_list, CRL_list_length, 0, &verify), 347 { 348 TRACE_DEBUG(INFO, "Failed to verify the local certificate '%s' against local credentials. Please check your certificate is valid.", fd_g_config->cnf_sec_data.cert_file); 349 return EINVAL; 350 } ); 351 if (verify) { 352 fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file); 353 if (verify & GNUTLS_CERT_INVALID) 354 fd_log_debug(" - The certificate is not trusted (unknown CA? expired?)\n"); 355 if (verify & GNUTLS_CERT_REVOKED) 356 fd_log_debug(" - The certificate has been revoked.\n"); 357 if (verify & GNUTLS_CERT_SIGNER_NOT_FOUND) 358 fd_log_debug(" - The certificate hasn't got a known issuer.\n"); 359 if (verify & GNUTLS_CERT_SIGNER_NOT_CA) 360 fd_log_debug(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints.\n"); 361 if (verify & GNUTLS_CERT_INSECURE_ALGORITHM) 362 fd_log_debug(" - The certificate signature uses a weak algorithm.\n"); 363 return EINVAL; 364 } 365 366 /* Check the local Identity is valid with the certificate */ 367 if (!gnutls_x509_crt_check_hostname (certs[0], fd_g_config->cnf_diamid)) { 368 fd_log_debug("TLS: Local certificate '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file); 369 fd_log_debug(" - The certificate hostname does not match '%s'\n", fd_g_config->cnf_diamid); 370 return EINVAL; 371 } 372 373 /* Check validity of all the certificates in the chain */ 374 now = time(NULL); 375 for (i = 0; i < cert_max; i++) 376 { 377 time_t deadline; 378 379 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(certs[i]) ); 380 if ((deadline != (time_t)-1) && (deadline < now)) { 381 fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file); 382 fd_log_debug(" - The certificate %d in the chain is expired\n", i); 383 return EINVAL; 384 } 385 386 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(certs[i]) ); 387 if ((deadline != (time_t)-1) && (deadline > now)) { 388 fd_log_debug("TLS: Local certificate chain '%s' is invalid :\n", fd_g_config->cnf_sec_data.cert_file); 389 fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i); 390 return EINVAL; 391 } 392 } 393 394 /* Everything checked OK, free the certificate list */ 395 for (i = 0; i < cert_max; i++) 396 { 397 GNUTLS_TRACE( gnutls_x509_crt_deinit (certs[i]) ); 398 } 399 free(certs); 400 } 401 402 403 /* gnutls_certificate_set_verify_limits -- so far the default values are fine... */ 404 271 405 return 0; 272 406 }
Note: See TracChangeset
for help on using the changeset viewer.