Exemplo n.º 1
0
static int DetectFlowbitParse(char *str, char *cmd, int cmd_len, char *name,
    int name_len)
{
    const int max_substrings = 30;
    int count, rc;
    int ov[max_substrings];

    count = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
        ov, max_substrings);
    if (count != 2 && count != 3) {
        SCLogError(SC_ERR_PCRE_MATCH,
            "\"%s\" is not a valid setting for flowbits.", str);
        return 0;
    }

    rc = pcre_copy_substring((char *)str, ov, max_substrings, 1, cmd, cmd_len);
    if (rc < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        return 0;
    }

    if (count == 3) {
        rc = pcre_copy_substring((char *)str, ov, max_substrings, 2, name,
            name_len);
        if (rc < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            return 0;
        }
    }

    return 1;
}
Exemplo n.º 2
0
/**
 * \brief Parses a line from the reference config file and adds it to Reference
 *        Config hash table DetectEngineCtx->reference_conf_ht.
 *
 * \param rawstr Pointer to the string to be parsed.
 * \param de_ctx Pointer to the Detection Engine Context.
 *
 * \retval  0 On success.
 * \retval -1 On failure.
 */
static int SCRConfAddReference(char *rawstr, DetectEngineCtx *de_ctx)
{
    char system[64];
    char url[1024];

    SCRConfReference *ref_new = NULL;
    SCRConfReference *ref_lookup = NULL;

#define MAX_SUBSTRINGS 30
    int ret = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, 30);
    if (ret < 0) {
        SCLogError(SC_ERR_REFERENCE_CONFIG, "Invalid Reference Config in "
                   "reference.config file");
        goto error;
    }

    /* retrieve the reference system */
    ret = pcre_copy_substring((char *)rawstr, ov, 30, 1, system, sizeof(system));
    if (ret < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring() failed");
        goto error;
    }

    /* retrieve the reference url */
    ret = pcre_copy_substring((char *)rawstr, ov, 30, 2, url, sizeof(url));
    if (ret < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring() failed");
        goto error;
    }

    /* Create a new instance of the parsed Reference string */
    ref_new = SCRConfAllocSCRConfReference(system, url);
    if (ref_new == NULL)
        goto error;

    /* Check if the Reference is present in the HashTable.  In case it's present
     * ignore it, as it's a duplicate.  If not present, add it to the table */
    ref_lookup = HashTableLookup(de_ctx->reference_conf_ht, ref_new, 0);
    if (ref_lookup == NULL) {
        if (HashTableAdd(de_ctx->reference_conf_ht, ref_new, 0) < 0) {
            SCLogDebug("HashTable Add failed");
        }
    } else {
        SCLogDebug("Duplicate reference found inside reference.config");
        SCRConfDeAllocSCRConfReference(ref_new);
    }

    return 0;

 error:
    return -1;
}
Exemplo n.º 3
0
int regex_match_substring(tvh_regex_t *regex, unsigned number, char *buf, size_t size_buf)
{
  assert(buf);
  if (number >= TVHREGEX_MAX_MATCHES)
    return -2;
#if ENABLE_PCRE || ENABLE_PCRE2
  if (regex->is_posix) {
#endif
    if (regex->re_posix_match[number].rm_so == -1)
      return -1;
    ssize_t size = regex->re_posix_match[number].rm_eo - regex->re_posix_match[number].rm_so;
    if (size < 0 || size > (size_buf - 1))
      return -1;
    strlcpy(buf, regex->re_posix_text + regex->re_posix_match[number].rm_so, size + 1);
    return 0;
#if ENABLE_PCRE || ENABLE_PCRE2
  } else {
#if ENABLE_PCRE
    return pcre_copy_substring(regex->re_text, regex->re_match,
                               (regex->re_matches == 0)
                               ? TVHREGEX_MAX_MATCHES
                               : regex->re_matches,
                               number, buf, size_buf) < 0;
#elif ENABLE_PCRE2
    PCRE2_SIZE psiz = size_buf;
    return pcre2_substring_copy_bynumber(regex->re_match, number, (PCRE2_UCHAR8*)buf, &psiz);
#endif
  }
#endif
}
Exemplo n.º 4
0
/**
 * \brief This function is used to parse options passed via krb5_errcode: keyword
 *
 * \param krb5str Pointer to the user provided krb5_err_code options
 *
 * \retval krb5d pointer to DetectKrb5Data on success
 * \retval NULL on failure
 */
static DetectKrb5ErrCodeData *DetectKrb5ErrCodeParse (const char *krb5str)
{
    DetectKrb5ErrCodeData *krb5d = NULL;
    char arg1[4] = "";
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study,
                    krb5str, strlen(krb5str),
                    0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 2) {
        SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
        goto error;
    }

    res = pcre_copy_substring((char *) krb5str, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        goto error;
    }

    krb5d = SCMalloc(sizeof (DetectKrb5ErrCodeData));
    if (unlikely(krb5d == NULL))
        goto error;
    krb5d->err_code = (int32_t)atoi(arg1);

    return krb5d;

error:
    if (krb5d)
        SCFree(krb5d);
    return NULL;
}
Exemplo n.º 5
0
/**
 * \brief This function is used to parse template options passed via template: keyword
 *
 * \param templatestr Pointer to the user provided template options
 *
 * \retval templated pointer to DetectTemplateData on success
 * \retval NULL on failure
 */
static DetectTemplateData *DetectTemplateParse (const char *templatestr)
{
    DetectTemplateData *templated = NULL;
    char arg1[4] = "";
    char arg2[4] = "";
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study,
                    templatestr, strlen(templatestr),
                    0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 3) {
        SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
        goto error;
    }

    res = pcre_copy_substring((char *) templatestr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        goto error;
    }
    SCLogDebug("Arg1 \"%s\"", arg1);

    if (ret >= 3) {
        res = pcre_copy_substring((char *) templatestr, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            goto error;
        }
        SCLogDebug("Arg2 \"%s\"", arg2);

    }

    templated = SCMalloc(sizeof (DetectTemplateData));
    if (unlikely(templated == NULL))
        goto error;
    templated->arg1 = (uint8_t)atoi(arg1);
    templated->arg2 = (uint8_t)atoi(arg2);

    return templated;

error:
    if (templated)
        SCFree(templated);
    return NULL;
}
Exemplo n.º 6
0
static int DetectFlowbitParse(char *str, char *cmd, int cmd_len, char *name,
    int name_len)
{
    const int max_substrings = 30;
    int count, rc;
    int ov[max_substrings];

    count = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
        ov, max_substrings);
    if (count != 2 && count != 3) {
        SCLogError(SC_ERR_PCRE_MATCH,
            "\"%s\" is not a valid setting for flowbits.", str);
        return 0;
    }

    rc = pcre_copy_substring((char *)str, ov, max_substrings, 1, cmd, cmd_len);
    if (rc < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        return 0;
    }

    if (count == 3) {
        rc = pcre_copy_substring((char *)str, ov, max_substrings, 2, name,
            name_len);
        if (rc < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            return 0;
        }

        /* Trim trailing whitespace. */
        while (strlen(name) > 0 && isblank(name[strlen(name) - 1])) {
            name[strlen(name) - 1] = '\0';
        }

        /* Validate name, spaces are not allowed. */
        for (size_t i = 0; i < strlen(name); i++) {
            if (isblank(name[i])) {
                SCLogError(SC_ERR_INVALID_SIGNATURE,
                    "spaces not allowed in flowbit names");
                return 0;
            }
        }
    }

    return 1;
}
Exemplo n.º 7
0
int
pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector,
  int stringcount, const char *stringname, char *buffer, int size)
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
}
Exemplo n.º 8
0
int
pcre_copy_named_substring(const pcre *code, const pcre_char *subject, int *ovector,
  int stringcount, const pcre_char *stringname, pcre_char *buffer, int size)
{
int n = pcre_get_stringnumber(code, stringname);
if (n <= 0) return n;
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
}
Exemplo n.º 9
0
static DetectTosData *DetectTosParse(const char *arg, bool negate)
{
    DetectTosData *tosd = NULL;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study, arg, strlen(arg), 0, 0,
                    ov, MAX_SUBSTRINGS);

    if (ret != 2) {
        SCLogError(SC_ERR_PCRE_MATCH, "invalid tos option - %s. "
                   "The tos option value must be in the range "
                   "%u - %u", arg, DETECT_IPTOS_MIN, DETECT_IPTOS_MAX);
        goto error;
    }

    /* For TOS value */
    char tosbytes_str[64] = "";
    res = pcre_copy_substring((char *)arg, ov, MAX_SUBSTRINGS, 1,
                             tosbytes_str, sizeof(tosbytes_str));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        goto error;
    }

    int64_t tos = 0;

    if (tosbytes_str[0] == 'x' || tosbytes_str[0] == 'X') {
        int r = ByteExtractStringSigned(&tos, 16, 0, &tosbytes_str[1]);
        if (r < 0) {
            goto error;
        }
    } else {
        int r = ByteExtractStringSigned(&tos, 10, 0, &tosbytes_str[0]);
        if (r < 0) {
            goto error;
        }
    }

    if (!(tos >= DETECT_IPTOS_MIN && tos <= DETECT_IPTOS_MAX)) {
        SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid tos argument - "
                   "%s.  The tos option value must be in the range "
                   "%u - %u", tosbytes_str, DETECT_IPTOS_MIN, DETECT_IPTOS_MAX);
        goto error;
    }

    tosd = SCMalloc(sizeof(DetectTosData));
    if (unlikely(tosd == NULL))
        goto error;
    tosd->tos = (uint8_t)tos;
    tosd->negated = negate;

    return tosd;

error:
    return NULL;
}
Exemplo n.º 10
0
/**
 * Handler called whenever a global message is spoken in a NPC's area
 */
int npc_chat_sub(struct block_list* bl, va_list ap)
{
	struct npc_data* nd = (struct npc_data *) bl;
	struct npc_parse* npcParse = (struct npc_parse *) nd->chatdb;
	char* msg;
	int len, i;
	struct map_session_data* sd;
	struct npc_label_list* lst;
	struct pcrematch_set* pcreset;
	struct pcrematch_entry* e;

	// Not interested in anything you might have to say...
	if (npcParse == NULL || npcParse->active == NULL)
		return 0;

	msg = va_arg(ap,char*);
	len = va_arg(ap,int);
	sd = va_arg(ap,struct map_session_data *);

	// iterate across all active sets
	for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next)
	{
		// interate across all patterns in that set
		for (e = pcreset->head; e != NULL; e = e->next)
		{
			int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec

			// perform pattern match
			int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets));
			if (r > 0)
			{
				// save out the matched strings
				for (i = 0; i < r; i++)
				{
					char var[6], val[255];
					snprintf(var, sizeof(var), "$@p%i$", i);
					pcre_copy_substring(msg, offsets, r, i, val, sizeof(val));
					set_var(sd, var, val);
				}

				// find the target label.. this sucks..
				lst = nd->u.scr.label_list;
				ARR_FIND(0, nd->u.scr.label_list_num, i, strncmp(lst[i].name, e->label, sizeof(lst[i].name)) == 0);
				if (i == nd->u.scr.label_list_num) {
					ShowWarning("Unable to find label: %s\n", e->label);
					return 0;
				}

				// run the npc script
				run_script(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id);
				return 0;
			}
		}
	}

	return 0;
}
Exemplo n.º 11
0
/**
 * \brief This function is used to parse decoder events options passed via decode-event: keyword
 *
 * \param rawstr Pointer to the user provided decode-event options
 *
 * \retval de pointer to DetectFlowData on success
 * \retval NULL on failure
 */
DetectEngineEventData *DetectEngineEventParse (char *rawstr)
{
    int i;
    DetectEngineEventData *de = NULL;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0, found = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret < 1) {
        SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32
                ", string %s", ret, rawstr);
        goto error;
    }

    char copy_str[128] = "";
    res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 0,
            copy_str, sizeof(copy_str));

    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        goto error;
    }

    for (i = 0; DEvents[i].event_name != NULL; i++) {
        if (strcasecmp(DEvents[i].event_name,copy_str) == 0) {
            found = 1;
            break;
        }
    }

    if (found == 0) {
        SCLogError(SC_ERR_UNKNOWN_DECODE_EVENT, "unknown decode event \"%s\"",
                copy_str);
        goto error;
    }

    de = SCMalloc(sizeof(DetectEngineEventData));
    if (unlikely(de == NULL))
        goto error;

    de->event = DEvents[i].code;

    if (de->event == STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA) {
        StreamTcpReassembleConfigEnableOverlapCheck();
    }
    return de;

error:
    if (de)
        SCFree(de);
    return NULL;
}
Exemplo n.º 12
0
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
  int *ovector, int stringcount, PCRE_SPTR16 stringname,
  PCRE_UCHAR16 *buffer, int size)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#ifdef COMPILE_PCRE8
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
#else
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
#endif
}
Exemplo n.º 13
0
void format(char* s, const char* fmt, const char* p, int* v, int n)
{
	const char* t = fmt;
	while (1) {
		int c = (int)strcspn(t, ESCAPE_STR);
		memcpy(s, t, c);
		s += c;
		t += c;
		if (!*t) {
			break;
		} else if (*t == ESCAPE_CHAR) {
			if (isdigit(*++t)) {	/* \N */
				c = (*t-'0') * 2;
				++t;
				memcpy(s, p+v[c], v[c+1]-v[c]);
				s += v[c+1] - v[c];
			} else if (isalpha(*t) && isdigit(*(t+1))) {
								/* \xN */
				const char* q;
				++t;
				c = *t - '0';
				if (pcre_get_substring(p, v, n, c, &q) <= 0) {
					++t;
					/* TODO: handle error */
					continue;
				}
				if (find_translation(q, s,
							to_section(*(t-1)))) {
					s += strlen(s);
				} else {
					s += pcre_copy_substring(p, v, n, c, s,
							100);
					/* TODO: fix the use of magic number */
				}
				++t;
				pcre_free_substring(q);
			} else {
				++t;
				/* do nothing */
			}
		} else {
			printf("\nformat: impossible!\n");
			system("pause");
		}
	}
	*s = 0;
}
Exemplo n.º 14
0
/**
 * \brief This function is used to parse ftpcommand options passed via ftpcommand: keyword
 *
 * \param ftpcommandstr Pointer to the user provided ftpcommand options
 *
 * \retval ftpcommandd pointer to DetectFtpdataData on success
 * \retval NULL on failure
 */
static DetectFtpdataData *DetectFtpdataParse(const char *ftpcommandstr)
{
    DetectFtpdataData *ftpcommandd = NULL;
    char arg1[5] = "";
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];

    ret = pcre_exec(parse_regex, parse_regex_study,
                    ftpcommandstr, strlen(ftpcommandstr),
                    0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 2) {
        SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
        goto error;
    }

    res = pcre_copy_substring((char *) ftpcommandstr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        goto error;
    }
    SCLogDebug("Arg1 \"%s\"", arg1);

    ftpcommandd = SCMalloc(sizeof (DetectFtpdataData));
    if (unlikely(ftpcommandd == NULL))
        goto error;
    if (!strcmp(arg1, "stor")) {
        ftpcommandd->command = FTP_COMMAND_STOR;
    } else if (!strcmp(arg1, "retr")) {
        ftpcommandd->command = FTP_COMMAND_RETR;
    } else {
        SCLogError(SC_ERR_NOT_SUPPORTED, "Invalid command value");
        goto error;
    }


    return ftpcommandd;

error:
    if (ftpcommandd)
        SCFree(ftpcommandd);
    return NULL;
}
Exemplo n.º 15
0
SWITCH_DECLARE(void) switch_perform_substitution(switch_regex_t *re, int match_count, const char *data, const char *field_data,
        char *substituted, switch_size_t len, int *ovector)
{
    char index[10] = "";
    char replace[1024] = "";
    switch_size_t x, y = 0, z = 0;
    int num = 0;

    for (x = 0; x < (len - 1) && x < strlen(data);) {
        if (data[x] == '$') {
            x++;

            if (!(data[x] > 47 && data[x] < 58)) {
                substituted[y++] = data[x - 1];
                continue;
            }

            while (data[x] > 47 && data[x] < 58) {
                index[z++] = data[x];
                x++;
            }
            index[z++] = '\0';
            z = 0;
            num = atoi(index);

            if (num < 0 || num > 256) {
                num = -1;
            }

            if (pcre_copy_substring(field_data, ovector, match_count, num, replace, sizeof(replace)) > 0) {
                switch_size_t r;
                for (r = 0; r < strlen(replace); r++) {
                    substituted[y++] = replace[r];
                }
            }
        } else {
            substituted[y++] = data[x];
            x++;
        }
    }
    substituted[y++] = '\0';
}
Exemplo n.º 16
0
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
  int *ovector, int stringcount, PCRE_SPTR32 stringname,
  PCRE_UCHAR32 *buffer, int size)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#if defined COMPILE_PCRE8
#if defined(ERLANG_INTEGRATION)
return erts_pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
#else
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
#endif
#elif defined COMPILE_PCRE16
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
#elif defined COMPILE_PCRE32
return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size);
#endif
}
Exemplo n.º 17
0
int main(int argc, char **argv)
{
  const char *error;
  int erroffset;
  int ovector[186];
  char re[8192]="";
  char txt[]="05:Feb:2012 \"This is an Example!\"";

  char re1[]="(05:Feb:2012)";	// DDMMMYYYY 1
  strcat(re,re1);

  pcre *r =  pcre_compile(re, PCRE_CASELESS|PCRE_DOTALL, &error, &erroffset, NULL);
  int rc = pcre_exec(r, NULL, txt, strlen(txt), 0, 0, ovector, 186);
  if (rc>0)
  {
      char ddmmmyyyy1[1024];
      pcre_copy_substring(txt, ovector, rc,1,ddmmmyyyy1, 1024);
      printf("(%s)",ddmmmyyyy1);
      puts("\n");
  }
}
Exemplo n.º 18
0
/* Returning a struct as part of a bad hack to get around pointer traversal issues. TODO: Dynamic mem alloc */
regexStr regexMatch(char *re, char *txt)
{
	const char *error;
	int erroffset;
	int ovector[186];
	int substrCount;
	regexStr t;

	pcre *r =  pcre_compile(re, PCRE_CASELESS|PCRE_DOTALL, &error, &erroffset, NULL);
	int rc = pcre_exec(r, NULL, txt, strlen(txt), 0, 0, ovector, 186);
	//printf("%d\n", rc);

	if (rc > 0) {
		for (substrCount = 1; substrCount <= rc; substrCount++) {
			pcre_copy_substring(txt, ovector, rc, substrCount, t.substr[substrCount - 1], 1024);
		}
	}

	free(r);
	return t;
}
Exemplo n.º 19
0
/** \internal
 *
 * \brief This function is used to parse Modbus parameters in access mode
 *
 * \param str Pointer to the user provided id option
 *
 * \retval Pointer to DetectModbusData on success or NULL on failure
 */
static DetectModbus *DetectModbusAccessParse(char *str)
{
    SCEnter();
    DetectModbus *modbus = NULL;

    char    arg[MAX_SUBSTRINGS];
    int     ov[MAX_SUBSTRINGS], ret, res;

    ret = pcre_exec(access_parse_regex, access_parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS);

    if (ret < 1)
        goto error;

    res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 1, arg, MAX_SUBSTRINGS);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        goto error;
    }

    /* We have a correct Modbus option */
    modbus = (DetectModbus *) SCCalloc(1, sizeof(DetectModbus));
    if (unlikely(modbus == NULL))
        goto error;

    if (strcmp(arg, "read") == 0)
        modbus->type = MODBUS_TYP_READ;
    else if (strcmp(arg, "write") == 0)
        modbus->type = MODBUS_TYP_WRITE;
    else
        goto error;

    if (ret > 2) {
        res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 2, arg, MAX_SUBSTRINGS);
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            goto error;
        }

        if (*arg != '\0') {
            if (strcmp(arg, "discretes") == 0) {
                if (modbus->type == MODBUS_TYP_WRITE)
                    /* Discrete access is only read access. */
                    goto error;

                modbus->type |= MODBUS_TYP_DISCRETES;
            }
            else if (strcmp(arg, "coils") == 0) {
                modbus->type |= MODBUS_TYP_COILS;
            }
            else if (strcmp(arg, "input") == 0) {
                if (modbus->type == MODBUS_TYP_WRITE) {
                    /* Input access is only read access. */
                    goto error;
                }

                modbus->type |= MODBUS_TYP_INPUT;
            }
            else if (strcmp(arg, "holding") == 0) {
                modbus->type |= MODBUS_TYP_HOLDING;
            }
            else
                goto error;
        }

        if (ret > 4) {
            res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 4, arg, MAX_SUBSTRINGS);
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                goto error;
            }

            /* We have a correct address option */
            modbus->address = (DetectModbusValue *) SCCalloc(1, sizeof(DetectModbusValue));
            if (unlikely(modbus->address == NULL))
                goto error;

            if (arg[0] == '>') {
                modbus->address->min    = atoi((const char*) (arg+1));
                modbus->address->mode   = DETECT_MODBUS_GT;
            } else if (arg[0] == '<') {
                modbus->address->min    = atoi((const char*) (arg+1));
                modbus->address->mode   = DETECT_MODBUS_LT;
            } else {
                modbus->address->min    = atoi((const char*) arg);
            }
            SCLogDebug("and min/equal address %d", modbus->address->min);

            if (ret > 5) {
                res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 5, arg, MAX_SUBSTRINGS);
                if (res < 0) {
                    SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                    goto error;
                }

                if (*arg != '\0') {
                    modbus->address->max    = atoi((const char*) (arg+2));
                    modbus->address->mode   = DETECT_MODBUS_RA;
                    SCLogDebug("and max address %d", modbus->address->max);
                }

                if (ret > 7) {
                    res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 7, arg, MAX_SUBSTRINGS);
                    if (res < 0) {
                        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                        goto error;
                    }

                    if (modbus->address->mode != DETECT_MODBUS_EQ) {
                        SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords (address range and value).");
                        goto error;
                    }

                    /* We have a correct address option */
                    modbus->data = (DetectModbusValue *) SCCalloc(1, sizeof(DetectModbusValue));
                    if (unlikely(modbus->data == NULL))
                        goto error;

                    if (arg[0] == '>') {
                        modbus->data->min   = atoi((const char*) (arg+1));
                        modbus->data->mode  = DETECT_MODBUS_GT;
                    } else if (arg[0] == '<') {
                        modbus->data->min   = atoi((const char*) (arg+1));
                        modbus->data->mode  = DETECT_MODBUS_LT;
                    } else {
                        modbus->data->min   = atoi((const char*) arg);
                    }
                    SCLogDebug("and min/equal value %d", modbus->data->min);

                    if (ret > 8) {
                        res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 8, arg, MAX_SUBSTRINGS);
                        if (res < 0) {
                            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                            goto error;
                        }

                        if (*arg != '\0') {
                            modbus->data->max   = atoi((const char*) (arg+2));
                            modbus->data->mode  = DETECT_MODBUS_RA;
                            SCLogDebug("and max value %d", modbus->data->max);
                        }
                    }
                }
            }
        }
    }

    SCReturnPtr(modbus, "DetectModbusAccess");

error:
    if (modbus != NULL)
        DetectModbusFree(modbus);

    SCReturnPtr(NULL, "DetectModbus");
}
Exemplo n.º 20
0
/**
 * \brief This function is used to parse flow options passed via flow: keyword
 *
 * \param flowstr Pointer to the user provided flow options
 *
 * \retval fd pointer to DetectFlowData on success
 * \retval NULL on failure
 */
DetectFlowData *DetectFlowParse (char *flowstr)
{
    DetectFlowData *fd = NULL;
    char *args[3] = {NULL,NULL,NULL};
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    char str1[16] = "", str2[16] = "", str3[16] = "";

    ret = pcre_exec(parse_regex, parse_regex_study, flowstr, strlen(flowstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret < 1 || ret > 4) {
        SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, flowstr);
        goto error;
    }

    if (ret > 1) {
        res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 1, str1, sizeof(str1));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            goto error;
        }
        args[0] = (char *)str1;

        if (ret > 2) {
            res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 2, str2, sizeof(str2));
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                goto error;
            }
            args[1] = (char *)str2;
        }
        if (ret > 3) {
            res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 3, str3, sizeof(str3));
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                goto error;
            }
            args[2] = (char *)str3;
        }
    }

    fd = SCMalloc(sizeof(DetectFlowData));
    if (unlikely(fd == NULL))
        goto error;
    fd->flags = 0;
    fd->match_cnt = 0;

    int i;
    for (i = 0; i < (ret - 1); i++) {
        if (args[i]) {
            /* inspect our options and set the flags */
            if (strcasecmp(args[i], "established") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_ESTABLISHED flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_ESTABLISHED;
            } else if (strcasecmp(args[i], "not_established") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_NOT_ESTABLISHED flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_NOT_ESTABLISHED, DETECT_FLOW_FLAG_ESTABLISHED already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_NOT_ESTABLISHED;
            } else if (strcasecmp(args[i], "stateless") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_STATELESS, DETECT_FLOW_FLAG_ESTABLISHED already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_STATELESS;
            } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOCLIENT flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_client, DETECT_FLOW_FLAG_TOSERVER already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_TOCLIENT;
            } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){
                if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOSERVER flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_server, DETECT_FLOW_FLAG_TO_CLIENT flag already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_TOSERVER;
            } else if (strcasecmp(args[i], "only_stream") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag, DETECT_FLOW_FLAG_NOSTREAM already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_ONLYSTREAM;
            } else if (strcasecmp(args[i], "no_stream") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag, DETECT_FLOW_FLAG_ONLYSTREAM already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_NOSTREAM;
            } else if (strcasecmp(args[i], "no_frag") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag, only_frag already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_NO_FRAG;
            } else if (strcasecmp(args[i], "only_frag") == 0) {
                if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag is already set");
                    goto error;
                } else if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
                    SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag, no_frag already set");
                    goto error;
                }
                fd->flags |= DETECT_FLOW_FLAG_ONLY_FRAG;
            } else {
                SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]);
                goto error;
            }

            fd->match_cnt++;
            //printf("args[%" PRId32 "]: %s match_cnt: %" PRId32 " flags: 0x%02X\n", i, args[i], fd->match_cnt, fd->flags);
        }
    }
    return fd;

error:
    if (fd != NULL)
        DetectFlowFree(fd);
    return NULL;

}
Exemplo n.º 21
0
int do_la_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp)
{
	static char *la_params[]          = { "DS:la:GAUGE:600:U:U", NULL };
	static void *la_tpl               = NULL;
	static char *clock_params[]       = { "DS:la:GAUGE:600:U:U", NULL }; /* "la" is a misnomer, but to stay compatiable with existing RRD files */
	static void *clock_tpl            = NULL;

	static pcre *as400_exp = NULL;
	static pcre *zVM_exp = NULL;
	static time_t starttime = 0;

	char *p, *eoln = NULL;
	int gotusers=0, gotprocs=0, gotload=0, gotclock=0;
	int users=0, procs=0, load=0, clockdiff=0;
	time_t now = getcurrenttime(NULL);

	if (la_tpl == NULL) la_tpl = setup_template(la_params);
	if (clock_tpl == NULL) clock_tpl = setup_template(clock_params);
	if (starttime == 0) starttime = now;

	if (strstr(msg, "bb-xsnmp")) {
		/*
		 * bb-xsnmp.pl script output.
		 *
		 * green Tue Apr  5 12:57:37 2005 up: 254.58 days, CPU Usage=  9%
		 *
		 * &green  CPU Time in Busy Mode:   9%
		 * &green  CPU Time in Idle Mode:  91%
		 *
		 * &yellow CPU Usage Threshold: 90%
		 * &red CPU Usage Threshold: 95%
		 *
		 * <!-- Enterprise: netapp , Version: 6.42 -->
		 * bb-xsnmp.pl Version: 1.78
		 */

		p = strstr(msg, "CPU Usage=");
		if (p) {
			p += strlen("CPU Usage=");
			gotload = 1;
			load = atoi(p);
		}

		goto done_parsing;
	}
	else if (strstr(msg, "z/VM") || strstr(msg, "VSE/ESA") || strstr(msg, "z/VSE") || strstr(msg, "z/OS")) {
		/* z/VM cpu message. Looks like this, from Rich Smrcina (client config mode):
		 * green 5 Apr 2005 20:07:34  CPU Utilization  7% z/VM Version 4 Release 4.0, service level 0402 (32-bit) AVGPROC-007% 01
		 * VSE/ESA or z/VSE cpu message.
		 * VSE/ESA 2.7.2 cr IPLed on ...
		 * or
		 * z/VSE 3.1.1 cr IPLed on ...
		 * In server (centralized) config mode or for z/OS (which is centralized config only)
		 * the operating system name is part of the message (as in the tests above).
		 */

		int ovector[30];
		char w[100];
		int res;

		if (zVM_exp == NULL) {
			const char *errmsg = NULL;
			int errofs = 0;

			zVM_exp = pcre_compile(".* CPU Utilization *([0-9]+)%", PCRE_CASELESS, &errmsg, &errofs, NULL);
		}

		res = pcre_exec(zVM_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
		if (res >= 0) {
			/* We have a match - pick up the data. */
			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w));
			if (strlen(w)) {
				load = atoi(w); gotload = 1;
			}
		}

		goto done_parsing;
	}

	eoln = strchr(msg, '\n'); if (eoln) *eoln = '\0';
	p = strstr(msg, "up: ");
	if (!p) p = strstr(msg, "Uptime:");	/* Netapp filerstats2bb script */
	if (!p) p = strstr(msg, "uptime:");
	if (p) {
		/* First line of cpu report, contains "up: 159 days, 1 users, 169 procs, load=21" */
		p = strchr(p, ',');
		if (p) {
			gotusers = (sscanf(p, ", %d users", &users) == 1);
			p = strchr(p+1, ',');
		}

		if (p) {
			gotprocs = (sscanf(p, ", %d procs", &procs) == 1);
			p = strchr(p+1, ',');
		}

		/*
		 * Load can be either 
		 * -  "load=xx%"   (Windows)
		 * -  "load=xx.xx" (Unix, DISPREALLOADAVG=TRUE)
		 * -  "load=xx"    (Unix, DISPREALLOADAVG=FALSE)
		 *
		 * We want the load in percent (Windows), or LA*100 (Unix).
		 */
		p = strstr(msg, "load="); 
		if (p) { 
			p += 5;
			if (strchr(p, '%')) {
				gotload = 1; 
				load = atoi(p);
			}
			else if (strchr(p, '.')) {
				gotload = 1; 
				load = 100*atoi(p);
				/* Find the decimal part, and cut off at 2 decimals */
				p = strchr(p, '.'); if (strlen(p) > 3) *(p+3) = '\0';
				load += atoi(p+1);
			}
			else {
				gotload = 1; 
				load = atoi(p);
			}
		}
	}
	else {
		/* 
		 * No "uptime" in message - could be from an AS/400. They look like this:
		 * green March 21, 2005 12:33:24 PM EST deltacdc 108 users 45525 jobs(126 batch,0 waiting for message), load=26%
		 */
		int ovector[30];
		char w[100];
		int res;

		if (as400_exp == NULL) {
			const char *errmsg = NULL;
			int errofs = 0;

			as400_exp = pcre_compile(".* ([0-9]+) users ([0-9]+) jobs.* load=([0-9]+)\\%", 
						 PCRE_CASELESS, &errmsg, &errofs, NULL);
		}

		res = pcre_exec(as400_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
		if (res >= 0) {
			/* We have a match - pick up the AS/400 data. */
			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w));
			if (strlen(w)) {
				users = atoi(w); gotusers = 1;
			}

			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 3, w, sizeof(w));
			if (strlen(w)) {
				load = atoi(w); gotload = 1;
			}
		}
	}

done_parsing:
	if (eoln) *eoln = '\n';

	p = strstr(msg, "System clock is ");
	if (p) {
		if (sscanf(p, "System clock is %d seconds off", &clockdiff) == 1) gotclock = 1;
	}

	if (!gotload) {
		/* See if it's a report from the ciscocpu.pl script. */
		p = strstr(msg, "<br>CPU 5 min average:");
		if (p) {
			/* It reports in % cpu utilization */
			p = strchr(p, ':');
			load = atoi(p+1);
			gotload = 1;
		}
	}

	if (gotload) {
		setupfn("%s.rrd", "la");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, load);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotprocs) {
		setupfn("%s.rrd", "procs");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, procs);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotusers) {
		setupfn("%s.rrd", "users");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, users);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotclock) {
		setupfn("%s.rrd", "clock");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, clockdiff);
		create_and_update_rrd(hostname, testname, classname, pagepaths, clock_params, clock_tpl);
	}

	/*
	 * If we have run for less than 6 minutes, drop the memory updates here.
	 * We want to be sure not to use memory statistics from the CPU report
	 * if there is a memory add-on sending a separate memory statistics
	 */
	if ((now - starttime) < 360) return 0;

	if (!memhosts_init || (xtreeFind(memhosts, hostname) == xtreeEnd(memhosts))) {
		/* Pick up memory statistics */
		int found, overflow, realuse, swapuse;
		long long phystotal, physavail, pagetotal, pageavail;

		found = overflow = realuse = swapuse = 0;
		phystotal = physavail = pagetotal = pageavail = 0;

		p = strstr(msg, "Total Physical memory:");
		if (p) { 
			phystotal = str2ll(strchr(p, ':') + 1, NULL); 
			if (phystotal != LONG_MAX) found++; else overflow++;
		}

		if (found == 1) {
			p = strstr(msg, "Available Physical memory:");
			if (p) { 
				physavail = str2ll(strchr(p, ':') + 1, NULL); 
				if (physavail != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 2) {
			p = strstr(msg, "Total PageFile size:"); 
			if (p) { 
				pagetotal = str2ll(strchr(p, ':') + 1, NULL); 
				if (pagetotal != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 3) {
			p = strstr(msg, "Available PageFile size:"); 
			if (p) { 
				pageavail = str2ll(strchr(p, ':') + 1, NULL); 
				if (pageavail != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 4) {
			if (!phystotal || !pagetotal) { errprintf("Host %s cpu report had 0 total physical/pagefile memory listed\n", hostname); return 0; }
			phystotal = phystotal / 100;
			pagetotal = pagetotal / 100;
			realuse = 100 - (physavail / phystotal);
			swapuse = 100 - (pageavail / pagetotal);
			do_memory_rrd_update(tstamp, hostname, testname, classname, pagepaths, realuse, swapuse, -1);
		}
		else if (overflow) {
			errprintf("Host %s cpu report overflows in memory usage calculation\n", hostname);
		}
	}

	return 0;
}
Exemplo n.º 22
0
int DetectXbitSetup (DetectEngineCtx *de_ctx, Signature *s, char *rawstr)
{
    DetectXbitsData *cd = NULL;
    SigMatch *sm = NULL;
    uint8_t fb_cmd = 0;
    uint8_t hb_dir = 0;
#define MAX_SUBSTRINGS 30
    int ret = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    char fb_cmd_str[16] = "", fb_name[256] = "";
    char hb_dir_str[16] = "";
    enum VarTypes var_type = VAR_TYPE_NOT_SET;
    int expire = 30;

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS);
    if (ret != 2 && ret != 3 && ret != 4 && ret != 5) {
        SCLogError(SC_ERR_PCRE_MATCH, "\"%s\" is not a valid setting for xbits.", rawstr);
        return -1;
    }
    SCLogDebug("ret %d, %s", ret, rawstr);
    res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, fb_cmd_str, sizeof(fb_cmd_str));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
        return -1;
    }

    if (ret >= 3) {
        res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, fb_name, sizeof(fb_name));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
            goto error;
        }
        if (ret >= 4) {
            res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, hb_dir_str, sizeof(hb_dir_str));
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                goto error;
            }
            SCLogDebug("hb_dir_str %s", hb_dir_str);
            if (strlen(hb_dir_str) > 0) {
                if (strcmp(hb_dir_str, "ip_src") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPSRC;
                    var_type = VAR_TYPE_HOST_BIT;
                } else if (strcmp(hb_dir_str, "ip_dst") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPDST;
                    var_type = VAR_TYPE_HOST_BIT;
                } else if (strcmp(hb_dir_str, "ip_pair") == 0) {
                    hb_dir = DETECT_XBITS_TRACK_IPPAIR;
                    var_type = VAR_TYPE_IPPAIR_BIT;
                } else {
                    // TODO
                    goto error;
                }
            }

            if (ret >= 5) {
                char expire_str[16] = "";
                res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 4, expire_str, sizeof(expire_str));
                if (res < 0) {
                    SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
                    goto error;
                }
                SCLogDebug("expire_str %s", expire_str);
                expire = atoi(expire_str);
                SCLogDebug("expire %d", expire);
            }
        }
    }

    if (strcmp(fb_cmd_str,"noalert") == 0) {
        fb_cmd = DETECT_XBITS_CMD_NOALERT;
    } else if (strcmp(fb_cmd_str,"isset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_ISSET;
    } else if (strcmp(fb_cmd_str,"isnotset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_ISNOTSET;
    } else if (strcmp(fb_cmd_str,"set") == 0) {
        fb_cmd = DETECT_XBITS_CMD_SET;
    } else if (strcmp(fb_cmd_str,"unset") == 0) {
        fb_cmd = DETECT_XBITS_CMD_UNSET;
    } else if (strcmp(fb_cmd_str,"toggle") == 0) {
        fb_cmd = DETECT_XBITS_CMD_TOGGLE;
    } else {
        SCLogError(SC_ERR_UNKNOWN_VALUE, "ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
        goto error;
    }

    switch (fb_cmd) {
        case DETECT_XBITS_CMD_NOALERT:
            if (strlen(fb_name) != 0)
                goto error;
            s->flags |= SIG_FLAG_NOALERT;
            return 0;
        case DETECT_XBITS_CMD_ISNOTSET:
        case DETECT_XBITS_CMD_ISSET:
        case DETECT_XBITS_CMD_SET:
        case DETECT_XBITS_CMD_UNSET:
        case DETECT_XBITS_CMD_TOGGLE:
        default:
            if (strlen(fb_name) == 0)
                goto error;
            break;
    }

    cd = SCMalloc(sizeof(DetectXbitsData));
    if (unlikely(cd == NULL))
        goto error;

    cd->idx = VariableNameGetIdx(de_ctx, fb_name, var_type);
    cd->cmd = fb_cmd;
    cd->tracker = hb_dir;
    cd->type = var_type;
    cd->expire = expire;

    SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
        cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)");

    /* Okay so far so good, lets get this into a SigMatch
     * and put it in the Signature. */
    sm = SigMatchAlloc();
    if (sm == NULL)
        goto error;

    sm->type = DETECT_XBITS;
    sm->ctx = (void *)cd;

    switch (fb_cmd) {
        case DETECT_XBITS_CMD_NOALERT:
            /* nothing to do */
            break;

        case DETECT_XBITS_CMD_ISNOTSET:
        case DETECT_XBITS_CMD_ISSET:
            /* checks, so packet list */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
            break;

        case DETECT_XBITS_CMD_SET:
        case DETECT_XBITS_CMD_UNSET:
        case DETECT_XBITS_CMD_TOGGLE:
            /* modifiers, only run when entire sig has matched */
            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_POSTMATCH);
            break;
    }

    return 0;

error:
    if (cd != NULL)
        SCFree(cd);
    if (sm != NULL)
        SCFree(sm);
    return -1;
}
Exemplo n.º 23
0
Arquivo: main.c Projeto: larsivsi/cbot
int main(int argc, char **argv)
{
	tic();

	char *conf_file = NULL;
	socket_fd = -1;
	for (int i=1; i<argc; i++) {
		if (!strcmp(argv[i], "-c")) {
			if (argc <= i) {
				print_usage();
			}
			conf_file = argv[++i];
		} else if (!strcmp(argv[i], "-fd")) {
			if (argc <= i) {
				print_usage();
			}
			socket_fd = atoi(argv[++i]);
		} else {
			printf(" >> unknown option: %s\n", argv[i]);
		}
	}

	if (!conf_file)
		conf_file = "cbot.conf";
	load_config(conf_file);

	// Set rand seed
	srand(time(NULL));

	// Set up cURL
	curl_global_init(CURL_GLOBAL_ALL);

	// Set up db connection for logging
	if (config->enabled_modules & MODULE_LOG) {
		log_init();
	}

	// Parse markov corpus
	if (config->enabled_modules & MODULE_MARKOV) {
		markov_init(config->markovcorpus);
	}

	irc_init();

	if (socket_fd == -1) {
		printf(" - Connecting to %s:%s with nick %s, joining channels...\n",
			config->host, config->port, config->nick);
		net_connect();
	} else { // In-place upgrade yo
		printf(" >> Already connected, upgraded in-place!\n");
		join_channels();
	}

	struct recv_data *irc = malloc(sizeof(struct recv_data));
	patterns = malloc(sizeof(*patterns));
	compile_patterns(patterns);

	// Select param
	fd_set socket_set;
	FD_ZERO(&socket_set);
	FD_SET(STDIN_FILENO, &socket_set);
	FD_SET(socket_fd, &socket_set);


	int recv_size;
	char buffer[BUFFER_SIZE];
	char input[BUFFER_SIZE];
	memset(buffer, 0, BUFFER_SIZE);
	size_t buffer_length = 0;
	while (1) {
		int ret = select(socket_fd+1, &socket_set, 0, 0, 0);
		if (ret == -1) {
			printf(" >> Disconnected, reconnecting...\n");
			close(socket_fd);
			net_connect();
		}
		if (FD_ISSET(STDIN_FILENO, &socket_set)) {
			if (fgets(input, BUFFER_SIZE, stdin) == NULL) {
				printf(" >> Error while reading from stdin!\n");
				continue;
			}

			if (strcmp(input, "quit\n") == 0) {
				printf(" >> Bye!\n");
				break;
			} else if (strcmp(input, "reload\n") == 0) {
				terminate();
				free(irc);
				free_patterns(patterns);
				free(patterns);

				// Set up arguments
				char * arguments[6];
				arguments[0] = argv[0];
				arguments[1] = "-c";
				arguments[2] = conf_file;
				arguments[3] = "-fd";
				char fdstring[snprintf(NULL, 0, "%d", socket_fd)];
				sprintf(fdstring, "%d", socket_fd);
				arguments[4] = fdstring;
				arguments[5] = NULL;

				printf(" >> Upgrading...\n");
				execvp(argv[0], arguments);

				printf(" !!! Execvp failing, giving up...\n");
				exit(-1);
			} else if (strncmp(input, "say ", 4) == 0) {
				int offsets[30];
				int offsetcount = pcre_exec(patterns->command_say, 0, input, strlen(input), 0, 0, offsets, 30);
				if (offsetcount > 0) {
					char channel[BUFFER_SIZE];
					char message[BUFFER_SIZE];
					pcre_copy_substring(input, offsets, offsetcount, 1, channel, BUFFER_SIZE);
					pcre_copy_substring(input, offsets, offsetcount, 2, message, BUFFER_SIZE);
					char sendbuf[strlen("PRIVMSG  : ") + strlen(channel) + strlen(message)];
					sprintf(sendbuf, "PRIVMSG %s :%s\n", channel, message);
					irc_send_str(sendbuf);
				}
			} else if (strncmp(input, "kick ", 5) == 0) {
				int offsets[30];
				int offsetcount = pcre_exec(patterns->command_kick, 0, input, strlen(input), 0, 0, offsets, 30);
				if (offsetcount > 0) {
					char channel[BUFFER_SIZE];
					char user[BUFFER_SIZE];
					pcre_copy_substring(input, offsets, offsetcount, 1, channel, BUFFER_SIZE);
					pcre_copy_substring(input, offsets, offsetcount, 2, user, BUFFER_SIZE);
					char sendbuf[strlen("KICK   :Gene police! You! Out of the pool, now!\n") + strlen(channel) + strlen(user)];
					sprintf(sendbuf, "KICK %s %s :Gene police! You! Out of the pool, now!\n", channel, user);
					irc_send_str(sendbuf);
				}
			} else {
				printf(" >> Unrecognized command. Try 'quit'\n");
			}
			FD_SET(socket_fd, &socket_set);
		} else {
			if (buffer_length >= BUFFER_SIZE - 1) {
				printf(" >> what the f**k, IRCd, a line longer than 4k? dropping some buffer\n");
				memset(buffer, 0, BUFFER_SIZE);
				buffer_length = 0;
				continue;
			}

			recv_size = recv(socket_fd, buffer + buffer_length, BUFFER_SIZE - buffer_length - 1, 0);
			buffer_length += recv_size;
			buffer[buffer_length] = '\0';
			if (recv_size == 0) {
				printf(" >> recv_size is 0, assuming closed remote socket, reconnecting\n");
				close(socket_fd);
				printf("closed\n");
				net_connect();
				printf("reconnected\n");
			}
			char *newlinepos = 0;
			char *bufbegin = buffer;
			while ((newlinepos = strchr(bufbegin, '\n'))) {
				*newlinepos = 0;
				printf(" ~ %s\n", bufbegin);
				// Only handle privmsg
				if (irc_parse_input(bufbegin, irc, patterns)) {
					irc_handle_input(irc, patterns);
				}
				bufbegin = newlinepos + 1;
			}
			size_t bytes_removed = bufbegin - buffer;
			memmove(buffer, bufbegin, buffer_length - bytes_removed);
			buffer_length -= bytes_removed;
			memset(buffer + buffer_length, 0, BUFFER_SIZE - buffer_length);

			FD_SET(STDIN_FILENO, &socket_set);
		}
	}
	printf(" >> Socket closed, quitting...\n");

	close(socket_fd);

	free(irc);
	free_patterns(patterns);
	free(patterns);

	terminate();

	return 0;
}
Exemplo n.º 24
0
// TODO: field_name will be removed once we make this function read in field names as well
static int read_field(kFile *file, long offset, char* field_name, dField *field, int field_type) {

    int field_length;
    char field_contents[FIELD_SIZE];
    pcre *re;
    const char *error;
    int erroffset;
    int rc;
    int ovector[30];
    
    // TODO: Will be replaced when this function reads in the field name as well
    memcpy(field->name, field_name, strlen(field_name) + 1);
    

    // the length of the field is the first 4 bytes
    memcpy(&field_length, file->buffer + offset, 4);
    
    // get the contents of the field 
    if (field_length >= FIELD_SIZE) {
        memcpy(field_contents, file->buffer + offset + 4, FIELD_SIZE - 1);
        field_contents[FIELD_SIZE - 1] = '\0';
    }
    else {
        memcpy(field_contents, file->buffer + offset + 4, field_length);
        field_contents[field_length] = '\0';
    }
        
    if (field_type == COLLECTION_FIELD) { // match value
        // match value
        char *value_pattern = ":(\\s+.*)"; 
        re = pcre_compile(value_pattern, 0, &error, &erroffset, NULL);    

        if (re == NULL) {
            fprintf(stderr, "Unable to compile regex. Error message: %s\n", error);
            exit(EXIT_FAILURE);
        }
    
        rc = pcre_exec(re, NULL, field_contents, strlen(field_contents), 0, 0, ovector, 30); 
        pcre_free(re);
        
        if (rc >= 1) {
            if (rc == 2) {
                pcre_copy_substring(field_contents, ovector, rc, 1, field->value, FIELD_SIZE);
                trim(field->value);
            }
            else {
                field->value[0] = '\0';
            }
        }
        else {
            fprintf(stderr, "Pattern not matched. Error code: %d\n", rc);
            exit(EXIT_FAILURE);
        }
        
        // there are no units for this type of field
        field->units[0] = '\0';
    }
    else if (field_type == VALUE_FIELD) {  // copy the value
        memcpy(field->value, field_contents, strlen(field_contents) + 1);

        // there are no units for this type of field
        field->units[0] = '\0';
    }
    else { // match value and units (if any)
        char *value_pattern = "\\s{3,}(.+)";
        re = pcre_compile(value_pattern, 0, &error, &erroffset, NULL);            
        
        if (re == NULL) {
            fprintf(stderr, "Unable to compile regex. Error message: %s\n", error);
            exit(EXIT_FAILURE);
        }

        rc = pcre_exec(re, NULL, field_contents, strlen(field_contents), 0, 0, ovector, 30); 
        pcre_free(re);

        if (rc >= 1) {
            if (rc == 2) {
                pcre_copy_substring(field_contents, ovector, rc, 1, field->value, FIELD_SIZE);
                trim(field->value);
            }
            else {
                field->value[0] = '\0';
            }
        }
        else {
            fprintf(stderr, "Pattern not matched. Error code: %d\n", rc);
            exit(EXIT_FAILURE);
        }

        // match units
        char *units_pattern = "\\((.+)\\)";
        re = pcre_compile(units_pattern, 0, &error, &erroffset, NULL);            
        
        if (re == NULL) {
            fprintf(stderr, "Unable to compile regex. Error message: %s\n", error);
            exit(EXIT_FAILURE);
        }
        
        rc = pcre_exec(re, NULL, field_contents, strlen(field_contents), 0, 0, ovector, 30); 
        pcre_free(re);

        if (rc == 2) {
            pcre_copy_substring(field_contents, ovector, rc, 1, field->units, UNIT_SIZE);
            trim(field->units);
        }
        else {
            field->units[0] = '\0';
        }
    }
    
    return 4 + field_length;
}
Exemplo n.º 25
0
SWITCH_DECLARE(int) switch_regex_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int size)
{
	return pcre_copy_substring(subject, ovector, stringcount, stringnumber, buffer, size);
}
Exemplo n.º 26
0
int main(int argc, char *argv[])
{
	strbuffer_t *inbuf;
	char *ackbuf;
	char *subjectline = NULL;
	char *returnpathline = NULL;
	char *fromline = NULL;
	char *firsttxtline = NULL;
	int inheaders = 1;
	char *p;
	pcre *subjexp;
	const char *errmsg;
	int errofs, result;
	int ovector[30];
	char cookie[10];
	int duration = 0;
	int argi;
	char *envarea = NULL;

	for (argi=1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--env=")) {
			char *p = strchr(argv[argi], '=');
			loadenv(p+1, envarea);
		}
		else if (argnmatch(argv[argi], "--area=")) {
			char *p = strchr(argv[argi], '=');
			envarea = strdup(p+1);
		}
	}

	initfgets(stdin);
	inbuf = newstrbuffer(0);
	while (unlimfgets(inbuf, stdin)) {
		sanitize_input(inbuf, 0, 0);

		if (!inheaders) {
			/* We're in the message body. Look for a "delay=N" line here. */
			if ((strncasecmp(STRBUF(inbuf), "delay=", 6) == 0) || (strncasecmp(STRBUF(inbuf), "delay ", 6) == 0)) {
				duration = durationvalue(STRBUF(inbuf)+6);
				continue;
			}
			else if ((strncasecmp(STRBUF(inbuf), "ack=", 4) == 0) || (strncasecmp(STRBUF(inbuf), "ack ", 4) == 0)) {
				/* Some systems cannot generate a subject. Allow them to ack
				 * via text in the message body. */
				subjectline = (char *)malloc(STRBUFLEN(inbuf) + 1024);
				sprintf(subjectline, "Subject: Xymon [%s]", STRBUF(inbuf)+4);
			}
			else if (*STRBUF(inbuf) && !firsttxtline) {
				/* Save the first line of the message body, but ignore blank lines */
				firsttxtline = strdup(STRBUF(inbuf));
			}

			continue;	/* We don't care about the rest of the message body */
		}

		/* See if we're at the end of the mail headers */
		if (inheaders && (STRBUFLEN(inbuf) == 0)) { inheaders = 0; continue; }

		/* Is it one of those we want to keep ? */
		if (strncasecmp(STRBUF(inbuf), "return-path:", 12) == 0) returnpathline = strdup(skipwhitespace(STRBUF(inbuf)+12));
		else if (strncasecmp(STRBUF(inbuf), "from:", 5) == 0)    fromline = strdup(skipwhitespace(STRBUF(inbuf)+5));
		else if (strncasecmp(STRBUF(inbuf), "subject:", 8) == 0) subjectline = strdup(skipwhitespace(STRBUF(inbuf)+8));
	}
	freestrbuffer(inbuf);

	/* No subject ? No deal */
	if (subjectline == NULL) {
		dbgprintf("Subject-line not found\n");
		return 1;
	}

	/* Get the alert cookie */
	subjexp = pcre_compile(".*(Xymon|Hobbit|BB)[ -]* \\[*(-*[0-9]+)[\\]!]*", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 1\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result < 0) {
		dbgprintf("Subject line did not match pattern\n");
		return 3; /* Subject did not match what we expected */
	}
	if (pcre_copy_substring(subjectline, ovector, result, 2, cookie, sizeof(cookie)) <= 0) {
		dbgprintf("Could not find cookie value\n");
		return 4; /* No cookie */
	}
	pcre_free(subjexp);

	/* See if there's a "DELAY=" delay-value also */
	subjexp = pcre_compile(".*DELAY[ =]+([0-9]+[mhdw]*)", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 2\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result >= 0) {
		char delaytxt[4096];
		if (pcre_copy_substring(subjectline, ovector, result, 1, delaytxt, sizeof(delaytxt)) > 0) {
			duration = durationvalue(delaytxt);
		}
	}
	pcre_free(subjexp);

	/* See if there's a "msg" text also */
	subjexp = pcre_compile(".*MSG[ =]+(.*)", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 3\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result >= 0) {
		char msgtxt[4096];
		if (pcre_copy_substring(subjectline, ovector, result, 1, msgtxt, sizeof(msgtxt)) > 0) {
			firsttxtline = strdup(msgtxt);
		}
	}
	pcre_free(subjexp);

	/* Use the "return-path:" header if we didn't see a From: line */
	if ((fromline == NULL) && returnpathline) fromline = returnpathline;
	if (fromline) {
		/* Remove '<' and '>' from the fromline - they mess up HTML */
		while ((p = strchr(fromline, '<')) != NULL) *p = ' ';
		while ((p = strchr(fromline, '>')) != NULL) *p = ' ';
	}

	/* Setup the acknowledge message */
	if (duration == 0) duration = 60;	/* Default: Ack for 60 minutes */
	if (firsttxtline == NULL) firsttxtline = "<No cause specified>";
	ackbuf = (char *)malloc(4096 + strlen(firsttxtline) + (fromline ? strlen(fromline) : 0));
	p = ackbuf;
	p += sprintf(p, "xymondack %s %d %s", cookie, duration, firsttxtline);
	if (fromline) {
		p += sprintf(p, "\nAcked by: %s", fromline);
	}

	if (debug) {
		printf("%s\n", ackbuf);
		return 0;
	}

	sendmessage(ackbuf, NULL, XYMON_TIMEOUT, NULL);
	return 0;
}
Exemplo n.º 27
0
int main(int argc, char **argv)
{
FILE *infile = stdin;
int options = 0;
int study_options = 0;
int op = 1;
int timeit = 0;
int showinfo = 0;
int showstore = 0;
int size_offsets = 45;
int size_offsets_max;
int *offsets;
#if !defined NOPOSIX
int posix = 0;
#endif
int debug = 0;
int done = 0;
unsigned char buffer[30000];
unsigned char dbuffer[1024];

/* Static so that new_malloc can use it. */

outfile = stdout;

/* Scan options */

while (argc > 1 && argv[op][0] == '-')
  {
  char *endptr;

  if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0)
    showstore = 1;
  else if (strcmp(argv[op], "-t") == 0) timeit = 1;
  else if (strcmp(argv[op], "-i") == 0) showinfo = 1;
  else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1;
  else if (strcmp(argv[op], "-o") == 0 && argc > 2 &&
      ((size_offsets = (int)strtoul(argv[op+1], &endptr, 10)), *endptr == 0))
    {
    op++;
    argc--;
    }
#if !defined NOPOSIX
  else if (strcmp(argv[op], "-p") == 0) posix = 1;
#endif
  else
    {
    printf("** Unknown or malformed option %s\n", argv[op]);
    printf("Usage:   pcretest [-d] [-i] [-o <n>] [-p] [-s] [-t] [<input> [<output>]]\n");
    printf("  -d     debug: show compiled code; implies -i\n"
           "  -i     show information about compiled pattern\n"
           "  -o <n> set size of offsets vector to <n>\n");
#if !defined NOPOSIX
    printf("  -p     use POSIX interface\n");
#endif
    printf("  -s     output store information\n"
           "  -t     time compilation and execution\n");
    return 1;
    }
  op++;
  argc--;
  }

/* Get the store for the offsets vector, and remember what it was */

size_offsets_max = size_offsets;
offsets = malloc(size_offsets_max * sizeof(int));
if (offsets == NULL)
  {
  printf("** Failed to get %d bytes of memory for offsets vector\n",
    size_offsets_max * sizeof(int));
  return 1;
  }

/* Sort out the input and output files */

if (argc > 1)
  {
  infile = fopen(argv[op], "r");
  if (infile == NULL)
    {
    printf("** Failed to open %s\n", argv[op]);
    return 1;
    }
  }

if (argc > 2)
  {
  outfile = fopen(argv[op+1], "w");
  if (outfile == NULL)
    {
    printf("** Failed to open %s\n", argv[op+1]);
    return 1;
    }
  }

/* Set alternative malloc function */

pcre_malloc = new_malloc;

/* Heading line, then prompt for first regex if stdin */

fprintf(outfile, "PCRE version %s\n\n", pcre_version());

/* Main loop */

while (!done)
  {
  pcre *re = NULL;
  pcre_extra *extra = NULL;

#if !defined NOPOSIX  /* There are still compilers that require no indent */
  regex_t preg;
  int do_posix = 0;
#endif

  const char *error;
  unsigned char *p, *pp, *ppp;
  const unsigned char *tables = NULL;
  int do_study = 0;
  int do_debug = debug;
  int do_G = 0;
  int do_g = 0;
  int do_showinfo = showinfo;
  int do_showrest = 0;
  int utf8 = 0;
  int erroroffset, len, delimiter;

  if (infile == stdin) printf("  re> ");
  if (fgets((char *)buffer, sizeof(buffer), infile) == NULL) break;
  if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);

  p = buffer;
  while (isspace(*p)) p++;
  if (*p == 0) continue;

  /* Get the delimiter and seek the end of the pattern; if is isn't
  complete, read more. */

  delimiter = *p++;

  if (isalnum(delimiter) || delimiter == '\\')
    {
    fprintf(outfile, "** Delimiter must not be alphameric or \\\n");
    goto SKIP_DATA;
    }

  pp = p;

  for(;;)
    {
    while (*pp != 0)
      {
      if (*pp == '\\' && pp[1] != 0) pp++;
        else if (*pp == delimiter) break;
      pp++;
      }
    if (*pp != 0) break;

    len = sizeof(buffer) - (pp - buffer);
    if (len < 256)
      {
      fprintf(outfile, "** Expression too long - missing delimiter?\n");
      goto SKIP_DATA;
      }

    if (infile == stdin) printf("    > ");
    if (fgets((char *)pp, len, infile) == NULL)
      {
      fprintf(outfile, "** Unexpected EOF\n");
      done = 1;
      goto CONTINUE;
      }
    if (infile != stdin) fprintf(outfile, "%s", (char *)pp);
    }

  /* If the first character after the delimiter is backslash, make
  the pattern end with backslash. This is purely to provide a way
  of testing for the error message when a pattern ends with backslash. */

  if (pp[1] == '\\') *pp++ = '\\';

  /* Terminate the pattern at the delimiter */

  *pp++ = 0;

  /* Look for options after final delimiter */

  options = 0;
  study_options = 0;
  log_store = showstore;  /* default from command line */

  while (*pp != 0)
    {
    switch (*pp++)
      {
      case 'g': do_g = 1; break;
      case 'i': options |= PCRE_CASELESS; break;
      case 'm': options |= PCRE_MULTILINE; break;
      case 's': options |= PCRE_DOTALL; break;
      case 'x': options |= PCRE_EXTENDED; break;

      case '+': do_showrest = 1; break;
      case 'A': options |= PCRE_ANCHORED; break;
      case 'D': do_debug = do_showinfo = 1; break;
      case 'E': options |= PCRE_DOLLAR_ENDONLY; break;
      case 'G': do_G = 1; break;
      case 'I': do_showinfo = 1; break;
      case 'M': log_store = 1; break;

#if !defined NOPOSIX
      case 'P': do_posix = 1; break;
#endif

      case 'S': do_study = 1; break;
      case 'U': options |= PCRE_UNGREEDY; break;
      case 'X': options |= PCRE_EXTRA; break;
      case '8': options |= PCRE_UTF8; utf8 = 1; break;

      case 'L':
      ppp = pp;
      while (*ppp != '\n' && *ppp != ' ') ppp++;
      *ppp = 0;
      if (setlocale(LC_CTYPE, (const char *)pp) == NULL)
        {
        fprintf(outfile, "** Failed to set locale \"%s\"\n", pp);
        goto SKIP_DATA;
        }
      tables = pcre_maketables();
      pp = ppp;
      break;

      case '\n': case ' ': break;
      default:
      fprintf(outfile, "** Unknown option '%c'\n", pp[-1]);
      goto SKIP_DATA;
      }
    }

  /* Handle compiling via the POSIX interface, which doesn't support the
  timing, showing, or debugging options, nor the ability to pass over
  local character tables. */

#if !defined NOPOSIX
  if (posix || do_posix)
    {
    int rc;
    int cflags = 0;
    if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE;
    if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE;
    rc = regcomp(&preg, (char *)p, cflags);

    /* Compilation failed; go back for another re, skipping to blank line
    if non-interactive. */

    if (rc != 0)
      {
      (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
      fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer);
      goto SKIP_DATA;
      }
    }

  /* Handle compiling via the native interface */

  else
#endif  /* !defined NOPOSIX */

    {
    if (timeit)
      {
      register int i;
      clock_t time_taken;
      clock_t start_time = clock();
      for (i = 0; i < LOOPREPEAT; i++)
        {
        re = pcre_compile((char *)p, options, &error, &erroroffset, tables);
        if (re != NULL) free(re);
        }
      time_taken = clock() - start_time;
      fprintf(outfile, "Compile time %.3f milliseconds\n",
        ((double)time_taken * 1000.0) /
        ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
      }

    re = pcre_compile((char *)p, options, &error, &erroroffset, tables);

    /* Compilation failed; go back for another re, skipping to blank line
    if non-interactive. */

    if (re == NULL)
      {
      fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset);
      SKIP_DATA:
      if (infile != stdin)
        {
        for (;;)
          {
          if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
            {
            done = 1;
            goto CONTINUE;
            }
          len = (int)strlen((char *)buffer);
          while (len > 0 && isspace(buffer[len-1])) len--;
          if (len == 0) break;
          }
        fprintf(outfile, "\n");
        }
      goto CONTINUE;
      }

    /* Compilation succeeded; print data if required. There are now two
    info-returning functions. The old one has a limited interface and
    returns only limited data. Check that it agrees with the newer one. */

    if (do_showinfo)
      {
      unsigned long int get_options;
      int old_first_char, old_options, old_count;
      int count, backrefmax, first_char, need_char;
      size_t size;

      if (do_debug) print_internals(re);

      new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options);
      new_info(re, NULL, PCRE_INFO_SIZE, &size);
      new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count);
      new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax);
      new_info(re, NULL, PCRE_INFO_FIRSTCHAR, &first_char);
      new_info(re, NULL, PCRE_INFO_LASTLITERAL, &need_char);

      old_count = pcre_info(re, &old_options, &old_first_char);
      if (count < 0) fprintf(outfile,
        "Error %d from pcre_info()\n", count);
      else
        {
        if (old_count != count) fprintf(outfile,
          "Count disagreement: pcre_fullinfo=%d pcre_info=%d\n", count,
            old_count);

        if (old_first_char != first_char) fprintf(outfile,
          "First char disagreement: pcre_fullinfo=%d pcre_info=%d\n",
            first_char, old_first_char);

        if (old_options != (int)get_options) fprintf(outfile,
          "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n",
            get_options, old_options);
        }

      if (size != gotten_store) fprintf(outfile,
        "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n",
        size, gotten_store);

      fprintf(outfile, "Capturing subpattern count = %d\n", count);
      if (backrefmax > 0)
        fprintf(outfile, "Max back reference = %d\n", backrefmax);
      if (get_options == 0) fprintf(outfile, "No options\n");
        else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s\n",
          ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "",
          ((get_options & PCRE_CASELESS) != 0)? " caseless" : "",
          ((get_options & PCRE_EXTENDED) != 0)? " extended" : "",
          ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "",
          ((get_options & PCRE_DOTALL) != 0)? " dotall" : "",
          ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "",
          ((get_options & PCRE_EXTRA) != 0)? " extra" : "",
          ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "",
          ((get_options & PCRE_UTF8) != 0)? " utf8" : "");

      if (((((real_pcre *)re)->options) & PCRE_ICHANGED) != 0)
        fprintf(outfile, "Case state changes\n");

      if (first_char == -1)
        {
        fprintf(outfile, "First char at start or follows \\n\n");
        }
      else if (first_char < 0)
        {
        fprintf(outfile, "No first char\n");
        }
      else
        {
        if (isprint(first_char))
          fprintf(outfile, "First char = \'%c\'\n", first_char);
        else
          fprintf(outfile, "First char = %d\n", first_char);
        }

      if (need_char < 0)
        {
        fprintf(outfile, "No need char\n");
        }
      else
        {
        if (isprint(need_char))
          fprintf(outfile, "Need char = \'%c\'\n", need_char);
        else
          fprintf(outfile, "Need char = %d\n", need_char);
        }
      }

    /* If /S was present, study the regexp to generate additional info to
    help with the matching. */

    if (do_study)
      {
      if (timeit)
        {
        register int i;
        clock_t time_taken;
        clock_t start_time = clock();
        for (i = 0; i < LOOPREPEAT; i++)
          extra = pcre_study(re, study_options, &error);
        time_taken = clock() - start_time;
        if (extra != NULL) free(extra);
        fprintf(outfile, "  Study time %.3f milliseconds\n",
          ((double)time_taken * 1000.0)/
          ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
        }

      extra = pcre_study(re, study_options, &error);
      if (error != NULL)
        fprintf(outfile, "Failed to study: %s\n", error);
      else if (extra == NULL)
        fprintf(outfile, "Study returned NULL\n");

      else if (do_showinfo)
        {
        uschar *start_bits = NULL;
        new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits);
        if (start_bits == NULL)
          fprintf(outfile, "No starting character set\n");
        else
          {
          int i;
          int c = 24;
          fprintf(outfile, "Starting character set: ");
          for (i = 0; i < 256; i++)
            {
            if ((start_bits[i/8] & (1<<(i%8))) != 0)
              {
              if (c > 75)
                {
                fprintf(outfile, "\n  ");
                c = 2;
                }
              if (isprint(i) && i != ' ')
                {
                fprintf(outfile, "%c ", i);
                c += 2;
                }
              else
                {
                fprintf(outfile, "\\x%02x ", i);
                c += 5;
                }
              }
            }
          fprintf(outfile, "\n");
          }
        }
      }
    }

  /* Read data lines and test them */

  for (;;)
    {
    unsigned char *q;
    unsigned char *bptr = dbuffer;
    int *use_offsets = offsets;
    int use_size_offsets = size_offsets;
    int count, c;
    int copystrings = 0;
    int getstrings = 0;
    int getlist = 0;
    int gmatched = 0;
    int start_offset = 0;
    int g_notempty = 0;

    options = 0;

    if (infile == stdin) printf("data> ");
    if (fgets((char *)buffer, sizeof(buffer), infile) == NULL)
      {
      done = 1;
      goto CONTINUE;
      }
    if (infile != stdin) fprintf(outfile, "%s", (char *)buffer);

    len = (int)strlen((char *)buffer);
    while (len > 0 && isspace(buffer[len-1])) len--;
    buffer[len] = 0;
    if (len == 0) break;

    p = buffer;
    while (isspace(*p)) p++;

    q = dbuffer;
    while ((c = *p++) != 0)
      {
      int i = 0;
      int n = 0;
      if (c == '\\') switch ((c = *p++))
        {
        case 'a': c =    7; break;
        case 'b': c = '\b'; break;
        case 'e': c =   27; break;
        case 'f': c = '\f'; break;
        case 'n': c = '\n'; break;
        case 'r': c = '\r'; break;
        case 't': c = '\t'; break;
        case 'v': c = '\v'; break;

        case '0': case '1': case '2': case '3':
        case '4': case '5': case '6': case '7':
        c -= '0';
        while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9')
          c = c * 8 + *p++ - '0';
        break;

        case 'x':

        /* Handle \x{..} specially - new Perl thing for utf8 */

        if (*p == '{')
          {
          unsigned char *pt = p;
          c = 0;
          while (isxdigit(*(++pt)))
            c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'W');
          if (*pt == '}')
            {
            unsigned char buffer[8];
            int ii, utn;
            utn = ord2utf8(c, buffer);
            for (ii = 0; ii < utn - 1; ii++) *q++ = buffer[ii];
            c = buffer[ii];   /* Last byte */
            p = pt + 1;
            break;
            }
          /* Not correct form; fall through */
          }

        /* Ordinary \x */

        c = 0;
        while (i++ < 2 && isxdigit(*p))
          {
          c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W');
          p++;
          }
        break;

        case 0:   /* Allows for an empty line */
        p--;
        continue;

        case 'A':  /* Option setting */
        options |= PCRE_ANCHORED;
        continue;

        case 'B':
        options |= PCRE_NOTBOL;
        continue;

        case 'C':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        copystrings |= 1 << n;
        continue;

        case 'G':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        getstrings |= 1 << n;
        continue;

        case 'L':
        getlist = 1;
        continue;

        case 'N':
        options |= PCRE_NOTEMPTY;
        continue;

        case 'O':
        while(isdigit(*p)) n = n * 10 + *p++ - '0';
        if (n > size_offsets_max)
          {
          size_offsets_max = n;
          free(offsets);
          use_offsets = offsets = malloc(size_offsets_max * sizeof(int));
          if (offsets == NULL)
            {
            printf("** Failed to get %d bytes of memory for offsets vector\n",
              size_offsets_max * sizeof(int));
            return 1;
            }
          }
        use_size_offsets = n;
        if (n == 0) use_offsets = NULL;
        continue;

        case 'Z':
        options |= PCRE_NOTEOL;
        continue;
        }
      *q++ = c;
      }
    *q = 0;
    len = q - dbuffer;

    /* Handle matching via the POSIX interface, which does not
    support timing. */

#if !defined NOPOSIX
    if (posix || do_posix)
      {
      int rc;
      int eflags = 0;
      regmatch_t *pmatch = malloc(sizeof(regmatch_t) * use_size_offsets);
      if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL;
      if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL;

      rc = regexec(&preg, (const char *)bptr, use_size_offsets, pmatch, eflags);

      if (rc != 0)
        {
        (void)regerror(rc, &preg, (char *)buffer, sizeof(buffer));
        fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer);
        }
      else
        {
        size_t i;
        for (i = 0; i < use_size_offsets; i++)
          {
          if (pmatch[i].rm_so >= 0)
            {
            fprintf(outfile, "%2d: ", (int)i);
            pchars(dbuffer + pmatch[i].rm_so,
              pmatch[i].rm_eo - pmatch[i].rm_so, utf8);
            fprintf(outfile, "\n");
            if (i == 0 && do_showrest)
              {
              fprintf(outfile, " 0+ ");
              pchars(dbuffer + pmatch[i].rm_eo, len - pmatch[i].rm_eo, utf8);
              fprintf(outfile, "\n");
              }
            }
          }
        }
      free(pmatch);
      }

    /* Handle matching via the native interface - repeats for /g and /G */

    else
#endif  /* !defined NOPOSIX */

    for (;; gmatched++)    /* Loop for /g or /G */
      {
      if (timeit)
        {
        register int i;
        clock_t time_taken;
        clock_t start_time = clock();
        for (i = 0; i < LOOPREPEAT; i++)
          count = pcre_exec(re, extra, (char *)bptr, len,
            start_offset, options | g_notempty, use_offsets, use_size_offsets);
        time_taken = clock() - start_time;
        fprintf(outfile, "Execute time %.3f milliseconds\n",
          ((double)time_taken * 1000.0)/
          ((double)LOOPREPEAT * (double)CLOCKS_PER_SEC));
        }

      count = pcre_exec(re, extra, (char *)bptr, len,
        start_offset, options | g_notempty, use_offsets, use_size_offsets);

      if (count == 0)
        {
        fprintf(outfile, "Matched, but too many substrings\n");
        count = use_size_offsets/3;
        }

      /* Matched */

      if (count >= 0)
        {
        int i;
        for (i = 0; i < count * 2; i += 2)
          {
          if (use_offsets[i] < 0)
            fprintf(outfile, "%2d: <unset>\n", i/2);
          else
            {
            fprintf(outfile, "%2d: ", i/2);
            pchars(bptr + use_offsets[i], use_offsets[i+1] - use_offsets[i], utf8);
            fprintf(outfile, "\n");
            if (i == 0)
              {
              if (do_showrest)
                {
                fprintf(outfile, " 0+ ");
                pchars(bptr + use_offsets[i+1], len - use_offsets[i+1], utf8);
                fprintf(outfile, "\n");
                }
              }
            }
          }

        for (i = 0; i < 32; i++)
          {
          if ((copystrings & (1 << i)) != 0)
            {
            char copybuffer[16];
            int rc = pcre_copy_substring((char *)bptr, use_offsets, count,
              i, copybuffer, sizeof(copybuffer));
            if (rc < 0)
              fprintf(outfile, "copy substring %d failed %d\n", i, rc);
            else
              fprintf(outfile, "%2dC %s (%d)\n", i, copybuffer, rc);
            }
          }

        for (i = 0; i < 32; i++)
          {
          if ((getstrings & (1 << i)) != 0)
            {
            const char *substring;
            int rc = pcre_get_substring((char *)bptr, use_offsets, count,
              i, &substring);
            if (rc < 0)
              fprintf(outfile, "get substring %d failed %d\n", i, rc);
            else
              {
              fprintf(outfile, "%2dG %s (%d)\n", i, substring, rc);
              /* free((void *)substring); */
              pcre_free_substring(substring);
              }
            }
          }

        if (getlist)
          {
          const char **stringlist;
          int rc = pcre_get_substring_list((char *)bptr, use_offsets, count,
            &stringlist);
          if (rc < 0)
            fprintf(outfile, "get substring list failed %d\n", rc);
          else
            {
            for (i = 0; i < count; i++)
              fprintf(outfile, "%2dL %s\n", i, stringlist[i]);
            if (stringlist[i] != NULL)
              fprintf(outfile, "string list not terminated by NULL\n");
            /* free((void *)stringlist); */
            pcre_free_substring_list(stringlist);
            }
          }
        }

      /* Failed to match. If this is a /g or /G loop and we previously set
      g_notempty after a null match, this is not necessarily the end.
      We want to advance the start offset, and continue. Fudge the offset
      values to achieve this. We won't be at the end of the string - that
      was checked before setting g_notempty. */

      else
        {
        if (g_notempty != 0)
          {
          use_offsets[0] = start_offset;
          use_offsets[1] = start_offset + 1;
          }
        else
          {
          if (gmatched == 0)   /* Error if no previous matches */
            {
            if (count == -1) fprintf(outfile, "No match\n");
              else fprintf(outfile, "Error %d\n", count);
            }
          break;  /* Out of the /g loop */
          }
        }

      /* If not /g or /G we are done */

      if (!do_g && !do_G) break;

      /* If we have matched an empty string, first check to see if we are at
      the end of the subject. If so, the /g loop is over. Otherwise, mimic
      what Perl's /g options does. This turns out to be rather cunning. First
      we set PCRE_NOTEMPTY and PCRE_ANCHORED and try the match again at the
      same point. If this fails (picked up above) we advance to the next
      character. */

      g_notempty = 0;
      if (use_offsets[0] == use_offsets[1])
        {
        if (use_offsets[0] == len) break;
        g_notempty = PCRE_NOTEMPTY | PCRE_ANCHORED;
        }

      /* For /g, update the start offset, leaving the rest alone */

      if (do_g) start_offset = use_offsets[1];

      /* For /G, update the pointer and length */

      else
        {
        bptr += use_offsets[1];
        len -= use_offsets[1];
        }
      }  /* End of loop for /g and /G */
    }    /* End of loop for data lines */

  CONTINUE:

#if !defined NOPOSIX
  if (posix || do_posix) regfree(&preg);
#endif

  if (re != NULL) free(re);
  if (extra != NULL) free(extra);
  if (tables != NULL)
    {
    free((void *)tables);
    setlocale(LC_CTYPE, "C");
    }
  }

fprintf(outfile, "\n");
return 0;
}
Exemplo n.º 28
0
/** \internal
 *
 * \brief This function is used to parse Modbus parameters in function mode
 *
 * \param str Pointer to the user provided id option
 *
 * \retval id_d pointer to DetectModbusData on success
 * \retval NULL on failure
 */
static DetectModbus *DetectModbusFunctionParse(char *str)
{
    SCEnter();
    DetectModbus *modbus = NULL;

    char    arg[MAX_SUBSTRINGS], *ptr = arg;
    int     ov[MAX_SUBSTRINGS], res, ret;

    ret = pcre_exec(function_parse_regex, function_parse_regex_study, str, strlen(str), 0, 0, ov, MAX_SUBSTRINGS);

    if (ret < 1)
        goto error;

    res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 1, arg, MAX_SUBSTRINGS);
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        goto error;
    }

    /* We have a correct Modbus function option */
    modbus = (DetectModbus *) SCCalloc(1, sizeof(DetectModbus));
    if (unlikely(modbus == NULL))
        goto error;

    if (isdigit(ptr[0])) {
        modbus->function = atoi((const char*) ptr);
        SCLogDebug("will look for modbus function %d", modbus->function);

        if (ret > 2) {
            res = pcre_copy_substring(str, ov, MAX_SUBSTRINGS, 3, arg, MAX_SUBSTRINGS);
            if (res < 0) {
                SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
                goto error;
            }

            /* We have a correct address option */
            modbus->subfunction =(uint16_t *) SCCalloc(1, sizeof(uint16_t));
            if (modbus->subfunction == NULL)
                goto error;

            *(modbus->subfunction) = atoi((const char*) arg);
            SCLogDebug("and subfunction %d", *(modbus->subfunction));
        }
    } else {
        uint8_t neg = 0;

        if (ptr[0] == '!') {
            neg = 1;
            ptr++;
        }

        if (strcmp("assigned", ptr) == 0)
            modbus->category = MODBUS_CAT_PUBLIC_ASSIGNED;
        else if (strcmp("unassigned", ptr) == 0)
            modbus->category = MODBUS_CAT_PUBLIC_UNASSIGNED;
        else if (strcmp("public", ptr) == 0)
            modbus->category = MODBUS_CAT_PUBLIC_ASSIGNED | MODBUS_CAT_PUBLIC_UNASSIGNED;
        else if (strcmp("user", ptr) == 0)
            modbus->category = MODBUS_CAT_USER_DEFINED;
        else if (strcmp("reserved", ptr) == 0)
            modbus->category = MODBUS_CAT_RESERVED;
        else if (strcmp("all", ptr) == 0)
            modbus->category = MODBUS_CAT_ALL;

        if (neg)
            modbus->category = ~modbus->category;
        SCLogDebug("will look for modbus category function %d", modbus->category);
    }

    SCReturnPtr(modbus, "DetectModbusFunction");

error:
    if (modbus != NULL)
        DetectModbusFree(modbus);

    SCReturnPtr(NULL, "DetectModbus");
}
Exemplo n.º 29
0
static int
expand_range(const char *range, char ***set, int max_count, const char **err) {
  int count, erroff, ovector[30], rv;
  char buff[32]; /* submatches */
  const char *pcre_err;
  *err = NULL;
  if(!IP_match) {
    IP_match = pcre_compile("^(full:)?(\\d+\\.\\d+\\.\\d+\\.\\d+)/(\\d+)$",
                            0, &pcre_err, &erroff, NULL);
    if(!IP_match) {
      *err = "IP match pattern failed to compile!";
      noitL(noit_error, "pcre_compiled failed offset %d: %s\n", erroff, pcre_err);
      return -1;
    }
  }
  if(!numeric_match) {
    numeric_match = pcre_compile("^(\\d+)(?:,(\\d+))?\\.\\.(\\d+)$",
                                 0, &pcre_err, &erroff, NULL);
    if(!numeric_match) {
      *err = "numeric match pattern failed to compile!";
      noitL(noit_error, "pcre_compiled failed offset %d: %s\n", erroff, pcre_err);
      return -1;
    }
  }
  rv = pcre_exec(IP_match, NULL, range, strlen(range), 0, 0, ovector, 30);
  if(rv >= 0) {
    int mask, full = 0, i;
    u_int32_t host_addr;
    struct in_addr addr;
    /* 0 is the full monty, 1 is "" or "full:", 2 is the IP, 3 is the mask */
    pcre_copy_substring(range, ovector, rv, 1, buff, sizeof(buff));
    full = buff[0] ? 1 : 0;
    pcre_copy_substring(range, ovector, rv, 3, buff, sizeof(buff));
    mask = atoi(buff);
    if(mask == 32) full = 1; /* host implies.. the host */
    if(mask < 0 || mask > 32) {
      *err = "invalid netmask";
      return 0;
    }
    count = 1 << (32-mask);
    pcre_copy_substring(range, ovector, rv, 2, buff, sizeof(buff));
    if(inet_pton(AF_INET, buff, &addr) != 1) {
      *err = "could not parse IP address";
      return 0;
    }
    host_addr = ntohl(addr.s_addr);
    host_addr &= ~((u_int32_t)count - 1);

    if(!full) count -= 2; /* No network or broadcast */
    if(count > max_count || !count) return -count;
    if(!full) host_addr++; /* Skip the network address */

    *set = malloc(count * sizeof(**set));
    for(i=0; i<count; i++)  {
      addr.s_addr = htonl(host_addr + i);
      inet_ntop(AF_INET, &addr, buff, sizeof(buff));
      (*set)[i] = strdup(buff);
    }
    return count;
  }
  rv = pcre_exec(numeric_match, NULL, range, strlen(range), 0, 0, ovector, 30);
  if(rv >= 0) {
    int s, n, e, i;
    pcre_copy_substring(range, ovector, rv, 1, buff, sizeof(buff));
    s = atoi(buff);
    pcre_copy_substring(range, ovector, rv, 3, buff, sizeof(buff));
    e = atoi(buff);
    pcre_copy_substring(range, ovector, rv, 2, buff, sizeof(buff));
    if(buff[0]) n = atoi(buff);
    else n = (s<e) ? s+1 : s-1;

    /* Ensure that s < n < e */
    if((s<e && s>n) || (s>e && s<n)) {
      *err = "mixed up sequence";
      return 0;
    }
    i = n - s; /* Our increment */
    count = (e - s) / i + 1;
    *set = malloc(count * sizeof(**set));
    count = 0;
    for(; (i>0 && s<=e) || (i<0 && s>=e); s += i) {
      snprintf(buff, sizeof(buff), "%d", s);
      (*set)[count] = strdup(buff);
      count++;
    }
    return count;
  }
  *err = "cannot understand range";
  return 0;
}
Exemplo n.º 30
0
/**
 * \internal
 * \brief This function is used to parse flags options passed via flags: keyword
 *
 * \param rawstr Pointer to the user provided flags options
 *
 * \retval de pointer to DetectFlagsData on success
 * \retval NULL on failure
 */
static DetectFlagsData *DetectFlagsParse (const char *rawstr)
{
    SCEnter();

#define MAX_SUBSTRINGS 30
    int ret = 0, found = 0, ignore = 0, res = 0;
    int ov[MAX_SUBSTRINGS];
    char *ptr;

    char arg1[16] = "";
    char arg2[16] = "";
    char arg3[16] = "";

    ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr),
            0, 0, ov, MAX_SUBSTRINGS);
    SCLogDebug("input '%s', pcre said %d", rawstr, ret);
    if (ret < 3) {
        SCLogError(SC_ERR_PCRE_MATCH, "pcre match failed");
        SCReturnPtr(NULL, "DetectFlagsData");
    }

    res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
    if (res < 0) {
        SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
        SCReturnPtr(NULL, "DetectFlagsData");
    }
    if (ret >= 2) {
        res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 2, arg2, sizeof(arg2));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            SCReturnPtr(NULL, "DetectFlagsData");
        }
    }
    if (ret >= 3) {
        res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 3, arg3, sizeof(arg3));
        if (res < 0) {
            SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
            SCReturnPtr(NULL, "DetectFlagsData");
        }
    }
    SCLogDebug("args '%s', '%s', '%s'", arg1, arg2, arg3);

    if (strlen(arg2) == 0) {
        SCLogDebug("empty argument");
        SCReturnPtr(NULL, "DetectFlagsData");
    }

    DetectFlagsData *de = SCMalloc(sizeof(DetectFlagsData));
    if (unlikely(de == NULL))
        goto error;
    memset(de, 0, sizeof(DetectFlagsData));
    de->ignored_flags = 0xff;

    /** First parse args1 */
    ptr = arg1;
    while (*ptr != '\0') {
        switch (*ptr) {
            case 'S':
            case 's':
                de->flags |= TH_SYN;
                found++;
                break;
            case 'A':
            case 'a':
                de->flags |= TH_ACK;
                found++;
                break;
            case 'F':
            case 'f':
                de->flags |= TH_FIN;
                found++;
                break;
            case 'R':
            case 'r':
                de->flags |= TH_RST;
                found++;
                break;
            case 'P':
            case 'p':
                de->flags |= TH_PUSH;
                found++;
                break;
            case 'U':
            case 'u':
                de->flags |= TH_URG;
                found++;
                break;
            case '1':
                de->flags |= TH_CWR;
                found++;
                break;
            case '2':
                de->flags |= TH_ECN;
                found++;
                break;
            case 'C':
            case 'c':
                de->flags |= TH_CWR;
                found++;
                break;
            case 'E':
            case 'e':
                de->flags |= TH_ECN;
                found++;
                break;
            case '0':
                de->flags = 0;
                found++;
                break;

            case '!':
                de->modifier = MODIFIER_NOT;
                break;
            case '+':
                de->modifier = MODIFIER_PLUS;
                break;
            case '*':
                de->modifier = MODIFIER_ANY;
                break;
        }
        ptr++;
    }

    /** Second parse first set of flags */
    if (strlen(arg2) > 0) {
        ptr = arg2;
        while (*ptr != '\0') {
            switch (*ptr) {
                case 'S':
                case 's':
                    de->flags |= TH_SYN;
                    found++;
                    break;
                case 'A':
                case 'a':
                    de->flags |= TH_ACK;
                    found++;
                    break;
                case 'F':
                case 'f':
                    de->flags |= TH_FIN;
                    found++;
                    break;
                case 'R':
                case 'r':
                    de->flags |= TH_RST;
                    found++;
                    break;
                case 'P':
                case 'p':
                    de->flags |= TH_PUSH;
                    found++;
                    break;
                case 'U':
                case 'u':
                    de->flags |= TH_URG;
                    found++;
                    break;
                case '1':
                case 'C':
                case 'c':
                    de->flags |= TH_CWR;
                    found++;
                    break;
                case '2':
                case 'E':
                case 'e':
                    de->flags |= TH_ECN;
                    found++;
                    break;
                case '0':
                    de->flags = 0;
                    found++;
                    break;

                case '!':
                    if (de->modifier != 0) {
                        SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
                                " one modifier at a time");
                        goto error;
                    }
                    de->modifier = MODIFIER_NOT;
                    SCLogDebug("NOT modifier is set");
                    break;
                case '+':
                    if (de->modifier != 0) {
                        SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
                                " one modifier at a time");
                        goto error;
                    }
                    de->modifier = MODIFIER_PLUS;
                    SCLogDebug("PLUS modifier is set");
                    break;
                case '*':
                    if (de->modifier != 0) {
                        SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
                                " one modifier at a time");
                        goto error;
                    }
                    de->modifier = MODIFIER_ANY;
                    SCLogDebug("ANY modifier is set");
                    break;
                default:
                    break;
            }
            ptr++;
        }

        if (found == 0)
            goto error;
    }

    /** Finally parse ignored flags */
    if (strlen(arg3) > 0) {
        ptr = arg3;

        while (*ptr != '\0') {
            switch (*ptr) {
                case 'S':
                case 's':
                    de->ignored_flags &= ~TH_SYN;
                    ignore++;
                    break;
                case 'A':
                case 'a':
                    de->ignored_flags &= ~TH_ACK;
                    ignore++;
                    break;
                case 'F':
                case 'f':
                    de->ignored_flags &= ~TH_FIN;
                    ignore++;
                    break;
                case 'R':
                case 'r':
                    de->ignored_flags &= ~TH_RST;
                    ignore++;
                    break;
                case 'P':
                case 'p':
                    de->ignored_flags &= ~TH_PUSH;
                    ignore++;
                    break;
                case 'U':
                case 'u':
                    de->ignored_flags &= ~TH_URG;
                    ignore++;
                    break;
                case '1':
                    de->ignored_flags &= ~TH_CWR;
                    ignore++;
                    break;
                case '2':
                    de->ignored_flags &= ~TH_ECN;
                    ignore++;
                    break;
                case 'C':
                case 'c':
                    de->ignored_flags &= ~TH_CWR;
                    ignore++;
                    break;
                case 'E':
                case 'e':
                    de->ignored_flags &= ~TH_ECN;
                    ignore++;
                    break;
                case '0':
                    break;
                default:
                    break;
            }
            ptr++;
        }

        if (ignore == 0) {
            SCLogDebug("ignore == 0");
            goto error;
        }
    }

    SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore);
    SCReturnPtr(de, "DetectFlagsData");

error:
    if (de) {
        SCFree(de);
    }
    SCReturnPtr(NULL, "DetectFlagsData");
}