diff options
Diffstat (limited to 'contrib/slapd-modules/dsaschema/dsaschema.c')
-rw-r--r-- | contrib/slapd-modules/dsaschema/dsaschema.c | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/contrib/slapd-modules/dsaschema/dsaschema.c b/contrib/slapd-modules/dsaschema/dsaschema.c new file mode 100644 index 0000000..fa8d07c --- /dev/null +++ b/contrib/slapd-modules/dsaschema/dsaschema.c @@ -0,0 +1,438 @@ +/* dsaschema.c */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 2004-2021 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ + +#include <portable.h> + +#include <ac/string.h> +#include <ac/ctype.h> +#include <ac/signal.h> +#include <ac/errno.h> +#include <ac/stdlib.h> +#include <ac/ctype.h> +#include <ac/time.h> +#include <ac/unistd.h> + +#include <stdio.h> + +/* + * Schema reader that allows us to define DSA schema (including + * operational attributes and non-user object classes) + * + * A kludge, at best, and in order to avoid including slapd + * headers we use fprintf() rather than slapd's native logging, + * which may confuse users... + * + */ + +#include <ldap.h> +#include <ldap_schema.h> + +extern int at_add(LDAPAttributeType *at, const char **err); +extern int oc_add(LDAPObjectClass *oc, int user, const char **err); +extern int cr_add(LDAPContentRule *cr, int user, const char **err); + +#define ARGS_STEP 512 + +static char *fp_getline(FILE *fp, int *lineno); +static void fp_getline_init(int *lineno); +static int fp_parse_line(int lineno, char *line); +static char *strtok_quote( char *line, char *sep ); + +static char **cargv = NULL; +static int cargv_size = 0; +static int cargc = 0; +static char *strtok_quote_ptr; + +int init_module(int argc, char *argv[]); + +static int dsaschema_parse_at(const char *fname, int lineno, char *line, char **argv) +{ + LDAPAttributeType *at; + int code; + const char *err; + + at = ldap_str2attributetype(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL); + if (!at) { + fprintf(stderr, "%s: line %d: %s before %s\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + if (at->at_oid == NULL) { + fprintf(stderr, "%s: line %d: attributeType has no OID\n", + fname, lineno); + return 1; + } + + code = at_add(at, &err); + if (code) { + fprintf(stderr, "%s: line %d: %s: \"%s\"\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + ldap_memfree(at); + + return 0; +} + +static int dsaschema_parse_oc(const char *fname, int lineno, char *line, char **argv) +{ + LDAPObjectClass *oc; + int code; + const char *err; + + oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL); + if (!oc) { + fprintf(stderr, "%s: line %d: %s before %s\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + if (oc->oc_oid == NULL) { + fprintf(stderr, + "%s: line %d: objectclass has no OID\n", + fname, lineno); + return 1; + } + + code = oc_add(oc, 0, &err); + if (code) { + fprintf(stderr, "%s: line %d: %s: \"%s\"\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + ldap_memfree(oc); + return 0; +} + +static int dsaschema_parse_cr(const char *fname, int lineno, char *line, char **argv) +{ + LDAPContentRule *cr; + int code; + const char *err; + + cr = ldap_str2contentrule(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL); + if (!cr) { + fprintf(stderr, "%s: line %d: %s before %s\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + if (cr->cr_oid == NULL) { + fprintf(stderr, + "%s: line %d: objectclass has no OID\n", + fname, lineno); + return 1; + } + + code = cr_add(cr, 0, &err); + if (code) { + fprintf(stderr, "%s: line %d: %s: \"%s\"\n", + fname, lineno, ldap_scherr2str(code), err); + return 1; + } + + ldap_memfree(cr); + return 0; +} + +static int dsaschema_read_config(const char *fname, int depth) +{ + FILE *fp; + char *line, *savefname, *saveline; + int savelineno, lineno; + int rc; + + if (depth == 0) { + cargv = calloc(ARGS_STEP + 1, sizeof(*cargv)); + if (cargv == NULL) { + return 1; + } + cargv_size = ARGS_STEP + 1; + } + + fp = fopen(fname, "r"); + if (fp == NULL) { + fprintf(stderr, "could not open config file \"%s\": %s (%d)\n", + fname, strerror(errno), errno); + return 1; + } + fp_getline_init(&lineno); + + while ((line = fp_getline(fp, &lineno)) != NULL) { + /* skip comments and blank lines */ + if (line[0] == '#' || line[0] == '\0') { + continue; + } + + saveline = strdup(line); + if (saveline == NULL) { + return 1; + } + + if (fp_parse_line(lineno, line) != 0) { + return 1; + } + + if (cargc < 1) { + continue; + } + + if (strcasecmp(cargv[0], "attributetype") == 0 || + strcasecmp(cargv[0], "attribute") == 0) { + if (cargc < 2) { + fprintf(stderr, "%s: line %d: illegal attribute type format\n", + fname, lineno); + return 1; + } else if (*cargv[1] == '(' /*')'*/) { + char *p; + + p = strchr(saveline, '(' /*')'*/); + rc = dsaschema_parse_at(fname, lineno, p, cargv); + if (rc != 0) + return rc; + } else { + fprintf(stderr, "%s: line %d: old attribute type format not supported\n", + fname, lineno); + } + } else if (strcasecmp(cargv[0], "ditcontentrule") == 0) { + char *p; + p = strchr(saveline, '(' /*')'*/); + rc = dsaschema_parse_cr(fname, lineno, p, cargv); + if (rc != 0) + return rc; + } else if (strcasecmp(cargv[0], "objectclass") == 0) { + if (cargc < 2) { + fprintf(stderr, "%s: line %d: illegal objectclass format\n", + fname, lineno); + return 1; + } else if (*cargv[1] == '(' /*')'*/) { + char *p; + + p = strchr(saveline, '(' /*')'*/); + rc = dsaschema_parse_oc(fname, lineno, p, cargv); + if (rc != 0) + return rc; + } else { + fprintf(stderr, "%s: line %d: object class format not supported\n", + fname, lineno); + } + } else if (strcasecmp(cargv[0], "include") == 0) { + if (cargc < 2) { + fprintf(stderr, "%s: line %d: missing file name in \"include <filename>\" line", + fname, lineno); + return 1; + } + savefname = strdup(cargv[1]); + if (savefname == NULL) { + return 1; + } + if (dsaschema_read_config(savefname, depth + 1) != 0) { + return 1; + } + free(savefname); + lineno = savelineno - 1; + } else { + fprintf(stderr, "%s: line %d: unknown directive \"%s\" (ignored)\n", + fname, lineno, cargv[0]); + } + } + + fclose(fp); + + if (depth == 0) + free(cargv); + + return 0; +} + +int init_module(int argc, char *argv[]) +{ + int i; + int rc; + + for (i = 0; i < argc; i++) { + rc = dsaschema_read_config(argv[i], 0); + if (rc != 0) { + break; + } + } + + return rc; +} + + +static int +fp_parse_line( + int lineno, + char *line +) +{ + char * token; + + cargc = 0; + token = strtok_quote( line, " \t" ); + + if ( strtok_quote_ptr ) { + *strtok_quote_ptr = ' '; + } + + if ( strtok_quote_ptr ) { + *strtok_quote_ptr = '\0'; + } + + for ( ; token != NULL; token = strtok_quote( NULL, " \t" ) ) { + if ( cargc == cargv_size - 1 ) { + char **tmp; + tmp = realloc( cargv, (cargv_size + ARGS_STEP) * + sizeof(*cargv) ); + if ( tmp == NULL ) { + return -1; + } + cargv = tmp; + cargv_size += ARGS_STEP; + } + cargv[cargc++] = token; + } + cargv[cargc] = NULL; + return 0; +} + +static char * +strtok_quote( char *line, char *sep ) +{ + int inquote; + char *tmp; + static char *next; + + strtok_quote_ptr = NULL; + if ( line != NULL ) { + next = line; + } + while ( *next && strchr( sep, *next ) ) { + next++; + } + + if ( *next == '\0' ) { + next = NULL; + return( NULL ); + } + tmp = next; + + for ( inquote = 0; *next; ) { + switch ( *next ) { + case '"': + if ( inquote ) { + inquote = 0; + } else { + inquote = 1; + } + AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 ); + break; + + case '\\': + if ( next[1] ) + AC_MEMCPY( next, + next + 1, strlen( next + 1 ) + 1 ); + next++; /* dont parse the escaped character */ + break; + + default: + if ( ! inquote ) { + if ( strchr( sep, *next ) != NULL ) { + strtok_quote_ptr = next; + *next++ = '\0'; + return( tmp ); + } + } + next++; + break; + } + } + + return( tmp ); +} + +static char buf[BUFSIZ]; +static char *line; +static size_t lmax, lcur; + +#define CATLINE( buf ) \ + do { \ + size_t len = strlen( buf ); \ + while ( lcur + len + 1 > lmax ) { \ + lmax += BUFSIZ; \ + line = (char *) realloc( line, lmax ); \ + } \ + strcpy( line + lcur, buf ); \ + lcur += len; \ + } while( 0 ) + +static char * +fp_getline( FILE *fp, int *lineno ) +{ + char *p; + + lcur = 0; + CATLINE( buf ); + (*lineno)++; + + /* hack attack - keeps us from having to keep a stack of bufs... */ + if ( strncasecmp( line, "include", 7 ) == 0 ) { + buf[0] = '\0'; + return( line ); + } + + while ( fgets( buf, sizeof(buf), fp ) != NULL ) { + /* trim off \r\n or \n */ + if ( (p = strchr( buf, '\n' )) != NULL ) { + if( p > buf && p[-1] == '\r' ) --p; + *p = '\0'; + } + + /* trim off trailing \ and append the next line */ + if ( line[ 0 ] != '\0' + && (p = line + strlen( line ) - 1)[ 0 ] == '\\' + && p[ -1 ] != '\\' ) { + p[ 0 ] = '\0'; + lcur--; + + } else { + if ( ! isspace( (unsigned char) buf[0] ) ) { + return( line ); + } + + /* change leading whitespace to a space */ + buf[0] = ' '; + } + + CATLINE( buf ); + (*lineno)++; + } + buf[0] = '\0'; + + return( line[0] ? line : NULL ); +} + +static void +fp_getline_init( int *lineno ) +{ + *lineno = -1; + buf[0] = '\0'; +} + |