for bug #235, use strategy to implements the schema0 and schema1.
正在显示
2 个修改的文件
包含
566 行增加
和
243 行删除
| @@ -638,261 +638,273 @@ namespace _srs_internal | @@ -638,261 +638,273 @@ namespace _srs_internal | ||
| 638 | return bytes; | 638 | return bytes; |
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | - c2s2::c2s2() | 641 | + c1s1_strategy::c1s1_strategy() |
| 642 | { | 642 | { |
| 643 | - srs_random_generate(random, 1504); | 643 | + } |
| 644 | 644 | ||
| 645 | - int size = snprintf(random, 1504, "%s", RTMP_SIG_SRS_HANDSHAKE); | ||
| 646 | - srs_assert(++size < 1504); | ||
| 647 | - snprintf(random + 1504 - size, size, "%s", RTMP_SIG_SRS_HANDSHAKE); | 645 | + c1s1_strategy::~c1s1_strategy() |
| 646 | + { | ||
| 647 | + } | ||
| 648 | 648 | ||
| 649 | - srs_random_generate(digest, 32); | 649 | + c1s1_strategy_schema0::c1s1_strategy_schema0() |
| 650 | + { | ||
| 651 | + key.init(); | ||
| 652 | + digest.init(); | ||
| 650 | } | 653 | } |
| 651 | 654 | ||
| 652 | - c2s2::~c2s2() | 655 | + c1s1_strategy_schema0::~c1s1_strategy_schema0() |
| 653 | { | 656 | { |
| 657 | + key.free(); | ||
| 658 | + digest.free(); | ||
| 654 | } | 659 | } |
| 655 | 660 | ||
| 656 | - void c2s2::dump(char* _c2s2) | 661 | + srs_schema_type c1s1_strategy_schema0::schema() |
| 657 | { | 662 | { |
| 658 | - memcpy(_c2s2, random, 1504); | ||
| 659 | - memcpy(_c2s2 + 1504, digest, 32); | 663 | + return srs_schema0; |
| 660 | } | 664 | } |
| 661 | 665 | ||
| 662 | - void c2s2::parse(char* _c2s2) | 666 | + char* c1s1_strategy_schema0::get_digest() |
| 663 | { | 667 | { |
| 664 | - memcpy(random, _c2s2, 1504); | ||
| 665 | - memcpy(digest, _c2s2 + 1504, 32); | 668 | + return digest.digest; |
| 666 | } | 669 | } |
| 667 | 670 | ||
| 668 | - int c2s2::c2_create(c1s1* s1) | 671 | + void c1s1_strategy_schema0::dump(c1s1* owner, char* _c1s1) |
| 672 | + { | ||
| 673 | + srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest); | ||
| 674 | + } | ||
| 675 | + | ||
| 676 | + int c1s1_strategy_schema0::parse(char* _c1s1) | ||
| 669 | { | 677 | { |
| 670 | int ret = ERROR_SUCCESS; | 678 | int ret = ERROR_SUCCESS; |
| 671 | 679 | ||
| 672 | - char temp_key[__SRS_OpensslHashSize]; | ||
| 673 | - if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 62, s1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 674 | - srs_error("create c2 temp key failed. ret=%d", ret); | 680 | + if ((ret = key.parse(_c1s1 + 8)) != ERROR_SUCCESS) { |
| 681 | + srs_error("parse the c1 key failed. ret=%d", ret); | ||
| 675 | return ret; | 682 | return ret; |
| 676 | } | 683 | } |
| 677 | - srs_verbose("generate c2 temp key success."); | ||
| 678 | 684 | ||
| 679 | - char _digest[__SRS_OpensslHashSize]; | ||
| 680 | - if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 681 | - srs_error("create c2 digest failed. ret=%d", ret); | 685 | + if ((ret = digest.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) { |
| 686 | + srs_error("parse the c1 digest failed. ret=%d", ret); | ||
| 682 | return ret; | 687 | return ret; |
| 683 | } | 688 | } |
| 684 | - srs_verbose("generate c2 digest success."); | ||
| 685 | 689 | ||
| 686 | - memcpy(digest, _digest, 32); | 690 | + srs_verbose("parse c1 key-digest success"); |
| 687 | 691 | ||
| 688 | return ret; | 692 | return ret; |
| 689 | } | 693 | } |
| 690 | 694 | ||
| 691 | - int c2s2::c2_validate(c1s1* s1, bool& is_valid) | 695 | + int c1s1_strategy_schema0::c1_create(c1s1* owner) |
| 692 | { | 696 | { |
| 693 | - is_valid = false; | ||
| 694 | int ret = ERROR_SUCCESS; | 697 | int ret = ERROR_SUCCESS; |
| 695 | 698 | ||
| 696 | - char temp_key[__SRS_OpensslHashSize]; | ||
| 697 | - if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 62, s1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 698 | - srs_error("create c2 temp key failed. ret=%d", ret); | ||
| 699 | - return ret; | ||
| 700 | - } | ||
| 701 | - srs_verbose("generate c2 temp key success."); | 699 | + // generate digest |
| 700 | + char* c1_digest = NULL; | ||
| 702 | 701 | ||
| 703 | - char _digest[__SRS_OpensslHashSize]; | ||
| 704 | - if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 705 | - srs_error("create c2 digest failed. ret=%d", ret); | 702 | + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) { |
| 703 | + srs_error("sign c1 error, failed to calc digest. ret=%d", ret); | ||
| 706 | return ret; | 704 | return ret; |
| 707 | } | 705 | } |
| 708 | - srs_verbose("generate c2 digest success."); | ||
| 709 | 706 | ||
| 710 | - is_valid = srs_bytes_equals(digest, _digest, 32); | 707 | + srs_assert(c1_digest != NULL); |
| 708 | + SrsAutoFree(char, c1_digest); | ||
| 709 | + | ||
| 710 | + memcpy(digest.digest, c1_digest, 32); | ||
| 711 | 711 | ||
| 712 | return ret; | 712 | return ret; |
| 713 | } | 713 | } |
| 714 | 714 | ||
| 715 | - int c2s2::s2_create(c1s1* c1) | 715 | + int c1s1_strategy_schema0::c1_validate_digest(c1s1* owner, bool& is_valid) |
| 716 | { | 716 | { |
| 717 | int ret = ERROR_SUCCESS; | 717 | int ret = ERROR_SUCCESS; |
| 718 | 718 | ||
| 719 | - char temp_key[__SRS_OpensslHashSize]; | ||
| 720 | - if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 68, c1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 721 | - srs_error("create s2 temp key failed. ret=%d", ret); | ||
| 722 | - return ret; | ||
| 723 | - } | ||
| 724 | - srs_verbose("generate s2 temp key success."); | 719 | + char* c1_digest = NULL; |
| 725 | 720 | ||
| 726 | - char _digest[__SRS_OpensslHashSize]; | ||
| 727 | - if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 728 | - srs_error("create s2 digest failed. ret=%d", ret); | 721 | + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) { |
| 722 | + srs_error("validate c1 error, failed to calc digest. ret=%d", ret); | ||
| 729 | return ret; | 723 | return ret; |
| 730 | } | 724 | } |
| 731 | - srs_verbose("generate s2 digest success."); | ||
| 732 | 725 | ||
| 733 | - memcpy(digest, _digest, 32); | 726 | + srs_assert(c1_digest != NULL); |
| 727 | + SrsAutoFree(char, c1_digest); | ||
| 728 | + | ||
| 729 | + is_valid = srs_bytes_equals(digest.digest, c1_digest, 32); | ||
| 734 | 730 | ||
| 735 | return ret; | 731 | return ret; |
| 736 | } | 732 | } |
| 737 | 733 | ||
| 738 | - int c2s2::s2_validate(c1s1* c1, bool& is_valid) | 734 | + int c1s1_strategy_schema0::s1_create(c1s1* owner) |
| 739 | { | 735 | { |
| 740 | - is_valid = false; | ||
| 741 | int ret = ERROR_SUCCESS; | 736 | int ret = ERROR_SUCCESS; |
| 742 | 737 | ||
| 743 | - char temp_key[__SRS_OpensslHashSize]; | ||
| 744 | - if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 68, c1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 745 | - srs_error("create s2 temp key failed. ret=%d", ret); | 738 | + SrsDH dh; |
| 739 | + | ||
| 740 | + // ensure generate 128bytes public key. | ||
| 741 | + if ((ret = dh.initialize(true)) != ERROR_SUCCESS) { | ||
| 746 | return ret; | 742 | return ret; |
| 747 | } | 743 | } |
| 748 | - srs_verbose("generate s2 temp key success."); | ||
| 749 | 744 | ||
| 750 | - char _digest[__SRS_OpensslHashSize]; | ||
| 751 | - if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 752 | - srs_error("create s2 digest failed. ret=%d", ret); | 745 | + // directly generate the public key. |
| 746 | + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | ||
| 747 | + int pkey_size = 128; | ||
| 748 | + // TODO: FIXME: use c1 public key to calc the shared key. | ||
| 749 | + if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) { | ||
| 750 | + srs_error("calc s1 key failed. ret=%d", ret); | ||
| 753 | return ret; | 751 | return ret; |
| 754 | } | 752 | } |
| 755 | - srs_verbose("generate s2 digest success."); | ||
| 756 | - | ||
| 757 | - is_valid = srs_bytes_equals(digest, _digest, 32); | 753 | + srs_assert(pkey_size == 128); |
| 754 | + srs_verbose("calc s1 key success."); | ||
| 758 | 755 | ||
| 756 | + char* s1_digest = NULL; | ||
| 757 | + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) { | ||
| 758 | + srs_error("calc s1 digest failed. ret=%d", ret); | ||
| 759 | return ret; | 759 | return ret; |
| 760 | } | 760 | } |
| 761 | + srs_verbose("calc s1 digest success."); | ||
| 761 | 762 | ||
| 762 | - // TODO: FIXME: move to the right position. | ||
| 763 | - c1s1::c1s1() | ||
| 764 | - { | ||
| 765 | - schema = srs_schema_invalid; | ||
| 766 | - } | ||
| 767 | - c1s1::~c1s1() | ||
| 768 | - { | ||
| 769 | - destroy_blocks(); | ||
| 770 | - } | 763 | + srs_assert(s1_digest != NULL); |
| 764 | + SrsAutoFree(char, s1_digest); | ||
| 771 | 765 | ||
| 772 | - char* c1s1::get_digest() | ||
| 773 | - { | ||
| 774 | - srs_assert(schema != srs_schema_invalid); | 766 | + memcpy(digest.digest, s1_digest, 32); |
| 767 | + srs_verbose("copy s1 key success."); | ||
| 775 | 768 | ||
| 776 | - if (schema == srs_schema0) { | ||
| 777 | - return block1.digest.digest; | ||
| 778 | - } else { | ||
| 779 | - return block0.digest.digest; | ||
| 780 | - } | 769 | + return ret; |
| 781 | } | 770 | } |
| 782 | 771 | ||
| 783 | - void c1s1::dump(char* _c1s1) | 772 | + int c1s1_strategy_schema0::s1_validate_digest(c1s1* owner, bool& is_valid) |
| 784 | { | 773 | { |
| 785 | - srs_assert(schema != srs_schema_invalid); | 774 | + int ret = ERROR_SUCCESS; |
| 786 | 775 | ||
| 787 | - if (schema == srs_schema0) { | ||
| 788 | - srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest); | ||
| 789 | - } else { | ||
| 790 | - srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key); | 776 | + char* s1_digest = NULL; |
| 777 | + | ||
| 778 | + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) { | ||
| 779 | + srs_error("validate s1 error, failed to calc digest. ret=%d", ret); | ||
| 780 | + return ret; | ||
| 791 | } | 781 | } |
| 782 | + | ||
| 783 | + srs_assert(s1_digest != NULL); | ||
| 784 | + SrsAutoFree(char, s1_digest); | ||
| 785 | + | ||
| 786 | + is_valid = srs_bytes_equals(digest.digest, s1_digest, 32); | ||
| 787 | + | ||
| 788 | + return ret; | ||
| 792 | } | 789 | } |
| 793 | 790 | ||
| 794 | - int c1s1::parse(char* _c1s1, srs_schema_type _schema) | 791 | + int c1s1_strategy_schema0::calc_c1_digest(c1s1* owner, char*& c1_digest) |
| 795 | { | 792 | { |
| 796 | int ret = ERROR_SUCCESS; | 793 | int ret = ERROR_SUCCESS; |
| 797 | 794 | ||
| 798 | - if (_schema == srs_schema_invalid) { | ||
| 799 | - ret = ERROR_RTMP_CH_SCHEMA; | ||
| 800 | - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); | 795 | + char* c1s1_joined_bytes = NULL; |
| 796 | + | ||
| 797 | + c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest); | ||
| 798 | + | ||
| 799 | + srs_assert(c1s1_joined_bytes != NULL); | ||
| 800 | + SrsAutoFree(char, c1s1_joined_bytes); | ||
| 801 | + | ||
| 802 | + c1_digest = new char[__SRS_OpensslHashSize]; | ||
| 803 | + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) { | ||
| 804 | + srs_freep(c1_digest); | ||
| 805 | + srs_error("calc digest for c1 failed. ret=%d", ret); | ||
| 801 | return ret; | 806 | return ret; |
| 802 | } | 807 | } |
| 808 | + srs_verbose("digest calculated for c1"); | ||
| 803 | 809 | ||
| 804 | - destroy_blocks(); | 810 | + return ret; |
| 811 | + } | ||
| 812 | + | ||
| 813 | + int c1s1_strategy_schema0::calc_s1_digest(c1s1* owner, char*& s1_digest) | ||
| 814 | + { | ||
| 815 | + int ret = ERROR_SUCCESS; | ||
| 805 | 816 | ||
| 817 | + char* c1s1_joined_bytes = NULL; | ||
| 806 | 818 | ||
| 807 | - time = __srs_stream_read_4bytes(_c1s1); | ||
| 808 | - version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version | 819 | + c1s1_joined_bytes = srs_bytes_join_schema0(owner->time, owner->version, &key, &digest); |
| 809 | 820 | ||
| 810 | - if (_schema == srs_schema0) { | ||
| 811 | - if ((ret = block0.key.parse(_c1s1 + 8)) != ERROR_SUCCESS) { | ||
| 812 | - srs_error("parse the c1 key failed. ret=%d", ret); | 821 | + srs_assert(c1s1_joined_bytes != NULL); |
| 822 | + SrsAutoFree(char, c1s1_joined_bytes); | ||
| 823 | + | ||
| 824 | + s1_digest = new char[__SRS_OpensslHashSize]; | ||
| 825 | + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) { | ||
| 826 | + srs_freep(s1_digest); | ||
| 827 | + srs_error("calc digest for s1 failed. ret=%d", ret); | ||
| 813 | return ret; | 828 | return ret; |
| 814 | } | 829 | } |
| 815 | - if ((ret = block1.digest.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) { | ||
| 816 | - srs_error("parse the c1 digest failed. ret=%d", ret); | 830 | + srs_verbose("digest calculated for s1"); |
| 831 | + | ||
| 817 | return ret; | 832 | return ret; |
| 818 | } | 833 | } |
| 819 | - srs_verbose("parse c1 key-digest success"); | ||
| 820 | - } else if (_schema == srs_schema1) { | ||
| 821 | - if ((ret = block0.digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) { | ||
| 822 | - srs_error("parse the c1 key failed. ret=%d", ret); | ||
| 823 | - return ret; | 834 | + |
| 835 | + c1s1_strategy_schema1::c1s1_strategy_schema1() | ||
| 836 | + { | ||
| 837 | + key.init(); | ||
| 838 | + digest.init(); | ||
| 824 | } | 839 | } |
| 825 | - if ((ret = block1.key.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) { | ||
| 826 | - srs_error("parse the c1 digest failed. ret=%d", ret); | ||
| 827 | - return ret; | 840 | + |
| 841 | + c1s1_strategy_schema1::~c1s1_strategy_schema1() | ||
| 842 | + { | ||
| 843 | + key.free(); | ||
| 844 | + digest.free(); | ||
| 828 | } | 845 | } |
| 829 | - srs_verbose("parse c1 digest-key success"); | ||
| 830 | - } else { | ||
| 831 | - ret = ERROR_RTMP_CH_SCHEMA; | ||
| 832 | - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); | ||
| 833 | - return ret; | 846 | + |
| 847 | + srs_schema_type c1s1_strategy_schema1::schema() | ||
| 848 | + { | ||
| 849 | + return srs_schema1; | ||
| 834 | } | 850 | } |
| 835 | 851 | ||
| 836 | - schema = _schema; | 852 | + char* c1s1_strategy_schema1::get_digest() |
| 853 | + { | ||
| 854 | + return digest.digest; | ||
| 855 | + } | ||
| 837 | 856 | ||
| 838 | - return ret; | 857 | + void c1s1_strategy_schema1::dump(c1s1* owner, char* _c1s1) |
| 858 | + { | ||
| 859 | + srs_schema0_copy_to(_c1s1, true, owner->time, owner->version, &key, &digest); | ||
| 839 | } | 860 | } |
| 840 | 861 | ||
| 841 | - int c1s1::c1_create(srs_schema_type _schema) | 862 | + int c1s1_strategy_schema1::parse(char* _c1s1) |
| 842 | { | 863 | { |
| 843 | int ret = ERROR_SUCCESS; | 864 | int ret = ERROR_SUCCESS; |
| 844 | 865 | ||
| 845 | - if (_schema == srs_schema_invalid) { | ||
| 846 | - ret = ERROR_RTMP_CH_SCHEMA; | ||
| 847 | - srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret); | 866 | + if ((ret = digest.parse(_c1s1 + 8)) != ERROR_SUCCESS) { |
| 867 | + srs_error("parse the c1 digest failed. ret=%d", ret); | ||
| 848 | return ret; | 868 | return ret; |
| 849 | } | 869 | } |
| 850 | 870 | ||
| 851 | - destroy_blocks(); | 871 | + if ((ret = key.parse(_c1s1 + 8 + 764)) != ERROR_SUCCESS) { |
| 872 | + srs_error("parse the c1 key failed. ret=%d", ret); | ||
| 873 | + return ret; | ||
| 874 | + } | ||
| 852 | 875 | ||
| 853 | - // client c1 time and version | ||
| 854 | - time = ::time(NULL); | ||
| 855 | - version = 0x80000702; // client c1 version | 876 | + srs_verbose("parse c1 digest-key success"); |
| 856 | 877 | ||
| 857 | - // generate signature by schema | ||
| 858 | - if (_schema == srs_schema0) { | ||
| 859 | - block0.key.init(); | ||
| 860 | - block1.digest.init(); | ||
| 861 | - } else { | ||
| 862 | - block0.digest.init(); | ||
| 863 | - block1.key.init(); | 878 | + return ret; |
| 864 | } | 879 | } |
| 865 | 880 | ||
| 866 | - schema = _schema; | 881 | + int c1s1_strategy_schema1::c1_create(c1s1* owner) |
| 882 | + { | ||
| 883 | + int ret = ERROR_SUCCESS; | ||
| 867 | 884 | ||
| 868 | // generate digest | 885 | // generate digest |
| 869 | - char* digest = NULL; | 886 | + char* c1_digest = NULL; |
| 870 | 887 | ||
| 871 | - if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) { | 888 | + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) { |
| 872 | srs_error("sign c1 error, failed to calc digest. ret=%d", ret); | 889 | srs_error("sign c1 error, failed to calc digest. ret=%d", ret); |
| 873 | return ret; | 890 | return ret; |
| 874 | } | 891 | } |
| 875 | 892 | ||
| 876 | - srs_assert(digest != NULL); | ||
| 877 | - SrsAutoFree(char, digest); | 893 | + srs_assert(c1_digest != NULL); |
| 894 | + SrsAutoFree(char, c1_digest); | ||
| 878 | 895 | ||
| 879 | - if (schema == srs_schema0) { | ||
| 880 | - memcpy(block1.digest.digest, digest, 32); | ||
| 881 | - } else { | ||
| 882 | - memcpy(block0.digest.digest, digest, 32); | ||
| 883 | - } | 896 | + memcpy(digest.digest, c1_digest, 32); |
| 884 | 897 | ||
| 885 | return ret; | 898 | return ret; |
| 886 | } | 899 | } |
| 887 | 900 | ||
| 888 | - int c1s1::c1_validate_digest(bool& is_valid) | 901 | + int c1s1_strategy_schema1::c1_validate_digest(c1s1* owner, bool& is_valid) |
| 889 | { | 902 | { |
| 890 | - is_valid = false; | ||
| 891 | int ret = ERROR_SUCCESS; | 903 | int ret = ERROR_SUCCESS; |
| 892 | 904 | ||
| 893 | char* c1_digest = NULL; | 905 | char* c1_digest = NULL; |
| 894 | 906 | ||
| 895 | - if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) { | 907 | + if ((ret = calc_c1_digest(owner, c1_digest)) != ERROR_SUCCESS) { |
| 896 | srs_error("validate c1 error, failed to calc digest. ret=%d", ret); | 908 | srs_error("validate c1 error, failed to calc digest. ret=%d", ret); |
| 897 | return ret; | 909 | return ret; |
| 898 | } | 910 | } |
| @@ -900,163 +912,241 @@ namespace _srs_internal | @@ -900,163 +912,241 @@ namespace _srs_internal | ||
| 900 | srs_assert(c1_digest != NULL); | 912 | srs_assert(c1_digest != NULL); |
| 901 | SrsAutoFree(char, c1_digest); | 913 | SrsAutoFree(char, c1_digest); |
| 902 | 914 | ||
| 903 | - if (schema == srs_schema0) { | ||
| 904 | - is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32); | ||
| 905 | - } else { | ||
| 906 | - is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32); | ||
| 907 | - } | 915 | + is_valid = srs_bytes_equals(digest.digest, c1_digest, 32); |
| 908 | 916 | ||
| 909 | return ret; | 917 | return ret; |
| 910 | } | 918 | } |
| 911 | 919 | ||
| 912 | - int c1s1::s1_validate_digest(bool& is_valid) | 920 | + int c1s1_strategy_schema1::s1_create(c1s1* owner) |
| 913 | { | 921 | { |
| 914 | - is_valid = false; | ||
| 915 | int ret = ERROR_SUCCESS; | 922 | int ret = ERROR_SUCCESS; |
| 916 | 923 | ||
| 917 | - char* s1_digest = NULL; | 924 | + SrsDH dh; |
| 918 | 925 | ||
| 919 | - if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) { | ||
| 920 | - srs_error("validate s1 error, failed to calc digest. ret=%d", ret); | 926 | + // ensure generate 128bytes public key. |
| 927 | + if ((ret = dh.initialize(true)) != ERROR_SUCCESS) { | ||
| 921 | return ret; | 928 | return ret; |
| 922 | } | 929 | } |
| 923 | 930 | ||
| 931 | + // directly generate the public key. | ||
| 932 | + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | ||
| 933 | + int pkey_size = 128; | ||
| 934 | + if ((ret = dh.copy_public_key(key.key, pkey_size)) != ERROR_SUCCESS) { | ||
| 935 | + srs_error("calc s1 key failed. ret=%d", ret); | ||
| 936 | + return ret; | ||
| 937 | + } | ||
| 938 | + srs_assert(pkey_size == 128); | ||
| 939 | + srs_verbose("calc s1 key success."); | ||
| 940 | + | ||
| 941 | + char* s1_digest = NULL; | ||
| 942 | + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) { | ||
| 943 | + srs_error("calc s1 digest failed. ret=%d", ret); | ||
| 944 | + return ret; | ||
| 945 | + } | ||
| 946 | + srs_verbose("calc s1 digest success."); | ||
| 947 | + | ||
| 924 | srs_assert(s1_digest != NULL); | 948 | srs_assert(s1_digest != NULL); |
| 925 | SrsAutoFree(char, s1_digest); | 949 | SrsAutoFree(char, s1_digest); |
| 926 | 950 | ||
| 927 | - if (schema == srs_schema0) { | ||
| 928 | - is_valid = srs_bytes_equals(block1.digest.digest, s1_digest, 32); | ||
| 929 | - } else { | ||
| 930 | - is_valid = srs_bytes_equals(block0.digest.digest, s1_digest, 32); | ||
| 931 | - } | 951 | + memcpy(digest.digest, s1_digest, 32); |
| 952 | + srs_verbose("copy s1 key success."); | ||
| 932 | 953 | ||
| 933 | return ret; | 954 | return ret; |
| 934 | } | 955 | } |
| 935 | 956 | ||
| 936 | - int c1s1::s1_create(c1s1* c1) | 957 | + int c1s1_strategy_schema1::s1_validate_digest(c1s1* owner, bool& is_valid) |
| 937 | { | 958 | { |
| 938 | int ret = ERROR_SUCCESS; | 959 | int ret = ERROR_SUCCESS; |
| 939 | 960 | ||
| 940 | - if (c1->schema == srs_schema_invalid) { | ||
| 941 | - ret = ERROR_RTMP_CH_SCHEMA; | ||
| 942 | - srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret); | 961 | + char* s1_digest = NULL; |
| 962 | + | ||
| 963 | + if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) { | ||
| 964 | + srs_error("validate s1 error, failed to calc digest. ret=%d", ret); | ||
| 943 | return ret; | 965 | return ret; |
| 944 | } | 966 | } |
| 945 | 967 | ||
| 946 | - destroy_blocks(); | ||
| 947 | - schema = c1->schema; | 968 | + srs_assert(s1_digest != NULL); |
| 969 | + SrsAutoFree(char, s1_digest); | ||
| 948 | 970 | ||
| 949 | - time = ::time(NULL); | ||
| 950 | - version = 0x01000504; // server s1 version | 971 | + is_valid = srs_bytes_equals(digest.digest, s1_digest, 32); |
| 951 | 972 | ||
| 952 | - SrsDH dh; | ||
| 953 | - | ||
| 954 | - // ensure generate 128bytes public key. | ||
| 955 | - if ((ret = dh.initialize(true)) != ERROR_SUCCESS) { | ||
| 956 | return ret; | 973 | return ret; |
| 957 | } | 974 | } |
| 958 | 975 | ||
| 959 | - if (schema == srs_schema0) { | ||
| 960 | - block0.key.init(); | ||
| 961 | - block1.digest.init(); | 976 | + int c1s1_strategy_schema1::calc_c1_digest(c1s1* owner, char*& c1_digest) |
| 977 | + { | ||
| 978 | + int ret = ERROR_SUCCESS; | ||
| 962 | 979 | ||
| 963 | - // directly generate the public key. | ||
| 964 | - // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | ||
| 965 | - int pkey_size = 128; | ||
| 966 | - if ((ret = dh.copy_public_key(block0.key.key, pkey_size)) != ERROR_SUCCESS) { | ||
| 967 | - srs_error("calc s1 key failed. ret=%d", ret); | 980 | + char* c1s1_joined_bytes = NULL; |
| 981 | + | ||
| 982 | + c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key); | ||
| 983 | + | ||
| 984 | + srs_assert(c1s1_joined_bytes != NULL); | ||
| 985 | + SrsAutoFree(char, c1s1_joined_bytes); | ||
| 986 | + | ||
| 987 | + c1_digest = new char[__SRS_OpensslHashSize]; | ||
| 988 | + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, c1_digest)) != ERROR_SUCCESS) { | ||
| 989 | + srs_freep(c1_digest); | ||
| 990 | + srs_error("calc digest for c1 failed. ret=%d", ret); | ||
| 968 | return ret; | 991 | return ret; |
| 969 | } | 992 | } |
| 970 | - srs_assert(pkey_size == 128); | ||
| 971 | - } else { | ||
| 972 | - block0.digest.init(); | ||
| 973 | - block1.key.init(); | 993 | + srs_verbose("digest calculated for c1"); |
| 974 | 994 | ||
| 975 | - // directly generate the public key. | ||
| 976 | - // @see: https://github.com/winlinvip/simple-rtmp-server/issues/148 | ||
| 977 | - int pkey_size = 128; | ||
| 978 | - if ((ret = dh.copy_public_key(block1.key.key, pkey_size)) != ERROR_SUCCESS) { | ||
| 979 | - srs_error("calc s1 key failed. ret=%d", ret); | ||
| 980 | return ret; | 995 | return ret; |
| 981 | } | 996 | } |
| 982 | - srs_assert(pkey_size == 128); | 997 | + |
| 998 | + int c1s1_strategy_schema1::calc_s1_digest(c1s1* owner, char*& s1_digest) | ||
| 999 | + { | ||
| 1000 | + int ret = ERROR_SUCCESS; | ||
| 1001 | + | ||
| 1002 | + char* c1s1_joined_bytes = NULL; | ||
| 1003 | + | ||
| 1004 | + c1s1_joined_bytes = srs_bytes_join_schema1(owner->time, owner->version, &digest, &key); | ||
| 1005 | + | ||
| 1006 | + srs_assert(c1s1_joined_bytes != NULL); | ||
| 1007 | + SrsAutoFree(char, c1s1_joined_bytes); | ||
| 1008 | + | ||
| 1009 | + s1_digest = new char[__SRS_OpensslHashSize]; | ||
| 1010 | + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, s1_digest)) != ERROR_SUCCESS) { | ||
| 1011 | + srs_freep(s1_digest); | ||
| 1012 | + srs_error("calc digest for s1 failed. ret=%d", ret); | ||
| 1013 | + return ret; | ||
| 983 | } | 1014 | } |
| 984 | - srs_verbose("calc s1 key success."); | 1015 | + srs_verbose("digest calculated for s1"); |
| 985 | 1016 | ||
| 986 | - char* s1_digest = NULL; | ||
| 987 | - if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) { | ||
| 988 | - srs_error("calc s1 digest failed. ret=%d", ret); | ||
| 989 | return ret; | 1017 | return ret; |
| 990 | } | 1018 | } |
| 991 | - srs_verbose("calc s1 digest success."); | ||
| 992 | 1019 | ||
| 993 | - srs_assert(s1_digest != NULL); | ||
| 994 | - SrsAutoFree(char, s1_digest); | 1020 | + c2s2::c2s2() |
| 1021 | + { | ||
| 1022 | + srs_random_generate(random, 1504); | ||
| 995 | 1023 | ||
| 996 | - if (schema == srs_schema0) { | ||
| 997 | - memcpy(block1.digest.digest, s1_digest, 32); | ||
| 998 | - } else { | ||
| 999 | - memcpy(block0.digest.digest, s1_digest, 32); | 1024 | + int size = snprintf(random, 1504, "%s", RTMP_SIG_SRS_HANDSHAKE); |
| 1025 | + srs_assert(++size < 1504); | ||
| 1026 | + snprintf(random + 1504 - size, size, "%s", RTMP_SIG_SRS_HANDSHAKE); | ||
| 1027 | + | ||
| 1028 | + srs_random_generate(digest, 32); | ||
| 1000 | } | 1029 | } |
| 1001 | - srs_verbose("copy s1 key success."); | ||
| 1002 | 1030 | ||
| 1003 | - return ret; | 1031 | + c2s2::~c2s2() |
| 1032 | + { | ||
| 1033 | + } | ||
| 1034 | + | ||
| 1035 | + void c2s2::dump(char* _c2s2) | ||
| 1036 | + { | ||
| 1037 | + memcpy(_c2s2, random, 1504); | ||
| 1038 | + memcpy(_c2s2 + 1504, digest, 32); | ||
| 1004 | } | 1039 | } |
| 1005 | 1040 | ||
| 1006 | - int c1s1::calc_s1_digest(char*& digest) | 1041 | + void c2s2::parse(char* _c2s2) |
| 1042 | + { | ||
| 1043 | + memcpy(random, _c2s2, 1504); | ||
| 1044 | + memcpy(digest, _c2s2 + 1504, 32); | ||
| 1045 | + } | ||
| 1046 | + | ||
| 1047 | + int c2s2::c2_create(c1s1* s1) | ||
| 1007 | { | 1048 | { |
| 1008 | int ret = ERROR_SUCCESS; | 1049 | int ret = ERROR_SUCCESS; |
| 1009 | 1050 | ||
| 1010 | - srs_assert(schema == srs_schema0 || schema == srs_schema1); | 1051 | + char temp_key[__SRS_OpensslHashSize]; |
| 1052 | + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 62, s1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 1053 | + srs_error("create c2 temp key failed. ret=%d", ret); | ||
| 1054 | + return ret; | ||
| 1055 | + } | ||
| 1056 | + srs_verbose("generate c2 temp key success."); | ||
| 1011 | 1057 | ||
| 1012 | - char* c1s1_joined_bytes = NULL; | 1058 | + char _digest[__SRS_OpensslHashSize]; |
| 1059 | + if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 1060 | + srs_error("create c2 digest failed. ret=%d", ret); | ||
| 1061 | + return ret; | ||
| 1062 | + } | ||
| 1063 | + srs_verbose("generate c2 digest success."); | ||
| 1013 | 1064 | ||
| 1014 | - if (schema == srs_schema0) { | ||
| 1015 | - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); | ||
| 1016 | - } else { | ||
| 1017 | - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); | 1065 | + memcpy(digest, _digest, 32); |
| 1066 | + | ||
| 1067 | + return ret; | ||
| 1018 | } | 1068 | } |
| 1019 | 1069 | ||
| 1020 | - srs_assert(c1s1_joined_bytes != NULL); | ||
| 1021 | - SrsAutoFree(char, c1s1_joined_bytes); | 1070 | + int c2s2::c2_validate(c1s1* s1, bool& is_valid) |
| 1071 | + { | ||
| 1072 | + is_valid = false; | ||
| 1073 | + int ret = ERROR_SUCCESS; | ||
| 1022 | 1074 | ||
| 1023 | - digest = new char[__SRS_OpensslHashSize]; | ||
| 1024 | - if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 36, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) { | ||
| 1025 | - srs_error("calc digest for s1 failed. ret=%d", ret); | 1075 | + char temp_key[__SRS_OpensslHashSize]; |
| 1076 | + if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 62, s1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 1077 | + srs_error("create c2 temp key failed. ret=%d", ret); | ||
| 1026 | return ret; | 1078 | return ret; |
| 1027 | } | 1079 | } |
| 1028 | - srs_verbose("digest calculated for s1"); | 1080 | + srs_verbose("generate c2 temp key success."); |
| 1081 | + | ||
| 1082 | + char _digest[__SRS_OpensslHashSize]; | ||
| 1083 | + if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 1084 | + srs_error("create c2 digest failed. ret=%d", ret); | ||
| 1085 | + return ret; | ||
| 1086 | + } | ||
| 1087 | + srs_verbose("generate c2 digest success."); | ||
| 1088 | + | ||
| 1089 | + is_valid = srs_bytes_equals(digest, _digest, 32); | ||
| 1029 | 1090 | ||
| 1030 | return ret; | 1091 | return ret; |
| 1031 | } | 1092 | } |
| 1032 | 1093 | ||
| 1033 | - int c1s1::calc_c1_digest(char*& digest) | 1094 | + int c2s2::s2_create(c1s1* c1) |
| 1034 | { | 1095 | { |
| 1035 | int ret = ERROR_SUCCESS; | 1096 | int ret = ERROR_SUCCESS; |
| 1036 | 1097 | ||
| 1037 | - srs_assert(schema == srs_schema0 || schema == srs_schema1); | 1098 | + char temp_key[__SRS_OpensslHashSize]; |
| 1099 | + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 68, c1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 1100 | + srs_error("create s2 temp key failed. ret=%d", ret); | ||
| 1101 | + return ret; | ||
| 1102 | + } | ||
| 1103 | + srs_verbose("generate s2 temp key success."); | ||
| 1104 | + | ||
| 1105 | + char _digest[__SRS_OpensslHashSize]; | ||
| 1106 | + if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 1107 | + srs_error("create s2 digest failed. ret=%d", ret); | ||
| 1108 | + return ret; | ||
| 1109 | + } | ||
| 1110 | + srs_verbose("generate s2 digest success."); | ||
| 1038 | 1111 | ||
| 1039 | - char* c1s1_joined_bytes = NULL; | 1112 | + memcpy(digest, _digest, 32); |
| 1040 | 1113 | ||
| 1041 | - if (schema == srs_schema0) { | ||
| 1042 | - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); | ||
| 1043 | - } else { | ||
| 1044 | - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); | 1114 | + return ret; |
| 1045 | } | 1115 | } |
| 1046 | 1116 | ||
| 1047 | - srs_assert(c1s1_joined_bytes != NULL); | ||
| 1048 | - SrsAutoFree(char, c1s1_joined_bytes); | 1117 | + int c2s2::s2_validate(c1s1* c1, bool& is_valid) |
| 1118 | + { | ||
| 1119 | + is_valid = false; | ||
| 1120 | + int ret = ERROR_SUCCESS; | ||
| 1049 | 1121 | ||
| 1050 | - digest = new char[__SRS_OpensslHashSize]; | ||
| 1051 | - if ((ret = openssl_HMACsha256(SrsGenuineFPKey, 30, c1s1_joined_bytes, 1536 - 32, digest)) != ERROR_SUCCESS) { | ||
| 1052 | - srs_error("calc digest for c1 failed. ret=%d", ret); | 1122 | + char temp_key[__SRS_OpensslHashSize]; |
| 1123 | + if ((ret = openssl_HMACsha256(SrsGenuineFMSKey, 68, c1->get_digest(), 32, temp_key)) != ERROR_SUCCESS) { | ||
| 1124 | + srs_error("create s2 temp key failed. ret=%d", ret); | ||
| 1053 | return ret; | 1125 | return ret; |
| 1054 | } | 1126 | } |
| 1055 | - srs_verbose("digest calculated for c1"); | 1127 | + srs_verbose("generate s2 temp key success."); |
| 1128 | + | ||
| 1129 | + char _digest[__SRS_OpensslHashSize]; | ||
| 1130 | + if ((ret = openssl_HMACsha256(temp_key, 32, random, 1504, _digest)) != ERROR_SUCCESS) { | ||
| 1131 | + srs_error("create s2 digest failed. ret=%d", ret); | ||
| 1132 | + return ret; | ||
| 1133 | + } | ||
| 1134 | + srs_verbose("generate s2 digest success."); | ||
| 1135 | + | ||
| 1136 | + is_valid = srs_bytes_equals(digest, _digest, 32); | ||
| 1056 | 1137 | ||
| 1057 | return ret; | 1138 | return ret; |
| 1058 | } | 1139 | } |
| 1059 | 1140 | ||
| 1141 | + // TODO: FIXME: move to the right position. | ||
| 1142 | + c1s1::c1s1() | ||
| 1143 | + { | ||
| 1144 | + payload = NULL; | ||
| 1145 | + } | ||
| 1146 | + c1s1::~c1s1() | ||
| 1147 | + { | ||
| 1148 | + srs_freep(payload); | ||
| 1149 | + /* | ||
| 1060 | void c1s1::destroy_blocks() | 1150 | void c1s1::destroy_blocks() |
| 1061 | { | 1151 | { |
| 1062 | if (schema == srs_schema_invalid) { | 1152 | if (schema == srs_schema_invalid) { |
| @@ -1070,6 +1160,110 @@ namespace _srs_internal | @@ -1070,6 +1160,110 @@ namespace _srs_internal | ||
| 1070 | block0.digest.free(); | 1160 | block0.digest.free(); |
| 1071 | block1.key.free(); | 1161 | block1.key.free(); |
| 1072 | } | 1162 | } |
| 1163 | + }*/ | ||
| 1164 | + } | ||
| 1165 | + | ||
| 1166 | + srs_schema_type c1s1::schema() | ||
| 1167 | + { | ||
| 1168 | + srs_assert(payload != NULL); | ||
| 1169 | + return payload->schema(); | ||
| 1170 | + } | ||
| 1171 | + | ||
| 1172 | + char* c1s1::get_digest() | ||
| 1173 | + { | ||
| 1174 | + srs_assert(payload != NULL); | ||
| 1175 | + return payload->get_digest(); | ||
| 1176 | + } | ||
| 1177 | + | ||
| 1178 | + void c1s1::dump(char* _c1s1) | ||
| 1179 | + { | ||
| 1180 | + srs_assert(payload != NULL); | ||
| 1181 | + return payload->dump(this, _c1s1); | ||
| 1182 | + } | ||
| 1183 | + | ||
| 1184 | + int c1s1::parse(char* _c1s1, srs_schema_type schema) | ||
| 1185 | + { | ||
| 1186 | + int ret = ERROR_SUCCESS; | ||
| 1187 | + | ||
| 1188 | + if (schema != srs_schema0 && schema != srs_schema1) { | ||
| 1189 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 1190 | + srs_error("parse c1 failed. invalid schema=%d, ret=%d", schema, ret); | ||
| 1191 | + return ret; | ||
| 1192 | + } | ||
| 1193 | + | ||
| 1194 | + time = __srs_stream_read_4bytes(_c1s1); | ||
| 1195 | + version = __srs_stream_read_4bytes(_c1s1 + 4); // client c1 version | ||
| 1196 | + | ||
| 1197 | + srs_freep(payload); | ||
| 1198 | + if (schema == srs_schema0) { | ||
| 1199 | + payload = new c1s1_strategy_schema0(); | ||
| 1200 | + } else { | ||
| 1201 | + payload = new c1s1_strategy_schema1(); | ||
| 1202 | + } | ||
| 1203 | + | ||
| 1204 | + return payload->parse(_c1s1); | ||
| 1205 | + } | ||
| 1206 | + | ||
| 1207 | + int c1s1::c1_create(srs_schema_type schema) | ||
| 1208 | + { | ||
| 1209 | + int ret = ERROR_SUCCESS; | ||
| 1210 | + | ||
| 1211 | + if (schema != srs_schema0 && schema != srs_schema1) { | ||
| 1212 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 1213 | + srs_error("create c1 failed. invalid schema=%d, ret=%d", schema, ret); | ||
| 1214 | + return ret; | ||
| 1215 | + } | ||
| 1216 | + | ||
| 1217 | + // client c1 time and version | ||
| 1218 | + time = ::time(NULL); | ||
| 1219 | + version = 0x80000702; // client c1 version | ||
| 1220 | + | ||
| 1221 | + // generate signature by schema | ||
| 1222 | + srs_freep(payload); | ||
| 1223 | + if (schema == srs_schema0) { | ||
| 1224 | + payload = new c1s1_strategy_schema0(); | ||
| 1225 | + } else { | ||
| 1226 | + payload = new c1s1_strategy_schema1(); | ||
| 1227 | + } | ||
| 1228 | + | ||
| 1229 | + return payload->c1_create(this); | ||
| 1230 | + } | ||
| 1231 | + | ||
| 1232 | + int c1s1::c1_validate_digest(bool& is_valid) | ||
| 1233 | + { | ||
| 1234 | + is_valid = false; | ||
| 1235 | + srs_assert(payload); | ||
| 1236 | + return payload->c1_validate_digest(this, is_valid); | ||
| 1237 | + } | ||
| 1238 | + | ||
| 1239 | + int c1s1::s1_validate_digest(bool& is_valid) | ||
| 1240 | + { | ||
| 1241 | + is_valid = false; | ||
| 1242 | + srs_assert(payload); | ||
| 1243 | + return payload->s1_validate_digest(this, is_valid); | ||
| 1244 | + } | ||
| 1245 | + | ||
| 1246 | + int c1s1::s1_create(c1s1* c1) | ||
| 1247 | + { | ||
| 1248 | + int ret = ERROR_SUCCESS; | ||
| 1249 | + | ||
| 1250 | + if (c1->schema() != srs_schema0 && c1->schema() != srs_schema1) { | ||
| 1251 | + ret = ERROR_RTMP_CH_SCHEMA; | ||
| 1252 | + srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema(), ret); | ||
| 1253 | + return ret; | ||
| 1254 | + } | ||
| 1255 | + | ||
| 1256 | + time = ::time(NULL); | ||
| 1257 | + version = 0x01000504; // server s1 version | ||
| 1258 | + | ||
| 1259 | + srs_freep(payload); | ||
| 1260 | + if (c1->schema() == srs_schema0) { | ||
| 1261 | + payload = new c1s1_strategy_schema0(); | ||
| 1262 | + } else { | ||
| 1263 | + payload = new c1s1_strategy_schema1(); | ||
| 1264 | + } | ||
| 1265 | + | ||
| 1266 | + return payload->s1_create(this); | ||
| 1073 | } | 1267 | } |
| 1074 | } | 1268 | } |
| 1075 | 1269 | ||
| @@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | @@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | ||
| 1190 | // decode c1 | 1384 | // decode c1 |
| 1191 | c1s1 c1; | 1385 | c1s1 c1; |
| 1192 | // try schema0. | 1386 | // try schema0. |
| 1387 | + // @remark, use schema0 to make flash player happy. | ||
| 1193 | if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) { | 1388 | if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema0)) != ERROR_SUCCESS) { |
| 1194 | srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); | 1389 | srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); |
| 1195 | return ret; | 1390 | return ret; |
| @@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | @@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | ||
| 1197 | // try schema1 | 1392 | // try schema1 |
| 1198 | bool is_valid = false; | 1393 | bool is_valid = false; |
| 1199 | if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { | 1394 | if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { |
| 1395 | + srs_info("schema0 failed, try schema1."); | ||
| 1200 | if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) { | 1396 | if ((ret = c1.parse(hs_bytes->c0c1 + 1, srs_schema1)) != ERROR_SUCCESS) { |
| 1201 | srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); | 1397 | srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); |
| 1202 | return ret; | 1398 | return ret; |
| @@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | @@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs | ||
| 1207 | srs_info("all schema valid failed, try simple handshake. ret=%d", ret); | 1403 | srs_info("all schema valid failed, try simple handshake. ret=%d", ret); |
| 1208 | return ret; | 1404 | return ret; |
| 1209 | } | 1405 | } |
| 1406 | + } else { | ||
| 1407 | + srs_info("schema0 is ok."); | ||
| 1210 | } | 1408 | } |
| 1211 | srs_verbose("decode c1 success."); | 1409 | srs_verbose("decode c1 success."); |
| 1212 | 1410 | ||
| @@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs | @@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs | ||
| 1321 | 1519 | ||
| 1322 | // verify s1s2 | 1520 | // verify s1s2 |
| 1323 | c1s1 s1; | 1521 | c1s1 s1; |
| 1324 | - if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema)) != ERROR_SUCCESS) { | 1522 | + if ((ret = s1.parse(hs_bytes->s0s1s2 + 1, c1.schema())) != ERROR_SUCCESS) { |
| 1325 | return ret; | 1523 | return ret; |
| 1326 | } | 1524 | } |
| 1327 | 1525 |
| @@ -219,6 +219,121 @@ namespace _srs_internal | @@ -219,6 +219,121 @@ namespace _srs_internal | ||
| 219 | */ | 219 | */ |
| 220 | char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key); | 220 | char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key); |
| 221 | 221 | ||
| 222 | + class c1s1; | ||
| 223 | + | ||
| 224 | + /** | ||
| 225 | + * the c1s1 strategy, use schema0 or schema1. | ||
| 226 | + * the template method class to defines common behaviors, | ||
| 227 | + * while the concrete class to implements in schema0 or schema1. | ||
| 228 | + */ | ||
| 229 | + class c1s1_strategy | ||
| 230 | + { | ||
| 231 | + public: | ||
| 232 | + c1s1_strategy(); | ||
| 233 | + virtual ~c1s1_strategy(); | ||
| 234 | + public: | ||
| 235 | + /** | ||
| 236 | + * get the scema. | ||
| 237 | + */ | ||
| 238 | + virtual srs_schema_type schema() = 0; | ||
| 239 | + /** | ||
| 240 | + * get the digest key. | ||
| 241 | + */ | ||
| 242 | + virtual char* get_digest() = 0; | ||
| 243 | + /** | ||
| 244 | + * copy to bytes. | ||
| 245 | + */ | ||
| 246 | + virtual void dump(c1s1* owner, char* _c1s1) = 0; | ||
| 247 | + /** | ||
| 248 | + * server: parse the c1s1, discovery the key and digest by schema. | ||
| 249 | + * use the c1_validate_digest() to valid the digest of c1. | ||
| 250 | + */ | ||
| 251 | + virtual int parse(char* _c1s1) = 0; | ||
| 252 | + public: | ||
| 253 | + /** | ||
| 254 | + * client: create and sign c1 by schema. | ||
| 255 | + * sign the c1, generate the digest. | ||
| 256 | + * calc_c1_digest(c1, schema) { | ||
| 257 | + * get c1s1-joined from c1 by specified schema | ||
| 258 | + * digest-data = HMACsha256(c1s1-joined, FPKey, 30) | ||
| 259 | + * return digest-data; | ||
| 260 | + * } | ||
| 261 | + * random fill 1536bytes c1 // also fill the c1-128bytes-key | ||
| 262 | + * time = time() // c1[0-3] | ||
| 263 | + * version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] | ||
| 264 | + * schema = choose schema0 or schema1 | ||
| 265 | + * digest-data = calc_c1_digest(c1, schema) | ||
| 266 | + * copy digest-data to c1 | ||
| 267 | + */ | ||
| 268 | + virtual int c1_create(c1s1* owner) = 0; | ||
| 269 | + /** | ||
| 270 | + * server: validate the parsed c1 schema | ||
| 271 | + */ | ||
| 272 | + virtual int c1_validate_digest(c1s1* owner, bool& is_valid) = 0; | ||
| 273 | + /** | ||
| 274 | + * server: create and sign the s1 from c1. | ||
| 275 | + */ | ||
| 276 | + virtual int s1_create(c1s1* owner) = 0; | ||
| 277 | + /** | ||
| 278 | + * server: validate the parsed s1 schema | ||
| 279 | + */ | ||
| 280 | + virtual int s1_validate_digest(c1s1* owner, bool& is_valid) = 0; | ||
| 281 | + }; | ||
| 282 | + | ||
| 283 | + /** | ||
| 284 | + * c1s1 schema0 | ||
| 285 | + * key: 764bytes | ||
| 286 | + * digest: 764bytes | ||
| 287 | + */ | ||
| 288 | + class c1s1_strategy_schema0 : public c1s1_strategy | ||
| 289 | + { | ||
| 290 | + private: | ||
| 291 | + key_block key; | ||
| 292 | + digest_block digest; | ||
| 293 | + public: | ||
| 294 | + c1s1_strategy_schema0(); | ||
| 295 | + virtual ~c1s1_strategy_schema0(); | ||
| 296 | + public: | ||
| 297 | + virtual srs_schema_type schema(); | ||
| 298 | + virtual char* get_digest(); | ||
| 299 | + virtual void dump(c1s1* owner, char* _c1s1); | ||
| 300 | + virtual int parse(char* _c1s1); | ||
| 301 | + virtual int c1_create(c1s1* owner); | ||
| 302 | + virtual int c1_validate_digest(c1s1* owner, bool& is_valid); | ||
| 303 | + virtual int s1_create(c1s1* owner); | ||
| 304 | + virtual int s1_validate_digest(c1s1* owner, bool& is_valid); | ||
| 305 | + private: | ||
| 306 | + virtual int calc_c1_digest(c1s1* owner, char*& c1_digest); | ||
| 307 | + virtual int calc_s1_digest(c1s1* owner, char*& s1_digest); | ||
| 308 | + }; | ||
| 309 | + | ||
| 310 | + /** | ||
| 311 | + * c1s1 schema1 | ||
| 312 | + * digest: 764bytes | ||
| 313 | + * key: 764bytes | ||
| 314 | + */ | ||
| 315 | + class c1s1_strategy_schema1 : public c1s1_strategy | ||
| 316 | + { | ||
| 317 | + private: | ||
| 318 | + digest_block digest; | ||
| 319 | + key_block key; | ||
| 320 | + public: | ||
| 321 | + c1s1_strategy_schema1(); | ||
| 322 | + virtual ~c1s1_strategy_schema1(); | ||
| 323 | + public: | ||
| 324 | + virtual srs_schema_type schema(); | ||
| 325 | + virtual char* get_digest(); | ||
| 326 | + virtual void dump(c1s1* owner, char* _c1s1); | ||
| 327 | + virtual int parse(char* _c1s1); | ||
| 328 | + virtual int c1_create(c1s1* owner); | ||
| 329 | + virtual int c1_validate_digest(c1s1* owner, bool& is_valid); | ||
| 330 | + virtual int s1_create(c1s1* owner); | ||
| 331 | + virtual int s1_validate_digest(c1s1* owner, bool& is_valid); | ||
| 332 | + private: | ||
| 333 | + virtual int calc_c1_digest(c1s1* owner, char*& c1_digest); | ||
| 334 | + virtual int calc_s1_digest(c1s1* owner, char*& s1_digest); | ||
| 335 | + }; | ||
| 336 | + | ||
| 222 | /** | 337 | /** |
| 223 | * c1s1 schema0 | 338 | * c1s1 schema0 |
| 224 | * time: 4bytes | 339 | * time: 4bytes |
| @@ -235,30 +350,20 @@ namespace _srs_internal | @@ -235,30 +350,20 @@ namespace _srs_internal | ||
| 235 | class c1s1 | 350 | class c1s1 |
| 236 | { | 351 | { |
| 237 | public: | 352 | public: |
| 238 | - union block { | ||
| 239 | - key_block key; | ||
| 240 | - digest_block digest; | ||
| 241 | - }; | ||
| 242 | - | ||
| 243 | // 4bytes | 353 | // 4bytes |
| 244 | int32_t time; | 354 | int32_t time; |
| 245 | // 4bytes | 355 | // 4bytes |
| 246 | int32_t version; | 356 | int32_t version; |
| 247 | - // 764bytes | ||
| 248 | - // if schema0, use key | ||
| 249 | - // if schema1, use digest | ||
| 250 | - block block0; | ||
| 251 | - // 764bytes | ||
| 252 | - // if schema0, use digest | ||
| 253 | - // if schema1, use key | ||
| 254 | - block block1; | ||
| 255 | - | ||
| 256 | - // the logic schema | ||
| 257 | - srs_schema_type schema; | 357 | + // 764bytes+764bytes |
| 358 | + c1s1_strategy* payload; | ||
| 258 | 359 | ||
| 259 | c1s1(); | 360 | c1s1(); |
| 260 | virtual ~c1s1(); | 361 | virtual ~c1s1(); |
| 261 | /** | 362 | /** |
| 363 | + * get the scema. | ||
| 364 | + */ | ||
| 365 | + virtual srs_schema_type schema(); | ||
| 366 | + /** | ||
| 262 | * get the digest key. | 367 | * get the digest key. |
| 263 | */ | 368 | */ |
| 264 | virtual char* get_digest(); | 369 | virtual char* get_digest(); |
| @@ -269,6 +374,7 @@ namespace _srs_internal | @@ -269,6 +374,7 @@ namespace _srs_internal | ||
| 269 | /** | 374 | /** |
| 270 | * server: parse the c1s1, discovery the key and digest by schema. | 375 | * server: parse the c1s1, discovery the key and digest by schema. |
| 271 | * use the c1_validate_digest() to valid the digest of c1. | 376 | * use the c1_validate_digest() to valid the digest of c1. |
| 377 | + * use the s1_validate_digest() to valid the digest of s1. | ||
| 272 | */ | 378 | */ |
| 273 | virtual int parse(char* _c1s1, srs_schema_type _schema); | 379 | virtual int parse(char* _c1s1, srs_schema_type _schema); |
| 274 | 380 | ||
| @@ -294,16 +400,35 @@ namespace _srs_internal | @@ -294,16 +400,35 @@ namespace _srs_internal | ||
| 294 | virtual int c1_validate_digest(bool& is_valid); | 400 | virtual int c1_validate_digest(bool& is_valid); |
| 295 | /** | 401 | /** |
| 296 | * server: create and sign the s1 from c1. | 402 | * server: create and sign the s1 from c1. |
| 403 | + * // decode c1 try schema0 then schema1 | ||
| 404 | + * c1-digest-data = get-c1-digest-data(schema0) | ||
| 405 | + * if c1-digest-data equals to calc_c1_digest(c1, schema0) { | ||
| 406 | + * c1-key-data = get-c1-key-data(schema0) | ||
| 407 | + * schema = schema0 | ||
| 408 | + * } else { | ||
| 409 | + * c1-digest-data = get-c1-digest-data(schema1) | ||
| 410 | + * if c1-digest-data not equals to calc_c1_digest(c1, schema1) { | ||
| 411 | + * switch to simple handshake. | ||
| 412 | + * return | ||
| 413 | + * } | ||
| 414 | + * c1-key-data = get-c1-key-data(schema1) | ||
| 415 | + * schema = schema1 | ||
| 416 | + * } | ||
| 417 | + * | ||
| 418 | + * // generate s1 | ||
| 419 | + * random fill 1536bytes s1 | ||
| 420 | + * time = time() // c1[0-3] | ||
| 421 | + * version = [0x04, 0x05, 0x00, 0x01] // s1[4-7] | ||
| 422 | + * s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data) | ||
| 423 | + * get c1s1-joined by specified schema | ||
| 424 | + * s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36) | ||
| 425 | + * copy s1-digest-data and s1-key-data to s1. | ||
| 297 | */ | 426 | */ |
| 298 | virtual int s1_create(c1s1* c1); | 427 | virtual int s1_create(c1s1* c1); |
| 299 | /** | 428 | /** |
| 300 | * server: validate the parsed s1 schema | 429 | * server: validate the parsed s1 schema |
| 301 | */ | 430 | */ |
| 302 | virtual int s1_validate_digest(bool& is_valid); | 431 | virtual int s1_validate_digest(bool& is_valid); |
| 303 | - private: | ||
| 304 | - virtual int calc_s1_digest(char*& digest); | ||
| 305 | - virtual int calc_c1_digest(char*& digest); | ||
| 306 | - virtual void destroy_blocks(); | ||
| 307 | }; | 432 | }; |
| 308 | 433 | ||
| 309 | /** | 434 | /** |
-
请 注册 或 登录 后发表评论