... | ... |
@@ -553,10 +553,12 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length, |
553 | 553 |
* @param bm the byte comparison meta data struct, contains all the other info needed to do the comparison |
554 | 554 |
* |
555 | 555 |
*/ |
556 |
-cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_length, int offset, struct cli_bcomp_meta *bm) |
|
556 |
+cl_error_t cli_bcomp_compare_check(const unsigned char* f_buffer, size_t buffer_length, int offset, struct cli_bcomp_meta *bm) |
|
557 | 557 |
{ |
558 | 558 |
|
559 | 559 |
uint32_t byte_len = 0; |
560 |
+ uint32_t pad_len = 0; |
|
561 |
+ uint32_t norm_len = 0; |
|
560 | 562 |
uint32_t length = 0; |
561 | 563 |
uint32_t i = 0; |
562 | 564 |
cl_error_t ret = 0; |
... | ... |
@@ -564,9 +566,10 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
564 | 564 |
uint16_t opt_val = 0; |
565 | 565 |
int64_t value = 0; |
566 | 566 |
const unsigned char* end_buf = NULL; |
567 |
+ const unsigned char* buffer = NULL; |
|
567 | 568 |
unsigned char* tmp_buffer = NULL; |
568 | 569 |
|
569 |
- if (!buffer || !bm) { |
|
570 |
+ if (!f_buffer || !bm) { |
|
570 | 571 |
bcm_dbgmsg("cli_bcomp_compare_check: a param is null\n"); |
571 | 572 |
return CL_ENULLARG; |
572 | 573 |
} |
... | ... |
@@ -590,71 +593,40 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
590 | 590 |
|
591 | 591 |
/* jump to byte compare offset, then store off specified bytes into a null terminated buffer */ |
592 | 592 |
offset += bm->offset; |
593 |
- buffer += offset; |
|
593 |
+ f_buffer += offset; |
|
594 | 594 |
|
595 |
- bcm_dbgmsg("cli_bcomp_compare_check: literal extracted bytes before comparison %.*s\n", byte_len, buffer); |
|
595 |
+ bcm_dbgmsg("cli_bcomp_compare_check: literal extracted bytes before comparison %.*s\n", byte_len, f_buffer); |
|
596 |
+ |
|
597 |
+ /* normalize buffer for whitespace */ |
|
598 |
+ |
|
599 |
+ opt_val = opt & 0x000F; |
|
600 |
+ if ( !(opt_val & CLI_BCOMP_BIN) ) { |
|
601 |
+ buffer = cli_bcomp_normalize_buffer(f_buffer, byte_len, &pad_len, opt, 1); |
|
602 |
+ if (NULL == buffer) { |
|
603 |
+ cli_errmsg("cli_bcomp_compare_check: unable to whitespace normalize temp buffer, allocation failed\n"); |
|
604 |
+ return CL_EMEM; |
|
605 |
+ } |
|
606 |
+ |
|
607 |
+ /* adjust byte_len accordingly */ |
|
608 |
+ byte_len -= pad_len; |
|
609 |
+ } |
|
596 | 610 |
|
597 | 611 |
/* normalize buffer for little endian vals */ |
598 | 612 |
opt_val = opt & 0x00F0; |
599 | 613 |
if (opt_val == CLI_BCOMP_LE) { |
600 | 614 |
opt_val = opt & 0x000F; |
601 |
- if (opt_val & CLI_BCOMP_HEX || opt_val & CLI_BCOMP_AUTO) { |
|
602 |
- tmp_buffer = cli_calloc(byte_len+1, sizeof(char)); |
|
615 |
+ if ( !(opt_val & CLI_BCOMP_BIN) ) { |
|
616 |
+ tmp_buffer = cli_bcomp_normalize_buffer(f_buffer, byte_len, NULL, opt, 0); |
|
603 | 617 |
if (NULL == tmp_buffer) { |
604 |
- cli_errmsg("cli_bcomp_compare_check: unable to allocate memory for temp buffer\n"); |
|
618 |
+ cli_errmsg("cli_bcomp_compare_check: unable to normalize temp, allocation failed\n"); |
|
605 | 619 |
return CL_EMEM; |
606 | 620 |
} |
607 |
- |
|
608 |
- if (byte_len == 1) { |
|
609 |
- tmp_buffer[0] = buffer[0]; |
|
610 |
- } else { |
|
611 |
- for (i = 0; i < byte_len; i = i+2) { |
|
612 |
- if (((int32_t) byte_len - (int32_t) i) - 2 >= 0) { |
|
613 |
- if ( isxdigit(buffer[byte_len-i-2]) || toupper(buffer[byte_len-i-2]) == 'X' ) { |
|
614 |
- tmp_buffer[i] = buffer[byte_len-i-2]; |
|
615 |
- } else { |
|
616 |
- tmp_buffer[i] = '0'; |
|
617 |
- } |
|
618 |
- } |
|
619 |
- |
|
620 |
- if ( isxdigit(buffer[byte_len-i-1]) || toupper(buffer[byte_len-i-1]) == 'X' ) { |
|
621 |
- tmp_buffer[i+1] = buffer[byte_len-i-1]; |
|
622 |
- } else { |
|
623 |
- tmp_buffer[i+1] = '0'; |
|
624 |
- } |
|
625 |
- } |
|
626 |
- } |
|
627 |
- tmp_buffer[byte_len+1] = '\0'; |
|
628 |
- bcm_dbgmsg("cli_bcomp_compare_check: normalized extracted bytes before comparison %.*s\n", byte_len, tmp_buffer); |
|
629 | 621 |
} |
630 | 622 |
} |
631 | 623 |
|
632 | 624 |
opt_val = opt; |
633 | 625 |
if (opt_val & CLI_BCOMP_AUTO) { |
634 |
- if (tmp_buffer) { |
|
635 |
- /* tmp_buffer is based on the size of byte_len, so we can check against that safely */ |
|
636 |
- if ((opt & 0x00F0) & CLI_BCOMP_LE && byte_len >= 3) { |
|
637 |
- if(!strncmp((char*) &tmp_buffer[byte_len-2], "0x", 2) || !strncmp((char*) &tmp_buffer[byte_len-2], "0X", 2)) { |
|
638 |
- tmp_buffer[byte_len-2] = '\0'; |
|
639 |
- bcm_dbgmsg("cli_bcomp_compare_check: adjusted bytes before comparison %.*s\n", byte_len-2, tmp_buffer); |
|
640 |
- opt |= CLI_BCOMP_HEX; |
|
641 |
- } else { |
|
642 |
- opt |= CLI_BCOMP_DEC; |
|
643 |
- } |
|
644 |
- } |
|
645 |
- else if(!strncmp((char*) tmp_buffer, "0x", 2) || !strncmp((char*) tmp_buffer, "0X", 2)) { |
|
646 |
- opt |= CLI_BCOMP_HEX; |
|
647 |
- } else { |
|
648 |
- opt |= CLI_BCOMP_DEC; |
|
649 |
- } |
|
650 |
- } else { |
|
651 |
- if(!strncmp((char*) buffer, "0x", 2) || !strncmp((char*) buffer, "0X", 2)) { |
|
652 |
- opt |= CLI_BCOMP_HEX; |
|
653 |
- } else { |
|
654 |
- opt |= CLI_BCOMP_DEC; |
|
655 |
- } |
|
656 |
- } |
|
657 |
- opt ^= CLI_BCOMP_AUTO; |
|
626 |
+ opt = cli_bcomp_chk_hex(f_buffer, opt_val, byte_len, 0); |
|
658 | 627 |
} |
659 | 628 |
|
660 | 629 |
/* grab the first byte to handle byte length options to convert the string appropriately */ |
... | ... |
@@ -671,7 +643,7 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
671 | 671 |
} |
672 | 672 |
/*hle*/ |
673 | 673 |
if (opt & CLI_BCOMP_EXACT) { |
674 |
- if (tmp_buffer+byte_len != end_buf) { |
|
674 |
+ if (tmp_buffer+byte_len != end_buf || pad_len != 0) { |
|
675 | 675 |
|
676 | 676 |
free(tmp_buffer); |
677 | 677 |
bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
... | ... |
@@ -691,7 +663,7 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
691 | 691 |
} |
692 | 692 |
/*hbe*/ |
693 | 693 |
if (opt & CLI_BCOMP_EXACT) { |
694 |
- if (buffer+byte_len != end_buf) { |
|
694 |
+ if (buffer+byte_len != end_buf || pad_len != 0) { |
|
695 | 695 |
|
696 | 696 |
bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
697 | 697 |
return CL_CLEAN; |
... | ... |
@@ -717,24 +689,23 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
717 | 717 |
} |
718 | 718 |
/*dbe*/ |
719 | 719 |
if (opt & CLI_BCOMP_EXACT) { |
720 |
- if (buffer+byte_len != end_buf) { |
|
720 |
+ if (buffer+byte_len != end_buf || pad_len != 0) { |
|
721 | 721 |
|
722 | 722 |
bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
723 | 723 |
return CL_CLEAN; |
724 | 724 |
} |
725 | 725 |
} |
726 | 726 |
|
727 |
- value = be64_to_host(value); |
|
728 | 727 |
break; |
729 | 728 |
|
730 | 729 |
/*il*/ |
731 | 730 |
case CLI_BCOMP_BIN | CLI_BCOMP_LE: |
732 | 731 |
/* exact byte_length option is implied for binary extraction */ |
733 | 732 |
switch (byte_len) { |
734 |
- case 1: value = (*(int8_t*) buffer); break; |
|
735 |
- case 2: value = (int16_t) le16_to_host( *(int16_t*) buffer); break; |
|
736 |
- case 4: value = (int32_t) le32_to_host( *(int32_t*) buffer); break; |
|
737 |
- case 8: value = (int64_t) le64_to_host( *(int64_t*) buffer); break; |
|
733 |
+ case 1: value = (*(int8_t*) f_buffer); break; |
|
734 |
+ case 2: value = (int16_t) le16_to_host( *(int16_t*) f_buffer); break; |
|
735 |
+ case 4: value = (int32_t) le32_to_host( *(int32_t*) f_buffer); break; |
|
736 |
+ case 8: value = (int64_t) le64_to_host( *(int64_t*) f_buffer); break; |
|
738 | 737 |
|
739 | 738 |
default: |
740 | 739 |
bcm_dbgmsg("cli_bcomp_compare_check: invalid byte size for binary integer field (%u)\n", byte_len); |
... | ... |
@@ -746,10 +717,10 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
746 | 746 |
case CLI_BCOMP_BIN | CLI_BCOMP_BE: |
747 | 747 |
/* exact byte_length option is implied for binary extraction */ |
748 | 748 |
switch (byte_len) { |
749 |
- case 1: value = ( *(int8_t*) buffer); break; |
|
750 |
- case 2: value = (int16_t) be16_to_host( *(int16_t*) buffer); break; |
|
751 |
- case 4: value = (int32_t) be32_to_host( *(int32_t*) buffer); break; |
|
752 |
- case 8: value = (int64_t) be64_to_host( *(int64_t*) buffer); break; |
|
749 |
+ case 1: value = ( *(int8_t*) f_buffer); break; |
|
750 |
+ case 2: value = (int16_t) be16_to_host( *(int16_t*) f_buffer); break; |
|
751 |
+ case 4: value = (int32_t) be32_to_host( *(int32_t*) f_buffer); break; |
|
752 |
+ case 8: value = (int64_t) be64_to_host( *(int64_t*) f_buffer); break; |
|
753 | 753 |
|
754 | 754 |
default: |
755 | 755 |
bcm_dbgmsg("cli_bcomp_compare_check: invalid byte size for binary integer field (%u)\n", byte_len); |
... | ... |
@@ -818,6 +789,165 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
818 | 818 |
} |
819 | 819 |
|
820 | 820 |
/** |
821 |
+ * @brief checks to see if an ascii buffer should be considered hex or not |
|
822 |
+ * |
|
823 |
+ * @param buffer is the buffer to evaluate |
|
824 |
+ * @param opts the bcomp opts bitfield to set/evaluate during the check |
|
825 |
+ * @param len the length of the buffer, must be larger than 3 bytes |
|
826 |
+ * @param check_only specifies whether to return true/false or the modified opt value |
|
827 |
+ * |
|
828 |
+ * @return if check only is set, it will return true or false, otherwise it returns a modifiied byte compare bitfield |
|
829 |
+ */ |
|
830 |
+uint16_t cli_bcomp_chk_hex(const unsigned char* buffer, uint16_t opt, uint32_t len, uint32_t check_only) { |
|
831 |
+ |
|
832 |
+ uint16_t check = 0; |
|
833 |
+ |
|
834 |
+ if (!buffer || len < 3) { |
|
835 |
+ return check_only ? check : opt; |
|
836 |
+ } |
|
837 |
+ |
|
838 |
+ if(!strncmp((char*) buffer, "0x", 2) || !strncmp((char*) buffer, "0X", 2)) { |
|
839 |
+ opt |= CLI_BCOMP_HEX; |
|
840 |
+ check = 1; |
|
841 |
+ } else { |
|
842 |
+ opt |= CLI_BCOMP_DEC; |
|
843 |
+ check = 0; |
|
844 |
+ } |
|
845 |
+ opt ^= CLI_BCOMP_AUTO; |
|
846 |
+ |
|
847 |
+ return check_only ? check : opt; |
|
848 |
+} |
|
849 |
+ |
|
850 |
+/** |
|
851 |
+ * @brief multipurpose buffer normalization support function for bytcompare |
|
852 |
+ * |
|
853 |
+ * Currently can be used to normalize a little endian hex buffer to big endian. |
|
854 |
+ * Can also be used to trim whitespace from the front of the buffer. |
|
855 |
+ * |
|
856 |
+ * @param buffer is the ascii bytes which are to be normalized |
|
857 |
+ * @param byte_len is the length of these bytes |
|
858 |
+ * @param pad_len if the address passed is non-null function will store the amount of whitespace found in bytes |
|
859 |
+ * @param opt the byte compare option bitfield |
|
860 |
+ * @param whitespace_only if true will only do whitespace normalization, will not perform whitespace |
|
861 |
+ * normalization if set to no |
|
862 |
+ * |
|
863 |
+ * @return returns an allocated, normalized buffer or NULL if an allocation error has occurred |
|
864 |
+ */ |
|
865 |
+unsigned char* cli_bcomp_normalize_buffer(const unsigned char* buffer, uint32_t byte_len, uint32_t *pad_len, uint16_t opt, uint16_t whitespace_only) { |
|
866 |
+ uint32_t norm_len = 0; |
|
867 |
+ uint32_t pad = 0; |
|
868 |
+ uint32_t i = 0; |
|
869 |
+ uint16_t opt_val = 0; |
|
870 |
+ uint16_t hex = 0; |
|
871 |
+ unsigned char* tmp_buffer = NULL; |
|
872 |
+ unsigned char* hex_buffer = NULL; |
|
873 |
+ |
|
874 |
+ if (!buffer) { |
|
875 |
+ cli_errmsg("cli_bcomp_compare_check: unable to normalize temp buffer, params null\n"); |
|
876 |
+ return NULL; |
|
877 |
+ } |
|
878 |
+ |
|
879 |
+ if (whitespace_only) { |
|
880 |
+ for(i = 0; i < byte_len; i++) { |
|
881 |
+ if (isspace(buffer[i])) { |
|
882 |
+ bcm_dbgmsg("cli_bcomp_compare_check: buffer has whitespace \n"); |
|
883 |
+ pad++; |
|
884 |
+ } else { |
|
885 |
+ /* break on first non-padding whitespace */ |
|
886 |
+ break; |
|
887 |
+ } |
|
888 |
+ } |
|
889 |
+ /* keep in mind byte_len is a stack variable so this won't change byte_len in our calling functioning */ |
|
890 |
+ byte_len = byte_len - pad; |
|
891 |
+ tmp_buffer = cli_calloc(byte_len+1, sizeof(char)); |
|
892 |
+ if (NULL == tmp_buffer) { |
|
893 |
+ cli_errmsg("cli_bcomp_compare_check: unable to allocate memory for whitespace normalized temp buffer\n"); |
|
894 |
+ return NULL; |
|
895 |
+ } |
|
896 |
+ memset(tmp_buffer, '0', byte_len+1); |
|
897 |
+ memcpy(tmp_buffer, buffer+pad, byte_len); |
|
898 |
+ tmp_buffer[byte_len] = '\0'; |
|
899 |
+ if (pad_len) { |
|
900 |
+ *pad_len = pad; |
|
901 |
+ } |
|
902 |
+ return tmp_buffer; |
|
903 |
+ } |
|
904 |
+ |
|
905 |
+ opt_val = opt & 0x000F; |
|
906 |
+ if (opt_val & CLI_BCOMP_HEX || opt_val & CLI_BCOMP_AUTO) { |
|
907 |
+ norm_len = (byte_len % 2) == 0 ? byte_len : byte_len + 1; |
|
908 |
+ tmp_buffer = cli_calloc(norm_len+1, sizeof(char)); |
|
909 |
+ if (NULL == tmp_buffer) { |
|
910 |
+ cli_errmsg("cli_bcomp_compare_check: unable to allocate memory for normalized temp buffer\n"); |
|
911 |
+ return NULL; |
|
912 |
+ } |
|
913 |
+ |
|
914 |
+ hex_buffer = cli_calloc(norm_len+1, sizeof(char)); |
|
915 |
+ if(NULL == hex_buffer) { |
|
916 |
+ free(tmp_buffer); |
|
917 |
+ cli_errmsg("cli_bcomp_compare_check: unable to reallocate memory for hex buffer\n"); |
|
918 |
+ return NULL; |
|
919 |
+ } |
|
920 |
+ |
|
921 |
+ memset(tmp_buffer, '0', norm_len+1); |
|
922 |
+ memset(hex_buffer, '0', norm_len+1); |
|
923 |
+ |
|
924 |
+ if (byte_len == 1) { |
|
925 |
+ tmp_buffer[0] = buffer[0]; |
|
926 |
+ } else { |
|
927 |
+ |
|
928 |
+ if (norm_len == byte_len + 1) { |
|
929 |
+ opt_val = opt; |
|
930 |
+ if (cli_bcomp_chk_hex(buffer, opt_val, byte_len, 1)) { |
|
931 |
+ memcpy(hex_buffer+3, buffer+2, byte_len-2); |
|
932 |
+ hex_buffer[0] = 'x'; |
|
933 |
+ } else { |
|
934 |
+ memcpy(hex_buffer+1, buffer, byte_len); |
|
935 |
+ } |
|
936 |
+ } else { |
|
937 |
+ opt_val = opt; |
|
938 |
+ memcpy(hex_buffer, buffer, byte_len); |
|
939 |
+ if (cli_bcomp_chk_hex(buffer, opt_val, byte_len, 1)) { |
|
940 |
+ hex_buffer[0] = 'x'; |
|
941 |
+ } |
|
942 |
+ } |
|
943 |
+ |
|
944 |
+ for (i = 0; i < norm_len; i = i+2) { |
|
945 |
+ if (((int32_t) norm_len - (int32_t) i) - 2 >= 0) { |
|
946 |
+ /* 0000BA -> B0000A */ |
|
947 |
+ if ( isxdigit(hex_buffer[norm_len-i-2]) || toupper(hex_buffer[norm_len-i-2]) == 'X' ) { |
|
948 |
+ if ( isxdigit(hex_buffer[norm_len-i-2]) ) { |
|
949 |
+ hex = 1; |
|
950 |
+ } |
|
951 |
+ tmp_buffer[i] = hex_buffer[norm_len-i-2]; |
|
952 |
+ } else { |
|
953 |
+ /* non-hex detected, our current buffer is invalid so zero it out and continue */ |
|
954 |
+ memset(tmp_buffer, '0', norm_len+1); |
|
955 |
+ hex = 0; |
|
956 |
+ } |
|
957 |
+ } |
|
958 |
+ |
|
959 |
+ /* 0000BA -> 0A00B0 */ |
|
960 |
+ if ( isxdigit(hex_buffer[norm_len-i-1]) || toupper(hex_buffer[norm_len-i-1]) == 'X' ) { |
|
961 |
+ if ( isxdigit(hex_buffer[norm_len-i-2]) ) { |
|
962 |
+ hex = 1; |
|
963 |
+ } |
|
964 |
+ tmp_buffer[i+1] = hex_buffer[norm_len-i-1]; |
|
965 |
+ } else { |
|
966 |
+ /* non-hex detected, our current buffer is invalid so zero it out and continue */ |
|
967 |
+ memset(tmp_buffer, '0', norm_len+1); |
|
968 |
+ hex = 0; |
|
969 |
+ } |
|
970 |
+ } |
|
971 |
+ } |
|
972 |
+ tmp_buffer[norm_len+1] = '\0'; |
|
973 |
+ bcm_dbgmsg("cli_bcomp_compare_check: normalized extracted bytes before comparison %.*s\n", byte_len, tmp_buffer); |
|
974 |
+ } |
|
975 |
+ |
|
976 |
+ return tmp_buffer; |
|
977 |
+} |
|
978 |
+ |
|
979 |
+/** |
|
821 | 980 |
* @brief cleans up the byte compare data struct |
822 | 981 |
* |
823 | 982 |
* @param root the root matcher struct whose mempool instance the bcomp struct has been allocated with |
... | ... |
@@ -64,7 +64,10 @@ struct cli_bcomp_comp { |
64 | 64 |
|
65 | 65 |
cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, const char* hexsig, const uint32_t *lsigid, unsigned int options); |
66 | 66 |
cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length, const char **virname, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, cli_ctx *ctx); |
67 |
-cl_error_t cli_bcomp_compare_check(const unsigned char *buffer, size_t buffer_length, int offset, struct cli_bcomp_meta *bm); |
|
67 |
+cl_error_t cli_bcomp_compare_check(const unsigned char *f_buffer, size_t buffer_length, int offset, struct cli_bcomp_meta *bm); |
|
68 | 68 |
void cli_bcomp_freemeta(struct cli_matcher *root, struct cli_bcomp_meta *bm); |
69 |
+uint16_t cli_bcomp_chk_hex(const unsigned char* buffer, uint16_t opt, uint32_t len, uint32_t check_only); |
|
70 |
+unsigned char* cli_bcomp_normalize_buffer(const unsigned char* buffer, uint32_t byte_len, uint32_t *pad_len, uint16_t opt, uint16_t whitespace_only); |
|
71 |
+ |
|
69 | 72 |
|
70 | 73 |
#endif |