예제 #1
0
/* Pulls server library out of plugin folder */
int
scrapePlugin (const char *filename, void * data)
{
    lt_dlhandle pluginHandle = lt_dlopenext (filename);
    if (!pluginHandle)
    {
        doLog (ERROR, LOG_COMP, _("Unable to link %s\nDetails: %s."), filename, lt_dlerror());
        return 0;
    }
    
    /* Get Info for loaded Plugin */
    lt_dlinfo const * pluginInfo = lt_dlgetinfo (pluginHandle);
    if (!pluginInfo)
    {
        doLog (ERROR, LOG_COMP, _("Unable to get plugin SO info for %s\nDetails: %s."), 
               filename, lt_dlerror());
        return 0;
    }
    
    /* Continue Loading Plugin */
    doLog (NOTICE, LOG_COMP, _("Found %s."), pluginInfo->name);
    checkAddPlugin (pluginInfo->filename, pluginInfo->name, pluginHandle);
    
    return 0;
}
예제 #2
0
module_handle module_open(const char* name, enum module_type_t type, int flags){
	log_message(Log_Debug, "Loading plugin '%s'\n", name);

	/* dlopenext tries all searchpaths and adds appropriate suffix */
	lt_dlhandle handle = lt_dlopenext(name);

	if ( !handle ){
		log_message(Log_Debug, "Failed to load plugin '%s': %s\n", name, lt_dlerror());
		errnum = MODULE_NOT_FOUND;
		return NULL;
	}

	/* test if the module is valid by quering a symbol which must exists in
	 * every module. */
	void* sym = lt_dlsym(handle, "__module_type");
	if ( !sym ){
		log_message(Log_Debug, "Plugin '%s' found but is invalid\n", name);
		errnum = MODULE_INVALID;
		return NULL;
	}

	if ( type != ANY_MODULE && *((enum module_type_t*)sym) != type ){
		log_message(Log_Debug, "Plugin '%s' found but is invalid\n", name);
		errnum = MODULE_INVALID;
		return NULL;
	}

	/* base functions */
	void* module_init    = lt_dlsym(handle, "module_init");
	void* module_cleanup = lt_dlsym(handle, "module_cleanup");
	void* module_alloc   = lt_dlsym(handle, "module_alloc");
	void* module_free    = lt_dlsym(handle, "module_free");

	/* create base structure (later copied into the real struct */
	struct module_t base;
	base.handle  = handle;
	base.info    = lt_dlgetinfo(handle);
	base.init    = (module_init_callback)module_init;
	base.cleanup = (module_cleanup_callback)module_cleanup;
	base.alloc   = module_alloc ? (module_alloc_callback)module_alloc : default_alloc;
	base.free    = module_free  ?  (module_free_callback)module_free  : default_free;

	/* allocate real structure and copy base fields */
	module_handle module = base.alloc();
	*module = base;

	/* run module initialization if available */
	if ( callee_init(flags) && module->init && module->init(module) != 0 ){
		log_message(Log_Fatal, "Plugin `%s' initialization failed.\n", name);
		return NULL;
	}

	return module;
}
예제 #3
0
/**
 * initializeScanRules
 *
 * this reads in the rules definition file for identifying the playload.
 * It compiles the regular
 * expressions and loads in the dynamic libraries as defined for later use
 *
 * @param scriptFile a file pointer to the rule definition file
 *
 */
gboolean
ycInitializeScanRules (
    FILE * scriptFile,
    GError ** err)
{
/*
// for every rule that is "imagined" can be returned on a single call to
   pcre_exec, you need to multiply that number by 6 for the correct number of
   "vector" entries (and because of pcre limitation should be a multiple of 3)
*/
#define NUM_SUBSTRING_VECTS 60
    const char         *errorString;
    int                 errorPos;

    char                eString[ESTRING_SIZE];
    pcre               *ruleScanner;
    pcre               *pluginScanner;
    pcre               *commentScanner;
    pcre               *pluginArgScanner;
    pcre               *signatureScanner;
    const char          commentScannerExp[] = "^\\s*#[^\\n]*\\n";
    const char          pluginScannerExp[] =
      "^[[:space:]]*label[[:space:]]+([[:digit:]]+)"
      "[[:space:]]+plugin[[:space:]]*([^[:space:]\\n].*)\\n";
    const char          ruleScannerExp[] =
      "^[[:space:]]*label[[:space:]]+([[:digit:]]+)"
      "[[:space:]]+regex[[:space:]]*([^\\n].*)\\n";
    const char          signatureScannerExp[] =
      "^[[:space:]]*label[[:space:]]+([[:digit:]]+)"
      "[[:space:]]+signature[[:space:]]*([^\\n].*)\\n";
    const char          pluginArgScannerExp[] = "[[:word:]]";
    int                 rc;
    int                 substringVects[NUM_SUBSTRING_VECTS];
    char                lineBuffer[LINE_BUF_SIZE];
    int                 readLength;
    char               *captString;
    unsigned int        bufferOffset = 0;
    int                 currentStartPos = 0;
    int                 loop;
    char                *ltdl_lib_path = NULL;

    /* first mark all plugin entries as empty, just in case */
    for (loop = 0; loop < MAX_PAYLOAD_RULES; loop++) {
        ruleTable[loop].ruleType = EMPTY;
    }

    /* initialize the hash table */
    ycPortHashInitialize();


    /* initialize the dynamic loader library */
    rc = lt_dlinit();
    if (0 != rc) {
        *err = g_error_new (YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
                     "error initializing the dynamic loader library: \"%s\"",
                     lt_dlerror ());
        return FALSE;
    }
    /* if LTDL_LIBRARY_PATH is set - add this one first */
    ltdl_lib_path = getenv("LTDL_LIBRARY_PATH");
    if (ltdl_lib_path) {
        lt_dladdsearchdir(ltdl_lib_path);
    }

#ifdef YAF_APPLABEL_PATH
    /* add the applabel path based on libdir at build time */
    lt_dladdsearchdir(YAF_APPLABEL_PATH);
#else
    /* add /usr/local/lib/yaf to path since libtool can never find it */

    lt_dladdsearchdir(YAF_SEARCH_PATH);
    lt_dladdsearchdir(ALT_SEARCH_PATH);
    lt_dladdsearchdir(ALT_SEARCH_PATH64);
#endif
    /* create the hash table for library modules to library handle names */
    if (!hcreate ((MAX_PAYLOAD_RULES * 20) / 100)) {
        *err = g_error_new (YAF_ERROR_DOMAIN, YAF_ERROR_IMPL,
                     "couldn't create load module hash table (%d)", errno);
        return FALSE;
    }


    /*
     * take all of the rules needed to parse the rule file and compile
     * them into a form that // the regular expression engine can deal with */
    ruleScanner = pcre_compile(ruleScannerExp, PCRE_MULTILINE, &errorString,
                               &errorPos, NULL);
    if (NULL == ruleScanner) {
        ycDisplayScannerRuleError(eString, ESTRING_SIZE,
                                  "couldn't build the rule scanner",
                                  errorString, ruleScannerExp, errorPos);
        *err = g_error_new(YAF_ERROR_DOMAIN,YAF_ERROR_INTERNAL, "%s", eString);
        return FALSE;
    }

    pluginScanner = pcre_compile(pluginScannerExp, PCRE_MULTILINE,
                                 &errorString, &errorPos, NULL);
    if (NULL == pluginScanner) {
        ycDisplayScannerRuleError(eString, ESTRING_SIZE,
                                  "couldn't build the plugin scanner",
                                  errorString, pluginScannerExp, errorPos);
        *err = g_error_new(YAF_ERROR_DOMAIN,YAF_ERROR_INTERNAL, "%s", eString);
        return FALSE;
    }

    commentScanner = pcre_compile(commentScannerExp, PCRE_MULTILINE,
                                  &errorString, &errorPos, NULL);
    if (NULL == commentScanner) {
        ycDisplayScannerRuleError (eString, ESTRING_SIZE,
                                   "couldn't build the comment scanner",
                                   errorString, commentScannerExp, errorPos);
        *err = g_error_new(YAF_ERROR_DOMAIN,YAF_ERROR_INTERNAL, "%s", eString);
        return FALSE;
    }

    pluginArgScanner = pcre_compile(pluginArgScannerExp, PCRE_MULTILINE,
                                    &errorString, &errorPos, NULL);
    if (NULL == pluginArgScanner) {
        ycDisplayScannerRuleError(eString, ESTRING_SIZE,
                                  "couldn't build the plugin argument scanner",
                                  errorString, pluginArgScannerExp, errorPos);
        *err = g_error_new(YAF_ERROR_DOMAIN,YAF_ERROR_INTERNAL, "%s", eString);
        return FALSE;
    }

    signatureScanner = pcre_compile(signatureScannerExp, PCRE_MULTILINE,
                                    &errorString, &errorPos, NULL);
    if (NULL == signatureScanner) {
        ycDisplayScannerRuleError (eString, ESTRING_SIZE,
                       "couldn't build the signature scanner",
                       errorString, signatureScannerExp, errorPos);
        *err = g_error_new(YAF_ERROR_DOMAIN,YAF_ERROR_INTERNAL, "%s", eString);
        return FALSE;
    }

    /*
     * this is the loop that does the lion's share of the rule file
     * processing first read a hunk of the rule file, (this may include
     * multiple lines of stuff) this gets a little bit ugly, there are a
     * number of issues that have to handled; first, because there may be
     * multiple lines (which is in fact likely) it has to be able to work
     * its way through the buffer, a single pass of the buffer through the
     * pcre engine simply won't cut it; at the end, it is possible // to have
     * part of line, when this happens, it needs to copy the leftover part
     * of the read into the front of the buffer, and then read again to fill in
     * the rest of line.  (this detail limits a single line to
     * LINE_BUF_SIZE size) */
    do {
        readLength =
          fread (lineBuffer + bufferOffset, 1, LINE_BUF_SIZE - 1 -bufferOffset,
                 scriptFile);
        if (0 == readLength) {
            if (ferror (scriptFile)) {
                *err = g_error_new(YAF_ERROR_DOMAIN, YAF_ERROR_IO,
                                   "couldn't read the rule file: %s",
                                   strerror (errno));
                return FALSE;
            }
            break;
        }

        /* fread only returns how much it read from the file - need to add
           extra we put in the buffer from last read, if any */

        readLength += bufferOffset;

        /*
         * substringVects is used by the pcre library to indicate where the
         * matched substrings are in the input string, but [1] points to
         * the very end of the total match, we use this to iterate through
         * the readBuffer, always reset it after a read */
        substringVects[0] = 0;
        substringVects[1] = 0;

        /* parse as much of the input buffer as possible */
        while (substringVects[1] < readLength) {

#if YFDEBUG_APPLABEL
            g_debug("readLength %d startPosition %d\n", readLength,
                    substringVects[1]);
            for (loop=0; loop < 10; loop++) {
                if (loop+substringVects[1] > readLength) {
                    break;
                }
                char curChar = *(lineBuffer + substringVects[1] + loop);
                if (iscntrl(curChar)) {
                    g_debug(".");
                    continue;
                }
                if (isprint(curChar)) {
                    g_debug("%c", curChar);
                } else {
                    g_debug(".");
                }
            }
            g_debug("\n");
#endif
            /* get rid of CR's and LF's at the begging, use the simple manual
             * method, they gum up the regex works */
            if ('\n' == *(lineBuffer + substringVects[1])
                || '\r' == *(lineBuffer + substringVects[1])) {
                substringVects[1]++;
                continue;
            }

            /* first check for comments, and eliminate them */
            currentStartPos = substringVects[1];
            /* need to store the current offset, if we fail to match, we
               get -1 in [1] */
            rc = pcre_exec (commentScanner, NULL, lineBuffer, readLength,
                            substringVects[1], PCRE_ANCHORED, substringVects,
                            NUM_SUBSTRING_VECTS);
            if (rc > 0) {
#if YFDEBUG_APPLABEL
                g_debug("comment match pos %d to pos %d\n",
                    substringVects[0], substringVects[1]);
                pcre_get_substring(lineBuffer, substringVects, rc, 0,
                    (const char**)&captString);
                g_debug("comment line is \"%s\"\n", captString);
                pcre_free(captString);
#endif
                continue;
            }
            substringVects[1] = currentStartPos;

            /* scan the line to see if it is a regex statement, and get the
             * arguments if it is */
            rc = pcre_exec (ruleScanner, NULL, lineBuffer, readLength,
                            substringVects[1], PCRE_ANCHORED, substringVects,
                            NUM_SUBSTRING_VECTS);
            if (rc > 0) {
                pcre               *newRule;
                pcre_extra         *newExtra;

                /* get the first matched field from the regex rule expression
                 * (the label value) */
                pcre_get_substring (lineBuffer, substringVects, rc, 1,
                                    (const char **) &captString);
                ruleTable[numPayloadRules].payloadLabelValue =
                  strtoul (captString, NULL, 10);
#if YFDEBUG_APPLABEL
                g_debug("regex: rule # %u, label value %lu ",
                        numPayloadRules, strtoul(captString, NULL, 10));
#endif
                pcre_free (captString);

                /* get the second matched field from the regex rule expression
                 * (should be the regex) */

                pcre_get_substring(lineBuffer, substringVects, rc, 2,
                                   (const char **) &captString);
#if YF_DEBUG_APPLABEL
                g_debug(" regex \"%s\"\n", captString);
#endif
                newRule = pcre_compile(captString, 0, &errorString, &errorPos,
                                       NULL);
                if (NULL == newRule) {
                    ycDisplayScannerRuleError(eString, ESTRING_SIZE,
                                     "error in regex application labeler rule",
                                              errorString, captString,
                                              errorPos);

                } else {
                    newExtra = pcre_study (newRule, 0, &errorString);
                    ruleTable[numPayloadRules].ruleArgs.regexFields.
                      scannerExpression = newRule;
                    ruleTable[numPayloadRules].ruleArgs.regexFields.
                      scannerExtra = newExtra;
                    ruleTable[numPayloadRules].ruleType = REGEX;
                    ycPortHashInsert(ruleTable[numPayloadRules].payloadLabelValue, numPayloadRules);
                    numPayloadRules++;
                }
                pcre_free (captString);

                if (MAX_PAYLOAD_RULES == numPayloadRules) {
                    *err = g_error_new (YAF_ERROR_DOMAIN, YAF_ERROR_LIMIT,
                                        "maximum number of application labeler"
                                        " rules has been reached");
                    return FALSE;
                }

                continue;
            }
            substringVects[1] = currentStartPos;
            /* scan the line to see if it is a plugin statement, and handle the
             * arguments if it is */
            rc = pcre_exec (pluginScanner, NULL, lineBuffer, readLength,
                            substringVects[1], PCRE_ANCHORED, substringVects,
                            NUM_SUBSTRING_VECTS);
            if (rc > 0) {
                int                 numArgs;
                char             **argStrings;

                /* get the first matched field from the regex rule expression
                 * (the lable value) */
                pcre_get_substring (lineBuffer, substringVects, rc, 1,
                                    (const char **) &captString);
                ruleTable[numPayloadRules].payloadLabelValue =
                  strtoul (captString, NULL, 10);
#if YFDEBUG_APPLABEL
                g_debug("plugin: rule # %u, label value %lu ",
                        numPayloadRules, strtoul(captString, NULL, 10));
#endif
                pcre_free (captString);

                /*
                 * get the second matched field, which should be the plugin
                 * name and all of its arguments, now we need to chunk that
                 * into an array of strings, ala argc, argv
                 */
                pcre_get_substring(lineBuffer, substringVects, rc, 2,
                                   (const char **) &captString);
                ycChunkString(captString, &numArgs, &argStrings);

                if (numArgs < 2) {
                    g_critical("error: not enough arguments to load and call "
                               "a plugin, at least a library name and function"
                               " name are needed\n");
                    pcre_free(captString);
                    pcre_get_substring(lineBuffer, substringVects, rc, 0,
                                       (const char **) &captString);
                    g_critical("input line: \"%s\"\n", captString);
                } else {
                    ENTRY               newItem;
                    ENTRY              *foundItem;
                    lt_dlhandle         modHandle;
                    lt_ptr              funcPtr;

                    ruleTable[numPayloadRules].ruleType = PLUGIN;
                    ruleTable[numPayloadRules].ruleArgs.pluginArgs.numArgs =
                      numArgs;
                    ruleTable[numPayloadRules].ruleArgs.pluginArgs.pluginArgs =
                      argStrings;
                    newItem.key = strdup(argStrings[0]);
                    if (NULL == newItem.key) {
                        g_error("out of memory error\n");
                        for (loop = 0; loop < numArgs; loop++) {
                            free ((char *) (argStrings[loop]));
                        }
                        free(argStrings);
                        return FALSE;
                    }
                    newItem.data = NULL;
                    foundItem = hsearch(newItem, FIND);
                    if (NULL == foundItem) {

                        modHandle = lt_dlopenext(newItem.key);
                        if (NULL == modHandle) {
                            g_critical("Couldn't open library \"%s\": %s",
                                       argStrings[0], lt_dlerror());
                            g_critical("Search path set to %s",
                                       lt_dlgetsearchpath());
                            g_critical("Set LTDL_LIBRARY_PATH to correct"
                                       " location.");
                            for (loop = 0; loop < numArgs; loop++) {
                                free((char *) (argStrings[loop]));
                            }
                            free(argStrings);
                            pcre_free(captString);
                            continue;
                        } else {
#if YFDEBUG_APPLABEL
                            const lt_dlinfo *info = lt_dlgetinfo(modHandle);
                            g_debug("Loading %s plugin from %s", info->name, info->filename);
#endif
                        }
                        newItem.data = (void *)modHandle;
                        hsearch(newItem, ENTER);
                    } else {
                        modHandle = (lt_dlhandle)foundItem->data;
                    }

                    funcPtr = lt_dlsym(modHandle, argStrings[1]);
                    if (NULL == funcPtr) {
                        g_critical("couldn't find function \"%s\" in library"
                                   " \"%s\"\n", argStrings[1], argStrings[0]);
                        for (loop = 0; loop < numArgs; loop++) {
                            free ((char *) (argStrings[loop]));
                        }
                        free (argStrings);
                        pcre_free (captString);
                        continue;
                    }
                    ruleTable[numPayloadRules].ruleArgs.pluginArgs.func =
                        (ycScannerPlugin_fn) funcPtr;

                    ycPortHashInsert(ruleTable[numPayloadRules].payloadLabelValue, numPayloadRules);
                    numPayloadRules++;
                }

                pcre_free(captString);

                if (MAX_PAYLOAD_RULES == numPayloadRules) {
                    g_warning ("maximum number of rules has been reached\n");
                    return TRUE;
                }
                continue;
            }


        substringVects[1] = currentStartPos;

        /* scan the line to see if it is a signature, and get the
         * arguments if it is */
        rc = pcre_exec(signatureScanner, NULL, lineBuffer, readLength,
                       substringVects[1], PCRE_ANCHORED, substringVects,
                       NUM_SUBSTRING_VECTS);
        if (rc > 0) {
            pcre               *newRule;
            pcre_extra         *newExtra;

            /* get the first matched field from the regex rule expression
             * (the label value) */
            pcre_get_substring(lineBuffer, substringVects, rc, 1,
                               (const char **) &captString);

            sigTable[numSigRules].payloadLabelValue = strtoul(captString, NULL,
                                                              10);
#if YFDEBUG_APPLABEL
            g_debug("signature: rule # %u, label value %lu ",
                    numSigRules, strtoul(captString, NULL, 10));
#endif
            pcre_free (captString);

            /* get the second matched field from the regex rule expression
             * (should be the regex) */
            pcre_get_substring(lineBuffer, substringVects, rc, 2,
                               (const char **) &captString);
#if YFDEBUG_APPLABEL
            g_debug(" signature \"%s\"\n", captString);
#endif
            newRule = pcre_compile(captString, 0, &errorString, &errorPos,
                                   NULL);
            if (NULL == newRule) {
                ycDisplayScannerRuleError (eString, ESTRING_SIZE,
                                           "error in signature application "
                                           "labeler rule", errorString,
                                           captString, errorPos);

            } else {
                newExtra = pcre_study (newRule, 0, &errorString);
                sigTable[numSigRules].ruleArgs.regexFields.
                    scannerExpression = newRule;
                sigTable[numSigRules].ruleArgs.regexFields.
                    scannerExtra = newExtra;
                sigTable[numSigRules].ruleType = SIGNATURE;
                numSigRules++;
            }

            pcre_free(captString);

            if (MAX_PAYLOAD_RULES == numSigRules) {
                *err = g_error_new(YAF_ERROR_DOMAIN, YAF_ERROR_LIMIT,
                                   "maximum number of signature rules has "
                                   "been reached");
                return FALSE;
            }

            continue;
        }

        substringVects[1] = currentStartPos;


        /*   pcre_free (captString);*/

#if YFDEBUG_APPLABEL
        g_debug("plugin args: ");
        for (loop = 0; loop < numArgs; loop++) {
            g_debug("\"%s\" ", (*argStrings)[loop]);
        }
        g_debug("\n");
#endif

        /*
         * check to see if we have partial text left over at the end of
         * the read buffer, if we copy it to the front of the read
         * buffer, and on the next read, read a little less to
         * compensate for the left over amount */
        if ((PCRE_ERROR_NOMATCH == rc) && (substringVects[1] < readLength)
            && !feof (scriptFile)) {
            memmove (lineBuffer, lineBuffer + substringVects[1],
                     readLength - substringVects[1]);
            bufferOffset = readLength - substringVects[1];
            break;
        } else if (PCRE_ERROR_NOMATCH == rc && feof (scriptFile)) {
            /* this is an error, we have crap left over at the end of the
             * file that we can't parse! */
            g_critical("unparsed text at the end of the application labeler"
                       " rule file!\n");
            break;
        }
        }

    } while (!ferror (scriptFile) && !feof (scriptFile));

    /*
     * get rid of the module handle lookup hash; this creates a mem leak of
     * the module handles, they can't be freed any longer (although this is a
     * crappy hash, and iterating the hash is not possible....) */
    hdestroy();

    g_debug("Application Labeler accepted %d rules.", numPayloadRules);
    g_debug("Application Labeler accepted %d signatures.", numSigRules);
    pcre_free(ruleScanner);
    pcre_free(pluginScanner);
    pcre_free(commentScanner);
    pcre_free(pluginArgScanner);
    pcre_free(signatureScanner);

    /* debug */
    return TRUE;
}