From 016f3326242f76bd32d13b366950f1b68385b804 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 10 Jan 2004 04:54:24 +0000 Subject: [PATCH] Add some sample plugins --- contrib/slapd-modules/dsaschema/README | 20 + contrib/slapd-modules/dsaschema/dsaschema.c | 432 ++++++++++++++++++ contrib/slapi-plugins/addrdnvalues/README | 11 + .../slapi-plugins/addrdnvalues/addrdnvalues.c | 100 ++++ 4 files changed, 563 insertions(+) create mode 100644 contrib/slapd-modules/dsaschema/README create mode 100644 contrib/slapd-modules/dsaschema/dsaschema.c create mode 100644 contrib/slapi-plugins/addrdnvalues/README create mode 100644 contrib/slapi-plugins/addrdnvalues/addrdnvalues.c diff --git a/contrib/slapd-modules/dsaschema/README b/contrib/slapd-modules/dsaschema/README new file mode 100644 index 0000000000..bdce6f818b --- /dev/null +++ b/contrib/slapd-modules/dsaschema/README @@ -0,0 +1,20 @@ + +This directory contains a native slapd plugin, dsaschema, that permits the +loading of DSA-specific schema from configuration files (including operational +attributes). + +To use the plugin, add: + +moduleload libdsaschema-plugin.so + /etc/openldap/schema/foo1.schema + ...etc... + /etc/openldap/schema/fooN.schema + +to your slapd configuration file. + +No Makefile is provided. Use a command line similar to: + +gcc -shared -I../../../include -Wall -g -o libdsaschema-plugin.so dsaschema.c + +to compile this plugin. + diff --git a/contrib/slapd-modules/dsaschema/dsaschema.c b/contrib/slapd-modules/dsaschema/dsaschema.c new file mode 100644 index 0000000000..9467145683 --- /dev/null +++ b/contrib/slapd-modules/dsaschema/dsaschema.c @@ -0,0 +1,432 @@ +/* $Id: dsaschema.c,v 1.4 2004/01/09 06:47:01 lukeh Exp $ */ +/* + * Copyright 2004 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 + * . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 +#include + +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 \" 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; + } + memcpy( next, next + 1, strlen( next + 1 ) + 1 ); + break; + + case '\\': + if ( next[1] ) + 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'; +} + diff --git a/contrib/slapi-plugins/addrdnvalues/README b/contrib/slapi-plugins/addrdnvalues/README new file mode 100644 index 0000000000..cff74fd72c --- /dev/null +++ b/contrib/slapi-plugins/addrdnvalues/README @@ -0,0 +1,11 @@ + +This directory contains a SLAPI plugin, addrdnvalues, which will add to +an entry any attribute values that appear in the entry's RDN but not in +the entry. This is necessary for compliance with some "broken" clients. + +No Makefile is provided. Use a command line similar to: + +gcc -shared -I../../../include -Wall -g -o libaddrdnvalues-plugin.so addrdnvalues.c + +to compile this plugin. + diff --git a/contrib/slapi-plugins/addrdnvalues/addrdnvalues.c b/contrib/slapi-plugins/addrdnvalues/addrdnvalues.c new file mode 100644 index 0000000000..243c4c9a3f --- /dev/null +++ b/contrib/slapi-plugins/addrdnvalues/addrdnvalues.c @@ -0,0 +1,100 @@ +/* + * Copyright 2003-2004 PADL Software Pty Ltd. + * 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 + * . + */ +/* (C) Copyright PADL Software Pty Ltd. 2003 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that this notice is preserved + * and that due credit is given to PADL Software Pty Ltd. This software + * is provided ``as is'' without express or implied warranty. + */ + +#include +#include + +#include +#include + +#include + +int addrdnvalues_preop_init(Slapi_PBlock *pb); + +static Slapi_PluginDesc pluginDescription = { + "addrdnvalues-plugin", + "PADL", + "1.0", + "RDN values addition plugin" +}; + +static int addrdnvalues_preop_add(Slapi_PBlock *pb) +{ + int rc; + Slapi_Entry *e; + char *szDN; + LDAPDN dn; + int i; + + if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, "addrdnvalues_preop_add", + "Error retrieving target entry\n"); + return -1; + } + + szDN = slapi_entry_get_dn(e); + rc = ldap_str2dn(szDN, &dn, LDAP_DN_FORMAT_LDAPV3); + if (rc != LDAP_SUCCESS) { + slapi_send_ldap_result(pb, rc, NULL, NULL, 0, NULL); + slapi_log_error(SLAPI_LOG_PLUGIN, "addrdnvalues_preop_add", "%s\n", ldap_err2string(rc)); + return -1; + } + + if (dn[0] != NULL) { + LDAPRDN rdn = dn[0]; + + for (i = 0; rdn[i] != NULL; i++) { + LDAPAVA *ava = &rdn[0][i]; + struct berval *vals[2]; + Slapi_Attr *a = NULL; + + /* 0 means attr exists */ + if (slapi_entry_attr_find(e, ava->la_attr.bv_val, &a) == 0 && + a != NULL && + slapi_attr_value_find(a, &ava->la_value) == 0) + { + /* RDN in entry */ + continue; + } /* else RDN not in entry */ + + vals[0] = &ava->la_value; + vals[1] = NULL; + + slapi_entry_attr_merge(e, ava->la_attr.bv_val, vals); + } + } + + ldap_dnfree(dn); + + return 0; +} + +int addrdnvalues_preop_init(Slapi_PBlock *pb) +{ + if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &pluginDescription) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void *)addrdnvalues_preop_add) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, "addrdnvalues_preop_init", + "Error registering %s\n", pluginDescription.spd_description); + return -1; + } + + return 0; +} + -- 2.39.5