Example #1
0
/** find elem using XPath like query
 *  name -- "name" for the child tag of that name
 *          "name/name" for a sub child (recurses)
 *          "?attrib" to match the first tag with that attrib defined
 *          "?attrib=value" to match the first tag with that attrib and value
 *          or any combination: "name/name/?attrib", etc
 */
int nad_find_elem_path(nad_t nad, int elem, int ns, const char *name) {
    char *str, *slash, *qmark, *equals;

    _nad_ptr_check(__func__, nad);

    /* make sure there are valid args */
    if(elem >= nad->ecur || name == NULL) return -1;

    /* if it's plain name just search children */
    if(strstr(name, "/") == NULL && strstr(name,"?") == NULL)
        return nad_find_elem(nad, elem, ns, name, 1);

    str = strdup(name);
    slash = strstr(str, "/");
    qmark = strstr(str, "?");
    equals = strstr(str, "=");

    /* no / in element name part */
    if(qmark != NULL && (slash == NULL || qmark < slash))
    { /* of type ?attrib */

        *qmark = '\0';
        qmark++;
        if(equals != NULL)
        {
            *equals = '\0';
            equals++;
        }

        for(elem = nad_find_elem(nad, elem, ns, str, 1); ; elem = nad_find_elem(nad, elem, ns, str, 0)) {
            if(elem < 0) break;
            if(strcmp(qmark, "xmlns") == 0) {
                if(nad_find_namespace(nad, elem, equals, NULL) >= 0) break;
            }
            else {
                if(nad_find_attr(nad, elem, ns, qmark, equals) >= 0) break;
            }
        }

        free(str);
        return elem;
    }

    /* there is a / in element name part - need to recurse */
    *slash = '\0';
    ++slash;

    for(elem = nad_find_elem(nad, elem, ns, str, 1); ; elem = nad_find_elem(nad, elem, ns, str, 0)) {
        if(elem < 0) break;
        if((elem = nad_find_elem_path(nad, elem, ns, slash)) >= 0) break;
    }

    free(str);
    return elem;
}
Example #2
0
int filter_packet(router_t r, nad_t nad) {
    acl_t acl;
    int ato, afrom, error = 0;
    unsigned char *cur, *to = NULL, *from = NULL;

    ato = nad_find_attr(nad, 1, -1, "to", NULL);
    afrom = nad_find_attr(nad, 1, -1, "from", NULL);
    if(ato >= 0 && NAD_AVAL_L(nad,ato) > 0) {
        to = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, ato) + 1));
        sprintf(to, "%.*s", NAD_AVAL_L(nad, ato), NAD_AVAL(nad, ato));
        cur = strstr(to, "@");       /* skip node part */
        if(cur != NULL)
            cur = strstr(cur, "/");
        else
            cur = strstr(to, "/");
        if(cur != NULL) *cur = '\0'; /* remove the resource part */
    }
    if(afrom >= 0 && NAD_AVAL_L(nad,afrom) > 0) {
        from = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, afrom) + 1));
        sprintf(from, "%.*s", NAD_AVAL_L(nad, afrom), NAD_AVAL(nad, afrom));
        cur = strstr(from, "@");
        if(cur != NULL)
            cur = strstr(cur, "/");
        else
            cur = strstr(from, "/");
        if(cur != NULL) *cur = '\0';
    }

    for(acl = r->filter; acl != NULL; acl = acl->next) {
        if( from == NULL && acl->from != NULL) continue;        /* no match if NULL matched vs not-NULL */
        if( to == NULL && acl->to != NULL ) continue;
        if( from != NULL && acl->from == NULL) continue;        /* no match if not-NULL matched vs NULL */
        if( to != NULL && acl->to == NULL ) continue;
        if( from != NULL && acl->from != NULL && fnmatch(acl->from, from, 0) != 0 ) continue;        /* do filename-like match */
        if( to != NULL && acl->to != NULL && fnmatch(acl->to, to, 0) != 0 ) continue;
        if( acl->what != NULL && nad_find_elem_path(nad, 0, -1, acl->what) < 0 ) continue;        /* match packet type */
        log_debug(ZONE, "matched packet %s->%s vs rule (%s %s->%s)", from, to, acl->what, acl->from, acl->to);
        if (acl->log) {
            if (acl->redirect) log_write(r->log, LOG_NOTICE, "filter: redirect packet from=%s to=%s - rule (from=%s to=%s what=%s), new to=%s", from, to, acl->from, acl->to, acl->what, acl->redirect);
            else log_write(r->log, LOG_NOTICE, "filter: %s packet from=%s to=%s - rule (from=%s to=%s what=%s)",(acl->error?"deny":"allow"), from, to, acl->from, acl->to, acl->what);
        }
        if (acl->redirect) nad_set_attr(nad, 0, -1, "to", acl->redirect, acl->redirect_len);
        error = acl->error;
        break;
    }

    if(to != NULL) free(to);
    if(from != NULL) free(from);
    return error;
}