[Forensics-changes] [yara] 43/415: Implemented external variables

Hilko Bengen bengen at moszumanska.debian.org
Thu Apr 3 05:42:41 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch debian
in repository yara.

commit b52681a63bd247fd532e58e435e688a02197347e
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Sat Oct 31 23:51:53 2009 +0000

    Implemented external variables
---
 Makefile                  |  10 +--
 libyara/Makefile          |  20 ++---
 libyara/ast.c             |  64 ++++++++++++++--
 libyara/ast.h             |  12 ++-
 libyara/eval.c            |  14 +++-
 libyara/grammar.c         |  25 +++----
 libyara/grammar.y         |  25 +++----
 libyara/libtool           | 130 ++++++++++++++++----------------
 libyara/libyara.c         | 116 ++++++++++++++++++++++++++++-
 libyara/yara.h            |  76 +++++++++++++------
 yara-python/README        |   2 +-
 yara-python/yara-python.c | 186 ++++++++++++++++++++++++++--------------------
 yara.c                    |  83 ++++++++++++++++-----
 yara.man                  |  35 ++++-----
 14 files changed, 536 insertions(+), 262 deletions(-)

diff --git a/Makefile b/Makefile
index 7160bf0..6b98c4a 100644
--- a/Makefile
+++ b/Makefile
@@ -91,7 +91,7 @@ AUTOCONF = ${SHELL} /Users/plusvic/Projects/yara/missing --run autoconf
 AUTOHEADER = ${SHELL} /Users/plusvic/Projects/yara/missing --run autoheader
 AUTOMAKE = ${SHELL} /Users/plusvic/Projects/yara/missing --run automake-1.10
 AWK = awk
-CC = gcc
+CC = gcc -m32 -march=i686
 CCDEPMODE = depmode=gcc3
 CFLAGS = -g -O2
 CPPFLAGS = 
@@ -107,7 +107,7 @@ INSTALL_DATA = ${INSTALL} -m 644
 INSTALL_PROGRAM = ${INSTALL}
 INSTALL_SCRIPT = ${INSTALL}
 INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
-LDFLAGS = 
+LDFLAGS = -m32
 LIBOBJS = 
 LIBS = -lpcre -lpcre -lpcre -lpcre 
 LTLIBOBJS = 
@@ -123,13 +123,13 @@ PACKAGE_VERSION = 1.3
 PATH_SEPARATOR = :
 SET_MAKE = 
 SHELL = /bin/sh
-STRIP = 
+STRIP = strip
 VERSION = 1.3
 abs_builddir = /Users/plusvic/Projects/yara
 abs_srcdir = /Users/plusvic/Projects/yara
 abs_top_builddir = /Users/plusvic/Projects/yara
 abs_top_srcdir = /Users/plusvic/Projects/yara
-ac_ct_CC = gcc
+ac_ct_CC = 
 am__include = include
 am__leading_dot = .
 am__quote = 
@@ -143,7 +143,7 @@ datarootdir = ${prefix}/share
 docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
 dvidir = ${docdir}
 exec_prefix = ${prefix}
-host_alias = 
+host_alias = i686
 htmldir = ${docdir}
 includedir = ${prefix}/include
 infodir = ${datarootdir}/info
diff --git a/libyara/Makefile b/libyara/Makefile
index 6c85c2d..b6c67f0 100644
--- a/libyara/Makefile
+++ b/libyara/Makefile
@@ -32,7 +32,7 @@ NORMAL_UNINSTALL = :
 PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = i386-apple-darwin10.0.0
-host_triplet = i386-apple-darwin10.0.0
+host_triplet = i686-pc-none
 subdir = .
 DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -104,10 +104,10 @@ AUTOCONF = ${SHELL} /Users/plusvic/Projects/yara/libyara/missing --run autoconf
 AUTOHEADER = ${SHELL} /Users/plusvic/Projects/yara/libyara/missing --run autoheader
 AUTOMAKE = ${SHELL} /Users/plusvic/Projects/yara/libyara/missing --run automake-1.10
 AWK = awk
-CC = gcc
+CC = gcc -m32 -march=i686
 CCDEPMODE = depmode=gcc3
 CFLAGS = -g -O2
-CPP = gcc -E
+CPP = gcc -m32 -march=i686 -E
 CPPFLAGS = 
 CXX = g++
 CXXCPP = g++ -E
@@ -130,7 +130,7 @@ INSTALL_DATA = ${INSTALL} -m 644
 INSTALL_PROGRAM = ${INSTALL}
 INSTALL_SCRIPT = ${INSTALL}
 INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
-LDFLAGS = 
+LDFLAGS = -m32
 LEX = flex
 LEXLIB = -lfl
 LEX_OUTPUT_ROOT = lex.yy
@@ -160,7 +160,7 @@ abs_builddir = /Users/plusvic/Projects/yara/libyara
 abs_srcdir = /Users/plusvic/Projects/yara/libyara
 abs_top_builddir = /Users/plusvic/Projects/yara/libyara
 abs_top_srcdir = /Users/plusvic/Projects/yara/libyara
-ac_ct_CC = gcc
+ac_ct_CC = 
 ac_ct_CXX = g++
 ac_ct_F77 = 
 am__include = include
@@ -180,11 +180,11 @@ datarootdir = ${prefix}/share
 docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
 dvidir = ${docdir}
 exec_prefix = ${prefix}
-host = i386-apple-darwin10.0.0
-host_alias = 
-host_cpu = i386
-host_os = darwin10.0.0
-host_vendor = apple
+host = i686-pc-none
+host_alias = i686
+host_cpu = i686
+host_os = none
+host_vendor = pc
 htmldir = ${docdir}
 includedir = ${prefix}/include
 infodir = ${datarootdir}/info
diff --git a/libyara/ast.c b/libyara/ast.c
index 1779bef..f9f20fe 100644
--- a/libyara/ast.c
+++ b/libyara/ast.c
@@ -25,7 +25,7 @@ GNU General Public License for more details.
 
 #define todigit(x)  ((x) >='A'&& (x) <='F')? ((unsigned char) (x - 'A' + 10)) : ((unsigned char) (x - '0'))
 
-RULE* lookup_rule(RULE_LIST* rules, char* identifier, NAMESPACE* namespace)
+RULE* lookup_rule(RULE_LIST* rules, const char* identifier, NAMESPACE* namespace)
 {
     RULE* rule = rules->head;
     
@@ -43,7 +43,7 @@ RULE* lookup_rule(RULE_LIST* rules, char* identifier, NAMESPACE* namespace)
     return NULL;
 }
 
-META* lookup_meta(META* meta_list_head, char* identifier)
+META* lookup_meta(META* meta_list_head, const char* identifier)
 {
     META* meta = meta_list_head;
     
@@ -61,7 +61,7 @@ META* lookup_meta(META* meta_list_head, char* identifier)
 }
 
 
-STRING* lookup_string(STRING* string_list_head, char* identifier)
+STRING* lookup_string(STRING* string_list_head, const char* identifier)
 {
     STRING* string = string_list_head;
     
@@ -78,7 +78,7 @@ STRING* lookup_string(STRING* string_list_head, char* identifier)
     return NULL;
 }
 
-TAG* lookup_tag(TAG* tag_list_head, char* identifier)
+TAG* lookup_tag(TAG* tag_list_head, const char* identifier)
 {
     TAG* tag = tag_list_head;
     
@@ -95,6 +95,23 @@ TAG* lookup_tag(TAG* tag_list_head, char* identifier)
     return NULL;
 }
 
+EXTERNAL_VARIABLE* lookup_external_variable(EXTERNAL_VARIABLE* ext_var_list_head, const char* identifier)
+{
+    EXTERNAL_VARIABLE* ext_var = ext_var_list_head;
+    
+    while (ext_var != NULL)
+    {
+        if (strcmp(ext_var->identifier, identifier) == 0)
+        {
+            return ext_var;
+        }
+            
+        ext_var = ext_var->next;
+    }
+    
+    return NULL;
+}
+
 
 int require_exe_file(TERM* term)
 {	
@@ -496,7 +513,7 @@ int new_text_string(    YARA_CONTEXT* context,
          }
          else /* compilation failed */
          {
-             strcpy(context->last_error_extra_info, error);
+             strncpy(context->last_error_extra_info, error, sizeof(context->last_error_extra_info));
              result = ERROR_INVALID_REGULAR_EXPRESSION;
          }
      }
@@ -707,12 +724,45 @@ int new_string_identifier(int type, STRING* defined_strings, char* identifier, T
     return result;
 }
 
+
+int new_external_variable(YARA_CONTEXT* context, char* identifier, TERM_EXTERNAL_VARIABLE** term)
+{
+    TERM_EXTERNAL_VARIABLE* new_term = NULL;
+    EXTERNAL_VARIABLE* ext_var;
+    int result = ERROR_SUCCESS;
+    
+    ext_var = lookup_external_variable(context->external_variables, identifier);
+    
+    if (ext_var != NULL) /* external variable should be defined */
+    {    
+        new_term = (TERM_EXTERNAL_VARIABLE*) yr_malloc(sizeof(TERM_EXTERNAL_VARIABLE));
+
+        if (new_term != NULL)
+        {
+            new_term->type = TERM_TYPE_EXTERNAL_VARIABLE;
+            new_term->variable = ext_var;
+        }
+        else
+        {
+            result = ERROR_INSUFICIENT_MEMORY;
+        }
+    }
+    else
+    {
+        strncpy(context->last_error_extra_info, identifier, sizeof(context->last_error_extra_info));
+        result = ERROR_UNDEFINED_IDENTIFIER;
+    }
+    
+    *term = new_term;
+    return result;    
+}
+
 /* 
 	free_term(TERM* term)
 
 	Frees a term. If the term depends on other terms they are also freed. Notice that
-	some terms hold references to STRING structures, but these structures are freed
-	by yr_free_rule_list, not by this function.
+	some terms hold references to STRING or EXTERNAL_VARIABLE structures, but these 
+	structures are freed by yr_destroy_context not by this function.
 	
 */
 
diff --git a/libyara/ast.h b/libyara/ast.h
index fad254b..c5330af 100644
--- a/libyara/ast.h
+++ b/libyara/ast.h
@@ -73,9 +73,9 @@ GNU General Public License for more details.
 #define TERM_TYPE_UINT8_AT_OFFSET                    29
 #define TERM_TYPE_UINT16_AT_OFFSET                   30
 #define TERM_TYPE_UINT32_AT_OFFSET                   31
+#define TERM_TYPE_EXTERNAL_VARIABLE                  32
                   
 
-
 typedef struct _TERM_CONST
 {
 	int				type;
@@ -129,6 +129,14 @@ typedef struct _TERM_STRING
 } TERM_STRING;
 
 
+typedef struct _TERM_EXTERNAL_VARIABLE
+{ 
+    int                 type;
+    EXTERNAL_VARIABLE*  variable;
+
+} TERM_EXTERNAL_VARIABLE;
+
+
 
 int new_rule(RULE_LIST* rules, char* identifier, NAMESPACE* namespace, int flags, TAG* tag_list_head, META* meta_list_head, STRING* string_list_head, TERM* condition);
 
@@ -146,7 +154,7 @@ int new_constant(unsigned int constant, TERM_CONST** term);
 
 int new_string_identifier(int type, STRING* defined_strings, char* identifier, TERM_STRING** term);
 
-
+int new_external_variable(YARA_CONTEXT* context, char* identifier, TERM_EXTERNAL_VARIABLE** term);
 
 #endif
 
diff --git a/libyara/eval.c b/libyara/eval.c
index dd1a380..4020ff7 100644
--- a/libyara/eval.c
+++ b/libyara/eval.c
@@ -31,6 +31,7 @@ int evaluate(TERM* term, EVALUATION_CONTEXT* context)
 	TERM_BINARY_OPERATION* term_binary = ((TERM_BINARY_OPERATION*) term);
 	TERM_TERNARY_OPERATION* term_ternary = ((TERM_TERNARY_OPERATION*) term);
 	TERM_STRING* term_string = ((TERM_STRING*) term);
+	TERM_EXTERNAL_VARIABLE* term_external_variable = ((TERM_EXTERNAL_VARIABLE*) term);
 	
 	MATCH* match;
 	TERM_STRING* t;
@@ -332,7 +333,18 @@ int evaluate(TERM* term, EVALUATION_CONTEXT* context)
         {
             return 0xE0FE0F;
         }
-		
+        
+    case TERM_TYPE_EXTERNAL_VARIABLE:
+    
+        if (term_external_variable->variable->type == EXTERNAL_VARIABLE_TYPE_STRING)
+        {
+            return ( term_external_variable->variable->string != NULL && *term_external_variable->variable->string != '\0');
+        }
+        else
+        {
+            return term_external_variable->variable->integer;
+        }
+     	
 	default:
 		return 0;
 	}
diff --git a/libyara/grammar.c b/libyara/grammar.c
index 73f555f..15335fa 100644
--- a/libyara/grammar.c
+++ b/libyara/grammar.c
@@ -324,8 +324,8 @@ TERM* reduce_term(  yyscan_t yyscanner,
 TERM* reduce_constant(  yyscan_t yyscanner,
                         unsigned int constant);
 
-TERM* reduce_rule(  yyscan_t yyscanner,
-                    char* identifier);
+TERM* reduce_identifier( yyscan_t yyscanner,
+                         char* identifier);
 
 int count_strings(TERM_STRING* st);
 
@@ -2006,7 +2006,7 @@ yyreduce:
   case 39:
 #line 387 "grammar.y"
     { 
-                        (yyval.term) = reduce_rule(yyscanner, (yyvsp[(1) - (1)].c_string));
+                        (yyval.term) = reduce_identifier(yyscanner, (yyvsp[(1) - (1)].c_string));
                         
                         if ((yyval.term) == NULL)
                         {
@@ -3031,25 +3031,22 @@ TERM* reduce_string_offset( yyscan_t yyscanner,
     return (TERM*) term;
 }
 
-TERM* reduce_rule(  yyscan_t yyscanner, 
-                    char* identifier)
+TERM* reduce_identifier(    yyscan_t yyscanner, 
+                            char* identifier)
 {
     YARA_CONTEXT* context = yyget_extra(yyscanner);
-    TERM_BINARY_OPERATION*  term;
+    TERM* term = NULL;
     RULE* rule;
-    YARA_CONTEXT*   current_context = yyget_extra(yyscanner);
-  
-    rule = lookup_rule(&current_context->rule_list, identifier, context->current_namespace);
-    
+      
+    rule = lookup_rule(&context->rule_list, identifier, context->current_namespace);
+        
     if (rule != NULL)
     {
-        context->last_result = new_binary_operation(TERM_TYPE_RULE, rule->condition, NULL, &term);        
+        context->last_result = new_binary_operation(TERM_TYPE_RULE, rule->condition, NULL, (TERM_BINARY_OPERATION**) &term);        
     }
     else
     {
-        strncpy(context->last_error_extra_info, identifier, sizeof(context->last_error_extra_info));
-        context->last_result = ERROR_UNDEFINED_RULE;
-        term = NULL;
+        context->last_result = new_external_variable(context, identifier, (TERM_EXTERNAL_VARIABLE**) &term);
     }
     
     yr_free(identifier);
diff --git a/libyara/grammar.y b/libyara/grammar.y
index 466dcd9..7bcb248 100644
--- a/libyara/grammar.y
+++ b/libyara/grammar.y
@@ -192,8 +192,8 @@ TERM* reduce_term(  yyscan_t yyscanner,
 TERM* reduce_constant(  yyscan_t yyscanner,
                         unsigned int constant);
 
-TERM* reduce_rule(  yyscan_t yyscanner,
-                    char* identifier);
+TERM* reduce_identifier( yyscan_t yyscanner,
+                         char* identifier);
 
 int count_strings(TERM_STRING* st);
 
@@ -385,7 +385,7 @@ boolean_expression : _TRUE_                                 { $$ = reduce_consta
                    | _FALSE_                                { $$ = reduce_constant(yyscanner, 0); } 
                    | _IDENTIFIER_                                   
                      { 
-                        $$ = reduce_rule(yyscanner, $1);
+                        $$ = reduce_identifier(yyscanner, $1);
                         
                         if ($$ == NULL)
                         {
@@ -1039,25 +1039,22 @@ TERM* reduce_string_offset( yyscan_t yyscanner,
     return (TERM*) term;
 }
 
-TERM* reduce_rule(  yyscan_t yyscanner, 
-                    char* identifier)
+TERM* reduce_identifier(    yyscan_t yyscanner, 
+                            char* identifier)
 {
     YARA_CONTEXT* context = yyget_extra(yyscanner);
-    TERM_BINARY_OPERATION*  term;
+    TERM* term = NULL;
     RULE* rule;
-    YARA_CONTEXT*   current_context = yyget_extra(yyscanner);
-  
-    rule = lookup_rule(&current_context->rule_list, identifier, context->current_namespace);
-    
+      
+    rule = lookup_rule(&context->rule_list, identifier, context->current_namespace);
+        
     if (rule != NULL)
     {
-        context->last_result = new_binary_operation(TERM_TYPE_RULE, rule->condition, NULL, &term);        
+        context->last_result = new_binary_operation(TERM_TYPE_RULE, rule->condition, NULL, (TERM_BINARY_OPERATION**) &term);        
     }
     else
     {
-        strncpy(context->last_error_extra_info, identifier, sizeof(context->last_error_extra_info));
-        context->last_result = ERROR_UNDEFINED_RULE;
-        term = NULL;
+        context->last_result = new_external_variable(context, identifier, (TERM_EXTERNAL_VARIABLE**) &term);
     }
     
     yr_free(identifier);
diff --git a/libyara/libtool b/libyara/libtool
index fb9ee61..a7ce678 100755
--- a/libyara/libtool
+++ b/libyara/libtool
@@ -50,24 +50,24 @@ available_tags=" CXX"
 SHELL="/bin/sh"
 
 # Whether or not to build shared libraries.
-build_libtool_libs=yes
+build_libtool_libs=no
 
 # Whether or not to build static libraries.
 build_old_libs=yes
 
 # Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=no
+build_libtool_need_lc=yes
 
 # Whether or not to disallow shared libs when runtime libs are static
 allow_libtool_libs_with_static_runtimes=no
 
 # Whether or not to optimize for fast installation.
-fast_install=needless
+fast_install=yes
 
 # The host system.
-host_alias=
-host=i386-apple-darwin10.0.0
-host_os=darwin10.0.0
+host_alias=i686
+host=i686-pc-none
+host_os=none
 
 # The build system.
 build_alias=
@@ -82,13 +82,13 @@ AR="ar"
 AR_FLAGS="cru"
 
 # A C compiler.
-LTCC="gcc"
+LTCC="gcc -m32 -march=i686"
 
 # LTCC compiler flags.
 LTCFLAGS="-g -O2"
 
 # A language-specific compiler.
-CC="gcc"
+CC="gcc -m32 -march=i686"
 
 # Is the compiler the GNU C compiler?
 with_gcc=yes
@@ -97,13 +97,13 @@ with_gcc=yes
 EGREP="/usr/bin/grep -E"
 
 # The linker used to build libraries.
-LD="/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld"
+LD="/usr/libexec/gcc/i686-apple-darwin10/4.0.1/ld"
 
 # Whether we need hard or soft links.
 LN_S="ln -s"
 
 # A BSD-compatible nm program.
-NM="/usr/bin/nm"
+NM="nm"
 
 # A symbol stripping program
 STRIP="strip"
@@ -125,7 +125,7 @@ objdir=.libs
 
 # How to create reloadable object files.
 reload_flag=" -r"
-reload_cmds="\$LTCC \$LTCFLAGS -nostdlib \${wl}-r -o \$output\$reload_objs"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
 
 # How to pass a linker flag through the compiler.
 wl="-Wl,"
@@ -137,13 +137,13 @@ objext="o"
 libext="a"
 
 # Shared library suffix (normally ".so").
-shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+shrext_cmds='.so'
 
 # Executable file suffix (normally "").
 exeext=""
 
 # Additional compiler flags for building library objects.
-pic_flag=" -fno-common -DPIC"
+pic_flag=" -fPIC -DPIC"
 pic_mode=default
 
 # What is the maximum length of a command?
@@ -156,10 +156,10 @@ compiler_c_o="yes"
 need_locks="no"
 
 # Do we need the lib prefix for modules?
-need_lib_prefix=no
+need_lib_prefix=unknown
 
 # Do we need a version for libraries?
-need_version=no
+need_version=unknown
 
 # Whether dlopen is supported.
 dlopen_support=unknown
@@ -186,17 +186,17 @@ whole_archive_flag_spec=""
 thread_safe_flag_spec=""
 
 # Library versioning type.
-version_type=darwin
+version_type=none
 
 # Format of library name prefix.
 libname_spec="lib\$name"
 
 # List of archive names.  First name is the real one, the rest are links.
 # The last name is the one that the linker finds with -lNAME.
-library_names_spec="\${libname}\${release}\${major}\$shared_ext \${libname}\$shared_ext \${libname}\${release}\${versuffix}\$shared_ext"
+library_names_spec=""
 
 # The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}\${major}\$shared_ext"
+soname_spec=""
 
 # Commands used to build and install an old-style archive.
 RANLIB="ranlib"
@@ -211,18 +211,18 @@ old_archive_from_new_cmds=""
 old_archive_from_expsyms_cmds=""
 
 # Commands used to build and install a shared archive.
-archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring"
-archive_expsym_cmds="sed -e \\\"s,#.*,,\\\" -e \\\"s,^[    ]*,,\\\" -e \\\"s,^\\\\(..*\\\\),_&,\\\" < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring~nmedit -s \$output_objdir/\${libname}-symbols.expsym \${lib}"
+archive_cmds=""
+archive_expsym_cmds=""
 postinstall_cmds=""
 postuninstall_cmds=""
 
 # Commands used to build a loadable module (assumed same as above if empty)
-module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs\$compiler_flags"
-module_expsym_cmds="sed -e \\\"s,#.*,,\\\" -e \\\"s,^[    ]*,,\\\" -e \\\"s,^\\\\(..*\\\\),_&,\\\" < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag  -o \$lib -bundle \$libobjs \$deplibs\$compiler_flags~nmedit -s \$output_objdir/\${libname}-symbols.expsym \${lib}"
+module_cmds=""
+module_expsym_cmds=""
 
 # Commands to strip libraries.
 old_striplib=""
-striplib="strip -x"
+striplib=""
 
 # Dependencies to place before the objects being linked to create a
 # shared library.
@@ -245,13 +245,13 @@ postdeps=""
 compiler_lib_search_path=""
 
 # Method to check whether dependent libraries are shared objects.
-deplibs_check_method="pass_all"
+deplibs_check_method="unknown"
 
 # Command to use when deplibs_check_method == file_magic.
 file_magic_cmd="\$MAGIC_CMD"
 
 # Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag="\${wl}-flat_namespace \${wl}-undefined \${wl}suppress"
+allow_undefined_flag=""
 
 # Flag that forces no undefined symbols.
 no_undefined_flag=""
@@ -275,13 +275,13 @@ global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\",
 runpath_var=
 
 # This is the shared library path variable.
-shlibpath_var=DYLD_LIBRARY_PATH
+shlibpath_var=
 
 # Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=yes
+shlibpath_overrides_runpath=unknown
 
 # How to hardcode a shared library path into an executable.
-hardcode_action=immediate
+hardcode_action=unsupported
 
 # Whether we should hardcode library paths into libraries.
 hardcode_into_libs=no
@@ -312,20 +312,20 @@ hardcode_shlibpath_var=unsupported
 
 # Set to yes if building a shared library automatically hardcodes DIR into the library
 # and all subsequent libraries and executables linked against it.
-hardcode_automatic=yes
+hardcode_automatic=no
 
 # Variables whose values should be saved in libtool wrapper scripts and
 # restored at relink time.
-variables_saved_for_relink="PATH DYLD_LIBRARY_PATH  GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+variables_saved_for_relink="PATH   GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 
 # Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=yes
+link_all_deplibs=unknown
 
 # Compile-time system search path for libraries
-sys_lib_search_path_spec=" /lib/i686-apple-darwin10/4.2.1/x86_64/ /lib/x86_64/ /usr/lib/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../../i686-apple-darwin10/lib/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../../i686-apple-darwin10/lib/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10 [...]
+sys_lib_search_path_spec=" /lib/i686-apple-darwin10/4.0.1/ /lib/ /usr/lib/i686-apple-darwin10/4.0.1/ /usr/lib/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../../i686-apple-darwin10/lib/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../../i686-apple-darwin10/lib/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../"
 
 # Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/usr/local/lib /lib /usr/lib"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
 
 # Fix the shell variable $srcfile for the compiler.
 fix_srcfile_path=""
@@ -7218,7 +7218,7 @@ disable_libs=static
 SHELL="/bin/sh"
 
 # Whether or not to build shared libraries.
-build_libtool_libs=yes
+build_libtool_libs=no
 
 # Whether or not to build static libraries.
 build_old_libs=yes
@@ -7233,9 +7233,9 @@ allow_libtool_libs_with_static_runtimes=no
 fast_install=needless
 
 # The host system.
-host_alias=
-host=i386-apple-darwin10.0.0
-host_os=darwin10.0.0
+host_alias=i686
+host=i686-pc-none
+host_os=none
 
 # The build system.
 build_alias=
@@ -7250,7 +7250,7 @@ AR="ar"
 AR_FLAGS="cru"
 
 # A C compiler.
-LTCC="gcc"
+LTCC="gcc -m32 -march=i686"
 
 # LTCC compiler flags.
 LTCFLAGS="-g -O2"
@@ -7265,13 +7265,13 @@ with_gcc=yes
 EGREP="/usr/bin/grep -E"
 
 # The linker used to build libraries.
-LD="/usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld"
+LD="/usr/libexec/gcc/i686-apple-darwin10/4.0.1/ld"
 
 # Whether we need hard or soft links.
 LN_S="ln -s"
 
 # A BSD-compatible nm program.
-NM="/usr/bin/nm"
+NM="nm"
 
 # A symbol stripping program
 STRIP="strip"
@@ -7293,7 +7293,7 @@ objdir=.libs
 
 # How to create reloadable object files.
 reload_flag=" -r"
-reload_cmds="\$LTCC \$LTCFLAGS -nostdlib \${wl}-r -o \$output\$reload_objs"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
 
 # How to pass a linker flag through the compiler.
 wl="-Wl,"
@@ -7305,13 +7305,13 @@ objext="o"
 libext="a"
 
 # Shared library suffix (normally ".so").
-shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+shrext_cmds='.so'
 
 # Executable file suffix (normally "").
 exeext=""
 
 # Additional compiler flags for building library objects.
-pic_flag=" -fno-common -DPIC"
+pic_flag=" -fPIC -DPIC"
 pic_mode=default
 
 # What is the maximum length of a command?
@@ -7324,10 +7324,10 @@ compiler_c_o="yes"
 need_locks="no"
 
 # Do we need the lib prefix for modules?
-need_lib_prefix=no
+need_lib_prefix=unknown
 
 # Do we need a version for libraries?
-need_version=no
+need_version=unknown
 
 # Whether dlopen is supported.
 dlopen_support=unknown
@@ -7354,17 +7354,17 @@ whole_archive_flag_spec=""
 thread_safe_flag_spec=""
 
 # Library versioning type.
-version_type=darwin
+version_type=none
 
 # Format of library name prefix.
 libname_spec="lib\$name"
 
 # List of archive names.  First name is the real one, the rest are links.
 # The last name is the one that the linker finds with -lNAME.
-library_names_spec="\${libname}\${release}\${major}\$shared_ext \${libname}\$shared_ext \${libname}\${release}\${versuffix}\$shared_ext"
+library_names_spec=""
 
 # The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}\${major}\$shared_ext"
+soname_spec=""
 
 # Commands used to build and install an old-style archive.
 RANLIB="ranlib"
@@ -7379,18 +7379,18 @@ old_archive_from_new_cmds=""
 old_archive_from_expsyms_cmds=""
 
 # Commands used to build and install a shared archive.
-archive_cmds="\$CC -dynamiclib -single_module \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring"
-archive_expsym_cmds="sed -e \\\"s,#.*,,\\\" -e \\\"s,^[    ]*,,\\\" -e \\\"s,^\\\\(..*\\\\),_&,\\\" < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib -single_module \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring~nmedit -s \$output_objdir/\${libname}-symbols.expsym \${lib}"
+archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags -o \$lib"
+archive_expsym_cmds=""
 postinstall_cmds=""
 postuninstall_cmds=""
 
 # Commands used to build a loadable module (assumed same as above if empty)
-module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs\$compiler_flags"
-module_expsym_cmds="sed -e \\\"s,#.*,,\\\" -e \\\"s,^[    ]*,,\\\" -e \\\"s,^\\\\(..*\\\\),_&,\\\" < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag  -o \$lib -bundle \$libobjs \$deplibs\$compiler_flags~nmedit -s \$output_objdir/\${libname}-symbols.expsym \${lib}"
+module_cmds=""
+module_expsym_cmds=""
 
 # Commands to strip libraries.
 old_striplib=""
-striplib="strip -x"
+striplib=""
 
 # Dependencies to place before the objects being linked to create a
 # shared library.
@@ -7406,20 +7406,20 @@ predeps=""
 
 # Dependencies to place after the objects being linked to create a
 # shared library.
-postdeps=""
+postdeps="-lstdc++ -lgcc_s.10.5 -lgcc -lSystem"
 
 # The library search path used internally by the compiler when linking
 # a shared library.
-compiler_lib_search_path=""
+compiler_lib_search_path="-L/usr/lib/i686-apple-darwin10/4.0.1 -L/usr/lib/gcc/i686-apple-darwin10/4.0.1 -L/usr/lib/gcc/i686-apple-darwin10/4.0.1 -L/usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../i686-apple-darwin10/4.0.1 -L/usr/lib/gcc/i686-apple-darwin10/4.0.1/../../.."
 
 # Method to check whether dependent libraries are shared objects.
-deplibs_check_method="pass_all"
+deplibs_check_method="unknown"
 
 # Command to use when deplibs_check_method == file_magic.
 file_magic_cmd="\$MAGIC_CMD"
 
 # Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag="\${wl}-flat_namespace \${wl}-undefined \${wl}suppress"
+allow_undefined_flag=""
 
 # Flag that forces no undefined symbols.
 no_undefined_flag=""
@@ -7443,13 +7443,13 @@ global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\",
 runpath_var=
 
 # This is the shared library path variable.
-shlibpath_var=DYLD_LIBRARY_PATH
+shlibpath_var=
 
 # Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=yes
+shlibpath_overrides_runpath=unknown
 
 # How to hardcode a shared library path into an executable.
-hardcode_action=immediate
+hardcode_action=unsupported
 
 # Whether we should hardcode library paths into libraries.
 hardcode_into_libs=no
@@ -7480,20 +7480,20 @@ hardcode_shlibpath_var=unsupported
 
 # Set to yes if building a shared library automatically hardcodes DIR into the library
 # and all subsequent libraries and executables linked against it.
-hardcode_automatic=yes
+hardcode_automatic=no
 
 # Variables whose values should be saved in libtool wrapper scripts and
 # restored at relink time.
-variables_saved_for_relink="PATH DYLD_LIBRARY_PATH  GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+variables_saved_for_relink="PATH   GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 
 # Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=yes
+link_all_deplibs=unknown
 
 # Compile-time system search path for libraries
-sys_lib_search_path_spec=" /lib/i686-apple-darwin10/4.2.1/x86_64/ /lib/x86_64/ /usr/lib/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../../i686-apple-darwin10/lib/i686-apple-darwin10/4.2.1/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../../i686-apple-darwin10/lib/x86_64/ /usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10 [...]
+sys_lib_search_path_spec=" /lib/i686-apple-darwin10/4.0.1/ /lib/ /usr/lib/i686-apple-darwin10/4.0.1/ /usr/lib/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../../i686-apple-darwin10/lib/i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../../i686-apple-darwin10/lib/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../i686-apple-darwin10/4.0.1/ /usr/lib/gcc/i686-apple-darwin10/4.0.1/../../../"
 
 # Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/usr/local/lib /lib /usr/lib"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
 
 # Fix the shell variable $srcfile for the compiler.
 fix_srcfile_path=""
diff --git a/libyara/libyara.c b/libyara/libyara.c
index a257afc..51f96be 100644
--- a/libyara/libyara.c
+++ b/libyara/libyara.c
@@ -50,6 +50,7 @@ YARA_CONTEXT* yr_create_context()
     context->current_rule_strings = NULL;
     context->inside_for = 0;
 	context->namespaces = NULL;
+	context->external_variables = NULL;
     context->allow_includes = TRUE;
 	context->current_namespace = yr_create_namespace(context, "default");
     
@@ -73,6 +74,8 @@ void yr_destroy_context(YARA_CONTEXT* context)
 	TAG* next_tag;
 	NAMESPACE* ns;
 	NAMESPACE* next_ns;
+    EXTERNAL_VARIABLE* ext_var;
+	EXTERNAL_VARIABLE* next_ext_var;
     
     rule = context->rule_list.head;
     
@@ -159,6 +162,23 @@ void yr_destroy_context(YARA_CONTEXT* context)
 		ns = next_ns;
 	}
 	
+	ext_var = context->external_variables;
+
+	while(ext_var != NULL)
+	{
+		next_ext_var = ext_var->next;
+/*		
+		if (ext_var->type == EXTERNAL_VARIABLE_TYPE_STRING)
+		{
+		    yr_free(ext_var->string);
+		}
+	*/	
+		yr_free(ext_var->identifier);
+		yr_free(ext_var);
+		
+		ext_var = next_ext_var;
+	}
+	
 	while (context->file_name_stack_ptr > 0)
     {
         yr_pop_file_name(context);
@@ -184,6 +204,98 @@ NAMESPACE* yr_create_namespace(YARA_CONTEXT* context, const char* namespace)
 	return ns;
 }
 
+
+int yr_set_external_integer(YARA_CONTEXT* context, const char* identifier, int value)
+{
+    EXTERNAL_VARIABLE* ext_var;
+
+    ext_var = lookup_external_variable(context->external_variables, identifier);
+    
+    if (ext_var == NULL) /* variable doesn't exists, create it */
+    {
+        ext_var = (EXTERNAL_VARIABLE*) yr_malloc(sizeof(EXTERNAL_VARIABLE));
+        
+        if (ext_var != NULL)
+        {
+            ext_var->type = EXTERNAL_VARIABLE_TYPE_INTEGER;
+            ext_var->identifier = yr_strdup(identifier);
+        
+            ext_var->next = context->external_variables;
+            context->external_variables = ext_var;
+        }
+        else
+        {
+            return ERROR_INSUFICIENT_MEMORY;
+        }
+    }
+
+    ext_var->integer = value;
+    
+    return ERROR_SUCCESS;
+}
+
+
+int yr_set_external_boolean(YARA_CONTEXT* context, const char* identifier, int value)
+{
+    EXTERNAL_VARIABLE* ext_var;
+
+    ext_var = lookup_external_variable(context->external_variables, identifier);
+    
+    if (ext_var == NULL) /* variable doesn't exists, create it */
+    {
+        ext_var = (EXTERNAL_VARIABLE*) yr_malloc(sizeof(EXTERNAL_VARIABLE));
+        
+        if (ext_var != NULL)
+        {
+            ext_var->type = EXTERNAL_VARIABLE_TYPE_BOOLEAN;
+            ext_var->identifier = yr_strdup(identifier);
+        
+            ext_var->next = context->external_variables;
+            context->external_variables = ext_var;
+        }
+        else
+        {
+            return ERROR_INSUFICIENT_MEMORY;
+        }
+    }
+
+    ext_var->boolean = value;
+    
+    return ERROR_SUCCESS;
+}
+
+
+int yr_set_external_string(YARA_CONTEXT* context, const char* identifier, const char* value)
+{
+    EXTERNAL_VARIABLE* ext_var;
+
+    ext_var = lookup_external_variable(context->external_variables, identifier);
+    
+    if (ext_var == NULL) /* variable doesn't exists, create it */
+    {
+        ext_var = (EXTERNAL_VARIABLE*) yr_malloc(sizeof(EXTERNAL_VARIABLE));
+        
+        if (ext_var != NULL)
+        {
+            ext_var->type = EXTERNAL_VARIABLE_TYPE_STRING;
+            ext_var->identifier = yr_strdup(identifier);
+        
+            ext_var->next = context->external_variables;
+            context->external_variables = ext_var;
+        }
+        else
+        {
+            return ERROR_INSUFICIENT_MEMORY;
+        }
+    }
+
+    ext_var->string = (char*) value;
+    
+    return ERROR_SUCCESS;
+}
+
+
+
 char* yr_get_current_file_name(YARA_CONTEXT* context)
 {   
     if (context->file_name_stack_ptr > 0)
@@ -452,8 +564,8 @@ char* yr_get_error_message(YARA_CONTEXT* context, char* buffer, int buffer_size)
 		case ERROR_UNDEFINED_STRING:
             snprintf(buffer, buffer_size, "undefined string \"%s\"", context->last_error_extra_info);
 			break;
-		case ERROR_UNDEFINED_RULE:
-		    snprintf(buffer, buffer_size, "undefined rule \"%s\"", context->last_error_extra_info);
+		case ERROR_UNDEFINED_IDENTIFIER:
+		    snprintf(buffer, buffer_size, "undefined identifier \"%s\"", context->last_error_extra_info);
 			break;
 		case ERROR_UNREFERENCED_STRING:
 		    snprintf(buffer, buffer_size, "unreferenced string \"%s\"", context->last_error_extra_info);
diff --git a/libyara/yara.h b/libyara/yara.h
index c48f916..44be200 100644
--- a/libyara/yara.h
+++ b/libyara/yara.h
@@ -76,7 +76,7 @@ GNU General Public License for more details.
 #define ERROR_CONSECUTIVE_SKIPS                 8
 #define ERROR_MISPLACED_WILDCARD_OR_SKIP        9
 #define ERROR_UNDEFINED_STRING                  10
-#define ERROR_UNDEFINED_RULE                    11
+#define ERROR_UNDEFINED_IDENTIFIER              11
 #define ERROR_COULD_NOT_OPEN_FILE               12
 #define ERROR_INVALID_REGULAR_EXPRESSION        13
 #define ERROR_SYNTAX_ERROR                      14
@@ -98,6 +98,11 @@ GNU General Public License for more details.
 #define META_TYPE_INTEGER                       1
 #define META_TYPE_STRING                        2
 #define META_TYPE_BOOLEAN                       3
+
+#define EXTERNAL_VARIABLE_TYPE_INTEGER          1
+#define EXTERNAL_VARIABLE_TYPE_STRING           2
+#define EXTERNAL_VARIABLE_TYPE_BOOLEAN          3
+
       
 
 typedef struct _MATCH
@@ -135,6 +140,22 @@ typedef struct _STRING
 } STRING;
 
 
+typedef struct _EXTERNAL_VARIABLE
+{
+    int     type;
+    char*   identifier;
+    
+    union {      
+        char*   string;
+        int     integer;
+        int     boolean;
+    };
+    
+    struct _EXTERNAL_VARIABLE* next;
+    
+} EXTERNAL_VARIABLE;
+
+
 typedef struct _TAG
 {
 	char*			identifier;
@@ -221,40 +242,43 @@ typedef void (*YARAREPORT)(const char* file_name, int line_number, const char* e
 
 typedef struct _YARA_CONTEXT
 {  
-    int             last_result;
-    YARAREPORT      error_report_function;
-    int             errors;
-    int             last_error;
-    int             last_error_line;
+    int                     last_result;
+    YARAREPORT              error_report_function;
+    int                     errors;
+    int                     last_error;
+    int                     last_error_line;
     
-    RULE_LIST       rule_list;
-    HASH_TABLE      hash_table;
+    RULE_LIST               rule_list;
+    HASH_TABLE              hash_table;
     
-	NAMESPACE*		namespaces;
-	NAMESPACE*		current_namespace;
+	NAMESPACE*		        namespaces;
+	NAMESPACE*		        current_namespace;
+	
+	EXTERNAL_VARIABLE*      external_variables;
 
-	STRING*         current_rule_strings;  
-    int             inside_for;
+	STRING*                 current_rule_strings;  
+    int                     inside_for;
     
-    char*           file_name_stack[MAX_INCLUDE_DEPTH];
-    int             file_name_stack_ptr;
+    char*                   file_name_stack[MAX_INCLUDE_DEPTH];
+    int                     file_name_stack_ptr;
            
-    char            last_error_extra_info[256];
+    char                    last_error_extra_info[256];
 
-    char 		    lex_buf[256];
-    char*		    lex_buf_ptr;
-    unsigned short  lex_buf_len;
+    char 		            lex_buf[256];
+    char*		            lex_buf_ptr;
+    unsigned short          lex_buf_len;
     
-    int             allow_includes;
-    char            include_base_dir[MAX_PATH];
+    int                     allow_includes;
+    char                    include_base_dir[MAX_PATH];
 
 } YARA_CONTEXT;
 
 
-RULE*       lookup_rule(RULE_LIST* rules, char* identifier, NAMESPACE* namespace);
-STRING*     lookup_string(STRING* string_list_head, char* identifier);
-TAG*        lookup_tag(TAG* tag_list_head, char* identifier);
-META*       lookup_meta(META* meta_list_head, char* identifier);
+RULE*                   lookup_rule(RULE_LIST* rules, const char* identifier, NAMESPACE* namespace);
+STRING*                 lookup_string(STRING* string_list_head, const char* identifier);
+TAG*                    lookup_tag(TAG* tag_list_head, const char* identifier);
+META*                   lookup_meta(META* meta_list_head, const char* identifier);
+EXTERNAL_VARIABLE*      lookup_external_variable(EXTERNAL_VARIABLE* ext_var_list_head, const char* identifier);
 
 void                yr_init();
 
@@ -263,6 +287,10 @@ void                yr_destroy_context(YARA_CONTEXT* context);
 
 NAMESPACE*			yr_create_namespace(YARA_CONTEXT* context, const char* namespace);
 
+int                 yr_set_external_integer(YARA_CONTEXT* context, const char* identifier, int value);
+int                 yr_set_external_boolean(YARA_CONTEXT* context, const char* identifier, int value);
+int                 yr_set_external_string(YARA_CONTEXT* context, const char* identifier, const char* value);
+
 char*               yr_get_current_file_name(YARA_CONTEXT* context);
 
 int 		yr_push_file_name(YARA_CONTEXT* context, const char* file_name);
diff --git a/yara-python/README b/yara-python/README
index 506d024..2da0c0b 100644
--- a/yara-python/README
+++ b/yara-python/README
@@ -94,7 +94,7 @@ rules = yara.compile(sources={
 Notice that both filepaths and sources must be dictionaries with keys of string type.
 The dictionary keys are used as a namespace identifier, allowing to differentiate between
 rules with the same name in different sources, as occurs in the second example with the
-�dummy� name.
+"dummy" name.
 
 The compile method also have an optional boolean parameter named includes which allows
 you to control whether or not the include directive should be accepted in the source files,
diff --git a/yara-python/yara-python.c b/yara-python/yara-python.c
index d31935f..fe1174e 100644
--- a/yara-python/yara-python.c
+++ b/yara-python/yara-python.c
@@ -264,9 +264,41 @@ static PyTypeObject Rules_Type = {
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-static PyObject * Rules_new_from_file(FILE* file, const char* filepath, const char* namespace, PyObject* rules, int allow_includes)
+int process_externals(PyObject* externals, YARA_CONTEXT* context)
+{
+    PyObject *key, *value;
+	Py_ssize_t pos = 0;
+	
+	char* identifier = NULL;
+
+    while (PyDict_Next(externals, &pos, &key, &value)) 
+    {
+        identifier = PyString_AsString(key);
+        
+        if (PyInt_Check(value))
+        {
+            yr_set_external_integer(context, identifier, PyInt_AsLong(value));
+        } 
+        else if (PyBool_Check(value))
+        {
+            yr_set_external_boolean(context, identifier, PyObject_IsTrue(value));
+        }
+        else if (PyString_Check(value))
+        {
+            yr_set_external_string(context, identifier, PyString_AsString(value));
+        }
+        else
+        {
+            return FALSE;
+        }				
+    }
+
+    return TRUE;
+}
+
+
+static PyObject * Rules_new_from_file(FILE* file, const char* filepath, PyObject* rules, YARA_CONTEXT* context)
 { 
-    YARA_CONTEXT* context;
     Rules* result;
     
     int  errors;
@@ -277,40 +309,18 @@ static PyObject * Rules_new_from_file(FILE* file, const char* filepath, const ch
     {
         return PyErr_SetFromErrno(PyExc_IOError);
     }
-
-    if (rules == NULL)
-    {
-        context = yr_create_context();
-   
-   		if (context == NULL)
-       		return PyErr_NoMemory();
-    }
-	else
-	{
-		context = ((Rules*)rules)->context;
-	}
-	
-	if (namespace != NULL)
-	{
-		context->current_namespace = yr_create_namespace(context, namespace);
-	}
 	
 	if (filepath != NULL)
 	{
         yr_push_file_name(context, filepath);
 	}
-	
-	context->allow_includes = allow_includes;
-         
+		         
     errors = yr_compile_file(file, context);
        
     if (errors)   /* errors during compilation */
     {
         error_line = context->last_error_line;
         yr_get_error_message(context, error_message, sizeof(error_message));
-
-		if (rules == NULL)
-        	yr_destroy_context(context); 
         
         return PyErr_Format(YaraSyntaxError, "line %d: %s", error_line, error_message);
     }
@@ -331,52 +341,22 @@ static PyObject * Rules_new_from_file(FILE* file, const char* filepath, const ch
 }
 
 
-static PyObject * Rules_new_from_string(const char* string, const char* namespace, PyObject* rules, int allow_includes)
+static PyObject * Rules_new_from_string(const char* string, PyObject* rules, YARA_CONTEXT* context)
 { 
-	YARA_CONTEXT* context;
 	Rules* result;
 
     int  errors;
     int  error_line;
     char error_message[256];
-    
-    if (rules == NULL)
-    {
-        context = yr_create_context();
-   
-   		if (context == NULL)
-       		return PyErr_NoMemory();
-    }
-	else
-	{
-		context = ((Rules*)rules)->context;
-	}
-	
-	if (namespace != NULL)
-	{
-		context->current_namespace = yr_create_namespace(context, namespace);
-	}
-	
-    context->allow_includes = allow_includes;
-	
+    	
     errors = yr_compile_string(string, context);
        
     if (errors)   /* errors during compilation */
     {
         error_line = context->last_error_line;
         yr_get_error_message(context, error_message, sizeof(error_message));
-        
-		if (rules == NULL)
-			yr_destroy_context(context); 
-        
-		if (namespace != NULL)
-		{
-			return PyErr_Format(YaraSyntaxError, "%s: line %d: %s", namespace, error_line, error_message);
-		}
-		else
-		{
-        	return PyErr_Format(YaraSyntaxError, "line %d: %s", error_line, error_message);
-		}	
+              
+        return PyErr_Format(YaraSyntaxError, "line %d: %s", error_line, error_message);	
     }
 
 	if (rules == NULL)
@@ -496,23 +476,40 @@ int callback(RULE* rule, unsigned char* buffer, unsigned int buffer_size, void*
 
 PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
 {
-    static char *kwlist[] = {"filepath", "data", NULL};
+    static char *kwlist[] = {"filepath", "data", "externals", NULL};
     
     char* filepath = NULL;
     char* data = NULL;
-    
+
     int length;
     int result;
     
     PyObject *matches = NULL;
-    Rules *object = (Rules *)self;
+    PyObject *externals = NULL;
+       
+    Rules* object = (Rules*) self;
     
-    if (PyArg_ParseTupleAndKeywords(args, keywords, "|ss#", kwlist, &filepath, &data, &length))
+    if (PyArg_ParseTupleAndKeywords(args, keywords, "|ss#O", kwlist, &filepath, &data, &length, &externals))
     {
-        matches = PyList_New(0);
-        
+        if (externals != NULL)
+        {
+            if (PyDict_Check(externals))
+			{
+				if (!process_externals(externals, object->context))
+			    {
+			        return PyErr_Format(PyExc_TypeError, "external values must be of type integer, boolean or string");
+				}				
+			}
+			else
+			{
+				return PyErr_Format(PyExc_TypeError, "'externals' must be a dictionary");
+			}
+        }
+             
         if (filepath != NULL)
-        {            
+        {    
+            matches = PyList_New(0);
+        
             result = yr_scan_file(filepath, object->context, callback, matches);
 
             if (result != ERROR_SUCCESS)
@@ -534,6 +531,8 @@ PyObject * Rules_match(PyObject *self, PyObject *args, PyObject *keywords)
         }
         else if (data != NULL)
         {
+            matches = PyList_New(0);
+        
             result = yr_scan_mem((unsigned char*) data, (unsigned int) length, object->context, callback, matches);
 
             if (result != ERROR_SUCCESS)
@@ -560,8 +559,9 @@ static PyObject * Rules_getattro(PyObject *self, PyObject *name)
 
 static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keywords)
 { 
-    static char *kwlist[] = {"filepath", "source", "file", "filepaths", "sources", "includes", NULL};
+    static char *kwlist[] = {"filepath", "source", "file", "filepaths", "sources", "includes", "externals", NULL};
     
+    YARA_CONTEXT* context;
     FILE* fh;
     
     PyObject *result = NULL;
@@ -570,6 +570,7 @@ static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keyword
 	PyObject *sources_dict = NULL;
 	PyObject *filepaths_dict = NULL;
 	PyObject *includes = NULL;
+	PyObject *externals = NULL;
 	
 	PyObject *key, *value;
 	
@@ -578,30 +579,51 @@ static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keyword
     char* filepath = NULL;
     char* source = NULL;
 	char* namespace = NULL;
-	
-    int allow_includes = TRUE;
-    
-    if (PyArg_ParseTupleAndKeywords(args, keywords, "|ssOOOO", kwlist, &filepath, &source, &file, &filepaths_dict, &sources_dict, &includes))
-    {
-        if (includes != NULL)
+	    
+    if (PyArg_ParseTupleAndKeywords(args, keywords, "|ssOOOOO", kwlist, &filepath, &source, &file, &filepaths_dict, &sources_dict, &includes, &externals))
+    {      
+        context = yr_create_context();
+   
+   		if (context == NULL)
+       		return PyErr_NoMemory();
+       		      		
+       	if (includes != NULL)
         {
             if (PyBool_Check(includes))
             {
-                allow_includes = (PyObject_IsTrue(includes) == 1);  // PyObject_IsTrue can return -1 in case of error
+                context->allow_includes = (PyObject_IsTrue(includes) == 1);  // PyObject_IsTrue can return -1 in case of error
             }
             else
             {
-                result = PyErr_Format(PyExc_TypeError, "'includes' param must be of boolean type");
+                yr_destroy_context(context); 
+                return PyErr_Format(PyExc_TypeError, "'includes' param must be of boolean type");
             }
         }
-        
+          	
+        if (externals != NULL)
+        {
+            if (PyDict_Check(externals))
+            {
+                if (!process_externals(externals, context))
+                {
+                    yr_destroy_context(context); 
+                    return PyErr_Format(PyExc_TypeError, "external values must be of type integer, boolean or string");
+                }				
+            }
+            else
+            {
+                yr_destroy_context(context); 
+                return PyErr_Format(PyExc_TypeError, "'externals' must be a dictionary");
+            }
+        }
+     
         if (filepath != NULL)
         {            
             fh = fopen(filepath, "r");
             
             if (fh != NULL)
             {
-                result = Rules_new_from_file(fh, filepath, NULL, NULL, allow_includes);
+                result = Rules_new_from_file(fh, filepath, NULL, context);
                 fclose(fh);
             }
             else
@@ -611,12 +633,12 @@ static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keyword
         }
         else if (source != NULL)
         {
-            result = Rules_new_from_string(source, NULL, NULL, allow_includes);
+            result = Rules_new_from_string(source, NULL, context);
         }
         else if (file != NULL)
         {
             fh = PyFile_AsFile(file);   
-            result = Rules_new_from_file(fh, NULL, NULL, NULL, allow_includes);
+            result = Rules_new_from_file(fh, NULL, NULL, context);
         }
         else if (sources_dict != NULL)
         {
@@ -629,7 +651,9 @@ static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keyword
 					
 					if (source != NULL && namespace != NULL)
 					{
-						result = Rules_new_from_string(source, namespace, result, allow_includes);
+		                context->current_namespace = yr_create_namespace(context, namespace);
+
+						result = Rules_new_from_string(source, result, context);
 					}
 					else
 					{
@@ -658,7 +682,7 @@ static PyObject * yara_compile(PyObject *self, PyObject *args, PyObject *keyword
             
             			if (fh != NULL)
             			{
-                			result = Rules_new_from_file(fh, filepath, namespace, result, allow_includes);
+                			result = Rules_new_from_file(fh, filepath, result, context);
                 			fclose(fh);
             			}
             			else
diff --git a/yara.c b/yara.c
index fb62f33..8ae1c52 100644
--- a/yara.c
+++ b/yara.c
@@ -15,12 +15,16 @@ GNU General Public License for more details.
 */
 
 #ifndef WIN32
+
 #include <sys/stat.h> 
 #include <dirent.h>
 #include <unistd.h>
+
 #else
+
 #include <windows.h>
 #include "getopt.h"
+
 #endif
 
 #include <stdio.h>
@@ -56,22 +60,35 @@ IDENTIFIER* specified_rules_list = NULL;
 
 void show_help()
 {
-    printf("usage:  yara [ -t tag ] [ -i identifier ] [ -n ] [ -g ] [ -m ] [ -s ] [ -r ] [ -v ] [RULEFILE...] FILE\n");
+    printf("usage:  yara [ OPTION ]... [RULEFILE]... FILE\n");
     printf("options:\n");
-	printf("  -t <tag>          print rules tagged as <tag> and ignore the rest. Can be used more than once.\n");
-    printf("  -i <identifier>   print rules named <identifier> and ignore the rest. Can be used more than once.\n");
-	printf("  -n                print only not satisfied rules (negate).\n");
-	printf("  -g                print tags.\n");
-	printf("  -m                print metadata.\n");
-	printf("  -s                print matching strings.\n");
-    printf("  -r                recursively search directories.\n");
-	printf("  -v                show version information.\n");
+	printf("  -t <tag>                  print rules tagged as <tag> and ignore the rest. Can be used more than once.\n");
+    printf("  -i <identifier>           print rules named <identifier> and ignore the rest. Can be used more than once.\n");
+	printf("  -n                        print only not satisfied rules (negate).\n");
+	printf("  -g                        print tags.\n");
+	printf("  -m                        print metadata.\n");
+	printf("  -s                        print matching strings.\n");
+	printf("  -d <identifier>=<value>   define external variable.\n");
+    printf("  -r                        recursively search directories.\n");
+	printf("  -v                        show version information.\n");
 	printf("\nReport bugs to: <%s>\n", PACKAGE_BUGREPORT);
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
+int is_numeric(char *str)
+{
+  while(*str)
+  {
+    if(!isdigit(*str++))
+      return 0;
+  }
+
+  return 1;
+}
+
+
 #ifdef WIN32
 
 int is_directory(const char* path)
@@ -367,14 +384,16 @@ int callback(RULE* rule, unsigned char* buffer, unsigned int buffer_size, void*
     return 0;
 }
 
-int process_cmd_line(int argc, char const* argv[])
+int process_cmd_line(YARA_CONTEXT* context, int argc, char const* argv[])
 {
+    char* equal_sign;
+    char* value;
 	char c;	
 	TAG* tag;
     IDENTIFIER* identifier;
 	opterr = 0;
  
-	while ((c = getopt (argc, (char**) argv, "rnsvgmt:i:")) != -1)
+	while ((c = getopt (argc, (char**) argv, "rnsvgmt:i:d:")) != -1)
 	{
 		switch (c)
 	    {
@@ -441,6 +460,32 @@ int process_cmd_line(int argc, char const* argv[])
 				}
 
 		        break;
+		        
+		    case 'd':
+		    
+		        equal_sign = strchr(optarg, '=');
+		        
+		        if (equal_sign != NULL)
+		        {
+		            *equal_sign = '\0';
+		            
+		            value = equal_sign + 1;
+		            
+		            if (is_numeric(value))
+		            {		                
+		                yr_set_external_integer(context, optarg, atoi(value));
+		            }
+		            else if (strcmp(value, "true") == 0  || strcmp(value, "false") == 0)
+		            {
+		                yr_set_external_boolean(context, optarg, strcmp(value, "true") == 0);
+		            }
+		            else
+		            {
+		                yr_set_external_string(context, optarg, value);
+		            }	            
+		        }
+
+		        break;
 	
 		    case '?':
 	
@@ -480,8 +525,15 @@ int main(int argc, char const* argv[])
 	FILE* rule_file;
 	TAG* tag;
 	TAG* next_tag;
+	
+	yr_init();
+			
+	context = yr_create_context();
+	
+	if (context == NULL) 
+		return 0;
 		
-	if (!process_cmd_line(argc, argv))
+	if (!process_cmd_line(context, argc, argv))
 	{
 		return 0;
 	}	
@@ -491,13 +543,6 @@ int main(int argc, char const* argv[])
 		show_help();
 		return 0;
 	}
-			
-    yr_init();
-			
-	context = yr_create_context();
-	
-	if (context == NULL) 
-		return 0;
 	
 	context->error_report_function = report_error;	
 			
diff --git a/yara.man b/yara.man
index f52fc2e..d6cc4e4 100644
--- a/yara.man
+++ b/yara.man
@@ -3,23 +3,7 @@
 yara \- find files matching patterns and rules written in a special-purpose language.
 .SH SYNOPSIS
 .B yara 
-[
-.B \-t
-.I tag
-] [
-.B \-i
-.I identifier
-] [
-.B \-n
-] [
-.B \-g
-] [
-.B \-s
-] [
-.B \-r
-] [
-.B \-v
-] [RULEFILE...] FILE
+[ OPTION ]... [RULEFILE]... FILE
 .SH DESCRIPTION
 .I Yara 
 scans the given 
@@ -48,9 +32,15 @@ Print rules that doesn't apply (negate)
 .B \-g 
 Print the tags associated to the rule.
 .TP
+.B \-m 
+Print metadata associated to the rule.
+.TP
 .B \-s 
 Print strings found in the file.
 .TP
+.BI \-d " identifier"=value
+Define an external variable. This option can be used multiple times.
+.TP
 .B \-r 
 Scan files in directories recursively.
 .TP
@@ -87,5 +77,16 @@ Scan all files in the
 .I /foo
 directory and its subdirectories. Rules are read from standard input.
 .RE
+.PP
+$ yara -d mybool=true myint=5 mystring="my string" /foo/bar/rules bazfile  
+.RS
+.PP
+Defines three external variables 
+.I mybool
+.I myint 
+and
+.I mystring.
+.RE
+
 .SH AUTHOR 
 Victor M. Alvarez (vmalvarez at hispasec.com) 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list