| |
@@ -22,9 +22,7 @@
|
| |
#include <plhash.h>
|
| |
#include "slap.h"
|
| |
|
| |
- #if defined(USE_OPENLDAP)
|
| |
#include <ldap_schema.h> /* openldap schema parser */
|
| |
- #endif
|
| |
|
| |
static struct slapdplugin schema_plugin = {0};
|
| |
|
| |
@@ -184,30 +182,9 @@
|
| |
static int parse_at_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
|
| |
static int extension_is_user_defined(schemaext *extensions);
|
| |
static size_t strcat_qdlist(char *buf, char *prefix, char **qdlist);
|
| |
- #if defined(USE_OPENLDAP)
|
| |
- /*
|
| |
- * openldap
|
| |
- */
|
| |
static int parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
|
| |
static int parse_objclass_str(const char *input, struct objclass **oc, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, struct objclass *private_schema);
|
| |
|
| |
- #else
|
| |
- /*
|
| |
- * mozldap
|
| |
- */
|
| |
- static char **parse_qdescrs(const char *s, int *n);
|
| |
- static char **parse_qdstrings(const char *s, int *n);
|
| |
- static char **parse_qdlist(const char *s, int *n, int strip_options);
|
| |
- static void free_qdlist(char **vals, int n);
|
| |
- static int read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 flags, int is_user_defined, int schema_ds4x_compat, int is_remote);
|
| |
- static int read_oc_ldif(const char *input, struct objclass **oc, char *errorbuf, size_t errorbufsize, PRUint32 flags, int is_user_defined, int schema_ds4x_compat);
|
| |
- static int get_flag_keyword(const char *keyword, int flag_value, const char **inputp, schema_strstr_fn_t strstr_fn);
|
| |
- static char *get_tagged_oid(const char *tag, const char **inputp, schema_strstr_fn_t strstr_fn);
|
| |
- static char **read_dollar_values(char *vals);
|
| |
- static schemaext *parse_extensions(const char *schema_value, char **default_list);
|
| |
- #endif
|
| |
-
|
| |
-
|
| |
/*
|
| |
* Some utility functions for dealing with a dynamic buffer
|
| |
*/
|
| |
@@ -254,11 +231,7 @@
|
| |
if (asipp) {
|
| |
*asipp = NULL;
|
| |
}
|
| |
- #ifdef USE_OPENLDAP
|
| |
return parse_attr_str(input, asipp, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat, is_remote);
|
| |
- #else
|
| |
- return read_at_ldif(input, asipp, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat, is_remote);
|
| |
- #endif
|
| |
}
|
| |
|
| |
static int
|
| |
@@ -267,11 +240,7 @@
|
| |
if (oc) {
|
| |
*oc = NULL;
|
| |
}
|
| |
- #ifdef USE_OPENLDAP
|
| |
return parse_objclass_str(input, oc, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat, private_schema);
|
| |
- #else
|
| |
- return read_oc_ldif(input, oc, errorbuf, errorbufsize, schema_flags, is_user_defined, schema_ds4x_compat);
|
| |
- #endif
|
| |
}
|
| |
|
| |
|
| |
@@ -527,170 +496,6 @@
|
| |
return SLAPI_DSE_CALLBACK_ERROR;
|
| |
}
|
| |
|
| |
- #if !defined(USE_OPENLDAP)
|
| |
- static const char *
|
| |
- skipWS(const char *s)
|
| |
- {
|
| |
- while (s && isascii(*s) && isspace(*s)) {
|
| |
- ++s;
|
| |
- }
|
| |
-
|
| |
- if ((isascii(*s)) == 0) {
|
| |
- return NULL;
|
| |
- }
|
| |
- return s;
|
| |
- }
|
| |
-
|
| |
- /*
|
| |
- * like strchr() but strings within single quotes are skipped.
|
| |
- */
|
| |
- static char *
|
| |
- strchr_skip_quoted_strings(char *s, int c)
|
| |
- {
|
| |
- int in_quote = 0;
|
| |
-
|
| |
- while (*s != '\0') {
|
| |
- if (*s == '\'') {
|
| |
- in_quote = 1 - in_quote; /* toggle */
|
| |
- } else if (!in_quote && *s == c) {
|
| |
- return s;
|
| |
- }
|
| |
- ++s;
|
| |
- }
|
| |
-
|
| |
- return (NULL);
|
| |
- }
|
| |
- /**
|
| |
- * parses a string containing a qdescrs or qdstrings (as described by
|
| |
- * RFC 2252, section 4.1) into an array of strings; the second parameter
|
| |
- * will hold the actual number of strings in the array. The returned array
|
| |
- * is NULL terminated.
|
| |
- *
|
| |
- * This function can handle qdescrs or qdstrings because the only
|
| |
- * difference between the two is that fewer characters are allowed in
|
| |
- * a qdescr (our parsing code does not check anyway) and we want to
|
| |
- * strip attribute options when parsing qdescrs (indicated by a non-zero
|
| |
- * strip_options parameter).
|
| |
- */
|
| |
- static char **
|
| |
- parse_qdlist(const char *s, int *n, int strip_options)
|
| |
- {
|
| |
- char **retval = 0;
|
| |
- char *work = 0;
|
| |
- char *start = 0, *end = 0;
|
| |
- int num = 0;
|
| |
- int in_quote = 0;
|
| |
-
|
| |
- if (n)
|
| |
- *n = 0;
|
| |
-
|
| |
- if (!s || !*s || !n) {
|
| |
- return retval;
|
| |
- }
|
| |
-
|
| |
- /* make a working copy of the given string */
|
| |
- work = slapi_ch_strdup(s);
|
| |
-
|
| |
- /* count the number of qdescr items in the string e.g. just count
|
| |
- the number of spaces */
|
| |
- /* for a single qdescr, the terminal character will be the final
|
| |
- single quote; for a qdesclist, the terminal will be the close
|
| |
- parenthesis */
|
| |
- end = strrchr(work, '\'');
|
| |
- if ((start = strchr_skip_quoted_strings(work, '(')) != NULL)
|
| |
- end = strchr_skip_quoted_strings(work, ')');
|
| |
- else
|
| |
- start = strchr(work, '\'');
|
| |
-
|
| |
- if (!end) /* already nulled out */
|
| |
- end = work + strlen(work);
|
| |
-
|
| |
- if (start) {
|
| |
- num = 1;
|
| |
- /* first pass: count number of items and zero out non useful tokens */
|
| |
- for (; *start && (start != end); ++start) {
|
| |
- if (*start == '\'') {
|
| |
- in_quote = 1 - in_quote; /* toggle */
|
| |
- *start = 0;
|
| |
- } else if (!in_quote && ((*start == ' ') || (*start == '(') ||
|
| |
- (*start == ')'))) {
|
| |
- if (*start == ' ') {
|
| |
- num++;
|
| |
- }
|
| |
- *start = 0;
|
| |
- }
|
| |
- }
|
| |
- *start = 0;
|
| |
-
|
| |
- /* allocate retval; num will be >= actual number of items */
|
| |
- retval = (char **)slapi_ch_calloc(num + 1, sizeof(char *));
|
| |
-
|
| |
- /* second pass: copy strings into the return value and set the
|
| |
- actual number of items returned */
|
| |
- start = work;
|
| |
- while (start != end) {
|
| |
- /* skip over nulls */
|
| |
- while (!*start && (start != end))
|
| |
- ++start;
|
| |
- if (start == end)
|
| |
- break;
|
| |
- retval[*n] = slapi_ch_strdup(start);
|
| |
- /*
|
| |
- * A qdescr list may contain attribute options; we just strip
|
| |
- * them here. In the future, we may want to support them or do
|
| |
- * something really fancy with them
|
| |
- */
|
| |
- if (strip_options) {
|
| |
- stripOption(retval[*n]);
|
| |
- }
|
| |
- (*n)++;
|
| |
- start += strlen(start);
|
| |
- }
|
| |
- PR_ASSERT(*n <= num); /* sanity check */
|
| |
- retval[*n] = NULL;
|
| |
- } else {
|
| |
- /* syntax error - no start and/or end delimiters */
|
| |
- }
|
| |
-
|
| |
- /* free the working string */
|
| |
- slapi_ch_free((void **)&work);
|
| |
-
|
| |
- return retval;
|
| |
- }
|
| |
-
|
| |
- /**
|
| |
- * parses a string containing a qdescrs (as described by RFC 2252, section 4.1)
|
| |
- * into an array of strings; the second parameter will hold the actual number
|
| |
- * of strings in the array. The returned array is NULL terminated.
|
| |
- */
|
| |
- static char **
|
| |
- parse_qdescrs(const char *s, int *n)
|
| |
- {
|
| |
- return parse_qdlist(s, n, 1 /* strip attribute options */);
|
| |
- }
|
| |
-
|
| |
-
|
| |
- /*
|
| |
- * Parses a string containing a qdstrings (see RFC 2252, section 4.1) into
|
| |
- * an array of strings; the second parameter will hold the actual number
|
| |
- * of strings in the array.
|
| |
- */
|
| |
- static char **
|
| |
- parse_qdstrings(const char *s, int *n)
|
| |
- {
|
| |
- return parse_qdlist(s, n, 0 /* DO NOT strip attribute options */);
|
| |
- }
|
| |
-
|
| |
- static void
|
| |
- free_qdlist(char **vals, int n)
|
| |
- {
|
| |
- int ii;
|
| |
- for (ii = 0; ii < n; ++ii)
|
| |
- slapi_ch_free((void **)&(vals[ii]));
|
| |
- slapi_ch_free((void **)&vals);
|
| |
- }
|
| |
-
|
| |
- #endif /* not openldap */
|
| |
|
| |
/*
|
| |
* slapi_entry_schema_check - check that entry e conforms to the schema
|
| |
@@ -1582,7 +1387,6 @@
|
| |
}
|
| |
|
| |
if (!aew->schema_ds4x_compat) {
|
| |
- #if defined(USE_OPENLDAP)
|
| |
/*
|
| |
* These values in quotes are not supported by the openldap parser.
|
| |
* Even if nsslapd-enquote-sup-oc is on, quotes should not be added.
|
| |
@@ -1591,16 +1395,6 @@
|
| |
outp += put_tagged_oid(outp, "EQUALITY ", asip->asi_mr_equality, NULL, 0);
|
| |
outp += put_tagged_oid(outp, "ORDERING ", asip->asi_mr_ordering, NULL, 0);
|
| |
outp += put_tagged_oid(outp, "SUBSTR ", asip->asi_mr_substring, NULL, 0);
|
| |
- #else
|
| |
- outp += put_tagged_oid(outp, "SUP ",
|
| |
- asip->asi_superior, NULL, aew->enquote_sup_oc);
|
| |
- outp += put_tagged_oid(outp, "EQUALITY ",
|
| |
- asip->asi_mr_equality, NULL, aew->enquote_sup_oc);
|
| |
- outp += put_tagged_oid(outp, "ORDERING ",
|
| |
- asip->asi_mr_ordering, NULL, aew->enquote_sup_oc);
|
| |
- outp += put_tagged_oid(outp, "SUBSTR ",
|
| |
- asip->asi_mr_substring, NULL, aew->enquote_sup_oc);
|
| |
- #endif
|
| |
}
|
| |
|
| |
outp += put_tagged_oid(outp, "SYNTAX ", syntaxoid, syntaxlengthbuf,
|
| |
@@ -3215,976 +3009,147 @@
|
| |
}
|
| |
}
|
| |
|
| |
- #if !defined(USE_OPENLDAP)
|
| |
-
|
| |
- /*
|
| |
- * read_oc_ldif_return
|
| |
- * Free all the memory that read_oc_ldif() allocated, and return the retVal
|
| |
- *
|
| |
- * It's nice to do all the freeing in one spot, as read_oc_ldif() returns sideways
|
| |
- */
|
| |
-
|
| |
- static int
|
| |
- read_oc_ldif_return(int retVal,
|
| |
- char *oid,
|
| |
- struct sizedbuffer *name,
|
| |
- char *sup,
|
| |
- char *desc)
|
| |
- {
|
| |
- slapi_ch_free((void **)&oid);
|
| |
- sizedbuffer_destroy(name);
|
| |
- slapi_ch_free((void **)&sup);
|
| |
- slapi_ch_free((void **)&desc);
|
| |
- return retVal;
|
| |
- }
|
| |
|
| |
+ /* openldap attribute parser */
|
| |
/*
|
| |
- * read_oc_ldif
|
| |
- * Read the value of the objectclasses attribute in cn=schema, convert it
|
| |
- * into an objectclass struct.
|
| |
- *
|
| |
- * Arguments:
|
| |
- *
|
| |
- * input : value of objectclasses attribute to read
|
| |
- * oc : pointer write the objectclass to
|
| |
- * errorbuf : buffer to write any errors to
|
| |
- * is_user_defined : if non-zero, force objectclass to be user defined
|
| |
- * schema_flags : Any or none of the following bits could be set
|
| |
- * DSE_SCHEMA_NO_CHECK -- schema won't be checked
|
| |
- * DSE_SCHEMA_NO_GLOCK -- don't lock global resources
|
| |
- * DSE_SCHEMA_LOCKED -- already locked with
|
| |
- * reload_schemafile_lock;
|
| |
- * no further lock needed
|
| |
- * schema_ds4x_compat: if non-zero, act like Netscape DS 4.x
|
| |
+ * if asipp is NULL, the attribute type is added to the global set of schema.
|
| |
+ * if asipp is not NULL, the AT is not added but *asipp is set. When you are
|
| |
+ * finished with *asipp, use attr_syntax_free() to dispose of it.
|
| |
*
|
| |
- * Returns: an LDAP error code
|
| |
+ * schema_flags: Any or none of the following bits could be set
|
| |
+ * DSE_SCHEMA_NO_CHECK -- schema won't be checked
|
| |
+ * DSE_SCHEMA_NO_GLOCK -- locking of global resources is turned off;
|
| |
+ * this saves time during initialization since
|
| |
+ * the server operates in single threaded mode
|
| |
+ * at that time or in reload_schemafile_lock.
|
| |
+ * DSE_SCHEMA_LOCKED -- already locked with reload_schemafile_lock;
|
| |
+ * no further lock needed
|
| |
*
|
| |
- * LDAP_SUCCESS if the objectclass was sucessfully read, the new
|
| |
- * objectclass will be written to oc
|
| |
+ * if is_user_defined is true, force attribute type to be user defined.
|
| |
*
|
| |
- * All others: there was an error, an error message will
|
| |
- * be written to errorbuf
|
| |
- */
|
| |
+ * returns an LDAP error code (LDAP_SUCCESS if all goes well)
|
| |
+ */
|
| |
static int
|
| |
- read_oc_ldif(const char *input, struct objclass **oc, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat)
|
| |
+ parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote __attribute__((unused)))
|
| |
{
|
| |
- int i, j;
|
| |
- const char *pstart, *nextinput;
|
| |
- struct objclass *pnew_oc, *psup_oc;
|
| |
- char **RequiredAttrsArray, **AllowedAttrsArray;
|
| |
- char **OrigRequiredAttrsArray, **OrigAllowedAttrsArray;
|
| |
- char *pend, *pOcOid, *pOcSup, *pOcDesc;
|
| |
- struct sizedbuffer *psbOcName = sizedbuffer_construct(BUFSIZ);
|
| |
- PRUint8 kind, flags;
|
| |
+ struct asyntaxinfo *tmpasip;
|
| |
+ struct asyntaxinfo *tmpasi;
|
| |
+ schemaext *extensions = NULL, *head = NULL;
|
| |
+ struct objclass *poc;
|
| |
+ LDAPAttributeType *atype = NULL;
|
| |
+ const char *errp;
|
| |
+ char *first_attr_name = NULL;
|
| |
+ char **attr_names = NULL;
|
| |
+ unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
|
| |
+ /* If we ever accept openldap schema directly, then make parser_flags configurable */
|
| |
+ unsigned int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
| |
int invalid_syntax_error;
|
| |
- schema_strstr_fn_t keyword_strstr_fn;
|
| |
- schemaext *extensions = NULL;
|
| |
+ int syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
|
| |
+ int num_names = 0;
|
| |
+ int status = 0;
|
| |
+ int rc = 0;
|
| |
+ int a, aa;
|
| |
+
|
| |
+ if (config_get_enquote_sup_oc()) {
|
| |
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
| |
+ } else if (getenv("LDAP_SCHEMA_ALLOW_QUOTED")) {
|
| |
+ char ebuf[SLAPI_DSE_RETURNTEXT_SIZE];
|
| |
+ parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
| |
+ if (config_set_enquote_sup_oc(CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, "on", ebuf, CONFIG_APPLY)) {
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, "parse_attr_str", "Failed to enable %s: %s\n",
|
| |
+ CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, ebuf);
|
| |
+ }
|
| |
+ }
|
| |
|
| |
/*
|
| |
- * From RFC 2252 section 4.4:
|
| |
- *
|
| |
- * ObjectClassDescription = "(" whsp
|
| |
- * numericoid whsp ; ObjectClass identifier
|
| |
- * [ "NAME" qdescrs ]
|
| |
- * [ "DESC" qdstring ]
|
| |
- * [ "OBSOLETE" whsp ]
|
| |
- * [ "SUP" oids ] ; Superior ObjectClasses
|
| |
- * [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
|
| |
- * ; default structural
|
| |
- * [ "MUST" oids ] ; AttributeTypes
|
| |
- * [ "MAY" oids ] ; AttributeTypes
|
| |
- * whsp ")"
|
| |
- *
|
| |
- * XXXmcs: Our parsing technique is poor. In (Netscape) DS 4.12 and earlier
|
| |
- * releases, parsing was mostly done by looking anywhere within the input
|
| |
- * string for various keywords such as "MUST". But if, for example, a
|
| |
- * description contains the word "must", the parser would take assume that
|
| |
- * the tokens following the word were attribute types or OIDs. Bad news.
|
| |
- *
|
| |
- * In iDS 5.0 and later, we parse in order left to right and advance a
|
| |
- * pointer as we consume the input string (the nextinput variable). We
|
| |
- * also use a case-insensitive search when looking for keywords such as
|
| |
- * DESC. But the parser will still be fooled by sequences like:
|
| |
- *
|
| |
- * ( 1.2.3.4 NAME 'testOC' MUST ( DESC cn ) )
|
| |
- *
|
| |
- * Someday soon we will need to write a real parser.
|
| |
- *
|
| |
- * Compatibility notes: if schema_ds4x_compat is set, we:
|
| |
- * 1. always parse from the beginning of the string
|
| |
- * 2. use a case-insensitive compare when looking for keywords, e.g., MUST
|
| |
- */
|
| |
+ * OpenLDAP AttributeType struct
|
| |
+ *
|
| |
+ * typedef struct ldap_attributetype {
|
| |
+ * char *at_oid; OID
|
| |
+ * char **at_names; Names
|
| |
+ * char *at_desc; Description
|
| |
+ * int at_obsolete; Is obsolete?
|
| |
+ * char *at_sup_oid; OID of superior type
|
| |
+ * char *at_equality_oid; OID of equality matching rule
|
| |
+ * char *at_ordering_oid; OID of ordering matching rule
|
| |
+ * char *at_substr_oid; OID of substrings matching rule
|
| |
+ * char *at_syntax_oid; OID of syntax of values
|
| |
+ * int at_syntax_len; Suggested minimum maximum length
|
| |
+ * int at_single_value; Is single-valued?
|
| |
+ * int at_collective; Is collective?
|
| |
+ * int at_no_user_mod; Are changes forbidden through LDAP?
|
| |
+ * int at_usage; Usage, see below
|
| |
+ * LDAPSchemaExtensionItem **at_extensions; Extensions
|
| |
+ * } LDAPAttributeType;
|
| |
+ */
|
| |
|
| |
+ /*
|
| |
+ * Set the appropriate error code
|
| |
+ */
|
| |
if (schema_ds4x_compat) {
|
| |
- keyword_strstr_fn = PL_strcasestr;
|
| |
invalid_syntax_error = LDAP_OPERATIONS_ERROR;
|
| |
} else {
|
| |
- keyword_strstr_fn = PL_strstr;
|
| |
invalid_syntax_error = LDAP_INVALID_SYNTAX;
|
| |
}
|
| |
-
|
| |
- flags = 0;
|
| |
- pOcOid = pOcSup = pOcDesc = NULL;
|
| |
-
|
| |
- if (NULL == input || '\0' == input[0]) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc, NULL,
|
| |
- "One or more values are required for the objectClasses attribute");
|
| |
- slapi_log_err(SLAPI_LOG_ERR, "read_oc_ldif", "NULL args passed to read_oc_ldif\n");
|
| |
- return read_oc_ldif_return(LDAP_OPERATIONS_ERROR, pOcOid, psbOcName,
|
| |
- pOcSup, pOcDesc);
|
| |
- }
|
| |
-
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the OID */
|
| |
- if (NULL == (pOcOid = get_tagged_oid("(", &nextinput,
|
| |
- keyword_strstr_fn))) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc,
|
| |
- input, "Value is malformed. It must include a \"(\"");
|
| |
- return read_oc_ldif_return(invalid_syntax_error, pOcOid, psbOcName,
|
| |
- pOcSup, pOcDesc);
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat || (strcasecmp(pOcOid, "NAME") == 0))
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the NAME */
|
| |
- if ((pstart = (*keyword_strstr_fn)(nextinput, "NAME '")) != NULL) {
|
| |
- pstart += 6;
|
| |
- sizedbuffer_allocate(psbOcName, strlen(pstart) + 1);
|
| |
- if (sscanf(pstart, "%s", psbOcName->buffer) > 0) {
|
| |
- /* strip the trailing single quote */
|
| |
- if (psbOcName->buffer[strlen(psbOcName->buffer) - 1] == '\'') {
|
| |
- psbOcName->buffer[strlen(psbOcName->buffer) - 1] = '\0';
|
| |
- nextinput = pstart + strlen(psbOcName->buffer) + 1;
|
| |
- } else {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc,
|
| |
- input, "Value is malformed. It must include a single quote around"
|
| |
- " the name");
|
| |
- return read_oc_ldif_return(invalid_syntax_error, pOcOid, psbOcName,
|
| |
- pOcSup, pOcDesc);
|
| |
- }
|
| |
- }
|
| |
- } else {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_oc,
|
| |
- input, "Value is malformed. It must include a \"NAME '\"");
|
| |
- return read_oc_ldif_return(invalid_syntax_error, pOcOid, psbOcName,
|
| |
- pOcSup, pOcDesc);
|
| |
+ /*
|
| |
+ * Verify we have input
|
| |
+ */
|
| |
+ if (input == NULL || '\0' == input[0]) {
|
| |
+ schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, NULL,
|
| |
+ "One or more values are required for the attributeTypes attribute");
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, "parse_attr_str", "NULL args passed to parse_attr_str\n");
|
| |
+ return invalid_syntax_error;
|
| |
}
|
| |
-
|
| |
/*
|
| |
- ** if the objectclass ldif doesn't have an OID, we'll make the oid
|
| |
- ** ocname-oid
|
| |
- */
|
| |
- if (strcasecmp(pOcOid, "NAME") == 0) {
|
| |
- slapi_ch_free_string(&pOcOid);
|
| |
- pOcOid = slapi_ch_smprintf("%s-oid", psbOcName->buffer);
|
| |
+ * Parse the line and create of attribute structure
|
| |
+ */
|
| |
+ while (isspace(*input)) {
|
| |
+ /* trim any leading spaces */
|
| |
+ input++;
|
| |
+ }
|
| |
+ if ((atype = ldap_str2attributetype(input, &rc, &errp, (const unsigned int)parser_flags)) == NULL) {
|
| |
+ schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, input,
|
| |
+ "Failed to parse attribute, error(%d - %s) at (%s)", rc, ldap_scherr2str(rc), errp);
|
| |
+ return invalid_syntax_error;
|
| |
}
|
| |
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for an optional DESCription */
|
| |
- if ((pstart = (*keyword_strstr_fn)(nextinput, " DESC '")) != NULL) {
|
| |
- pstart += 7;
|
| |
- if ((pend = strchr(pstart, '\'')) == NULL) {
|
| |
- pend = (char *)(pstart + strlen(pstart));
|
| |
+ if (schema_flags & DSE_SCHEMA_NO_GLOCK) {
|
| |
+ flags |= SLAPI_ATTR_FLAG_NOLOCKING;
|
| |
+ }
|
| |
+ /*
|
| |
+ * Check the NAME and update our name list
|
| |
+ */
|
| |
+ if (NULL != atype->at_names) {
|
| |
+ for (; atype->at_names[num_names]; num_names++) {
|
| |
+ charray_add(&attr_names, slapi_ch_strdup(atype->at_names[num_names]));
|
| |
}
|
| |
- pOcDesc = slapi_ch_malloc(pend - pstart + 1);
|
| |
- memcpy(pOcDesc, pstart, pend - pstart);
|
| |
- pOcDesc[pend - pstart] = '\0';
|
| |
- nextinput = pend + 1;
|
| |
+ first_attr_name = atype->at_names[0];
|
| |
+ } else { /* NAME followed by nothing violates syntax */
|
| |
+ schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, input,
|
| |
+ "Missing or invalid attribute name");
|
| |
+ status = invalid_syntax_error;
|
| |
+ goto done;
|
| |
}
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional OBSOLETE marker */
|
| |
- flags |= get_flag_keyword(schema_obsolete_with_spaces,
|
| |
- OC_FLAG_OBSOLETE, &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
|
| |
- oc_lock_read(); /* needed because we access the superior oc */
|
| |
+ /*
|
| |
+ * If the attribute type doesn't have an OID, we'll make the oid attrname-oid.
|
| |
+ */
|
| |
+ if (NULL == atype->at_oid) {
|
| |
+ atype->at_oid = slapi_ch_smprintf("%s-oid", first_attr_name);
|
| |
}
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
/*
|
| |
- * Look for the superior objectclass. We first look for a parenthesized
|
| |
- * list and if not found we look for a simple OID.
|
| |
- *
|
| |
- * XXXmcs: Since we do not yet support multiple superior objectclasses, we
|
| |
- * just grab the first OID in a parenthesized list.
|
| |
- */
|
| |
- if (NULL == (pOcSup = get_tagged_oid(" SUP (", &nextinput,
|
| |
- keyword_strstr_fn))) {
|
| |
- pOcSup = get_tagged_oid(" SUP ", &nextinput, keyword_strstr_fn);
|
| |
+ * Set the flags
|
| |
+ */
|
| |
+ if (atype->at_obsolete) {
|
| |
+ flags |= SLAPI_ATTR_FLAG_OBSOLETE;
|
| |
}
|
| |
- psup_oc = oc_find_nolock(pOcSup, NULL, PR_FALSE);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional kind (ABSTRACT, STRUCTURAL, AUXILIARY) */
|
| |
- for (i = 0; i < SCHEMA_OC_KIND_COUNT; ++i) {
|
| |
- if (NULL != (pstart = (*keyword_strstr_fn)(nextinput,
|
| |
- schema_oc_kind_strings_with_spaces[i]))) {
|
| |
- kind = i;
|
| |
- nextinput = pstart + strlen(schema_oc_kind_strings_with_spaces[i]) - 1;
|
| |
- break;
|
| |
- }
|
| |
+ if (atype->at_single_value) {
|
| |
+ flags |= SLAPI_ATTR_FLAG_SINGLE;
|
| |
}
|
| |
- if (i >= SCHEMA_OC_KIND_COUNT) { /* not found */
|
| |
- if (NULL != psup_oc && OC_KIND_ABSTRACT != psup_oc->oc_kind) {
|
| |
- /* inherit kind from superior class if not ABSTRACT */
|
| |
- kind = psup_oc->oc_kind;
|
| |
- } else {
|
| |
- /* according to RFC 2252, the default is structural */
|
| |
- kind = OC_KIND_STRUCTURAL;
|
| |
- }
|
| |
+ if (atype->at_collective) {
|
| |
+ flags |= SLAPI_ATTR_FLAG_COLLECTIVE;
|
| |
}
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for required attributes (MUST) */
|
| |
- if ((pstart = (*keyword_strstr_fn)(nextinput, " MUST ")) != NULL) {
|
| |
- char *pRequiredAttrs;
|
| |
- int saw_open_paren = 0;
|
| |
-
|
| |
- pstart += 6;
|
| |
- pstart = skipWS(pstart); /* skip past any extra white space */
|
| |
- if (*pstart == '(') {
|
| |
- saw_open_paren = 1;
|
| |
- ++pstart;
|
| |
- }
|
| |
- pRequiredAttrs = slapi_ch_strdup(pstart);
|
| |
- if (saw_open_paren && (pend = strchr(pRequiredAttrs, ')')) != NULL) {
|
| |
- *pend = '\0';
|
| |
- } else if ((pend = strchr(pRequiredAttrs, ' ')) != NULL) {
|
| |
- *pend = '\0';
|
| |
- } else {
|
| |
- pend = pRequiredAttrs + strlen(pRequiredAttrs); /* at end of string */
|
| |
- }
|
| |
- nextinput = pstart + (pend - pRequiredAttrs);
|
| |
- RequiredAttrsArray = read_dollar_values(pRequiredAttrs);
|
| |
- slapi_ch_free((void **)&pRequiredAttrs);
|
| |
- } else {
|
| |
- RequiredAttrsArray = (char **)slapi_ch_malloc(1 * sizeof(char *));
|
| |
- RequiredAttrsArray[0] = NULL;
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for allowed attributes (MAY) */
|
| |
- if ((pstart = (*keyword_strstr_fn)(nextinput, " MAY ")) != NULL) {
|
| |
- char *pAllowedAttrs;
|
| |
- int saw_open_paren = 0;
|
| |
-
|
| |
- pstart += 5;
|
| |
- pstart = skipWS(pstart); /* skip past any extra white space */
|
| |
- if (*pstart == '(') {
|
| |
- saw_open_paren = 1;
|
| |
- ++pstart;
|
| |
- }
|
| |
- pAllowedAttrs = slapi_ch_strdup(pstart);
|
| |
- if (saw_open_paren && (pend = strchr(pAllowedAttrs, ')')) != NULL) {
|
| |
- *pend = '\0';
|
| |
- } else if ((pend = strchr(pAllowedAttrs, ' ')) != NULL) {
|
| |
- *pend = '\0';
|
| |
- } else {
|
| |
- pend = pAllowedAttrs + strlen(pAllowedAttrs); /* at end of string */
|
| |
- }
|
| |
- nextinput = pstart + (pend - pAllowedAttrs);
|
| |
- AllowedAttrsArray = read_dollar_values(pAllowedAttrs);
|
| |
- slapi_ch_free((void **)&pAllowedAttrs);
|
| |
- } else {
|
| |
- AllowedAttrsArray = (char **)slapi_ch_malloc(1 * sizeof(char *));
|
| |
- AllowedAttrsArray[0] = NULL;
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for X-ORIGIN list */
|
| |
- if (is_user_defined) {
|
| |
- /* add X-ORIGIN 'user defined' */
|
| |
- extensions = parse_extensions(nextinput, schema_user_defined_origin);
|
| |
- flags |= OC_FLAG_USER_OC;
|
| |
- } else {
|
| |
- /* add nothing */
|
| |
- extensions = parse_extensions(nextinput, NULL);
|
| |
- flags |= OC_FLAG_STANDARD_OC;
|
| |
- }
|
| |
-
|
| |
- /* generate OrigRequiredAttrsArray and OrigAllowedAttrsArray */
|
| |
- if (psup_oc) {
|
| |
- int found_it;
|
| |
-
|
| |
- OrigRequiredAttrsArray = (char **)slapi_ch_malloc(1 * sizeof(char *));
|
| |
- OrigRequiredAttrsArray[0] = NULL;
|
| |
- OrigAllowedAttrsArray = (char **)slapi_ch_malloc(1 * sizeof(char *));
|
| |
- OrigAllowedAttrsArray[0] = NULL;
|
| |
-
|
| |
- if (psup_oc->oc_required) {
|
| |
- for (i = 0; RequiredAttrsArray[i]; i++) {
|
| |
- for (j = 0, found_it = 0; psup_oc->oc_required[j]; j++) {
|
| |
- if (strcasecmp(psup_oc->oc_required[j], RequiredAttrsArray[i]) == 0) {
|
| |
- found_it = 1;
|
| |
- }
|
| |
- }
|
| |
- if (!found_it) {
|
| |
- charray_add(&OrigRequiredAttrsArray, slapi_ch_strdup(RequiredAttrsArray[i]));
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
- if (psup_oc->oc_allowed) {
|
| |
- for (i = 0; AllowedAttrsArray[i]; i++) {
|
| |
- for (j = 0, found_it = 0; psup_oc->oc_allowed[j]; j++) {
|
| |
- if (strcasecmp(psup_oc->oc_allowed[j], AllowedAttrsArray[i]) == 0) {
|
| |
- found_it = 1;
|
| |
- }
|
| |
- }
|
| |
- if (!found_it) {
|
| |
- charray_add(&OrigAllowedAttrsArray, slapi_ch_strdup(AllowedAttrsArray[i]));
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
- } else {
|
| |
- /* if no parent oc */
|
| |
- OrigRequiredAttrsArray = charray_dup(RequiredAttrsArray);
|
| |
- OrigAllowedAttrsArray = charray_dup(AllowedAttrsArray);
|
| |
- }
|
| |
-
|
| |
- if (!(schema_flags & DSE_SCHEMA_NO_GLOCK)) {
|
| |
- oc_unlock(); /* we are done accessing superior oc (psup_oc) */
|
| |
- }
|
| |
-
|
| |
- /* finally -- create new objclass structure */
|
| |
- pnew_oc = (struct objclass *)slapi_ch_malloc(1 * sizeof(struct objclass));
|
| |
- pnew_oc->oc_name = slapi_ch_strdup(psbOcName->buffer);
|
| |
- pnew_oc->oc_superior = pOcSup;
|
| |
- pOcSup = NULL; /* don't free this later */
|
| |
- pnew_oc->oc_oid = pOcOid;
|
| |
- pOcOid = NULL; /* don't free this later */
|
| |
- pnew_oc->oc_desc = pOcDesc;
|
| |
- pOcDesc = NULL; /* don't free this later */
|
| |
- pnew_oc->oc_required = RequiredAttrsArray;
|
| |
- pnew_oc->oc_allowed = AllowedAttrsArray;
|
| |
- pnew_oc->oc_orig_required = OrigRequiredAttrsArray;
|
| |
- pnew_oc->oc_orig_allowed = OrigAllowedAttrsArray;
|
| |
- pnew_oc->oc_extensions = extensions;
|
| |
- pnew_oc->oc_next = NULL;
|
| |
- pnew_oc->oc_flags = flags;
|
| |
- pnew_oc->oc_kind = kind;
|
| |
-
|
| |
- *oc = pnew_oc;
|
| |
-
|
| |
- return read_oc_ldif_return(LDAP_SUCCESS, pOcOid, psbOcName, pOcSup, pOcDesc);
|
| |
- }
|
| |
-
|
| |
- static char **
|
| |
- read_dollar_values(char *vals)
|
| |
- {
|
| |
- int i, k;
|
| |
- char **retVal;
|
| |
- static const char *charsToRemove = " ()";
|
| |
-
|
| |
- /* get rid of all the parens and spaces */
|
| |
- for (i = 0, k = 0; vals[i]; i++) {
|
| |
- if (!strchr(charsToRemove, vals[i])) {
|
| |
- vals[k++] = vals[i];
|
| |
- }
|
| |
- }
|
| |
- vals[k] = '\0';
|
| |
- retVal = slapi_str2charray(vals, "$");
|
| |
- return retVal;
|
| |
- }
|
| |
-
|
| |
- /*
|
| |
- * if asipp is NULL, the attribute type is added to the global set of schema.
|
| |
- * if asipp is not NULL, the AT is not added but *asipp is set. When you are
|
| |
- * finished with *asipp, use attr_syntax_free() to dispose of it.
|
| |
- *
|
| |
- * schema_flags: Any or none of the following bits could be set
|
| |
- * DSE_SCHEMA_NO_CHECK -- schema won't be checked
|
| |
- * DSE_SCHEMA_NO_GLOCK -- locking of global resources is turned off;
|
| |
- * this saves time during initialization since
|
| |
- * the server operates in single threaded mode
|
| |
- * at that time or in reload_schemafile_lock.
|
| |
- * DSE_SCHEMA_LOCKED -- already locked with reload_schemafile_lock;
|
| |
- * no further lock needed
|
| |
- *
|
| |
- * if is_user_defined is true, force attribute type to be user defined.
|
| |
- *
|
| |
- * returns an LDAP error code (LDAP_SUCCESS if all goes well)
|
| |
- */
|
| |
- static int
|
| |
- read_at_ldif(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote)
|
| |
- {
|
| |
- char *pStart, *pEnd;
|
| |
- char *pOid, *pSyntax, *pSuperior, *pMREquality, *pMROrdering, *pMRSubstring;
|
| |
- const char *nextinput;
|
| |
- struct sizedbuffer *psbAttrName = sizedbuffer_construct(BUFSIZ);
|
| |
- struct sizedbuffer *psbAttrDesc = sizedbuffer_construct(BUFSIZ);
|
| |
- int status = 0;
|
| |
- int syntaxlength;
|
| |
- char **attr_names = NULL;
|
| |
- char *first_attr_name = NULL;
|
| |
- int num_names = 0;
|
| |
- unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
|
| |
- const char *ss = 0;
|
| |
- struct asyntaxinfo *tmpasip;
|
| |
- int invalid_syntax_error;
|
| |
- schema_strstr_fn_t keyword_strstr_fn;
|
| |
- schemaext *extensions = NULL;
|
| |
-
|
| |
- /*
|
| |
- * From RFC 2252 section 4.2:
|
| |
- *
|
| |
- * AttributeTypeDescription = "(" whsp
|
| |
- * numericoid whsp ; AttributeType identifier
|
| |
- * [ "NAME" qdescrs ] ; name used in AttributeType
|
| |
- * [ "DESC" qdstring ] ; description
|
| |
- * [ "OBSOLETE" whsp ]
|
| |
- * [ "SUP" woid ] ; derived from this other
|
| |
- * ; AttributeType
|
| |
- * [ "EQUALITY" woid ; Matching Rule name
|
| |
- * [ "ORDERING" woid ; Matching Rule name
|
| |
- * [ "SUBSTR" woid ] ; Matching Rule name
|
| |
- * [ "SYNTAX" whsp noidlen whsp ] ; see section 4.3
|
| |
- * [ "SINGLE-VALUE" whsp ] ; default multi-valued
|
| |
- * [ "COLLECTIVE" whsp ] ; default not collective
|
| |
- * [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
|
| |
- * [ "USAGE" whsp AttributeUsage ]; default userApplications
|
| |
- * whsp ")"
|
| |
- *
|
| |
- * AttributeUsage =
|
| |
- * "userApplications" /
|
| |
- * "directoryOperation" /
|
| |
- * "distributedOperation" / ; DSA-shared
|
| |
- * "dSAOperation" ; DSA-specific, value depends on server
|
| |
- *
|
| |
- * XXXmcs: Our parsing technique is poor. In (Netscape) DS 4.12 and earlier
|
| |
- * releases, parsing was mostly done by looking anywhere within the input
|
| |
- * string for various keywords such as "EQUALITY". But if, for example, a
|
| |
- * description contains the word "equality", the parser would take assume
|
| |
- * that the token following the word was a matching rule. Bad news.
|
| |
- *
|
| |
- * In iDS 5.0 and later, we parse in order left to right and advance a
|
| |
- * pointer as we consume the input string (the nextinput variable). We
|
| |
- * also use a case-insensitive search when looking for keywords such as
|
| |
- * DESC. This is still less than ideal.
|
| |
- *
|
| |
- * Someday soon we will need to write a real parser.
|
| |
- *
|
| |
- * Compatibility notes: if schema_ds4x_compat is set, we:
|
| |
- * 1. always parse from the beginning of the string
|
| |
- * 2. use a case-insensitive compare when looking for keywords, e.g., DESC
|
| |
- */
|
| |
-
|
| |
- if (schema_ds4x_compat) {
|
| |
- keyword_strstr_fn = PL_strcasestr;
|
| |
- invalid_syntax_error = LDAP_OPERATIONS_ERROR;
|
| |
- } else {
|
| |
- keyword_strstr_fn = PL_strstr;
|
| |
- invalid_syntax_error = LDAP_INVALID_SYNTAX;
|
| |
- }
|
| |
-
|
| |
- if (schema_flags & DSE_SCHEMA_NO_GLOCK)
|
| |
- flags |= SLAPI_ATTR_FLAG_NOLOCKING;
|
| |
-
|
| |
- psbAttrName->buffer[0] = '\0';
|
| |
- psbAttrDesc->buffer[0] = '\0';
|
| |
- pOid = pSyntax = pSuperior = NULL;
|
| |
- pMREquality = pMROrdering = pMRSubstring = NULL;
|
| |
- syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
|
| |
-
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* get the OID */
|
| |
- pOid = get_tagged_oid("(", &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (NULL == pOid) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- input, "Missing or invalid OID");
|
| |
- status = invalid_syntax_error;
|
| |
- goto done;
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat || (strcasecmp(pOid, "NAME") == 0))
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the NAME (single or list of names) */
|
| |
- if ((pStart = (*keyword_strstr_fn)(nextinput, "NAME ")) != NULL) {
|
| |
- pStart += 5;
|
| |
- sizedbuffer_allocate(psbAttrName, strlen(pStart) + 1);
|
| |
- strcpy(psbAttrName->buffer, pStart);
|
| |
- if (*pStart == '(')
|
| |
- pEnd = strchr(psbAttrName->buffer, ')');
|
| |
- else
|
| |
- pEnd = strchr(psbAttrName->buffer + 1, '\'');
|
| |
- if (pEnd)
|
| |
- *(pEnd + 1) = 0;
|
| |
- nextinput = pStart + strlen(psbAttrName->buffer) + 1;
|
| |
- attr_names = parse_qdescrs(psbAttrName->buffer, &num_names);
|
| |
- if (NULL != attr_names) {
|
| |
- first_attr_name = attr_names[0];
|
| |
- } else { /* NAME followed by nothing violates syntax */
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- input, "Missing or invalid attribute name");
|
| |
- status = invalid_syntax_error;
|
| |
- goto done;
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /*
|
| |
- * if the attribute ldif doesn't have an OID, we'll make the oid
|
| |
- * attrname-oid
|
| |
- */
|
| |
- if ((strcasecmp(pOid, "NAME") == 0) && (first_attr_name)) {
|
| |
- slapi_ch_free_string(&pOid);
|
| |
- pOid = slapi_ch_smprintf("%s-oid", first_attr_name);
|
| |
- }
|
| |
-
|
| |
- /* look for the optional DESCription */
|
| |
- if ((pStart = (*keyword_strstr_fn)(nextinput, "DESC '")) != NULL) {
|
| |
- pStart += 6;
|
| |
- sizedbuffer_allocate(psbAttrDesc, strlen(pStart) + 1);
|
| |
- strcpy(psbAttrDesc->buffer, pStart);
|
| |
- if ((pEnd = strchr(psbAttrDesc->buffer, '\'')) != NULL) {
|
| |
- *pEnd = '\0';
|
| |
- }
|
| |
- nextinput = pStart + strlen(psbAttrDesc->buffer) + 1;
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional OBSOLETE marker */
|
| |
- flags |= get_flag_keyword(schema_obsolete_with_spaces,
|
| |
- SLAPI_ATTR_FLAG_OBSOLETE, &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional SUPerior type */
|
| |
- pSuperior = get_tagged_oid("SUP ", &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional matching rules */
|
| |
- pMREquality = get_tagged_oid("EQUALITY ", &nextinput, keyword_strstr_fn);
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
- pMROrdering = get_tagged_oid("ORDERING ", &nextinput, keyword_strstr_fn);
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
- pMRSubstring = get_tagged_oid("SUBSTR ", &nextinput, keyword_strstr_fn);
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional SYNTAX */
|
| |
- if (NULL != (pSyntax = get_tagged_oid("SYNTAX ", &nextinput,
|
| |
- keyword_strstr_fn))) {
|
| |
- /*
|
| |
- * Check for an optional {LEN}, which if present indicates a
|
| |
- * suggested maximum size for values of this attribute type.
|
| |
- *
|
| |
- * XXXmcs: we do not enforce length restrictions, but we do read
|
| |
- * and include them in the subschemasubentry.
|
| |
- */
|
| |
- if ((pEnd = strchr(pSyntax, '{')) != NULL /* balance } */) {
|
| |
- *pEnd = '\0';
|
| |
- syntaxlength = atoi(pEnd + 1);
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional SINGLE-VALUE marker */
|
| |
- flags |= get_flag_keyword(" SINGLE-VALUE ",
|
| |
- SLAPI_ATTR_FLAG_SINGLE, &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional COLLECTIVE marker */
|
| |
- flags |= get_flag_keyword(schema_collective_with_spaces,
|
| |
- SLAPI_ATTR_FLAG_COLLECTIVE, &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional NO-USER-MODIFICATION marker */
|
| |
- flags |= get_flag_keyword(schema_nousermod_with_spaces,
|
| |
- SLAPI_ATTR_FLAG_NOUSERMOD, &nextinput, keyword_strstr_fn);
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* look for the optional USAGE */
|
| |
- if (NULL != (ss = (*keyword_strstr_fn)(nextinput, " USAGE "))) {
|
| |
- ss += 7;
|
| |
- ss = skipWS(ss);
|
| |
- if (ss) {
|
| |
- if (!PL_strncmp(ss, "directoryOperation",
|
| |
- strlen("directoryOperation"))) {
|
| |
- flags |= SLAPI_ATTR_FLAG_OPATTR;
|
| |
- }
|
| |
- if (!PL_strncmp(ss, "distributedOperation",
|
| |
- strlen("distributedOperation"))) {
|
| |
- flags |= SLAPI_ATTR_FLAG_OPATTR | SLAPI_ATTR_FLAG_DISTRIBUTED_OPERATION;
|
| |
- }
|
| |
- if (!PL_strncmp(ss, "dSAOperation",
|
| |
- strlen("dSAOperation"))) {
|
| |
- flags |= SLAPI_ATTR_FLAG_OPATTR | SLAPI_ATTR_FLAG_DSA_OPERATION;
|
| |
- }
|
| |
- if (NULL == (nextinput = strchr(ss, ' '))) {
|
| |
- nextinput = ss + strlen(ss);
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (schema_ds4x_compat)
|
| |
- nextinput = input;
|
| |
-
|
| |
- /* X-ORIGIN list */
|
| |
- if (is_user_defined) {
|
| |
- /* add X-ORIGIN 'user defined' */
|
| |
- extensions = parse_extensions(nextinput, schema_user_defined_origin);
|
| |
- } else {
|
| |
- /* add nothing extra*/
|
| |
- extensions = parse_extensions(nextinput, NULL);
|
| |
- flags |= SLAPI_ATTR_FLAG_STD_ATTR;
|
| |
- }
|
| |
-
|
| |
- /* Do some sanity checking to make sure everything was read correctly */
|
| |
-
|
| |
- if (NULL == pOid) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- first_attr_name, "Missing OID");
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
- if (!status && (!attr_names || !num_names)) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- first_attr_name,
|
| |
- "Missing name (OID is \"%s\")", pOid);
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
-
|
| |
- if (!status && (NULL != pSuperior)) {
|
| |
- struct asyntaxinfo *asi_parent;
|
| |
-
|
| |
- asi_parent = attr_syntax_get_by_name(pSuperior, schema_flags);
|
| |
- /* if we find no match then server won't start or add the attribute type */
|
| |
- if (asi_parent == NULL) {
|
| |
- slapi_log_err(SLAPI_LOG_PARSE, "read_at_ldif",
|
| |
- "Cannot find parent attribute type \"%s\"\n", pSuperior);
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "Missing parent attribute syntax OID");
|
| |
- status = invalid_syntax_error;
|
| |
- /* We only want to use the parent syntax if a SYNTAX
|
| |
- * wasn't explicitly specified for this attribute. */
|
| |
- } else if ((NULL == pSyntax) || (NULL == pMREquality) || (NULL == pMRSubstring) ||
|
| |
- (NULL == pMROrdering)) {
|
| |
- char *pso = asi_parent->asi_plugin->plg_syntax_oid;
|
| |
-
|
| |
- if (pso && (NULL == pSyntax)) {
|
| |
- pSyntax = slapi_ch_strdup(pso);
|
| |
- slapi_log_err(SLAPI_LOG_TRACE, "read_at_ldif",
|
| |
- "Inheriting syntax %s from parent type %s\n",
|
| |
- pSyntax, pSuperior);
|
| |
- } else if (NULL == pSyntax) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "Missing parent attribute syntax OID");
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
-
|
| |
- if (NULL == pMREquality) {
|
| |
- pMREquality = slapi_ch_strdup(asi_parent->asi_mr_equality);
|
| |
- }
|
| |
- if (NULL == pMRSubstring) {
|
| |
- pMRSubstring = slapi_ch_strdup(asi_parent->asi_mr_substring);
|
| |
- }
|
| |
- if (NULL == pMROrdering) {
|
| |
- pMROrdering = slapi_ch_strdup(asi_parent->asi_mr_ordering);
|
| |
- }
|
| |
- attr_syntax_return(asi_parent);
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (!status && (NULL == pSyntax)) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- first_attr_name, "Missing attribute syntax OID");
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
-
|
| |
- if (!status && (plugin_syntax_find(pSyntax) == NULL)) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at,
|
| |
- first_attr_name, "Unknown attribute syntax OID \"%s\"",
|
| |
- pSyntax);
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
-
|
| |
- if (!status) {
|
| |
- struct objclass *poc;
|
| |
- /* check to make sure that the OID isn't being used by an objectclass */
|
| |
- if (!(schema_flags & DSE_SCHEMA_LOCKED))
|
| |
- oc_lock_read();
|
| |
- poc = oc_find_oid_nolock(pOid);
|
| |
- if (poc != NULL) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "The OID \"%s\" is also used by the object class \"%s\"",
|
| |
- pOid, poc->oc_name);
|
| |
- status = LDAP_TYPE_OR_VALUE_EXISTS;
|
| |
- }
|
| |
- if (!(schema_flags & DSE_SCHEMA_LOCKED))
|
| |
- oc_unlock();
|
| |
- }
|
| |
-
|
| |
- if (!(schema_flags & DSE_SCHEMA_NO_CHECK) && !status) {
|
| |
- int ii;
|
| |
- /* check to see if the attribute name is valid */
|
| |
- for (ii = 0; !status && (ii < num_names); ++ii) {
|
| |
- if (schema_check_name(attr_names[ii], PR_TRUE, errorbuf,
|
| |
- errorbufsize) == 0) {
|
| |
- status = invalid_syntax_error;
|
| |
- } else if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
|
| |
- attr_syntax_exists(attr_names[ii])) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, attr_names[ii],
|
| |
- "Could not be added because it already exists");
|
| |
- status = LDAP_TYPE_OR_VALUE_EXISTS;
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (!(schema_flags & DSE_SCHEMA_NO_CHECK) && !status) {
|
| |
- if (schema_check_oid(first_attr_name, pOid, PR_TRUE, errorbuf,
|
| |
- errorbufsize) == 0) {
|
| |
- status = invalid_syntax_error;
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- if (!status) {
|
| |
- struct asyntaxinfo *tmpasi;
|
| |
-
|
| |
- if (!(flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
|
| |
- (NULL != (tmpasi = attr_syntax_get_by_oid(pOid, schema_flags)))) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "Could not be added because the OID \"%s\" is already in use",
|
| |
- pOid);
|
| |
- status = LDAP_TYPE_OR_VALUE_EXISTS;
|
| |
- attr_syntax_return(tmpasi);
|
| |
- }
|
| |
- }
|
| |
-
|
| |
-
|
| |
- if (!status) {
|
| |
- status = attr_syntax_create(pOid, attr_names,
|
| |
- *psbAttrDesc->buffer == '\0' ? NULL : psbAttrDesc->buffer,
|
| |
- pSuperior, pMREquality, pMROrdering, pMRSubstring, extensions,
|
| |
- pSyntax, syntaxlength, flags, &tmpasip);
|
| |
- }
|
| |
-
|
| |
- if (!status) {
|
| |
- if (NULL != asipp) {
|
| |
- *asipp = tmpasip; /* just return it */
|
| |
- } else { /* add the new attribute to the global store */
|
| |
- status = attr_syntax_add(tmpasip, schema_flags);
|
| |
- if (LDAP_SUCCESS != status) {
|
| |
- if (0 != (flags & SLAPI_ATTR_FLAG_OVERRIDE) &&
|
| |
- LDAP_TYPE_OR_VALUE_EXISTS == status) {
|
| |
- /*
|
| |
- * This can only occur if the name and OID don't match the
|
| |
- * attribute we are trying to override (all other cases of
|
| |
- * "type or value exists" were trapped above).
|
| |
- */
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "Does not match the OID \"%s\". Another attribute"
|
| |
- " type is already using the name or OID.",
|
| |
- pOid);
|
| |
- } else {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize,
|
| |
- schema_errprefix_at, first_attr_name,
|
| |
- "Could not be added (OID is \"%s\")", pOid);
|
| |
- }
|
| |
- attr_syntax_free(tmpasip);
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- done:
|
| |
- /* free everything */
|
| |
- free_qdlist(attr_names, num_names);
|
| |
- sizedbuffer_destroy(psbAttrName);
|
| |
- sizedbuffer_destroy(psbAttrDesc);
|
| |
- slapi_ch_free((void **)&pOid);
|
| |
- slapi_ch_free((void **)&pSuperior);
|
| |
- slapi_ch_free((void **)&pMREquality);
|
| |
- slapi_ch_free((void **)&pMROrdering);
|
| |
- slapi_ch_free((void **)&pMRSubstring);
|
| |
- slapi_ch_free((void **)&pSyntax);
|
| |
- schema_free_extensions(extensions);
|
| |
- return status;
|
| |
- }
|
| |
-
|
| |
- #else /* (USE_OPENLDAP) */
|
| |
-
|
| |
-
|
| |
- /* openldap attribute parser */
|
| |
- /*
|
| |
- * if asipp is NULL, the attribute type is added to the global set of schema.
|
| |
- * if asipp is not NULL, the AT is not added but *asipp is set. When you are
|
| |
- * finished with *asipp, use attr_syntax_free() to dispose of it.
|
| |
- *
|
| |
- * schema_flags: Any or none of the following bits could be set
|
| |
- * DSE_SCHEMA_NO_CHECK -- schema won't be checked
|
| |
- * DSE_SCHEMA_NO_GLOCK -- locking of global resources is turned off;
|
| |
- * this saves time during initialization since
|
| |
- * the server operates in single threaded mode
|
| |
- * at that time or in reload_schemafile_lock.
|
| |
- * DSE_SCHEMA_LOCKED -- already locked with reload_schemafile_lock;
|
| |
- * no further lock needed
|
| |
- *
|
| |
- * if is_user_defined is true, force attribute type to be user defined.
|
| |
- *
|
| |
- * returns an LDAP error code (LDAP_SUCCESS if all goes well)
|
| |
- */
|
| |
- static int
|
| |
- parse_attr_str(const char *input, struct asyntaxinfo **asipp, char *errorbuf, size_t errorbufsize, PRUint32 schema_flags, int is_user_defined, int schema_ds4x_compat, int is_remote __attribute__((unused)))
|
| |
- {
|
| |
- struct asyntaxinfo *tmpasip;
|
| |
- struct asyntaxinfo *tmpasi;
|
| |
- schemaext *extensions = NULL, *head = NULL;
|
| |
- struct objclass *poc;
|
| |
- LDAPAttributeType *atype = NULL;
|
| |
- const char *errp;
|
| |
- char *first_attr_name = NULL;
|
| |
- char **attr_names = NULL;
|
| |
- unsigned long flags = SLAPI_ATTR_FLAG_OVERRIDE;
|
| |
- /* If we ever accept openldap schema directly, then make parser_flags configurable */
|
| |
- unsigned int parser_flags = LDAP_SCHEMA_ALLOW_NONE | LDAP_SCHEMA_ALLOW_NO_OID;
|
| |
- int invalid_syntax_error;
|
| |
- int syntaxlength = SLAPI_SYNTAXLENGTH_NONE;
|
| |
- int num_names = 0;
|
| |
- int status = 0;
|
| |
- int rc = 0;
|
| |
- int a, aa;
|
| |
-
|
| |
- if (config_get_enquote_sup_oc()) {
|
| |
- parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
| |
- } else if (getenv("LDAP_SCHEMA_ALLOW_QUOTED")) {
|
| |
- char ebuf[SLAPI_DSE_RETURNTEXT_SIZE];
|
| |
- parser_flags |= LDAP_SCHEMA_ALLOW_QUOTED;
|
| |
- if (config_set_enquote_sup_oc(CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, "on", ebuf, CONFIG_APPLY)) {
|
| |
- slapi_log_err(SLAPI_LOG_ERR, "parse_attr_str", "Failed to enable %s: %s\n",
|
| |
- CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, ebuf);
|
| |
- }
|
| |
- }
|
| |
-
|
| |
- /*
|
| |
- * OpenLDAP AttributeType struct
|
| |
- *
|
| |
- * typedef struct ldap_attributetype {
|
| |
- * char *at_oid; OID
|
| |
- * char **at_names; Names
|
| |
- * char *at_desc; Description
|
| |
- * int at_obsolete; Is obsolete?
|
| |
- * char *at_sup_oid; OID of superior type
|
| |
- * char *at_equality_oid; OID of equality matching rule
|
| |
- * char *at_ordering_oid; OID of ordering matching rule
|
| |
- * char *at_substr_oid; OID of substrings matching rule
|
| |
- * char *at_syntax_oid; OID of syntax of values
|
| |
- * int at_syntax_len; Suggested minimum maximum length
|
| |
- * int at_single_value; Is single-valued?
|
| |
- * int at_collective; Is collective?
|
| |
- * int at_no_user_mod; Are changes forbidden through LDAP?
|
| |
- * int at_usage; Usage, see below
|
| |
- * LDAPSchemaExtensionItem **at_extensions; Extensions
|
| |
- * } LDAPAttributeType;
|
| |
- */
|
| |
-
|
| |
- /*
|
| |
- * Set the appropriate error code
|
| |
- */
|
| |
- if (schema_ds4x_compat) {
|
| |
- invalid_syntax_error = LDAP_OPERATIONS_ERROR;
|
| |
- } else {
|
| |
- invalid_syntax_error = LDAP_INVALID_SYNTAX;
|
| |
- }
|
| |
- /*
|
| |
- * Verify we have input
|
| |
- */
|
| |
- if (input == NULL || '\0' == input[0]) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, NULL,
|
| |
- "One or more values are required for the attributeTypes attribute");
|
| |
- slapi_log_err(SLAPI_LOG_ERR, "parse_attr_str", "NULL args passed to parse_attr_str\n");
|
| |
- return invalid_syntax_error;
|
| |
- }
|
| |
- /*
|
| |
- * Parse the line and create of attribute structure
|
| |
- */
|
| |
- while (isspace(*input)) {
|
| |
- /* trim any leading spaces */
|
| |
- input++;
|
| |
- }
|
| |
- if ((atype = ldap_str2attributetype(input, &rc, &errp, (const unsigned int)parser_flags)) == NULL) {
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, input,
|
| |
- "Failed to parse attribute, error(%d - %s) at (%s)", rc, ldap_scherr2str(rc), errp);
|
| |
- return invalid_syntax_error;
|
| |
- }
|
| |
-
|
| |
- if (schema_flags & DSE_SCHEMA_NO_GLOCK) {
|
| |
- flags |= SLAPI_ATTR_FLAG_NOLOCKING;
|
| |
- }
|
| |
- /*
|
| |
- * Check the NAME and update our name list
|
| |
- */
|
| |
- if (NULL != atype->at_names) {
|
| |
- for (; atype->at_names[num_names]; num_names++) {
|
| |
- charray_add(&attr_names, slapi_ch_strdup(atype->at_names[num_names]));
|
| |
- }
|
| |
- first_attr_name = atype->at_names[0];
|
| |
- } else { /* NAME followed by nothing violates syntax */
|
| |
- schema_create_errormsg(errorbuf, errorbufsize, schema_errprefix_at, input,
|
| |
- "Missing or invalid attribute name");
|
| |
- status = invalid_syntax_error;
|
| |
- goto done;
|
| |
- }
|
| |
- /*
|
| |
- * If the attribute type doesn't have an OID, we'll make the oid attrname-oid.
|
| |
- */
|
| |
- if (NULL == atype->at_oid) {
|
| |
- atype->at_oid = slapi_ch_smprintf("%s-oid", first_attr_name);
|
| |
- }
|
| |
- /*
|
| |
- * Set the flags
|
| |
- */
|
| |
- if (atype->at_obsolete) {
|
| |
- flags |= SLAPI_ATTR_FLAG_OBSOLETE;
|
| |
- }
|
| |
- if (atype->at_single_value) {
|
| |
- flags |= SLAPI_ATTR_FLAG_SINGLE;
|
| |
- }
|
| |
- if (atype->at_collective) {
|
| |
- flags |= SLAPI_ATTR_FLAG_COLLECTIVE;
|
| |
- }
|
| |
- if (atype->at_no_user_mod) {
|
| |
- flags |= SLAPI_ATTR_FLAG_NOUSERMOD;
|
| |
+ if (atype->at_no_user_mod) {
|
| |
+ flags |= SLAPI_ATTR_FLAG_NOUSERMOD;
|
| |
}
|
| |
if (atype->at_usage == LDAP_SCHEMA_DIRECTORY_OPERATION) {
|
| |
flags |= SLAPI_ATTR_FLAG_OPATTR;
|
| |
@@ -4724,7 +3689,6 @@
|
| |
|
| |
return rc;
|
| |
}
|
| |
- #endif
|
| |
|
| |
/*
|
| |
* schema_check_oc_attrs:
|
| |
@@ -5265,15 +4229,9 @@
|
| |
checking during initialization; this will be overridden when
|
| |
its "real" definition is read from the schema conf files */
|
| |
|
| |
- #ifdef USE_OPENLDAP
|
| |
attr_str = "( 2.5.4.0 NAME 'objectClass' "
|
| |
"DESC 'Standard schema for LDAP' SYNTAX "
|
| |
"1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )";
|
| |
- #else
|
| |
- attr_str = "attributeTypes: ( 2.5.4.0 NAME 'objectClass' "
|
| |
- "DESC 'Standard schema for LDAP' SYNTAX "
|
| |
- "1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 2252' )";
|
| |
- #endif
|
| |
if (schema_flags & DSE_SCHEMA_NO_LOAD) {
|
| |
struct asyntaxinfo *tmpasip = NULL;
|
| |
rc = parse_at_str(attr_str, &tmpasip, errorbuf, sizeof(errorbuf),
|
| |
@@ -5365,242 +4323,6 @@
|
| |
return rc;
|
| |
}
|
| |
|
| |
- #if !defined(USE_OPENLDAP)
|
| |
-
|
| |
- static char **
|
| |
- parse_xstring_list(const char *schema_value, const char *name, size_t namelen, int *num_xvalsp, char **default_list)
|
| |
- {
|
| |
- char *start, *end, *xval_tmp;
|
| |
- char **xvals = NULL;
|
| |
-
|
| |
- if ((start = PL_strstr(schema_value, name)) != NULL) {
|
| |
- start += namelen + 1; /* +1 for space */
|
| |
- xval_tmp = slapi_ch_strdup(start);
|
| |
- if (*start == '(') {
|
| |
- end = strchr(xval_tmp, ')');
|
| |
- } else {
|
| |
- end = strchr(xval_tmp + 1, '\'');
|
| |
- }
|
| |
- if (end) {
|
| |
- *(end + 1) = 0;
|
| |
- }
|
| |
- xvals = parse_qdstrings(xval_tmp, num_xvalsp);
|
| |
- slapi_ch_free((void **)&xval_tmp);
|
| |
- } else {
|
| |
- xvals = NULL;
|
| |
- *num_xvalsp = 0;
|
| |
- }
|
| |
-
|
| |
- if (NULL == xvals && NULL != default_list) {
|
| |
- int i;
|
| |
-
|
| |
- for (i = 0; default_list[i] != NULL; ++i) {
|
| |
- ;
|
| |
- }
|
| |
- *num_xvalsp = i;
|
| |
- xvals = (char **)slapi_ch_malloc((i + 1) * sizeof(char *));
|
| |
- for (i = 0; default_list[i] != NULL; ++i) {
|
| |
- xvals[i] = slapi_ch_strdup(default_list[i]);
|
| |
- }
|
| |
- xvals[i] = NULL;
|
| |
- }
|
| |
-
|
| |
- /* for debugging
|
| |
- if ( xvals == NULL || xvals[0] == NULL ) {
|
| |
- slapi_log_err(SLAPI_LOG_ERR, "no xstring values for xstring (%s) in (%s)\n", name, schema_value, 0 );
|
| |
- }
|
| |
- */
|
| |
-
|
| |
- return xvals;
|
| |
- }
|
| |
-
|
| |
- /* used by mozldap read_at_ldif() & read_oc_ldif() */
|
| |
- static schemaext *
|
| |
- parse_extensions(const char *schema_value, char **default_list)
|
| |
- {
|
| |
- schemaext *extensions = NULL, *head = NULL;
|
| |
- char *input, *token, *iter = NULL;
|
| |
- int i;
|
| |
-
|
| |
- /*
|
| |
- * First make a copy of the input, then grab all the "X-" words,
|
| |
- * and extract the values.
|
| |
- */
|
| |
- input = slapi_ch_strdup(schema_value);
|
| |
- token = ldap_utf8strtok_r(input, " ", &iter);
|
| |
- while (token) {
|
| |
- if (strncmp(token, "X-", 2) == 0) {
|
| |
- /* we have a new extension */
|
| |
- schemaext *newext;
|
| |
- newext = (schemaext *)slapi_ch_calloc(1, sizeof(schemaext));
|
| |
- newext->term = slapi_ch_strdup(token);
|
| |
- newext->values = parse_xstring_list(schema_value, token, strlen(token), &newext->value_count, default_list);
|
| |
- if (extensions == NULL) {
|
| |
- extensions = newext;
|
| |
- head = newext;
|
| |
- } else {
|
| |
- extensions->next = newext;
|
| |
- extensions = extensions->next;
|
| |
- }
|
| |
- }
|
| |
- token = ldap_utf8strtok_r(iter, " ", &iter);
|
| |
- }
|
| |
- extensions = head;
|
| |
- /*
|
| |
- * Ok, if X-ORIGIN was not specified, then add it with the default values
|
| |
- */
|
| |
- if (!extension_is_user_defined(extensions) && default_list) {
|
| |
- int added = 0;
|
| |
- while (extensions) {
|
| |
- if (strcmp(extensions->term, "X-ORIGIN") == 0) {
|
| |
- charray_add(&extensions->values, slapi_ch_strdup(default_list[0]));
|
| |
- extensions->value_count++;
|
| |
- added = 1;
|
| |
- extensions = head;
|
| |
- break;
|
| |
- }
|
| |
- extensions = extensions->next;
|
| |
- }
|
| |
- if (!added) {
|
| |
- schemaext *newext = (schemaext *)slapi_ch_calloc(1, sizeof(schemaext));
|
| |
- newext->term = slapi_ch_strdup("X-ORIGIN");
|
| |
- for (i = 0; default_list[i]; ++i) {
|
| |
- newext->value_count++;
|
| |
- charray_add(&newext->values, slapi_ch_strdup(default_list[i]));
|
| |
- }
|
| |
- extensions = head;
|
| |
- while (extensions && extensions->next) {
|
| |
- /* move to the end of the list */
|
| |
- extensions = extensions->next;
|
| |
- }
|
| |
- if (extensions == NULL) {
|
| |
- extensions = newext;
|
| |
- } else {
|
| |
- extensions->next = newext;
|
| |
- }
|
| |
- }
|
| |
- }
|
| |
- slapi_ch_free_string(&input);
|
| |
-
|
| |
- return extensions;
|
| |
- }
|
| |
-
|
| |
- /*
|
| |
- * Look for `keyword' within `*inputp' and return the flag_value if found
|
| |
- * (zero if returned if not found).
|
| |
- *
|
| |
- * If the keyword is found, `*inputp' is set to point just beyond the end of
|
| |
- * the keyword. If the keyword is not found, `*inputp' is not changed.
|
| |
- *
|
| |
- * The `strstr_fn' function pointer is used to search for `keyword', e.g., it
|
| |
- * could be PL_strcasestr().
|
| |
- *
|
| |
- * The string passed in `keyword' MUST include a trailing space, e.g.,
|
| |
- *
|
| |
- * flag |= get_flag_keyword( " COLLECTIVE ", SLAPI_ATTR_FLAG_COLLECTIVE,
|
| |
- * &input, PL_strcasestr );
|
| |
- *
|
| |
- */
|
| |
- static int
|
| |
- get_flag_keyword(const char *keyword, int flag_value, const char **inputp, schema_strstr_fn_t strstr_fn)
|
| |
- {
|
| |
- const char *kw;
|
| |
-
|
| |
- PR_ASSERT(NULL != inputp);
|
| |
- PR_ASSERT(NULL != *inputp);
|
| |
- PR_ASSERT(' ' == keyword[strlen(keyword) - 1]);
|
| |
-
|
| |
- if (NULL == strstr_fn) {
|
| |
- strstr_fn = PL_strcasestr;
|
| |
- }
|
| |
-
|
| |
- kw = (*strstr_fn)(*inputp, keyword);
|
| |
- if (NULL == kw) {
|
| |
- flag_value = 0; /* not found -- return no value */
|
| |
- } else {
|
| |
- *inputp = kw + strlen(keyword) - 1; /* advance input */
|
| |
- }
|
| |
-
|
| |
- return flag_value;
|
| |
- }
|
| |
-
|
| |
- /*
|
| |
- * Look for `tag' within `*inputp' and return the OID string following `tag'.
|
| |
- * If the OID has single quotes around it they are removed (they are allowed
|
| |
- * for compatibility with DS 3.x and 4.x).
|
| |
- *
|
| |
- * If the tag is found, `*inputp' is set to point just beyond the end of
|
| |
- * the OID that was extracted and returned. If the tag is not found,
|
| |
- * `*inputp' is not changed.
|
| |
- *
|
| |
- * The `strstr_fn' function pointer is used to search for `tag', e.g., it
|
| |
- * could be PL_strcasestr().
|
| |
- *
|
| |
- * The string passed in `tag' SHOULD generally include a trailing space, e.g.,
|
| |
- *
|
| |
- * pSuperior = get_tagged_oid( "SUP ", &input, PL_strcasestr );
|
| |
- *
|
| |
- * The exception to this is when the tag contains '(' as a trailing character.
|
| |
- * This is used to process lists of oids, such as the following:
|
| |
- *
|
| |
- * SUP (inetOrgPerson $ testUser)
|
| |
- *
|
| |
- * A malloc'd string is returned if `tag; is found and NULL if not.
|
| |
- */
|
| |
- static char *
|
| |
- get_tagged_oid(const char *tag, const char **inputp, schema_strstr_fn_t strstr_fn)
|
| |
- {
|
| |
- const char *startp, *endp;
|
| |
- char *oid;
|
| |
-
|
| |
- PR_ASSERT(NULL != inputp);
|
| |
- PR_ASSERT(NULL != *inputp);
|
| |
- PR_ASSERT(NULL != tag);
|
| |
- PR_ASSERT('\0' != tag[0]);
|
| |
- if ('(' != tag[0])
|
| |
- PR_ASSERT((' ' == tag[strlen(tag) - 1]) || ('(' == tag[strlen(tag) - 1]));
|
| |
-
|
| |
- if (NULL == strstr_fn) {
|
| |
- strstr_fn = PL_strcasestr;
|
| |
- }
|
| |
-
|
| |
- oid = NULL;
|
| |
- if (NULL != (startp = (*strstr_fn)(*inputp, tag))) {
|
| |
- startp += strlen(tag);
|
| |
-
|
| |
- /* skip past any extra white space */
|
| |
- if (NULL == (startp = skipWS(startp))) {
|
| |
- return (NULL);
|
| |
- }
|
| |
-
|
| |
- /* skip past the leading single quote, if present */
|
| |
- if (*startp == '\'') {
|
| |
- ++startp;
|
| |
- /* skip past any extra white space */
|
| |
- startp = skipWS(startp);
|
| |
- }
|
| |
-
|
| |
- /* locate the end of the OID */
|
| |
- if ((NULL != (endp = strchr(startp, ' '))) ||
|
| |
- (NULL != (endp = strchr(startp, ')')))) {
|
| |
- if ('\'' == *(endp - 1) && endp > startp) {
|
| |
- --endp; /* ignore trailing quote */
|
| |
- }
|
| |
- } else {
|
| |
- endp = startp + strlen(startp); /* remainder of input */
|
| |
- }
|
| |
-
|
| |
- oid = slapi_ch_malloc(endp - startp + 1);
|
| |
- memcpy(oid, startp, endp - startp);
|
| |
- oid[endp - startp] = '\0';
|
| |
- *inputp = endp;
|
| |
- }
|
| |
-
|
| |
- return (oid);
|
| |
- }
|
| |
-
|
| |
- #endif
|
| |
-
|
| |
/*
|
| |
* sprintf to `outp' the contents of `tag' followed by `oid' followed by a
|
| |
* trailing space. If enquote is non-zero, single quotes are included
|
| |
Bug Description:
We haven't been supporting MozLDAP for a long time. In fact, it is not possible
to build without OpenLDAP as MozLDAP specifics were not maintained properly.
Fix Description:
Remove all MozLDAP-only features from the code.
Fixes https://pagure.io/389-ds-base/issue/49730
Author: mhonek
Review by: ???