diff options
| author | Simeon Simeonov | 2018-02-27 21:52:12 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2018-02-27 21:52:12 +0100 |
| commit | 1bb2a9d33e8cd193c21f9995fb7852c7562cafcf (patch) | |
| tree | bf54cba95a7b7afa68b33f8cb40b53d351b880ff | |
| parent | 3f7a3add4dc0814e01c3032d73a4cdd29372f8d4 (diff) | |
First prototype
| -rw-r--r-- | libsylph/account.c | 7 | ||||
| -rw-r--r-- | libsylph/defs.h | 3 | ||||
| -rw-r--r-- | libsylph/imap.c | 12 | ||||
| -rw-r--r-- | libsylph/prefs_account.c | 1 | ||||
| -rw-r--r-- | libsylph/prefs_account.h | 2 | ||||
| -rw-r--r-- | libsylph/ssl.c | 377 | ||||
| -rw-r--r-- | libsylph/ssl.h | 20 | ||||
| -rw-r--r-- | src/send_message.c | 20 |
8 files changed, 436 insertions, 6 deletions
diff --git a/libsylph/account.c b/libsylph/account.c index 2431bf3..de0d6f0 100644 --- a/libsylph/account.c +++ b/libsylph/account.c | |||
| @@ -51,6 +51,10 @@ void account_read_config_all(void) | |||
| 51 | FILE *fp; | 51 | FILE *fp; |
| 52 | gchar buf[PREFSBUFSIZE]; | 52 | gchar buf[PREFSBUFSIZE]; |
| 53 | PrefsAccount *ac_prefs; | 53 | PrefsAccount *ac_prefs; |
| 54 | #if USE_SSL | ||
| 55 | gchar *master_password; | ||
| 56 | master_password = input_query_password("Sylpheed", "Master password"); | ||
| 57 | #endif | ||
| 54 | 58 | ||
| 55 | debug_print(_("Reading all config for each account...\n")); | 59 | debug_print(_("Reading all config for each account...\n")); |
| 56 | 60 | ||
| @@ -79,6 +83,9 @@ void account_read_config_all(void) | |||
| 79 | for (cur = ac_label_list; cur != NULL; cur = cur->next) { | 83 | for (cur = ac_label_list; cur != NULL; cur = cur->next) { |
| 80 | ac_prefs = prefs_account_new(); | 84 | ac_prefs = prefs_account_new(); |
| 81 | prefs_account_read_config(ac_prefs, (gchar *)cur->data); | 85 | prefs_account_read_config(ac_prefs, (gchar *)cur->data); |
| 86 | #if USE_SSL | ||
| 87 | ac_prefs->master_password = master_password; | ||
| 88 | #endif | ||
| 82 | account_list = g_list_append(account_list, ac_prefs); | 89 | account_list = g_list_append(account_list, ac_prefs); |
| 83 | if (ac_prefs->is_default) | 90 | if (ac_prefs->is_default) |
| 84 | cur_account = ac_prefs; | 91 | cur_account = ac_prefs; |
diff --git a/libsylph/defs.h b/libsylph/defs.h index 9e3f82b..67325bf 100644 --- a/libsylph/defs.h +++ b/libsylph/defs.h | |||
| @@ -58,6 +58,9 @@ | |||
| 58 | #define DISPLAY_HEADER_RC "dispheaderrc" | 58 | #define DISPLAY_HEADER_RC "dispheaderrc" |
| 59 | #define MENU_RC "menurc" | 59 | #define MENU_RC "menurc" |
| 60 | #define ACTIONS_RC "actionsrc" | 60 | #define ACTIONS_RC "actionsrc" |
| 61 | #ifdef USE_SSL | ||
| 62 | #define SECURE_RC "securerc" | ||
| 63 | #endif | ||
| 61 | #define COMMAND_HISTORY "command_history" | 64 | #define COMMAND_HISTORY "command_history" |
| 62 | #define TEMPLATE_DIR "templates" | 65 | #define TEMPLATE_DIR "templates" |
| 63 | #define TMP_DIR "tmp" | 66 | #define TMP_DIR "tmp" |
diff --git a/libsylph/imap.c b/libsylph/imap.c index aa0d737..a61dc2b 100644 --- a/libsylph/imap.c +++ b/libsylph/imap.c | |||
| @@ -707,7 +707,17 @@ static gint imap_session_connect(IMAPSession *session) | |||
| 707 | log_message(_("creating IMAP4 connection to %s:%d ...\n"), | 707 | log_message(_("creating IMAP4 connection to %s:%d ...\n"), |
| 708 | SESSION(session)->server, SESSION(session)->port); | 708 | SESSION(session)->server, SESSION(session)->port); |
| 709 | 709 | ||
| 710 | pass = account->passwd; | 710 | if (account->master_password != NULL) { |
| 711 | if (decrypt_data(&pass, | ||
| 712 | account->passwd, | ||
| 713 | account->master_password, | ||
| 714 | strlen(account->passwd)) != RC_OK) { | ||
| 715 | session_destroy(session); | ||
| 716 | return -1; | ||
| 717 | } | ||
| 718 | } else { | ||
| 719 | pass = account->passwd; | ||
| 720 | } | ||
| 711 | if (!pass) | 721 | if (!pass) |
| 712 | pass = account->tmp_pass; | 722 | pass = account->tmp_pass; |
| 713 | if (!pass) { | 723 | if (!pass) { |
diff --git a/libsylph/prefs_account.c b/libsylph/prefs_account.c index 1aecba9..a16ba3d 100644 --- a/libsylph/prefs_account.c +++ b/libsylph/prefs_account.c | |||
| @@ -218,6 +218,7 @@ void prefs_account_read_config(PrefsAccount *ac_prefs, const gchar *label) | |||
| 218 | g_free(rcpath); | 218 | g_free(rcpath); |
| 219 | 219 | ||
| 220 | *ac_prefs = tmp_ac_prefs; | 220 | *ac_prefs = tmp_ac_prefs; |
| 221 | ac_prefs->master_password = NULL; | ||
| 221 | while (*p && !g_ascii_isdigit(*p)) p++; | 222 | while (*p && !g_ascii_isdigit(*p)) p++; |
| 222 | id = atoi(p); | 223 | id = atoi(p); |
| 223 | if (id < 0) g_warning("wrong account id: %d\n", id); | 224 | if (id < 0) g_warning("wrong account id: %d\n", id); |
diff --git a/libsylph/prefs_account.h b/libsylph/prefs_account.h index ad899f8..5239034 100644 --- a/libsylph/prefs_account.h +++ b/libsylph/prefs_account.h | |||
| @@ -187,6 +187,8 @@ struct _PrefsAccount | |||
| 187 | /* Compose */ | 187 | /* Compose */ |
| 188 | gchar *sig_names[10]; | 188 | gchar *sig_names[10]; |
| 189 | gchar *sig_texts[10]; | 189 | gchar *sig_texts[10]; |
| 190 | |||
| 191 | gchar *master_password; | ||
| 190 | }; | 192 | }; |
| 191 | 193 | ||
| 192 | PrefsAccount *prefs_account_new (void); | 194 | PrefsAccount *prefs_account_new (void); |
diff --git a/libsylph/ssl.c b/libsylph/ssl.c index 8413925..5a76b8b 100644 --- a/libsylph/ssl.c +++ b/libsylph/ssl.c | |||
| @@ -32,6 +32,11 @@ | |||
| 32 | #include "ssl.h" | 32 | #include "ssl.h" |
| 33 | #include "ssl_hostname_validation.h" | 33 | #include "ssl_hostname_validation.h" |
| 34 | 34 | ||
| 35 | #define SALT_SIZE 16 | ||
| 36 | #define CIPHER EVP_aes_256_cfb() | ||
| 37 | #define KEY_HASH EVP_sha256() | ||
| 38 | #define DIGEST_HASH EVP_sha256() | ||
| 39 | |||
| 35 | static SSL_CTX *ssl_ctx_SSLv23 = NULL; | 40 | static SSL_CTX *ssl_ctx_SSLv23 = NULL; |
| 36 | static SSL_CTX *ssl_ctx_TLSv1 = NULL; | 41 | static SSL_CTX *ssl_ctx_TLSv1 = NULL; |
| 37 | 42 | ||
| @@ -402,4 +407,376 @@ void ssl_set_verify_func(SSLVerifyFunc func) | |||
| 402 | verify_ui_func = func; | 407 | verify_ui_func = func; |
| 403 | } | 408 | } |
| 404 | 409 | ||
| 410 | /* master password related functions */ | ||
| 411 | static gint secure_derive_key(guchar *key, | ||
| 412 | gint length_key, | ||
| 413 | const gchar *passphrase, | ||
| 414 | const guchar *salt) { | ||
| 415 | |||
| 416 | guint length_buffer, length_hash; | ||
| 417 | guchar *buffer, *ptr_hash; | ||
| 418 | |||
| 419 | EVP_MD_CTX *mdctx; | ||
| 420 | |||
| 421 | OPENSSL_cleanse(key, length_key); | ||
| 422 | |||
| 423 | length_buffer = SALT_SIZE + strlen(passphrase); | ||
| 424 | buffer = OPENSSL_malloc(length_buffer); | ||
| 425 | OPENSSL_cleanse(buffer, length_buffer); | ||
| 426 | |||
| 427 | memcpy(buffer, salt, SALT_SIZE); | ||
| 428 | memcpy(buffer + SALT_SIZE, passphrase, strlen(passphrase)); | ||
| 429 | |||
| 430 | mdctx = EVP_MD_CTX_create(); | ||
| 431 | EVP_DigestInit_ex(mdctx, KEY_HASH, NULL); | ||
| 432 | EVP_DigestUpdate(mdctx, buffer, length_buffer); | ||
| 433 | OPENSSL_cleanse(buffer, length_buffer); | ||
| 434 | |||
| 435 | ptr_hash = OPENSSL_malloc(EVP_MD_size(KEY_HASH)); | ||
| 436 | EVP_DigestFinal_ex(mdctx, ptr_hash, &length_hash); | ||
| 437 | |||
| 438 | memcpy(key, | ||
| 439 | ptr_hash, | ||
| 440 | (length_hash > length_key) ? length_key : length_hash); | ||
| 441 | |||
| 442 | OPENSSL_cleanse(ptr_hash, length_hash); | ||
| 443 | OPENSSL_free(ptr_hash); | ||
| 444 | OPENSSL_free(buffer); | ||
| 445 | EVP_MD_CTX_destroy(mdctx); | ||
| 446 | |||
| 447 | return RC_OK; | ||
| 448 | |||
| 449 | } | ||
| 450 | |||
| 451 | |||
| 452 | gint encrypt_data(gchar **encrypted, | ||
| 453 | gint *length_encrypted, | ||
| 454 | const gchar *data, | ||
| 455 | const gchar *passphrase, | ||
| 456 | gint length_data, | ||
| 457 | guint min_data_length, | ||
| 458 | gboolean rnd_salt) { | ||
| 459 | |||
| 460 | gint crypt_buffer_cnt, rc; | ||
| 461 | guint key_size, length_hash; | ||
| 462 | guint length_cleartext, length_ciphertext, length_total; | ||
| 463 | guchar salt[SALT_SIZE]; | ||
| 464 | guchar *ciphertext_buffer, *total_buffer; | ||
| 465 | /* sensitive buffers and counters */ | ||
| 466 | guint length_data_payload, length_padding; | ||
| 467 | gchar str_data_size[3]; | ||
| 468 | guchar *data_payload_buffer, *hash_buffer, *padding_buffer, *key; | ||
| 469 | guchar *cleartext_buffer; | ||
| 470 | |||
| 471 | EVP_CIPHER_CTX *ctx; | ||
| 472 | EVP_MD_CTX *mdctx; | ||
| 473 | |||
| 474 | rc = RC_ERROR; | ||
| 475 | |||
| 476 | if (length_data < 1) { | ||
| 477 | return -1; | ||
| 478 | } | ||
| 479 | if (rnd_salt) { | ||
| 480 | if (RAND_bytes(salt, SALT_SIZE) != 1) { | ||
| 481 | debug_print("Random problems...\n"); | ||
| 482 | goto cleanup; | ||
| 483 | } | ||
| 484 | } else { | ||
| 485 | strncpy((gchar *)salt, "FOR TESTING ONLY", SALT_SIZE); | ||
| 486 | } | ||
| 487 | |||
| 488 | key_size = EVP_CIPHER_key_length(CIPHER); | ||
| 489 | key = OPENSSL_malloc(key_size); | ||
| 490 | OPENSSL_cleanse(key, key_size); | ||
| 491 | if (secure_derive_key(key, | ||
| 492 | key_size, | ||
| 493 | passphrase, | ||
| 494 | salt) != RC_OK) { | ||
| 495 | OPENSSL_cleanse(key, key_size); | ||
| 496 | debug_print("Could not generate secure key\n"); | ||
| 497 | goto cleanup; | ||
| 498 | } | ||
| 499 | |||
| 500 | /* prepare the data-buffer */ | ||
| 501 | length_padding = 0; | ||
| 502 | if (length_data < min_data_length) { | ||
| 503 | g_snprintf(str_data_size, 3, "%02d", length_data); | ||
| 504 | length_padding = min_data_length - length_data; | ||
| 505 | padding_buffer = OPENSSL_malloc(length_padding); | ||
| 506 | OPENSSL_cleanse(padding_buffer, length_padding); | ||
| 507 | if (RAND_bytes(padding_buffer, length_padding) != 1) { | ||
| 508 | debug_print("Random problems...\n"); | ||
| 509 | goto cleanup; | ||
| 510 | } | ||
| 511 | } else { | ||
| 512 | g_snprintf(str_data_size, 3, "-1"); | ||
| 513 | } | ||
| 514 | |||
| 515 | length_data_payload = 2 + length_data + length_padding; | ||
| 516 | data_payload_buffer = OPENSSL_malloc(length_data_payload); | ||
| 517 | OPENSSL_cleanse(data_payload_buffer, length_data_payload); | ||
| 518 | |||
| 519 | memcpy(data_payload_buffer, str_data_size, 2); | ||
| 520 | memcpy(data_payload_buffer + 2, data, length_data); | ||
| 521 | if (length_padding > 0) { | ||
| 522 | memcpy(data_payload_buffer + (2 + length_data), | ||
| 523 | padding_buffer, | ||
| 524 | length_padding); | ||
| 525 | } | ||
| 526 | |||
| 527 | mdctx = EVP_MD_CTX_create(); | ||
| 528 | EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL); | ||
| 529 | EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload); | ||
| 530 | |||
| 531 | length_hash = EVP_MD_size(DIGEST_HASH); | ||
| 532 | hash_buffer = OPENSSL_malloc(length_hash); | ||
| 533 | OPENSSL_cleanse(hash_buffer, length_hash); | ||
| 534 | EVP_DigestFinal_ex(mdctx, hash_buffer, NULL); | ||
| 535 | |||
| 536 | length_cleartext = length_hash + length_data_payload; | ||
| 537 | |||
| 538 | cleartext_buffer = OPENSSL_malloc(length_cleartext); | ||
| 539 | OPENSSL_cleanse(cleartext_buffer, length_cleartext); | ||
| 540 | |||
| 541 | /* assemble cleartext-buffer */ | ||
| 542 | memcpy(cleartext_buffer, hash_buffer, length_hash); | ||
| 543 | memcpy(cleartext_buffer + length_hash, | ||
| 544 | data_payload_buffer, | ||
| 545 | length_data_payload); | ||
| 546 | OPENSSL_cleanse(data_payload_buffer, length_data_payload); /* sensitive */ | ||
| 547 | |||
| 548 | /* encryption */ | ||
| 549 | if (!(ctx = EVP_CIPHER_CTX_new())) { | ||
| 550 | debug_print("New ctx failed\n"); | ||
| 551 | goto cleanup; | ||
| 552 | } | ||
| 553 | |||
| 554 | length_ciphertext = 0; | ||
| 555 | if (EVP_EncryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) { | ||
| 556 | debug_print("EVP_EncryptInit_ex failed\n"); | ||
| 557 | goto cleanup; | ||
| 558 | } | ||
| 559 | |||
| 560 | ciphertext_buffer = OPENSSL_malloc(length_cleartext); | ||
| 561 | |||
| 562 | crypt_buffer_cnt = 0; | ||
| 563 | while(1) { | ||
| 564 | if (EVP_EncryptUpdate(ctx, | ||
| 565 | ciphertext_buffer + length_ciphertext, | ||
| 566 | &crypt_buffer_cnt, | ||
| 567 | cleartext_buffer + length_ciphertext, | ||
| 568 | 1) != 1) { /* one byte at a time */ | ||
| 569 | debug_print("EVP_EncryptUpdate failed\n"); | ||
| 570 | goto cleanup; | ||
| 571 | } | ||
| 572 | |||
| 573 | if (crypt_buffer_cnt != 1) { /* paranoia */ | ||
| 574 | debug_print("The sizes of enc and dec text do not correspond\n"); | ||
| 575 | goto cleanup; | ||
| 576 | } | ||
| 577 | |||
| 578 | ++length_ciphertext; | ||
| 579 | |||
| 580 | if (length_ciphertext >= length_cleartext) { | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | /* No padding required for the CFB mode */ | ||
| 585 | |||
| 586 | OPENSSL_cleanse(cleartext_buffer, length_cleartext); /* sensitive */ | ||
| 587 | length_total = SALT_SIZE + length_ciphertext; | ||
| 588 | total_buffer = OPENSSL_malloc(length_total); | ||
| 589 | |||
| 590 | memcpy(total_buffer, salt, SALT_SIZE); | ||
| 591 | memcpy(total_buffer + SALT_SIZE, ciphertext_buffer, length_ciphertext); | ||
| 592 | |||
| 593 | *encrypted = g_base64_encode(total_buffer, length_total); | ||
| 594 | *length_encrypted = strlen(*encrypted); | ||
| 595 | |||
| 596 | rc = RC_OK; | ||
| 597 | |||
| 598 | cleanup: | ||
| 599 | /* key */ | ||
| 600 | OPENSSL_cleanse(key, key_size); | ||
| 601 | OPENSSL_free(key); | ||
| 602 | /* cleartext buffer */ | ||
| 603 | OPENSSL_cleanse(cleartext_buffer, length_cleartext); | ||
| 604 | OPENSSL_free(cleartext_buffer); | ||
| 605 | /* payload buffer */ | ||
| 606 | OPENSSL_cleanse(data_payload_buffer, length_data_payload); | ||
| 607 | OPENSSL_free(data_payload_buffer); | ||
| 608 | /* hash */ | ||
| 609 | OPENSSL_cleanse(hash_buffer, length_hash); | ||
| 610 | OPENSSL_free(hash_buffer); | ||
| 611 | /* padding */ | ||
| 612 | if (length_padding > 0) { | ||
| 613 | OPENSSL_cleanse(padding_buffer, length_padding); | ||
| 614 | OPENSSL_free(padding_buffer); | ||
| 615 | } | ||
| 616 | |||
| 617 | OPENSSL_cleanse(str_data_size, 3); /* paranoia */ | ||
| 618 | |||
| 619 | /* ciphertext buffer */ | ||
| 620 | OPENSSL_free(ciphertext_buffer); | ||
| 621 | |||
| 622 | /* total buffer */ | ||
| 623 | OPENSSL_free(total_buffer); | ||
| 624 | |||
| 625 | length_data_payload = 0; | ||
| 626 | length_padding = 0; | ||
| 627 | |||
| 628 | EVP_CIPHER_CTX_free(ctx); | ||
| 629 | EVP_MD_CTX_destroy(mdctx); | ||
| 630 | |||
| 631 | return rc; | ||
| 632 | |||
| 633 | } | ||
| 634 | |||
| 635 | |||
| 636 | gint decrypt_data(gchar **decrypted, | ||
| 637 | const gchar *data, | ||
| 638 | const gchar *passphrase, | ||
| 639 | gint length_data) { | ||
| 640 | |||
| 641 | gint rc; /* return code */ | ||
| 642 | gint decrypt_buffer_cnt, length_ciphertext, length_decrypted; | ||
| 643 | guint key_size, length_hash, length_cleartext; | ||
| 644 | gsize length_total; | ||
| 645 | guchar salt[SALT_SIZE]; | ||
| 646 | guchar *ciphertext_buffer, *total_buffer; | ||
| 647 | /* sensitive buffers and counters */ | ||
| 648 | gint data_size; | ||
| 649 | guint length_data_payload; | ||
| 650 | gchar str_data_size[3]; | ||
| 651 | guchar *data_payload_buffer, *hash_buffer, *key; | ||
| 652 | guchar *cleartext_buffer; | ||
| 653 | |||
| 654 | EVP_CIPHER_CTX *ctx; | ||
| 655 | EVP_MD_CTX *mdctx; | ||
| 656 | |||
| 657 | rc = -1; | ||
| 658 | |||
| 659 | if (length_data < 1) { | ||
| 660 | return -1; | ||
| 661 | } | ||
| 662 | |||
| 663 | total_buffer = g_base64_decode(data, &length_total); | ||
| 664 | length_ciphertext = length_total - SALT_SIZE; | ||
| 665 | ciphertext_buffer = OPENSSL_malloc(length_ciphertext); | ||
| 666 | OPENSSL_cleanse(ciphertext_buffer, length_ciphertext); | ||
| 667 | |||
| 668 | memcpy(salt, total_buffer, SALT_SIZE); | ||
| 669 | memcpy(ciphertext_buffer, total_buffer + SALT_SIZE, length_ciphertext); | ||
| 670 | |||
| 671 | key_size = EVP_CIPHER_key_length(CIPHER); | ||
| 672 | |||
| 673 | /* decryption */ | ||
| 674 | if(!(ctx = EVP_CIPHER_CTX_new())) { | ||
| 675 | debug_print("New ctx failed\n"); | ||
| 676 | goto cleanup; | ||
| 677 | } | ||
| 678 | |||
| 679 | key = OPENSSL_malloc(key_size); | ||
| 680 | OPENSSL_cleanse(key, key_size); | ||
| 681 | if (secure_derive_key(key, | ||
| 682 | key_size, | ||
| 683 | passphrase, | ||
| 684 | salt) != 0) { | ||
| 685 | OPENSSL_cleanse(key, key_size); | ||
| 686 | debug_print("Could not generate secure key\n"); | ||
| 687 | goto cleanup; | ||
| 688 | } | ||
| 689 | |||
| 690 | if (EVP_DecryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) { | ||
| 691 | debug_print("EVP_DecryptInit_ex failed\n"); | ||
| 692 | goto cleanup; | ||
| 693 | } | ||
| 694 | OPENSSL_cleanse(key, key_size); /* highly sensitive */ | ||
| 695 | cleartext_buffer = OPENSSL_malloc(length_ciphertext); | ||
| 696 | OPENSSL_cleanse(cleartext_buffer, length_ciphertext); | ||
| 697 | |||
| 698 | length_cleartext = 0; | ||
| 699 | decrypt_buffer_cnt = 0; | ||
| 700 | |||
| 701 | while(1) { | ||
| 702 | if (EVP_DecryptUpdate(ctx, | ||
| 703 | cleartext_buffer + length_cleartext, | ||
| 704 | &decrypt_buffer_cnt, | ||
| 705 | ciphertext_buffer + length_cleartext, | ||
| 706 | 1) != 1) { /* one byte at a time */ | ||
| 707 | debug_print("EVP_EncryptUpdate failed\n"); | ||
| 708 | goto cleanup; | ||
| 709 | } | ||
| 710 | |||
| 711 | if (decrypt_buffer_cnt != 1) { /* paranoia */ | ||
| 712 | debug_print("The sizes of enc and dec text do not correspond"); | ||
| 713 | goto cleanup; | ||
| 714 | } | ||
| 715 | |||
| 716 | ++length_cleartext; | ||
| 717 | |||
| 718 | if (length_cleartext >= length_ciphertext) { | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | |||
| 724 | length_hash = EVP_MD_size(DIGEST_HASH); | ||
| 725 | hash_buffer = OPENSSL_malloc(length_hash); | ||
| 726 | length_data_payload = length_cleartext - length_hash; | ||
| 727 | data_payload_buffer = OPENSSL_malloc(length_data_payload); | ||
| 728 | OPENSSL_cleanse(data_payload_buffer, length_data_payload); | ||
| 729 | |||
| 730 | memcpy(data_payload_buffer, | ||
| 731 | cleartext_buffer + length_hash, | ||
| 732 | length_data_payload); | ||
| 733 | |||
| 734 | mdctx = EVP_MD_CTX_create(); | ||
| 735 | EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL); | ||
| 736 | EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload); | ||
| 737 | EVP_DigestFinal_ex(mdctx, hash_buffer, &length_hash); | ||
| 738 | |||
| 739 | if (strncmp((const gchar*) hash_buffer, | ||
| 740 | (const gchar*) cleartext_buffer, | ||
| 741 | length_hash) != 0) { | ||
| 742 | debug_print("Invalid hash\n"); | ||
| 743 | rc = RC_WRONG_HASH_OR_KEY; | ||
| 744 | goto cleanup; | ||
| 745 | } | ||
| 746 | |||
| 747 | memcpy(str_data_size, cleartext_buffer + length_hash, 2); | ||
| 748 | data_size = atoi(str_data_size); | ||
| 749 | |||
| 750 | if (data_size < 0) { | ||
| 751 | length_decrypted = length_data_payload - 2; | ||
| 752 | } else { | ||
| 753 | length_decrypted = data_size; | ||
| 754 | } | ||
| 755 | *decrypted = OPENSSL_malloc(length_decrypted); | ||
| 756 | memcpy(*decrypted, data_payload_buffer + 2, length_decrypted); | ||
| 757 | |||
| 758 | rc = RC_OK; | ||
| 759 | |||
| 760 | cleanup: | ||
| 761 | |||
| 762 | /* key */ | ||
| 763 | OPENSSL_cleanse(key, key_size); | ||
| 764 | OPENSSL_free(key); | ||
| 765 | /* payload buffer */ | ||
| 766 | OPENSSL_cleanse(data_payload_buffer, length_data_payload); | ||
| 767 | OPENSSL_free(data_payload_buffer); | ||
| 768 | /* hash */ | ||
| 769 | OPENSSL_cleanse(hash_buffer, length_hash); | ||
| 770 | OPENSSL_free(hash_buffer); | ||
| 771 | /* ciphertext */ | ||
| 772 | OPENSSL_free(ciphertext_buffer); | ||
| 773 | OPENSSL_free(total_buffer); | ||
| 774 | |||
| 775 | EVP_CIPHER_CTX_free(ctx); | ||
| 776 | EVP_MD_CTX_destroy(mdctx); | ||
| 777 | |||
| 778 | return rc; | ||
| 779 | |||
| 780 | } | ||
| 781 | |||
| 405 | #endif /* USE_SSL */ | 782 | #endif /* USE_SSL */ |
diff --git a/libsylph/ssl.h b/libsylph/ssl.h index a9f690d..94ab4b7 100644 --- a/libsylph/ssl.h +++ b/libsylph/ssl.h | |||
| @@ -32,9 +32,15 @@ | |||
| 32 | #include <openssl/pem.h> | 32 | #include <openssl/pem.h> |
| 33 | #include <openssl/ssl.h> | 33 | #include <openssl/ssl.h> |
| 34 | #include <openssl/err.h> | 34 | #include <openssl/err.h> |
| 35 | #include <openssl/evp.h> | ||
| 36 | #include <openssl/rand.h> | ||
| 35 | 37 | ||
| 36 | #include "socket.h" | 38 | #include "socket.h" |
| 37 | 39 | ||
| 40 | #define RC_OK 0 | ||
| 41 | #define RC_ERROR -1 | ||
| 42 | #define RC_WRONG_HASH_OR_KEY 1 | ||
| 43 | |||
| 38 | typedef enum { | 44 | typedef enum { |
| 39 | SSL_METHOD_SSLv23, | 45 | SSL_METHOD_SSLv23, |
| 40 | SSL_METHOD_TLSv1 | 46 | SSL_METHOD_TLSv1 |
| @@ -60,6 +66,20 @@ void ssl_done_socket (SockInfo *sockinfo); | |||
| 60 | 66 | ||
| 61 | void ssl_set_verify_func (SSLVerifyFunc func); | 67 | void ssl_set_verify_func (SSLVerifyFunc func); |
| 62 | 68 | ||
| 69 | /* master password related code */ | ||
| 70 | gint encrypt_data(gchar **encrypted, | ||
| 71 | gint *length_encrypted, | ||
| 72 | const gchar *data, | ||
| 73 | const gchar *passphrase, | ||
| 74 | gint length_data, | ||
| 75 | guint min_data_length, | ||
| 76 | gboolean rnd_salt); | ||
| 77 | |||
| 78 | gint decrypt_data(gchar **decrypted, | ||
| 79 | const gchar *data, | ||
| 80 | const gchar *passphrase, | ||
| 81 | gint length_data); | ||
| 82 | /* ---------------------------- */ | ||
| 63 | #endif /* USE_SSL */ | 83 | #endif /* USE_SSL */ |
| 64 | 84 | ||
| 65 | #endif /* __SSL_H__ */ | 85 | #endif /* __SSL_H__ */ |
diff --git a/src/send_message.c b/src/send_message.c index a8c2c7a..695246a 100644 --- a/src/send_message.c +++ b/src/send_message.c | |||
| @@ -648,13 +648,23 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp) | |||
| 648 | 648 | ||
| 649 | if (ac_prefs->smtp_userid) { | 649 | if (ac_prefs->smtp_userid) { |
| 650 | smtp_session->user = g_strdup(ac_prefs->smtp_userid); | 650 | smtp_session->user = g_strdup(ac_prefs->smtp_userid); |
| 651 | if (ac_prefs->smtp_passwd) | 651 | if (ac_prefs->smtp_passwd) { |
| 652 | smtp_session->pass = | 652 | if(ac_prefs->master_password != NULL) { |
| 653 | g_strdup(ac_prefs->smtp_passwd); | 653 | if (decrypt_data(&(smtp_session->pass), |
| 654 | else if (ac_prefs->tmp_smtp_pass) | 654 | ac_prefs->smtp_passwd, |
| 655 | ac_prefs->master_password, | ||
| 656 | strlen(ac_prefs->smtp_passwd)) != RC_OK) { | ||
| 657 | session_destroy(session); | ||
| 658 | return -1; | ||
| 659 | } | ||
| 660 | } else { | ||
| 661 | smtp_session->pass = | ||
| 662 | g_strdup(ac_prefs->smtp_passwd); | ||
| 663 | } | ||
| 664 | } else if (ac_prefs->tmp_smtp_pass) { | ||
| 655 | smtp_session->pass = | 665 | smtp_session->pass = |
| 656 | g_strdup(ac_prefs->tmp_smtp_pass); | 666 | g_strdup(ac_prefs->tmp_smtp_pass); |
| 657 | else { | 667 | } else { |
| 658 | smtp_session->pass = | 668 | smtp_session->pass = |
| 659 | input_query_password | 669 | input_query_password |
| 660 | (ac_prefs->smtp_server, | 670 | (ac_prefs->smtp_server, |
