Browse code

[WIP] more robust yara string loading

Kevin Lin authored on 2015/02/12 06:08:47
Showing 1 changed files
... ...
@@ -2733,9 +2733,15 @@ static int cli_loadopenioc(FILE *fs, const char *dbname, struct cl_engine *engin
2733 2733
 }
2734 2734
 
2735 2735
 #ifndef _WIN32
2736
-#define YARATARGET0 "Target:0;"
2737
-#define YARATARGET1 "Target:1;"
2738
-#define EPSTR "EP+0:"
2736
+#define YARA_DEBUG 1
2737
+#if YARA_DEBUG == 2
2738
+#define cli_yaramsg(...) cli_errmsg(__VA_ARGS__)
2739
+#elseif YARA_DEBUG == 1
2740
+#define cli_yaramsg(...) cli_dbgmsg(__VA_ARGS__)
2741
+#else
2742
+#define cli_yaramsg(...) 
2743
+#endif
2744
+
2739 2745
 static char *parse_yara_hex_string(YR_STRING *string);
2740 2746
 
2741 2747
 static char *parse_yara_hex_string(YR_STRING *string)
... ...
@@ -2805,250 +2811,362 @@ static char *parse_yara_hex_string(YR_STRING *string)
2805 2805
     return res;
2806 2806
 }
2807 2807
 
2808
+int ytable_add(char ***ytablep, uint32_t *ytbl_cntp)
2809
+{
2810
+}
2811
+
2812
+uint32_t ytable_lookup(char **ytable, uint32_t ytbl_cnt)
2813
+{
2814
+}
2815
+
2816
+void ytable_delete(char **ytable, uint32_t ytbl_cnt)
2817
+{
2818
+    uint32_t i;
2819
+
2820
+    if (ytable) {
2821
+        for (i = 0; i < ytbl_cnt; ++i)
2822
+            free(ytable[i]);
2823
+        free(ytable);
2824
+    }
2825
+}
2826
+
2808 2827
 static unsigned int yara_total, yara_malform, yara_complex; 
2828
+#define YARATARGET0 "Target:0"
2829
+#define YARATARGET1 "Target:1"
2830
+#define EPSTR "EP+0:"
2809 2831
 
2810
-static int cli_loadyara(FILE *fs, const char *dbname, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
2832
+/* yara has no apparent cap on the number of strings; TODO - should we have one? */
2833
+/* function base off load_oneldb */
2834
+static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int options, unsigned int *sigs)
2811 2835
 {
2812
-    char buffer[FILEBUFF];
2813
-    char * current_rule = NULL;
2814
-    char * current_meta = NULL;
2815
-    char * current_string = NULL;
2816
-    char * current_condition = NULL;
2817
-    int rc = CL_SUCCESS;
2818
-    uint32_t line = 0;
2819
-    uint8_t is_comment;
2820
-    uint8_t rule_state;
2821
-    YR_COMPILER compiler = {0};
2822
-    YR_RULE * rule;
2823
-    YR_STRING * string;
2824
-    size_t nstrings, allstringsize, totsize;
2825
-    char *rulestr, *ruledup;
2826
-    unsigned int sigs, i;
2827
-    uint8_t has_short_string;
2828
-    char * exp_op = "|";
2836
+    YR_STRING *string;
2837
+    int str_error = 0, i = 0, ret = CL_SUCCESS;
2838
+    struct cli_lsig_tdb tdb;
2839
+    uint32_t lsigid[2];
2840
+    struct cli_matcher *root;
2841
+    struct cli_ac_lsig **newtable, *lsig;
2842
+    unsigned short target = 0;
2843
+    size_t lsize;
2844
+    char *logic = NULL;
2845
+    char *exp_op = "|";
2846
+    char *offset;
2829 2847
 
2830
-    if((rc = cli_initroots(engine, options)))
2831
-        return rc;
2848
+    char **ytable = NULL;
2849
+    uint32_t ytbl_cnt = 0;
2832 2850
 
2833
-    compiler.last_result = ERROR_SUCCESS;
2834
-    STAILQ_INIT(&compiler.rules);
2835
-    STAILQ_INIT(&compiler.current_rule_strings);
2851
+    cli_yaramsg("called load_oneyara()\n");
2836 2852
 
2837
-    //    cli_errmsg("Loading yara signatures\n");
2838
-#if 1 /* for compilation */
2839
-    yr_lex_parse_rules_file(fs, &compiler);
2840
-#endif
2841
-    while (!STAILQ_EMPTY(&compiler.rules)) {
2842
-        yara_total++;
2843
-        sigs=0;
2844
-        nstrings=0;
2845
-        rule = STAILQ_FIRST(&compiler.rules);
2846
-        STAILQ_REMOVE(&compiler.rules, rule, _yc_rule, link);
2853
+    if (!rule) {
2854
+        cli_errmsg("load_oneyara: empty rule passed as argument\n");
2855
+        return CL_ENULLARG;
2856
+    }
2847 2857
 
2848
-        /* First find out how long our dynamically-build ldb string should be */
2849
-        allstringsize = 0;
2850
-        totsize = strlen(rule->id) + 2 + strlen(YARATARGET0);
2851
-        STAILQ_FOREACH(string, &rule->strings, link) {
2852
-            nstrings++;
2853
-            if (STRING_IS_HEX(string)) {
2854
-                size_t len = strlen(string->string);
2855
-                for (i=0; i < len; i++) {
2856
-                    int ch = string->string[i];
2857
-                    if (!isspace(ch))
2858
-                        allstringsize++;
2859
-                }
2860
-            } else if (STRING_IS_REGEXP(string)) {
2861
-                char *trigger = PCRE_BYPASS;
2862
-                allstringsize += strlen(trigger);
2863
-                allstringsize += (strlen(string->string)+2); /* 2 from delimiters */
2864
-            } else if (STRING_IS_NO_CASE(string)) {
2865
-                allstringsize += (strlen(string->string)+2); /* 2 from delimiter+option */
2866
-            } else {
2867
-                allstringsize += strlen(string->string);
2858
+    /* PUA stuff, for the future
2859
+    if (chkpua && cli_chkpua(rule->id, engine->pua_cats, options))
2860
+        return CL_SUCCESS;
2861
+
2862
+    if (engine->ignored && cli_chkign(engine->ignored, rule->id, buffer_cpy ? buffer_cpy : rule->id)) {
2863
+        if(skip)
2864
+            *skip = 1;
2865
+        return CL_SUCCESS;
2866
+    }
2867
+    */
2868
+
2869
+    /*** rule specific checks ***/
2870
+    if (RULE_IS_PRIVATE(rule) || RULE_IS_GLOBAL(rule) || RULE_IS_NULL(rule) ||
2871
+        ((rule->g_flags) & RULE_GFLAGS_REQUIRE_FILE) || ((rule->g_flags) & RULE_GFLAGS_REQUIRE_EXECUTABLE)) {
2872
+
2873
+        cli_warnmsg("load_oneyara: skipping %s due to unsupported rule gflags\n", rule->id);
2874
+        (*sigs)--;
2875
+        return CL_SUCCESS;
2876
+    }
2877
+
2878
+    if(engine->cb_sigload && engine->cb_sigload("yara", rule->id, ~options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
2879
+        cli_dbgmsg("load_oneyara: skipping %s due to callback\n", rule->id);
2880
+        (*sigs)--;
2881
+        return CL_SUCCESS;
2882
+    }
2883
+
2884
+    /*** verification step - can clamav load it?       ***/
2885
+    /*** initial population pass for the strings table ***/
2886
+    STAILQ_FOREACH(string, &rule->strings, link) {
2887
+        char *substr;
2888
+
2889
+        /* string type handler */
2890
+        if (STRING_IS_NULL(string)) {
2891
+            cli_warnmsg("load_oneyara: skipping NULL string %s\n", rule->id);
2892
+            //str_error++; /* kill the insertion? */
2893
+            continue;
2894
+        } else if (STRING_IS_HEX(string)) {
2895
+            substr = parse_yara_hex_string(string);
2896
+            if (substr) {
2897
+                /*
2898
+                if (strlen(substr)/2 <= CLI_DEFAULT_AC_MINDEPTH)  //FIXME: Yara has no length minimum
2899
+                    has_short_string = 1;
2900
+                snprintf(rulestr+len, totsize-len, "%s", substr);
2901
+                free(substr);
2902
+                */
2868 2903
             }
2869
-        }
2870 2904
 
2871
-        if (!nstrings) {
2872
-            cli_errmsg("Rule %s contains to readable strings\n", rule->id);
2873
-#ifdef YARA_PROTO
2874
-            yara_malform++;
2875
-            free(rule->id);
2876
-            free(rule);
2905
+            cli_yaramsg("Yara hex string: \"%s\"\n", substr);
2906
+        } else if (STRING_IS_LITERAL(string)) {
2907
+        } else if (STRING_IS_REGEXP(string)) {
2908
+        } else {
2909
+            cli_warnmsg("load_oneyara: skipping undefined typed string %s\n", rule->id);
2910
+            //str_error++; /* kill the insertion? */
2877 2911
             continue;
2878
-#else
2879
-            return CL_EMALFDB;
2880
-#endif
2881 2912
         }
2882 2913
 
2883
-        /* ldb can only handle MAX_LDB_SUBSIGS(currently 64) substrings */
2884
-        if (nstrings > MAX_LDB_SUBSIGS) {
2885
-            cli_errmsg("cli_loadyara: rule %s exceeds MAX_LDB_SUBSIGS maximum strings - skipping.\n", rule->id);
2886
-            free(rule->id);
2887
-            free(rule);
2914
+        /* modifier handler */
2915
+        if (STRING_IS_NO_CASE(string)) {
2916
+        }
2917
+        if (STRING_IS_ASCII(string)) {
2918
+        }
2919
+        if (STRING_IS_WIDE(string)) {
2920
+        }
2921
+        if (STRING_IS_FULL_WORD(string)) {
2922
+        }
2923
+
2924
+        /* special modifier handler */
2925
+        if (STRING_IS_ANONYMOUS(string)) { /* empty */ }
2926
+
2927
+        /* unsupported(?) modifier handler */
2928
+        if (STRING_IS_REFERENCED(string) || STRING_IS_SINGLE_MATCH(string) || STRING_IS_FAST_HEX_REGEXP(string) ||
2929
+            STRING_IS_CHAIN_PART(string) || STRING_IS_CHAIN_TAIL(string) || STRING_FITS_IN_ATOM(string)) {
2930
+            cli_warnmsg("load_oneyara: skipping unsupported string %s\n", rule->id);
2931
+            str_error++;
2932
+            free(substr);
2888 2933
             continue;
2889 2934
         }
2935
+    }
2890 2936
 
2891
-        allstringsize *= 2; /* For converting to hex */
2892
-        totsize += allstringsize;
2893
-        totsize += (nstrings * 3); /* 3 for |; */
2894
-        if (nstrings > 10)
2895
-            totsize += nstrings-10;
2896
-        totsize++;
2937
+    if (str_error > 0) {
2938
+        cli_errmsg("load_oneyara: clamav does not support %d input strings\n", str_error);
2939
+        ytable_delete(ytable, ytbl_cnt);
2940
+        (*sigs)--;
2941
+        return CL_SUCCESS; /* TODO - kill signature instead? */
2942
+    } else if (ytbl_cnt == 0) {
2943
+        cli_errmsg("load_oneyara: yara contains no supported strings\n");
2944
+        ytable_delete(ytable, ytbl_cnt);
2945
+        (*sigs)--;
2946
+        return CL_SUCCESS; /* TODO - kill signature instead? */
2947
+    }
2897 2948
 
2898
-#ifdef YARA_PROTO
2899
-        if (rule->g_flags & RULE_EP && nstrings == 1)
2900
-            totsize += strlen(EPSTR);
2901
-#endif
2949
+    /*** conditional verification step (ex. do we define too many strings versus used?)  ***/
2950
+    /*** additional string table population (ex. offsets), second translation table pass ***/
2902 2951
 
2903
-        rulestr = cli_calloc(totsize, sizeof(char));
2904
-        if (!rulestr) {
2905
-            free(rule->id);
2906
-            free(rule);
2907
-            rc = CL_EMEM;
2908
-            break;
2952
+    lsize = 3*ytbl_cnt;
2953
+    logic = cli_calloc(lsize, sizeof(char));
2954
+    if (!logic) {
2955
+        cli_errmsg("load_oneyara: cannot allocate memory for logic statement\n");
2956
+        ytable_delete(ytable, ytbl_cnt);
2957
+        return CL_EMEM;
2958
+    }
2959
+
2960
+    if (rule->g_flags & RULE_ALL && rule->g_flags & RULE_THEM)
2961
+        exp_op = "&";
2962
+    else {
2963
+        exp_op = "|";
2964
+        if ((!(rule->g_flags & RULE_ANY && rule->g_flags & RULE_THEM) && ytbl_cnt > 1) &&
2965
+            !(rule->g_flags & RULE_EP && ytbl_cnt == 1))
2966
+            yara_complex++;
2967
+    }
2968
+
2969
+    for (i=0; i<ytbl_cnt; i++) {
2970
+        size_t len=strlen(logic);
2971
+        snprintf(logic+len, lsize-len, "%u%s", i, (i+1 == ytbl_cnt) ? "" : exp_op);
2972
+    }    
2973
+
2974
+    /*** END CONDITIONAL HANDLING ***/
2975
+
2976
+    /* TDB */
2977
+    memset(&tdb, 0, sizeof(tdb));
2978
+#ifdef USE_MPOOL
2979
+    tdb.mempool = engine->mempool;
2980
+#endif
2981
+    if((ret = lsigattribs(YARATARGET0, &tdb))) {
2982
+        FREE_TDB(tdb);
2983
+        if(ret == 1) {
2984
+            cli_dbgmsg("load_oneyara: Not supported attribute(s) in logical signature for %s, skipping\n", rule->id);
2985
+            ytable_delete(ytable, ytbl_cnt);
2986
+            free(logic);
2987
+            (*sigs)--;
2988
+            return CL_SUCCESS;
2909 2989
         }
2990
+        return CL_EMALFDB;
2991
+    }
2910 2992
 
2911
-#ifdef YARA_PROTO
2912
-        if (rule->g_flags & RULE_ALL && rule->g_flags & RULE_THEM)
2913
-            exp_op = "&";
2914
-        else {
2915
-            exp_op = "|";
2916
-            if ((!(rule->g_flags & RULE_ANY && rule->g_flags & RULE_THEM) && nstrings > 1) &&
2917
-                !(rule->g_flags & RULE_EP && nstrings == 1))
2918
-                yara_complex++;
2993
+    if(tdb.engine) {
2994
+        if(tdb.engine[0] > cl_retflevel()) {
2995
+            cli_dbgmsg("load_oneyara: Signature for %s not loaded (required f-level: %u)\n", rule->id, tdb.engine[0]);
2996
+            FREE_TDB(tdb);
2997
+            ytable_delete(ytable, ytbl_cnt);
2998
+            free(logic);
2999
+            (*sigs)--;
3000
+            return CL_SUCCESS;
3001
+        } else if(tdb.engine[1] < cl_retflevel()) {
3002
+            FREE_TDB(tdb);
3003
+            ytable_delete(ytable, ytbl_cnt);
3004
+            free(logic);
3005
+            (*sigs)--;
3006
+            return CL_SUCCESS;
2919 3007
         }
2920
-        if (rule->g_flags & RULE_EP)
2921
-            sprintf(rulestr, "%s;%s(", rule->id, YARATARGET1);
2922
-        else
2923
-#endif
2924
-        sprintf(rulestr, "%s;%s(", rule->id, YARATARGET0);
2925
-        for (i=0; i<nstrings; i++) {
2926
-            size_t len=strlen(rulestr);
2927
-            snprintf(rulestr+len, totsize-len, "%u%s", i, (i+1 == nstrings) ? "" : exp_op);
3008
+    }
3009
+
3010
+    if(!tdb.target) {
3011
+        cli_errmsg("load_oneyara: No target specified in TDB\n");
3012
+        FREE_TDB(tdb);
3013
+        ytable_delete(ytable, ytbl_cnt);
3014
+        free(logic);
3015
+        return CL_EMALFDB;
3016
+    } else if(tdb.target[0] >= CLI_MTARGETS) {
3017
+        cli_dbgmsg("load_oneyara: Not supported target type in logical signature for %s, skipping\n", rule->id);
3018
+        FREE_TDB(tdb);
3019
+        ytable_delete(ytable, ytbl_cnt);
3020
+        free(logic);
3021
+        (*sigs)--;
3022
+        return CL_SUCCESS;
3023
+    }
3024
+
3025
+    if((tdb.icongrp1 || tdb.icongrp2) && tdb.target[0] != 1) {
3026
+        cli_errmsg("load_oneyara: IconGroup is only supported in PE (target 1) signatures\n");
3027
+        FREE_TDB(tdb);
3028
+        ytable_delete(ytable, ytbl_cnt);
3029
+        free(logic);
3030
+        return CL_EMALFDB;
3031
+    }
3032
+
3033
+    if((tdb.ep || tdb.nos) && tdb.target[0] != 1 && tdb.target[0] != 6 && tdb.target[0] != 9) {
3034
+        cli_errmsg("load_oneyara: EntryPoint/NumberOfSections is only supported in PE/ELF/Mach-O signatures\n");
3035
+        FREE_TDB(tdb);
3036
+        ytable_delete(ytable, ytbl_cnt);
3037
+        free(logic);
3038
+        return CL_EMALFDB;
3039
+    }
3040
+
3041
+    /*** populating lsig ***/
3042
+    root = engine->root[tdb.target[0]];
3043
+
3044
+    lsig = (struct cli_ac_lsig *) mpool_calloc(engine->mempool, 1, sizeof(struct cli_ac_lsig));
3045
+    if(!lsig) {
3046
+        cli_errmsg("load_oneyara: Can't allocate memory for lsig\n");
3047
+        FREE_TDB(tdb);
3048
+        ytable_delete(ytable, ytbl_cnt);
3049
+        free(logic);
3050
+        return CL_EMEM;
3051
+    }
3052
+
3053
+    if (logic) {
3054
+        lsig->type = CLI_NORMAL_LSIG;
3055
+        lsig->u.logic = cli_mpool_strdup(engine->mempool, logic);
3056
+        if(!lsig->u.logic) {
3057
+            cli_errmsg("load_oneyara: Can't allocate memory for lsig->logic\n");
3058
+            FREE_TDB(tdb);
3059
+            ytable_delete(ytable, ytbl_cnt);
3060
+            free(logic);
3061
+            mpool_free(engine->mempool, lsig);
3062
+            return CL_EMEM;
2928 3063
         }
3064
+    } else {
3065
+            cli_errmsg("load_oneyara: Unsupported logic type\n");
3066
+            FREE_TDB(tdb);
3067
+            ytable_delete(ytable, ytbl_cnt);
3068
+            free(logic);
3069
+            mpool_free(engine->mempool, lsig);
3070
+            return CL_EMEM;
3071
+    }
3072
+    free(logic);
2929 3073
 
2930
-        strcat(rulestr, ");");
3074
+    lsigid[0] = lsig->id = root->ac_lsigs;
2931 3075
 
2932
-        has_short_string = 0;
2933
-        int dcount = 0;
2934
-        while (!STAILQ_EMPTY(&rule->strings)) {
2935
-            string = STAILQ_FIRST(&rule->strings);
2936
-            STAILQ_REMOVE(&rule->strings, string, _yc_string, link);
3076
+    root->ac_lsigs++;
3077
+    newtable = (struct cli_ac_lsig **) mpool_realloc(engine->mempool, root->ac_lsigtable, root->ac_lsigs * sizeof(struct cli_ac_lsig *));
3078
+    if(!newtable) {
3079
+        root->ac_lsigs--;
3080
+        cli_errmsg("cli_loadldb: Can't realloc root->ac_lsigtable\n");
3081
+        FREE_TDB(tdb);
3082
+        ytable_delete(ytable, ytbl_cnt);
3083
+        mpool_free(engine->mempool, lsig);
3084
+        return CL_EMEM;
3085
+    }
2937 3086
 
2938
-#if 0
2939
-            cli_errmsg("%i:", ++dcount);
2940
-#endif
2941
-#ifdef YARA_PROTO
2942
-            if (rule->g_flags & RULE_EP && nstrings == 1) {
2943
-                size_t len = strlen(rulestr);
2944
-                snprintf(rulestr+len, totsize-len, "%s", EPSTR);
2945
-            }
2946
-#endif
3087
+    newtable[root->ac_lsigs - 1] = lsig;
3088
+    root->ac_lsigtable = newtable;
3089
+    tdb.subsigs = ytbl_cnt;
2947 3090
 
2948
-            if (STRING_IS_HEX(string)) {
2949
-                char *substr;
2950
-                size_t len = strlen(rulestr);
3091
+    /*** loading step - put things into the AC trie ***/
3092
+    for (i = 0; i < ytbl_cnt; ++i) {
3093
+        lsigid[1] = i;
2951 3094
 
2952
-                substr = parse_yara_hex_string(string);
2953
-#if 0
2954
-                cli_errmsg("Yara hex string: \"%s\"\n", substr);
2955
-#endif
2956
-                if (substr) {
2957
-                    if (strlen(substr)/2 <= CLI_DEFAULT_AC_MINDEPTH)  //FIXME: Yara has no length minimum
2958
-                        has_short_string = 1;
2959
-                    snprintf(rulestr+len, totsize-len, "%s", substr);
2960
-                    free(substr);
2961
-                }
2962
-            } else if (STRING_IS_REGEXP(string)) {
2963
-                size_t len = strlen(rulestr);
2964
-#if 0
2965
-                cli_errmsg("Yara regex string: \"%s\"\n", string->string);
2966
-#endif
2967
-                snprintf(rulestr+len, totsize-len, "%s/%s/", PCRE_BYPASS, string->string);
2968
-            } else if (STRING_IS_NO_CASE(string)) {
2969
-                size_t len;
2970
-#if 0
2971
-                cli_errmsg("Yara nocase string: \"%s\"\n", string->string);
2972
-#endif
2973
-                if (strlen(string->string) <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum
2974
-                    has_short_string = 1;
2975
-                for (i=0; i < strlen(string->string); i++) {
2976
-                    len = strlen(rulestr);
2977
-                    snprintf(rulestr+len, totsize-len, "%02x", string->string[i]);
2978
-                }
3095
+        /* TODO - offsets as separate table or integrated into ytable[i]? */
3096
+        offset = "*";
2979 3097
 
2980
-                len = strlen(rulestr);
2981
-                snprintf(rulestr+len, totsize-len, "/i");
2982
-            } else {
2983
-#if 0
2984
-                cli_errmsg("Yara literal string: \"%s\"\n", string->string);
2985
-#endif
2986
-                if (strlen(string->string) <= CLI_DEFAULT_AC_MINDEPTH) //FIXME: Yara has no length minimum
2987
-                    has_short_string = 1;
2988
-                for (i=0; i < strlen(string->string); i++) {
2989
-                    size_t len = strlen(rulestr);
2990
-                    snprintf(rulestr+len, totsize-len, "%02x", string->string[i]);
2991
-                }
2992
-            }
3098
+        /* TODO - options as separate table or integrated into ytable[i]? */
2993 3099
 
2994
-            if (!STAILQ_EMPTY(&rule->strings))
2995
-                strcat(rulestr, ";");
3100
+        if((ret = cli_parse_add(root, rule->id, ytable[i], NULL, 0, 0, offset, target, lsigid, options)))
3101
+            return ret;
3102
+    }
2996 3103
 
2997
-            free(string->id);
2998
-            free(string->string);
2999
-            free(string);
3000
-        }
3104
+    memcpy(&lsig->tdb, &tdb, sizeof(tdb));
3105
+    ytable_delete(ytable, ytbl_cnt);
3106
+    return CL_SUCCESS;
3107
+}
3001 3108
 
3002
-        if (rulestr[strlen(rulestr)-1] == ';')
3003
-            rulestr[strlen(rulestr)-1] = '\0';
3109
+//TODO - pua? dbio?
3110
+static int cli_loadyara(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio, const char *dbname)
3111
+{
3112
+    YR_COMPILER compiler = {0};
3113
+    YR_RULE *rule;
3114
+    unsigned int sigs = 0, rules = 0;
3115
+    int rc;
3004 3116
 
3005
-#if 0
3006
-        printf("[+] computed ldb: \"%s\"\n", rulestr);
3007
-#endif
3008
-        ruledup = cli_malloc(strlen(rulestr)+1);
3009
-        if (!ruledup) {
3010
-            free(rulestr);
3011
-            free(rule->id);
3012
-            free(rule);
3013
-            rc = CL_EMEM;
3014
-            break;
3015
-        }
3117
+    UNUSEDPARAM(dbio);
3016 3118
 
3017
-        strcpy(ruledup, rulestr);
3119
+    if((rc = cli_initroots(engine, options)))
3120
+        return rc;
3018 3121
 
3019
-        if (has_short_string == 0) {
3020
-#if 1
3021
-            rc = load_oneldb(rulestr,
3022
-                 engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)),
3023
-                 engine, options, rule->id, line++, &sigs, 0, ruledup, NULL);
3024
-#endif
3122
+    compiler.last_result = ERROR_SUCCESS;
3123
+    STAILQ_INIT(&compiler.rules);
3124
+    STAILQ_INIT(&compiler.current_rule_strings);
3025 3125
 
3026
-        }
3027
-        else {
3028
-            cli_errmsg("cli_loadyara: has short strings, rule %s excluded\n", rulestr);
3029
-        }
3030
-#if 0
3031
-        printf("totsize: %zu\treal size: %zu\n", totsize, strlen(ruledup));
3032
-#endif
3126
+    rc = yr_lex_parse_rules_file(fs, &compiler);
3127
+    if (rc > 0) { /* rc = number of errors */
3128
+        /* TODO - handle the various errors? */
3129
+        cli_errmsg("cli_loadyara: failed to parse rules file\n");
3130
+        return CL_EMALFDB;
3131
+    }
3033 3132
 
3034
-        free(rulestr);
3035
-        free(ruledup);
3036
-        free(rule->id);
3037
-        free(rule);
3038
-#ifdef YARA_PROTO
3039
-        if (rc == CL_EMALFDB) {
3040
-            yara_malform++;
3041
-            cli_errmsg("+++++++++++++ load_oneldb returns CL_EMALFORMDB +++++++++++++\n");
3042
-            rc = CL_SUCCESS;
3043
-            continue;
3044
-        }
3045
-#endif
3133
+    while (!STAILQ_EMPTY(&compiler.rules)) {
3134
+        rule = STAILQ_FIRST(&compiler.rules);
3135
+        STAILQ_REMOVE(&compiler.rules, rule, _yc_rule, link);
3136
+
3137
+        rules++;
3138
+        sigs++;
3139
+
3140
+        /* TODO - PUA and engine->ignored */
3141
+        rc = load_oneyara(rule, engine, options, &sigs);
3046 3142
         if (rc != CL_SUCCESS)
3047 3143
             break;
3048 3144
     }
3049 3145
 
3050
-    return rc;
3146
+    if(rc) {
3147
+        cli_errmsg("cli_loadyara: problem parsing yara rule %s\n", rule->id);
3148
+        return rc;
3149
+    }
3150
+
3151
+    if(!rules) {
3152
+        cli_errmsg("cli_loadyara: empty database file\n");
3153
+        return CL_EMALFDB;
3154
+    }
3155
+
3156
+    if(signo)
3157
+        *signo += sigs;
3158
+
3159
+    cli_yaramsg("Successfully loaded %u of %u yara signatures from %s\n", sigs, rules, dbname);
3160
+
3161
+    return CL_SUCCESS;
3051 3162
 }
3163
+
3052 3164
 #endif
3053 3165
 
3054 3166
 static int cli_loaddbdir(const char *dirname, struct cl_engine *engine, unsigned int *signo, unsigned int options);
... ...
@@ -3183,7 +3301,7 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
3183 3183
 	ret = cli_loadopenioc(fs, dbname, engine, options);
3184 3184
 #ifndef _WIN32 /* FIXME: temp until clam yara for windows */
3185 3185
     } else if(cli_strbcasestr(dbname, ".yar") || cli_strbcasestr(dbname, ".yara")) {
3186
-        ret = cli_loadyara(fs, dbname, engine, options, dbio);
3186
+        ret = cli_loadyara(fs, engine, signo, options, dbio, dbname);
3187 3187
 #endif
3188 3188
     } else {
3189 3189
 	cli_dbgmsg("cli_load: unknown extension - assuming old database format\n");