📄 ldb_parse.c
字号:
/* ldb database library Copyright (C) Andrew Tridgell 2004 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released ** under the LGPL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>.*//* * Name: ldb * * Component: ldb expression parsing * * Description: parse LDAP-like search expressions * * Author: Andrew Tridgell *//* TODO: - add RFC2254 binary string handling - possibly add ~=, <= and >= handling - expand the test suite - add better parse error handling*/#include "ldb_includes.h"#include "system/locale.h"/*a filter is defined by: <filter> ::= '(' <filtercomp> ')' <filtercomp> ::= <and> | <or> | <not> | <simple> <and> ::= '&' <filterlist> <or> ::= '|' <filterlist> <not> ::= '!' <filter> <filterlist> ::= <filter> | <filter> <filterlist> <simple> ::= <attributetype> <filtertype> <attributevalue> <filtertype> ::= '=' | '~=' | '<=' | '>='*//* decode a RFC2254 binary string representation of a buffer. Used in LDAP filters.*/struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str){ int i, j; struct ldb_val ret; int slen = str?strlen(str):0; ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1); ret.length = 0; if (ret.data == NULL) return ret; for (i=j=0;i<slen;i++) { if (str[i] == '\\') { unsigned c; if (sscanf(&str[i+1], "%02X", &c) != 1) { talloc_free(ret.data); memset(&ret, 0, sizeof(ret)); return ret; } ((uint8_t *)ret.data)[j++] = c; i += 2; } else { ((uint8_t *)ret.data)[j++] = str[i]; } } ret.length = j; ((uint8_t *)ret.data)[j] = 0; return ret;}/* encode a blob as a RFC2254 binary string, escaping any non-printable or '\' characters*/char *ldb_binary_encode(void *mem_ctx, struct ldb_val val){ int i; char *ret; int len = val.length; unsigned char *buf = val.data; for (i=0;i<val.length;i++) { if (!isprint(buf[i]) || strchr(" *()\\&|!\"", buf[i])) { len += 2; } } ret = talloc_array(mem_ctx, char, len+1); if (ret == NULL) return NULL; len = 0; for (i=0;i<val.length;i++) { if (!isprint(buf[i]) || strchr(" *()\\&|!\"", buf[i])) { snprintf(ret+len, 4, "\\%02X", buf[i]); len += 3; } else { ret[len++] = buf[i]; } } ret[len] = 0; return ret; }/* encode a string as a RFC2254 binary string, escaping any non-printable or '\' characters. This routine is suitable for use in escaping user data in ldap filters.*/char *ldb_binary_encode_string(void *mem_ctx, const char *string){ struct ldb_val val; val.data = discard_const_p(uint8_t, string); val.length = strlen(string); return ldb_binary_encode(mem_ctx, val);}/* find the first matching wildcard */static char *ldb_parse_find_wildcard(char *value){ while (*value) { value = strpbrk(value, "\\*"); if (value == NULL) return NULL; if (value[0] == '\\') { if (value[1] == '\0') return NULL; value += 2; continue; } if (value[0] == '*') return value; } return NULL;}/* return a NULL terminated list of binary strings representing the value chunks separated by wildcards that makes the value portion of the filter*/static struct ldb_val **ldb_wildcard_decode(void *mem_ctx, const char *string){ struct ldb_val **ret = NULL; int val = 0; char *wc, *str; wc = talloc_strdup(mem_ctx, string); if (wc == NULL) return NULL; while (wc && *wc) { str = wc; wc = ldb_parse_find_wildcard(str); if (wc && *wc) { if (wc == str) { wc++; continue; } *wc = 0; wc++; } ret = talloc_realloc(mem_ctx, ret, struct ldb_val *, val + 2); if (ret == NULL) return NULL; ret[val] = talloc(mem_ctx, struct ldb_val); if (ret[val] == NULL) return NULL; *(ret[val]) = ldb_binary_decode(mem_ctx, str); if ((ret[val])->data == NULL) return NULL; val++; } if (ret != NULL) { ret[val] = NULL; } return ret;}static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s);/* parse an extended match possible forms: (attr:oid:=value) (attr:dn:oid:=value) (attr:dn:=value) (:dn:oid:=value) the ':dn' part sets the dnAttributes boolean if present the oid sets the rule_id string */static struct ldb_parse_tree *ldb_parse_extended(struct ldb_parse_tree *ret, char *attr, char *value){ char *p1, *p2; ret->operation = LDB_OP_EXTENDED; ret->u.extended.value = ldb_binary_decode(ret, value); if (ret->u.extended.value.data == NULL) goto failed; p1 = strchr(attr, ':'); if (p1 == NULL) goto failed; p2 = strchr(p1+1, ':'); *p1 = 0; if (p2) *p2 = 0; ret->u.extended.attr = attr; if (strcmp(p1+1, "dn") == 0) { ret->u.extended.dnAttributes = 1; if (p2) { ret->u.extended.rule_id = talloc_strdup(ret, p2+1); if (ret->u.extended.rule_id == NULL) goto failed; } else { ret->u.extended.rule_id = NULL; } } else { ret->u.extended.dnAttributes = 0; ret->u.extended.rule_id = talloc_strdup(ret, p1+1); if (ret->u.extended.rule_id == NULL) goto failed; } return ret;failed: talloc_free(ret); return NULL;}static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char **value, const char **s){ enum ldb_parse_op filter = 0; char *name, *val, *k; const char *p = *s; const char *t, *t1; /* retrieve attributetype name */ t = p; if (*p == '@') { /* for internal attributes the first char can be @ */ p++; } while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */ p++; } if (*p == ':') { /* but extended searches have : and . chars too */ p = strstr(p, ":="); if (p == NULL) { /* malformed attribute name */ return 0; } } t1 = p; while (isspace((unsigned char)*p)) p++; if (!strchr("=<>~:", *p)) { return 0; } /* save name */ name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1); if (name == NULL) return 0; name[t1 - t] = '\0'; /* retrieve filtertype */ if (*p == '=') { filter = LDB_OP_EQUALITY; } else if (*(p + 1) == '=') { switch (*p) { case '<': filter = LDB_OP_LESS; p++; break; case '>': filter = LDB_OP_GREATER; p++; break; case '~': filter = LDB_OP_APPROX; p++; break; case ':': filter = LDB_OP_EXTENDED; p++; break; } } if (!filter) { talloc_free(name); return filter; } p++; while (isspace((unsigned char)*p)) p++; /* retieve value */ t = p; while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++; val = (char *)talloc_memdup(mem_ctx, t, p - t + 1); if (val == NULL) { talloc_free(name); return 0; } val[p - t] = '\0'; k = &(val[p - t]); /* remove trailing spaces from value */ while ((k > val) && (isspace((unsigned char)*(k - 1)))) k--; *k = '\0'; *type = name; *value = val; *s = p; return filter;}/* <simple> ::= <attributetype> <filtertype> <attributevalue>*/static struct ldb_parse_tree *ldb_parse_simple(void *mem_ctx, const char **s){ char *attr, *value; struct ldb_parse_tree *ret; enum ldb_parse_op filtertype; ret = talloc(mem_ctx, struct ldb_parse_tree); if (!ret) { errno = ENOMEM; return NULL; } filtertype = ldb_parse_filtertype(ret, &attr, &value, s); if (!filtertype) { talloc_free(ret); return NULL; } switch (filtertype) { case LDB_OP_PRESENT: ret->operation = LDB_OP_PRESENT; ret->u.present.attr = attr; break; case LDB_OP_EQUALITY: if (strcmp(value, "*") == 0) { ret->operation = LDB_OP_PRESENT; ret->u.present.attr = attr; break; } if (ldb_parse_find_wildcard(value) != NULL) { ret->operation = LDB_OP_SUBSTRING; ret->u.substring.attr = attr; ret->u.substring.start_with_wildcard = 0; ret->u.substring.end_with_wildcard = 0; ret->u.substring.chunks = ldb_wildcard_decode(ret, value); if (ret->u.substring.chunks == NULL){ talloc_free(ret); return NULL; } if (value[0] == '*') ret->u.substring.start_with_wildcard = 1; if (value[strlen(value) - 1] == '*') ret->u.substring.end_with_wildcard = 1; talloc_free(value); break; } ret->operation = LDB_OP_EQUALITY; ret->u.equality.attr = attr; ret->u.equality.value = ldb_binary_decode(ret, value); if (ret->u.equality.value.data == NULL) { talloc_free(ret); return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -