#49579 Support certmap features and slapi_v4 api
Closed 3 years ago by spichugi. Opened 6 years ago by firstyear.
firstyear/389-ds-base 49218-certmap-plugin-latest  into  master

file modified
+30 -31
@@ -153,7 +153,8 @@ 

  # WARNING: This needs a clean up, because slap.h is a horrible mess and is publically exposed!

  DSPLUGIN_CPPFLAGS = $(DS_DEFINES) $(DS_INCLUDES) $(PATH_DEFINES) $(SYSTEMD_DEFINES) @openldap_inc@ $(NSS_CFLAGS) $(NSPR_INCLUDES) $(SYSTEMD_CFLAGS)

  # This should give access to internal headers only for tests!!!

- DSINTERNAL_CPPFLAGS = -I$(srcdir)/include/ldaputil

+ # DSINTERNAL_CPPFLAGS = -I$(srcdir)/include/ldaputil

+ DSINTERNAL_CPPFLAGS =

  # Flags for Datastructure Library

  SDS_CPPFLAGS = $(SDS_INCLUDES) $(NSPR_INCLUDES)

  
@@ -367,7 +368,7 @@ 

  # based on defines

  # ----------------------------------------------------------------------------------------

  

- server_LTLIBRARIES = libsds.la libslapd.la libldaputil.la libns-dshttpd.la librewriters.la

+ server_LTLIBRARIES = libsds.la libslapd.la libns-dshttpd.la librewriters.la

  

  lib_LTLIBRARIES = libsvrcore.la

  
@@ -402,6 +403,7 @@ 

  

  serverplugin_LTLIBRARIES = libacl-plugin.la \

  	libaddn-plugin.la \

+ 	libcertmap-plugin.la \

  	libattr-unique-plugin.la \

  	libautomember-plugin.la libback-ldbm.la libchainingdb-plugin.la \

  	libcollation-plugin.la libcos-plugin.la libderef-plugin.la \
@@ -438,14 +440,6 @@ 

  	include/base/systems.h \

  	include/base/systhr.h \

  	include/base/util.h \

- 	include/ldaputil/cert.h \

- 	include/ldaputil/certmap.h \

- 	include/ldaputil/dbconf.h \

- 	include/ldaputil/encode.h \

- 	include/ldaputil/errors.h \

- 	include/ldaputil/init.h \

- 	include/ldaputil/ldapauth.h \

- 	include/ldaputil/ldaputil.h \

  	include/libaccess/aclerror.h \

  	include/libaccess/acleval.h \

  	include/libaccess/aclglobal.h \
@@ -554,7 +548,10 @@ 

  	ldap/servers/slapd/slapi_pal.h \

  	ldap/servers/slapd/slapi-plugin-compat4.h \

  	ldap/servers/slapd/slapi-plugin.h \

+ 	ldap/servers/slapd/slapi-plugin-v4.h \

  	ldap/servers/slapd/slapi-private.h \

+ 	ldap/servers/slapd/slapi-private-v4.h \

+ 	ldap/servers/slapd/slapi-internal-v4.h \

  	ldap/servers/slapd/snmp_collator.h \

  	ldap/servers/slapd/sslerrstrs.h \

  	ldap/servers/slapd/statechange.h \
@@ -588,7 +585,6 @@ 

  	ldap/systools/pio.h \

  	lib/base/lexer_pvt.h \

  	lib/base/plist_pvt.h \

- 	lib/ldaputil/ldaputili.h \

  	lib/libaccess/access_plhash.h \

  	lib/libaccess/aclcache.h \

  	lib/libaccess/aclpriv.h \
@@ -960,6 +956,7 @@ 

  serverinc_HEADERS = ldap/servers/plugins/replication/repl-session-plugin.h \

  	ldap/servers/slapd/slapi_pal.h \

  	ldap/servers/slapd/slapi-plugin.h \

+ 	ldap/servers/slapd/slapi-plugin-v4.h \

  	ldap/servers/plugins/replication/winsync-plugin.h \

  	src/libsds/include/sds.h

  
@@ -1142,22 +1139,6 @@ 

  libavl_a_SOURCES = ldap/libraries/libavl/avl.c

  libavl_a_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS)

  

- #------------------------

- # libldaputil

- #------------------------

- libldaputil_la_SOURCES = lib/ldaputil/cert.c \

- 	lib/ldaputil/certmap.c \

- 	lib/ldaputil/dbconf.c \

- 	lib/ldaputil/encode.c \

- 	lib/ldaputil/errors.c \

- 	lib/ldaputil/init.c \

- 	lib/ldaputil/ldapauth.c \

- 	lib/ldaputil/vtable.c

- 

- libldaputil_la_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS) $(DSINTERNAL_CPPFLAGS) -I$(srcdir)/lib/ldaputil

- libldaputil_la_LIBADD = libslapd.la $(NSS_LINK) $(NSPR_LINK)

- libldaputil_la_LDFLAGS = $(AM_LDFLAGS)

- 

  #////////////////////////////////////////////////////////////////

  #

  #   Dynamic Server Libraries
@@ -1447,8 +1428,8 @@ 

  	lib/libsi18n/reshash.c \

  	lib/libsi18n/txtfile.c

  

- libns_dshttpd_la_CPPFLAGS = -I$(srcdir)/include/base $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS) -I$(srcdir)/lib/ldaputil

- libns_dshttpd_la_LIBADD = libslapd.la libldaputil.la $(LDAPSDK_LINK) $(SASL_LINK) $(NSS_LINK) $(NSPR_LINK)

+ libns_dshttpd_la_CPPFLAGS = -I$(srcdir)/include/base $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS)

+ libns_dshttpd_la_LIBADD = libslapd.la $(LDAPSDK_LINK) $(SASL_LINK) $(NSS_LINK) $(NSPR_LINK)

  # Mark that this is a per version library.

  libns_dshttpd_la_LDFLAGS = -release @PACKAGE_VERSION@

  
@@ -1467,6 +1448,8 @@ 

  	ldap/servers/slapd/backend_manager.c \

  	ldap/servers/slapd/bitset.c \

  	ldap/servers/slapd/bulk_import.c \

+ 	ldap/servers/slapd/bvarray_v4.c \

+ 	ldap/servers/slapd/cert_v4.c \

  	ldap/servers/slapd/charray.c \

  	ldap/servers/slapd/ch_malloc.c \

  	ldap/servers/slapd/computed.c \
@@ -1510,7 +1493,9 @@ 

  	ldap/servers/slapd/opshared.c \

  	ldap/servers/slapd/pagedresults.c \

  	ldap/servers/slapd/pblock.c \

+ 	ldap/servers/slapd/pblock_v4.c \

  	ldap/servers/slapd/plugin.c \

+ 	ldap/servers/slapd/plugin_v4.c \

  	ldap/servers/slapd/plugin_acl.c \

  	ldap/servers/slapd/plugin_mmr.c \

  	ldap/servers/slapd/plugin_internal_op.c \
@@ -1533,6 +1518,8 @@ 

  	ldap/servers/slapd/security_wrappers.c \

  	ldap/servers/slapd/slapd_plhash.c \

  	ldap/servers/slapd/slapi_counter.c \

+ 	ldap/servers/slapd/slapi-plugin-v4.c \

+ 	ldap/servers/slapd/slapi-private-v4.c \

  	ldap/servers/slapd/slapi2nspr.c \

  	ldap/servers/slapd/snmp_collator.c \

  	ldap/servers/slapd/sort.c \
@@ -1547,6 +1534,7 @@ 

  	ldap/servers/slapd/utf8.c \

  	ldap/servers/slapd/utf8compare.c \

  	ldap/servers/slapd/util.c \

+ 	ldap/servers/slapd/upgrade.c \

  	ldap/servers/slapd/uuid.c \

  	ldap/servers/slapd/value.c \

  	ldap/servers/slapd/valueset.c \
@@ -1701,6 +1689,16 @@ 

  libaddn_plugin_la_LDFLAGS = -avoid-version

  

  #------------------------

+ # libcertmap-plugin

+ #------------------------

+ libcertmap_plugin_la_SOURCES = ldap/servers/plugins/certmap/certmap.c

+ 

+ libcertmap_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS)

+ libcertmap_plugin_la_LIBADD = libslapd.la $(NSPR_LINK) $(PCRE_LINK)

+ libcertmap_plugin_la_DEPENDENCIES = libslapd.la

+ libcertmap_plugin_la_LDFLAGS = -avoid-version

+ 

+ #------------------------

  # librootdn-access-plugin

  #------------------------

  #
@@ -2286,13 +2284,14 @@ 

  	$(GETSOCKETPEER)

  

  ns_slapd_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS) $(SASL_CFLAGS) $(SVRCORE_INCLUDES)

- ns_slapd_LDADD = libslapd.la libldaputil.la libsvrcore.la $(LDAPSDK_LINK) $(NSS_LINK) $(LIBADD_DL) \

+ ns_slapd_LDADD = libslapd.la libsvrcore.la $(LDAPSDK_LINK) $(NSS_LINK) $(LIBADD_DL) \

  	$(NSPR_LINK) $(SASL_LINK) $(LIBNSL) $(LIBSOCKET) $(THREADLIB) $(SYSTEMD_LIBS) $(EVENT_LINK)

  if RUST_ENABLE

  ns_slapd_LDADD += $(RNSSLAPD_LIB)

  ns_slapd_CPPFLAGS += -lssl -lcrypto

  endif

- ns_slapd_DEPENDENCIES = libslapd.la libldaputil.la

+ ns_slapd_DEPENDENCIES = libslapd.la

+ 

  # We need to link ns-slapd with the C++ compiler on HP-UX since we load

  # some C++ shared libraries (such as icu).

  if HPUX

@@ -339,3 +339,4 @@ 

  objectClasses: ( 2.16.840.1.113730.3.2.328 NAME 'nsSchemaPolicy' DESC 'Netscape defined objectclass' SUP top  MAY ( cn $ schemaUpdateObjectclassAccept $ schemaUpdateObjectclassReject $ schemaUpdateAttributeAccept $ schemaUpdateAttributeReject) X-ORIGIN 'Netscape Directory Server' )

  objectClasses: ( 2.16.840.1.113730.3.2.332 NAME 'nsChangelogConfig' DESC 'Configuration of the changelog5 object' SUP top MUST ( cn $ nsslapd-changelogdir ) MAY ( nsslapd-changelogmaxage $ nsslapd-changelogtrim-interval $ nsslapd-changelogmaxentries $ nsslapd-changelogsuffix $ nsslapd-changelogcompactdb-interval $ nsslapd-encryptionalgorithm $ nsSymmetricKey ) X-ORIGIN '389 Directory Server' )

  objectClasses: ( 2.16.840.1.113730.3.2.337 NAME 'rewriterEntry' DESC '' SUP top MUST ( nsslapd-libPath ) MAY ( cn $ nsslapd-filterrewriter $ nsslapd-returnedAttrRewriter ) X-ORIGIN '389 Directory Server' )

+ objectClasses: ( 2.16.840.1.113730.3.2.330 NAME 'nsDylibPlugin4' DESC 'A version 4 slapi plugin that is loaded from a platform dylib' SUP top MUST ( cn $ nsslapd-pluginpath $ nsslapd-plugininitfunc $ nsslapd-pluginenabled ) X-ORIGIN '389 Directory Server Project' )

@@ -0,0 +1,639 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ 

+ #include <slapi-private-v4.h>

+ 

+ /* Fopen and snprintf */

+ #include <stdio.h>

+ /* To access errors with files */

+ #include <errno.h>

+ /* To convert errno to string errors */

+ #include <string.h>

+ /* To use regex in our config parser */

+ #include <pcre.h>

+ 

+ #define CERT_ATTR_TYPE "userCertificate;binary"

+ #define CERT_FILTER_SIZE 64

+ 

+ typedef struct _certmap_config {

+     /* There are the fields "certmap <issuername> <issuerdn>" */

+     char *issuerdn;

+     char *issuername;

+     /* Issuer name is used to associate the remaining fields */

+     char *basedn;

+     char **dncomps;

+     uint_fast16_t dncomps_set;

+     char **filtercomps;

+     uint_fast16_t verifycert;

+     char *compare_attr;

+ } certmap_config;

+ 

+ typedef struct _certmap_config_list {

+     size_t count;

+     certmap_config **configs;

+ } certmap_config_list;

+ 

+ static certmap_config *

+ certmap_get_config_by_name(certmap_config_list *cm_config_list, char *name) {

+     certmap_config *config = NULL;

+     /* this just does a dumb search */

+     for(size_t i = 0; i < cm_config_list->count; i++) {

+         if (strcmp(name, cm_config_list->configs[i]->issuername) == 0) {

+             config = cm_config_list->configs[i];

+         }

+     }

+     return config;

+ }

+ 

+ static certmap_config *

+ certmap_get_config_by_issuer(certmap_config_list *cm_config_list, char *issuer) {

+     certmap_config *config = NULL;

+     /* this just does a dumb search */

+     for(size_t i = 0; i < cm_config_list->count; i++) {

+         if (strcmp(issuer, cm_config_list->configs[i]->issuerdn) == 0) {

+             config = cm_config_list->configs[i];

+         }

+     }

+     return config;

+ }

+ 

+ static void

+ certmap_add_config(certmap_config_list *cm_config_list, char *name, char *issuer) {

+     cm_config_list->count += 1;

+     cm_config_list->configs = (certmap_config **)spal_realloc(cm_config_list->configs, cm_config_list->count * sizeof(certmap_config *));

+ 

+     certmap_config *config = (certmap_config *)spal_calloc(sizeof(certmap_config));

+ 

+     config->issuername = name;

+     /* YOU NEED TO NORMALISE THIS */

+     config->issuerdn = issuer;

+     /* This does strdup for us */

+     config->basedn = config_get_certmap_basedn();

+     /* This gives us a basedn we can search under if none provided */

+     if (config->basedn == NULL) {

+         config->basedn = strdup("");

+     }

+ 

+     cm_config_list->configs[cm_config_list->count - 1] = config;

+ 

+     return;

+ }

+ 

+ static char **

+ certmap_str2charray_stripped(unsigned char *value, char *token) {

+     if (value == NULL) {

+         return NULL;

+     }

+ 

+     size_t number_tokens = 2;

+     for(unsigned char *s = value; *s != '\0'; s++) {

+         if (strchr(token, *s) != NULL) {

+             number_tokens++;

+         }

+     }

+ 

+     char **result = spal_calloc(sizeof(char *) * number_tokens);

+     char *iter = NULL;

+     unsigned char *s = (unsigned char *)ldap_utf8strtok_r((char *)value, token, &iter);

+     for (size_t i = 0; s != NULL; i++) {

+         /* Strip duplicates the string. */

+         unsigned char *stripped = ldap_utf8strip(s);

+         slapi_log_error(SLAPI_LOG_DEBUG, "certmap_str2charray_stripped", "parsed %s\n", stripped);

+         if (stripped != NULL) {

+             result[i] = (char *)stripped;

+         }

+         s = (unsigned char *)ldap_utf8strtok_r(NULL, token, &iter);

+     }

+ 

+     return result;

+ }

+ 

+ static void

+ certmap_add_option_by_name(certmap_config_list *cm_config_list, char *name, char *option, char *values) {

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_add_option_by_name", "certmap.conf section name %s option %s values %s\n", name, option, values);

+     /* Get the config we are modifying */

+     certmap_config *config = certmap_get_config_by_name(cm_config_list, name);

+     if (config == NULL) {

+         /* Skip the invalid option */

+         slapi_log_error(SLAPI_LOG_WARNING, "certmap_add_option_by_name", "certmap.conf section name %s does not exist\n", name);

+         return;

+     }

+ 

+     char *option_lower = (char *)slapi_utf8StrToLower((unsigned char *)option);

+ 

+     /* Which option is it? */

+     if (strcmp(option_lower, "basedn") == 0) {

+         spal_free(config->basedn);

+         if (values == NULL) {

+             config->basedn = config_get_certmap_basedn();

+         } else {

+             /* Values is already alloc by caller */

+             config->basedn = values;

+         }

+     } else if (strcmp(option_lower, "dncomps") == 0) {

+         slapi_v4_charray_free(config->dncomps);

+         /* Distinguish the commented / uncommented case */

+         config->dncomps_set = 1;

+         if (values == NULL) {

+             config->dncomps = NULL;

+         } else {

+             /* Needs to trim whitespaces. */

+             config->dncomps = certmap_str2charray_stripped((unsigned char *)values, ",");

+         }

+     } else if (strcmp(option_lower, "filtercomps") == 0) {

+         /* Parse these to arrays? */

+         slapi_v4_charray_free(config->filtercomps);

+         if (values == NULL) {

+             config->filtercomps = NULL;

+         } else {

+             /* Needs to trim whitespaces. */

+             config->filtercomps = certmap_str2charray_stripped((unsigned char *)values, ",");

+         }

+     } else if (strcmp(option_lower, "verifycert") == 0) {

+         if (values == NULL) {

+             config->verifycert = 0;

+         } else {

+             if (strcmp(values, "on") == 0) {

+                 config->verifycert = 1;

+             } else {

+                 config->verifycert = 0;

+             }

+             spal_free(values);

+         }

+     } else if (strcmp(option_lower, "cmapldapattr") == 0) {

+         /* It's valid for this to reset to NULL */

+         spal_free(config->compare_attr);

+         config->compare_attr = values;

+     } else {

+         slapi_log_error(SLAPI_LOG_WARNING, "certmap_add_option_by_name", "certmap.conf option %s not recognised\n", option);

+     }

+ 

+     spal_free(option_lower);

+ 

+     return;

+ }

+ 

+ static void

+ certmap_config_free(certmap_config *config) {

+     slapi_v4_charray_free(config->dncomps);

+     slapi_v4_charray_free(config->filtercomps);

+     spal_free(config->issuername);

+     spal_free(config->issuerdn);

+     spal_free(config->basedn);

+     spal_free(config);

+ }

+ 

+ slapi_v4_plugin_result *

+ certmap_start_fn(void **ctx) {

+     /* Get the config dir */

+     char *configdir = config_get_configdir();

+     char *configname = "/certmap.conf";

+ 

+     size_t config_path_size = strlen(configdir) + strlen(configname) + 1;

+     char *config_path = (char *)spal_calloc(config_path_size);

+     snprintf(config_path, config_path_size, "%s%s", configdir, configname);

+ 

+     spal_free(configdir);

+ 

+     /* Open the certmap file */

+     /* Handle all those nasty errors that can happen .... */

+     FILE *f = fopen(config_path, "r");

+     if (f == NULL) {

+         int cerrno = errno;

+         char serror[40] = {0};

+         strerror_r(cerrno, serror, 39);

+         char *msg = (char *)spal_calloc(64 * sizeof(char));

+         /* Failed to open */

+         snprintf(msg, 63, "certmap_start_fn - Failed to open file %s - %s", serror, config_path);

+         spal_free(config_path);

+         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, msg);

+     }

+ 

+     /* Create the config list. We may need to realloc as we go ... */

+     certmap_config_list *cm_config_list = (certmap_config_list *)spal_calloc(sizeof(certmap_config_list));

+ 

+     /* Prepare our regex */

+     char *reerr;

+     int reerroffset = 0;

+ 

+     char *cmap_regex = "^certmap\\s+(?P<name>\\S*?)\\s+(?P<issuer>.*)$";

+     pcre *cmap_regex_re = pcre_compile(cmap_regex, 0, (const char **)&reerr, &reerroffset, NULL);

+     if (cmap_regex_re == NULL) {

+         char *msg = spal_calloc(128 * sizeof(char));

+         snprintf(msg, 127, "certmap_start_fn - Failed to compile %s - %s", reerr, cmap_regex);

+         spal_free(config_path);

+         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, msg);

+     }

+ 

+     char *cmap_attr_regex = "^(?P<name>[^\\s#]*?):(?P<attr>[^\\s#]*?)$";

+     pcre *cmap_attr_regex_re = pcre_compile(cmap_attr_regex, 0, (const char **)&reerr, &reerroffset, NULL);

+     if (cmap_attr_regex_re == NULL) {

+         char *msg = spal_calloc(128 * sizeof(char));

+         snprintf(msg, 127, "certmap_start_fn - Failed to compile %s - %s", reerr, cmap_attr_regex);

+         pcre_free(cmap_regex_re);

+         spal_free(config_path);

+         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, msg);

+     }

+ 

+     char *cmap_option_regex = "^(?P<name>[^\\s#]*?):(?P<attr>[^\\s#]*?)\\s+(?P<values>.*)$";

+     pcre *cmap_option_regex_re = pcre_compile(cmap_option_regex, 0, (const char **)&reerr, &reerroffset, NULL);

+     if (cmap_option_regex_re == NULL) {

+         char *msg = spal_calloc(128 * sizeof(char));

+         snprintf(msg, 127, "certmap_start_fn - Failed to compile %s - %s", reerr, cmap_option_regex);

+         pcre_free(cmap_regex_re);

+         pcre_free(cmap_attr_regex_re);

+         spal_free(config_path);

+         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, msg);

+     }

+ 

+     /* For each line, match it to a config ... */

+     char buffer[256] = {0};

+     while (fgets(buffer, 255, f) != NULL) {

+         /* Setup the call to pcre */

+         /* Trim the \n */

+         size_t line_size = strlen(buffer);

+         if (buffer[line_size - 1] == '\n') {

+             buffer[line_size - 1] = '\0';

+             line_size -= 1;

+         }

+         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_start_fn", "parsing: %s\n", buffer);

+         /*

+          * Pcre is odd: it only uses the first 2/3rd of this as a multiple of 3

+          * for storing capture groups. So we have 3 groups, thus 6 indexes, so we

+          * need 9 in ovector. But the first 2 are the size of the match, so we need

+          # 12.

+          */

+         int ovector[12] = {0};

+         int rc = pcre_exec(cmap_regex_re, NULL, buffer, line_size, 0, 0, ovector, 12);

+         /* Is the line a new definition? */

+         if (rc >= 0) {

+             char *name = strndup(buffer + ovector[2], ovector[3] - ovector[2]);

+             char *issuer = strndup(buffer + ovector[4], ovector[5] - ovector[4]);

+             certmap_add_config(cm_config_list, name, issuer);

+         }

+ 

+         /* Is the line adding to a definition */

+         rc = pcre_exec(cmap_attr_regex_re, NULL, buffer, line_size, 0, 0, ovector, 12);

+         if (rc >= 0) {

+             char *name = strndup(buffer + ovector[2], ovector[3] - ovector[2]);

+             char *attr = strndup(buffer + ovector[4], ovector[5] - ovector[4]);

+             certmap_add_option_by_name(cm_config_list, name, attr, NULL);

+         }

+ 

+         rc = pcre_exec(cmap_option_regex_re, NULL, buffer, line_size, 0, 0, ovector, 12);

+         if (rc >= 0) {

+             char *name = strndup(buffer + ovector[2], ovector[3] - ovector[2]);

+             char *attr = strndup(buffer + ovector[4], ovector[5] - ovector[4]);

+             char *values = strndup(buffer + ovector[6], ovector[7] - ovector[6]);

+             certmap_add_option_by_name(cm_config_list, name, attr, values);

+         }

+ 

+         /* If it's none of these, we skip it .... */

+     }

+ 

+     /* Close the file */

+     fclose(f);

+ 

+     pcre_free(cmap_regex_re);

+     pcre_free(cmap_attr_regex_re);

+     pcre_free(cmap_option_regex_re);

+ 

+     /* Finally, hand this to our private data holder. */

+     *ctx = (void *)cm_config_list;

+ 

+     spal_free(config_path);

+     return slapi_v4_plugin_result_ok();

+ }

+ 

+ slapi_v4_plugin_result *

+ certmap_close_fn(void **ctx) {

+     /* Destroy the certmap configuration */

+     certmap_config_list *cm_config_list = (certmap_config_list *)*ctx;

+ 

+     if (cm_config_list != NULL) {

+         for (size_t i = 0; i < cm_config_list->count; i++) {

+             certmap_config_free(cm_config_list->configs[i]);

+         }

+ 

+         spal_free(cm_config_list->configs);

+         spal_free(cm_config_list);

+     }

+ 

+     return slapi_v4_plugin_result_ok();

+ }

+ 

+ static void

+ certmap_verifycert_fn(struct berval *bv, void *acc, void *arg) {

+     int64_t *status = (int64_t *)acc;

+     struct berval *bp_cert = (struct berval *)arg;

+ 

+     if (*status != 0) {

+         return;

+     }

+ 

+     /* Are the sizes the same? */

+     if (bv->bv_len != bp_cert->bv_len) {

+         return;

+     }

+ 

+     /* What about the actual data? */

+     if (memcmp(bv->bv_val, bp_cert->bv_val, bp_cert->bv_len) == 0) {

+         /*If all good, set status to 1! */

+         *status = 1;

+     }

+ 

+ }

+ 

+ static slapi_v4_dn *

+ certmap_search_int(certmap_config *config, slapi_v4_cert *cert, char *basedn, char *filter, int scope) {

+     /*

+      * Search for the entry.

+      */

+     slapi_v4_dn *base_sdn = slapi_v4_sdn_new_from_char_dn(basedn);

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_search_int", "Searching basedn: %s\n", basedn);

+ 

+     int32_t attrsonly = 0;

+     /* WE ONLY NEED userCertificate;binary */

+     char **attrs = slapi_v4_charray_append(NULL, strdup(CERT_ATTR_TYPE));

+ 

+     /* execute search */

+     /* If basedn == "", but scope == SUBTREE, we need a diff search handler. */

+     slapi_v4_search_pblock *pb_search_result = NULL;

+     if (strcmp(basedn, "") == 0 && scope == LDAP_SCOPE_SUBTREE) {

+         pb_search_result = slapi_v4_search_internal_all_contexts(scope, filter, attrs, attrsonly, NULL, NULL, 0);

+     } else {

+         pb_search_result = slapi_v4_search_internal(base_sdn, scope, filter, attrs, attrsonly, NULL, NULL, 0);

+     }

+ 

+     /* Search is over, don't need the basedn anymore. */

+     slapi_v4_charray_free(attrs);

+     slapi_v4_sdn_free(base_sdn);

+ 

+     /* get the number of entries */

+     uint64_t num_results = slapi_v4_search_pblock_get_num_results(pb_search_result);

+ 

+     if (num_results == 0) {

+         slapi_log_error(SLAPI_LOG_WARNING, "certmap_search_int", "No entries matched filter: %s basedn: %s\n", filter, basedn);

+         slapi_v4_search_pblock_destroy(pb_search_result);

+         return NULL;

+     } else if (num_results >= 2) {

+         slapi_log_error(SLAPI_LOG_WARNING, "certmap_search_int", "Multiple entries matched filter: %s basedn: %s\n", filter, basedn);

+         slapi_v4_search_pblock_destroy(pb_search_result);

+         return NULL;

+     }

+ 

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_search_int", "Query filter: %s basedn: %s number of entries: %"PRIu64"\n", filter, basedn, num_results);

+ 

+     Slapi_Entry **op_entries = slapi_v4_search_pblock_get_entries(pb_search_result);

+     Slapi_Entry *bind_entry = op_entries[0];

+ 

+     /*

+      * Now verify the cert if requested.

+      * This involves checking the certificate attribute contains the DER of our certificate.

+      * only matters if verifyCert == on

+      */

+ 

+     if (config->verifycert == 1) {

+ 

+         struct berval **barray = slapi_v4_entry_attr_get_bervals(bind_entry, CERT_ATTR_TYPE);

+         /*

+          * Now we have to memcmp the certs. We can do this by turning the cert

+          * into a berval.

+          */

+         struct berval *bp_cert = slapi_v4_cert_get_der_berval(cert);

+         int64_t status = 0;

+ 

+         slapi_v4_bvarray_fold(barray, certmap_verifycert_fn, (void *)&status, (void *)bp_cert);

+ 

+         slapi_v4_bv_free(bp_cert);

+         slapi_v4_bvarray_destroy(barray);

+ 

+         if (status == 0) {

+             slapi_log_error(SLAPI_LOG_WARNING, "certmap_search_int", "Certificate verification failed, no matching %s attribute\n", CERT_ATTR_TYPE);

+             slapi_v4_search_pblock_destroy(pb_search_result);

+             return NULL;

+         }

+         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_search_int", "Certificate verification was successful\n");

+     }

+ 

+     slapi_v4_dn *entry_dn = slapi_v4_sdn_dup(slapi_v4_entry_get_sdn(bind_entry));

+ 

+     slapi_v4_search_pblock_destroy(pb_search_result);

+     return entry_dn;

+ }

+ 

+ slapi_v4_plugin_result *

+ certmap_certmap_fn(void *ctx, slapi_v4_certmap_pblock *pbc) {

+     /*

+      * At this point pbc contains a populated struct of cert info. We need to extract

+      * this and determine an sdn (or entry?) that we should bind to.

+      */

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Calling bind_certmap plugin.\n");

+     certmap_config_list *cm_config_list = (certmap_config_list *)ctx;

+     /*

+      * Find the relevant certmap config in the list.

+      */

+     slapi_v4_cert *cert = slapi_v4_certmap_pblock_get_clientcert(pbc);

+ 

+     char *subject_dn = slapi_v4_cert_get_subjectdn(cert);

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Attempting to bind subjectdn: %s\n", subject_dn);

+     char *issuer_dn = slapi_v4_cert_get_issuerdn(cert);

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Attempting to bind issuerdn: %s\n", issuer_dn);

+ 

+     /* Check if subject and issuer are valid. */

+ 

+     certmap_config *config = certmap_get_config_by_issuer(cm_config_list, issuer_dn);

+     if (config == NULL) {

+         /* No config found, use default! */

+         config = certmap_get_config_by_name(cm_config_list, "default");

+         if (config == NULL) {

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "No default config nor issuer config could be found.\n");

+             /* Free some stuff and bail here */

+             spal_free(subject_dn);

+             spal_free(issuer_dn);

+             return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, strdup("Certificate can not be mapped to an identity."));

+         } else {

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "No issuer config could be found, falling back to default..\n");

+         }

+     } else {

+         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Found configuration for %s\n", issuer_dn);

+     }

+ 

+     slapi_v4_dn *mapped_dn = NULL;

+ 

+     if (config->dncomps_set == 0) {

+         if (config->compare_attr == NULL) {

+             /*

+              * If dncomps == NONE, cmapattr == None, bind to subject DN

+              */

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "dncomps == NULL, cmap == NULL,\n");

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Binding to to subjectdn: %s\n", subject_dn);

+ 

+             /* Do a base search for this object */

+             mapped_dn = certmap_search_int(config, cert, subject_dn, "(objectClass=*)", LDAP_SCOPE_BASE);

+ 

+         } else {

+             /*

+              * If dncomps == NONE, cmapattr == Some(dn), search under basedn for cmapattr = subject_dn

+              */

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "dncomps == NULL, cmap == %s,\n", config->compare_attr);

+ 

+             /* Filter escape the subject_dn */

+             char *subject_dn_escaped = slapi_v4_escape_filter_value(subject_dn, strlen(subject_dn));

+ 

+             /* Turn the cmap attr into a filter. */

+             size_t filterlen = strlen(config->compare_attr) + strlen(subject_dn_escaped) + 4;

+             char *filter = spal_calloc(filterlen);

+             snprintf(filter, filterlen, "(%s=%s)", config->compare_attr, subject_dn_escaped);

+             spal_free(subject_dn_escaped);

+ 

+             /* What abotu NULL basedn? */

+             mapped_dn = certmap_search_int(config, cert, config->basedn, filter, LDAP_SCOPE_SUBTREE);

+             spal_free(filter);

+         }

+     } else {

+         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "dncomps != NULL\n");

+         if (config->dncomps == NULL) {

+             /*

+              * if dncomps == "", use filter comps to search for an entry below basedn.

+              */

+ 

+             /* We have a filtercomps (I hope) */

+             if (config->filtercomps == NULL) {

+                 slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "dncomps != NULL and filtercomps == NULL, can not map certificate!\n");

+                 /* Error! */

+             } else {

+ 

+                 size_t filter_max_len = CERT_FILTER_SIZE;

+                 size_t filter_len = 2;

+                 char *filter = spal_calloc(sizeof(char) * filter_max_len);

+ 

+                 /* Open the filter */

+                 sprintf(filter, "(&");

+ 

+                 /* Take a pointer into the filter at some point range: */

+ 

+                 for (size_t j = 0; config->filtercomps[j] != NULL; j++) {

+                     char *filtercomp = config->filtercomps[j];

+                     /* For each value, extract the ava from the cert */

+                     /* Construct these to a filter. */

+                     char **avas = slapi_v4_cert_get_subject_ava_val(cert, filtercomp);

+                     if (avas == NULL) {

+                         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Failed to parse certificate filtercomp %s\n", filtercomp);

+                         spal_free(subject_dn);

+                         spal_free(issuer_dn);

+                         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, strdup("Certificate can not be mapped to an identity."));

+                     }

+                     for (size_t i = 0; avas[i] != NULL; i++) {

+                         char *ava = avas[i];

+                         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "%s avas %s\n", filtercomp, ava);

+ 

+                         /* Work out how large our new filter element will be */

+                         /* Remember it is: (%s=%s) so at least 3 extra chars. */

+                         size_t ava_len = 3 + strlen(ava) + strlen(filtercomp);

+                         while ((ava_len + filter_len) >= filter_max_len) {

+                             filter_max_len = filter_max_len + CERT_FILTER_SIZE;

+                             filter = spal_realloc(filter, sizeof(char) * filter_max_len);

+                         }

+                         char *filter_ptr = filter + filter_len;

+ 

+                         sprintf(filter_ptr, "(%s=%s)", filtercomp, ava);

+                         filter_len = filter_len + ava_len;

+ 

+                     }

+ 

+                     slapi_v4_charray_free(avas);

+                 }

+ 

+                 sprintf(filter + filter_len, ")");

+                 slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "filter %s\n", filter);

+ 

+                 /* Submit the search! */

+                 mapped_dn = certmap_search_int(config, cert, config->basedn, filter, LDAP_SCOPE_SUBTREE);

+                 spal_free(filter);

+             }

+         } else {

+             /*

+              * if dncomps == "attr list", construct a DN to bind to.

+              */

+             size_t binddn_max_len = CERT_FILTER_SIZE;

+             size_t binddn_len = 0;

+             char *binddn = spal_calloc(sizeof(char) * binddn_max_len);

+ 

+             for (size_t i = 0; config->dncomps[i] != NULL; i++) {

+                 char *dncomp = config->dncomps[i];

+ 

+                 char **avas = slapi_v4_cert_get_subject_ava_val(cert, dncomp);

+                 if (avas == NULL) {

+                     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "Failed to parse certificate dncomp %s\n", dncomp);

+                     spal_free(subject_dn);

+                     spal_free(issuer_dn);

+                     return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, strdup("Certificate can not be mapped to an identity."));

+                 }

+                 for (size_t j = 0; avas[j] != NULL; j++) {

+                     char *ava = avas[j];

+                     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "%s avas %s\n", dncomp, ava);

+ 

+                     /* Work out how large our new filter element will be */

+                     /* Remember it is: %s=%s, so at least 2 extra chars. */

+                     size_t ava_len = 2 + strlen(ava) + strlen(dncomp);

+                     while ((ava_len + binddn_len) >= binddn_max_len) {

+                         binddn_max_len = binddn_max_len + CERT_FILTER_SIZE;

+                         binddn = spal_realloc(binddn, sizeof(char) * binddn_max_len);

+                     }

+                     char *binddn_ptr = binddn + binddn_len;

+ 

+                     sprintf(binddn_ptr, "%s=%s,", dncomp, ava);

+                     binddn_len = binddn_len + ava_len;

+                 }

+ 

+                 slapi_v4_charray_free(avas);

+             }

+             /* Replace the final trailing , with a \0 */

+             binddn[binddn_len - 1] = '\0';

+ 

+             slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "binddn %s\n", binddn);

+ 

+             /* Submit the search! */

+             mapped_dn = certmap_search_int(config, cert, binddn, "(objectClass=*)", LDAP_SCOPE_BASE);

+             spal_free(binddn);

+         }

+     }

+ 

+     spal_free(subject_dn);

+     spal_free(issuer_dn);

+ 

+     if (mapped_dn == NULL) {

+         slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "bind_certmap plugin failed to map client certficate.\n");

+         return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_INVALID_CREDENTIALS, strdup("Failed to map client certificate to LDAP entry."));

+     }

+ 

+     /* If it exists, attach the SDN to the pbc */

+     slapi_v4_certmap_pblock_set_clientdn(pbc, mapped_dn);

+ 

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_certmap_fn", "bind_certmap plugin complete.\n");

+     return slapi_v4_plugin_result_ok();

+ }

+ 

+ slapi_v4_plugin_result *

+ certmap_init_fn(slapi_v4_plugin_registration *p_register) {

+     slapi_log_error(SLAPI_LOG_PLUGIN, "certmap_init_fn", "Initialising certmap plugin.\n");

+ 

+     /* register name will dup this for us. */

+     slapi_v4_plugin_register_name(p_register, "certmap plugin");

+     slapi_v4_plugin_register_precedence(p_register, SV4_PLUGIN_PRECEDENCE_DEFAULT);

+     slapi_v4_plugin_register_start_fn(p_register, certmap_start_fn);

+     slapi_v4_plugin_register_close_fn(p_register, certmap_close_fn);

+     slapi_v4_plugin_register_bind_certmap_fn(p_register, certmap_certmap_fn);

+ 

+     return slapi_v4_plugin_result_ok();

+ }

+ 

@@ -20,6 +20,11 @@ 

  #include "slap.h"

  #include <plbase64.h>

  

+ /* We pull in the internal headers for config */

+ 

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ #include <slapi-private-v4.h>

+ 

  #define AES_MECH 1

  #define DES_MECH 2

  #define AES_REVER_SCHEME_NAME "AES"

file modified
+34
@@ -38,6 +38,8 @@ 

  #include "pratom.h"

  #include "csngen.h"

  

+ #include <slapi-internal-v4.h>

+ 

  /* Forward declarations */

  static int add_internal_pb(Slapi_PBlock *pb);

  static void op_shared_add(Slapi_PBlock *pb);
@@ -331,6 +333,38 @@ 

      return add_internal_pb(pb);

  }

  

+ /*

+  * v4 add api. We discard the allow_operation check because plugins just have

+  * total access to the server memory - they can do what they please. Instead

+  * we just wrap the existing add code in a nicer api, and we forced the

+  * modifier name to come from the caller rather than the convoluted plugin_id

+  * mechanism. If a plugin wans to lie, we can't stop it, so just go with simple!

+  */

+ 

+ slapi_v4_search_pblock *

+ slapi_v4_add_internal_entry(Slapi_Entry *entry, const char *modifier_name) {

+     if (modifier_name == NULL) {

+         /* Should we create a pblock and return it with a failure code? */

+         return NULL;

+     }

+     /* Create a new pblock */

+     Slapi_PBlock *int_pbs = slapi_pblock_new();

+     /* Allocate a new operation */

+     /* There are NO cases I can find of these flags being used, so don't bother! */

+     Operation *op = internal_operation_new(SLAPI_OPERATION_ADD, 0);

+     slapi_pblock_set(int_pbs, SLAPI_OPERATION, op);

+     slapi_pblock_set(int_pbs, SLAPI_CONTROLS_ARG, NULL);

+     /* Inject the modifier into the entry */

+     slapi_entry_attr_set_charptr(entry, "internalModifiersname", modifier_name);

+     slapi_pblock_set(int_pbs, SLAPI_ADD_ENTRY, entry);

+     /* Add the entry */

+     add_internal_pb(int_pbs);

+     /* Extract and return the result */

+     slapi_v4_search_pblock *pbs = slapi_v4_search_pblock_extract(int_pbs);

+     slapi_pblock_destroy(int_pbs);

+     return pbs;

+ }

+ 

  int

  slapi_add_internal_set_pb(Slapi_PBlock *pb, const char *dn, LDAPMod **attrs, LDAPControl **controls, Slapi_ComponentId *plugin_identity, int operation_flags)

  {

file modified
+61 -406
@@ -20,334 +20,7 @@ 

  #include <sys/param.h>         /* MAXPATHLEN */

  #include "slap.h"              /* slapi_ch_malloc */

  #include "fe.h"

- 

- char *client_auth_config_file = NULL;

- 

- /* forward declarations */

- 

- static void generate_id(void);

- static Slapi_ComponentId *auth_get_component_id(void);

- 

- #define internal_ld NULL

- 

- static int LDAP_CALL LDAP_CALLBACK

- slapu_msgfree(LDAP *ld, LDAPMessage *msg)

- {

-     Slapi_PBlock *pb = (Slapi_PBlock *)msg;

-     if (ld != internal_ld) {

-         return ldap_msgfree(msg);

-     }

-     if (pb) {

-         slapi_free_search_results_internal(pb);

-         slapi_pblock_destroy(pb);

-     }

-     return LDAP_SUCCESS;

- }

- 

- static int LDAP_CALL LDAP_CALLBACK

- slapu_search_s(LDAP *ld, const char *rawbaseDN, int scope, const char *filter, char **attrs, int attrsonly, LDAPMessage **result)

- {

-     int err = LDAP_NO_SUCH_OBJECT;

-     Slapi_PBlock *pb = NULL;

-     LDAPControl **ctrls;

-     Slapi_DN *sdn = slapi_sdn_new_dn_byval(rawbaseDN);

-     const char *baseDN = slapi_sdn_get_dn(sdn);

- 

-     if (ld != internal_ld) {

-         err = ldap_search_ext_s(ld, baseDN, scope, filter, attrs, attrsonly,

-                                 NULL, NULL, NULL, -1, result);

-         slapi_sdn_free(&sdn);

-         return err;

-     }

-     slapi_log_err(SLAPI_LOG_TRACE, "slapu_search_s", "=> (\"%s\", %i, %s)\n",

-                   baseDN, scope, filter);

-     if (filter == NULL)

-         filter = "objectclass=*";

- 

-     /* use new internal search API */

-     pb = slapi_pblock_new();

-     /* we need to provide managedsait control to avoid returning continuation references */

-     ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl *));

-     ctrls[0] = (LDAPControl *)slapi_ch_malloc(sizeof(LDAPControl));

-     ctrls[0]->ldctl_oid = slapi_ch_strdup(LDAP_CONTROL_MANAGEDSAIT);

-     ctrls[0]->ldctl_value.bv_val = NULL;

-     ctrls[0]->ldctl_value.bv_len = 0;

-     ctrls[0]->ldctl_iscritical = '\0';

-     slapi_search_internal_set_pb(pb, baseDN, scope, (char *)filter, attrs,

-                                  attrsonly, ctrls, NULL,

-                                  auth_get_component_id(), 0 /* actions */);

-     slapi_search_internal_pb(pb);

- 

-     if (pb != NULL) {

-         if (slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &err)) {

-             err = LDAP_LOCAL_ERROR;

-         }

-         if (err != LDAP_SUCCESS) {

-             slapu_msgfree(ld, (LDAPMessage *)pb);

-             pb = NULL;

-             if (scope == LDAP_SCOPE_SUBTREE) {

-                 char fbuf[BUFSIZ];

-                 slapi_log_err(SLAPI_LOG_ERR, "slapu_search_s", "(\"%s\", subtree, %s) err %i\n",

-                               baseDN, escape_string((char *)filter, fbuf), err);

-             }

-         }

-     } else {

-         char fbuf[BUFSIZ];

-         slapi_log_err(SLAPI_LOG_ERR, "slapu_search_s", "(\"%s\", %i, %s) NULL\n",

-                       baseDN, scope, escape_string((char *)filter, fbuf));

-     }

-     slapi_sdn_free(&sdn);

-     *result = (LDAPMessage *)pb;

-     slapi_log_err(SLAPI_LOG_TRACE, "<= slapu_search_s", "%i\n", err);

-     return err;

- }

- 

- static int LDAP_CALL LDAP_CALLBACK

- slapu_count_entries(LDAP *ld, LDAPMessage *msg)

- {

-     Slapi_Entry **entry = NULL;

-     int count = 0;

-     if (ld != internal_ld) {

-         return ldap_count_entries(ld, msg);

-     }

-     if (!slapi_pblock_get((Slapi_PBlock *)msg, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry) && entry) {

-         for (; *entry; ++entry)

-             ++count;

-     }

-     return count;

- }

- 

- /* slapu_search_s() returns a Slapi_PBlock*, but slapu_first_entry() and

-  * slapu_next_entry() return a Slapi_Entry** pointing into the same array

-  * as the PBlock.  If one of the iteration (Slapi_Entry**) pointers was

-  * passed to slapu_msgfree(), havoc would ensue.  ldaputil never does this.

-  * But ldap_msgfree() would support it (no?); so a plugin function might.

-  * Yet another way this doesn't support plugin functions.

-  */

- 

- static LDAPMessage *LDAP_CALL LDAP_CALLBACK

- slapu_first_entry(LDAP *ld, LDAPMessage *msg)

- {

-     Slapi_Entry **entry = NULL;

-     if (ld != internal_ld) {

-         return ldap_first_entry(ld, msg);

-     }

-     if (!slapi_pblock_get((Slapi_PBlock *)msg, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry) && entry && *entry) {

-         return (LDAPMessage *)entry;

-     }

-     return NULL;

- }

- 

- static LDAPMessage *LDAP_CALL LDAP_CALLBACK

- slapu_next_entry(LDAP *ld, LDAPMessage *msg)

- {

-     Slapi_Entry **entry = (Slapi_Entry **)msg;

-     if (ld != internal_ld) {

-         if (msg) {

-             return ldap_next_entry(ld, msg);

-         } else {

-             return NULL;

-         }

-     }

-     if (entry && *entry && *++entry) {

-         return (LDAPMessage *)entry;

-     }

-     return NULL;

- }

- 

- static char *LDAP_CALL LDAP_CALLBACK

- slapu_get_dn(LDAP *ld, LDAPMessage *entry)

- {

-     if (ld != internal_ld) {

-         return ldap_get_dn(ld, entry);

-     }

-     return slapi_ch_strdup(slapi_entry_get_dn(*(Slapi_Entry **)entry));

- }

- 

- static void LDAP_CALL LDAP_CALLBACK

- slapu_memfree(LDAP *ld, void *dn)

- {

-     if (ld != internal_ld) {

-         ldap_memfree(dn);

-     } else {

-         free(dn);

-     }

- }

- 

- static char *

- slapu_attr_get_desc(Slapi_Attr *attr)

- {

-     char *desc = NULL;

-     if (slapi_attr_get_type(attr, &desc) == LDAP_SUCCESS && desc) {

-         return slapi_ch_strdup(desc);

-     }

-     return NULL;

- }

- 

- /* slapu_first_attribute and slapu_next_attribute use a Slapi_Attr*

-  * as an iterator.  It is malloc'd by first() and free'd by ber_free().

-  */

- 

- static char *LDAP_CALL LDAP_CALLBACK

- slapu_first_attribute(LDAP *ld, LDAPMessage *entry, BerElement **iter)

- {

-     if (ld != internal_ld) {

-         return ldap_first_attribute(ld, entry, iter);

-     } else {

-         Slapi_Attr **attr = (Slapi_Attr **)slapi_ch_malloc(sizeof(Slapi_Attr *));

-         *iter = (BerElement *)attr;

-         if (attr && slapi_entry_first_attr(*(Slapi_Entry **)entry, attr) == LDAP_SUCCESS) {

-             return slapu_attr_get_desc(*attr);

-         }

-     }

-     return NULL;

- }

- 

- static char *LDAP_CALL LDAP_CALLBACK

- slapu_next_attribute(LDAP *ld, LDAPMessage *entry, BerElement *iter)

- {

-     Slapi_Attr **attr = (Slapi_Attr **)iter;

-     if (ld != internal_ld) {

-         return ldap_next_attribute(ld, entry, iter);

-     }

-     if (attr && slapi_entry_next_attr(*(Slapi_Entry **)entry, *attr, attr) == LDAP_SUCCESS) {

-         return slapu_attr_get_desc(*attr);

-     }

-     return NULL;

- }

- 

- static void LDAP_CALL LDAP_CALLBACK

- slapu_ber_free(LDAP *ld, BerElement *iter, int freebuf)

- {

-     if (ld != internal_ld) {

-         ber_free(iter, freebuf);

-     } else {

-         free((Slapi_Attr **)iter);

-     }

- }

- 

- static struct berval **LDAP_CALL LDAP_CALLBACK

- slapu_get_values_len(LDAP *ld, LDAPMessage *entry, const char *desc)

- {

-     Slapi_Attr *attr = NULL;

-     if (ld != internal_ld) {

-         return ldap_get_values_len(ld, entry, desc);

-     }

-     if (slapi_entry_attr_find(*(Slapi_Entry **)entry, desc, &attr) == LDAP_SUCCESS && attr) {

-         struct berval **values = NULL;

-         if (slapi_attr_get_bervals_copy(attr, &values) == 0) {

-             return (values);

-         }

-     }

-     return NULL;

- }

- 

- static void LDAP_CALL LDAP_CALLBACK

- slapu_value_free_len(LDAP *ld, struct berval **values)

- {

-     if (ld != internal_ld) {

-         ldap_value_free_len(values);

-     } else {

-         ber_bvecfree(values);

-     }

- }

- 

- void

- client_auth_init()

- {

-     int err;

-     if (client_auth_config_file == NULL) {

-         char *confdir = config_get_configdir();

-         if (NULL == confdir) {

-             slapi_log_err(SLAPI_LOG_ERR, "client_auth_init", "Failed to get configdir\n");

-             return;

-         }

-         client_auth_config_file = PR_smprintf("%s/certmap.conf", confdir);

-         if (NULL == client_auth_config_file) {

-             slapi_log_err(SLAPI_LOG_ERR, "client_auth_init", "Failed to duplicate \"%s/certmap\"\n", confdir);

-             slapi_ch_free_string(&confdir);

-             return;

-         }

-         slapi_ch_free_string(&confdir);

-     }

-     err = ldaputil_init(client_auth_config_file, "", NULL, "slapd", NULL);

-     if (err != LDAPU_SUCCESS) {

-         slapi_log_err(SLAPI_LOG_TRACE, "client_auth_init", "ldaputil_init(%s,...) %i\n", client_auth_config_file, err);

-     } else {

-         LDAPUVTable_t vtable = {

-             NULL /* ssl_init */,

-             NULL /* set_option */,

-             NULL /* simple_bind_s */,

-             NULL /* unbind */,

-             slapu_search_s,

-             slapu_count_entries,

-             slapu_first_entry,

-             slapu_next_entry,

-             slapu_msgfree,

-             slapu_get_dn,

-             slapu_memfree,

-             slapu_first_attribute,

-             slapu_next_attribute,

-             slapu_ber_free,

-             NULL /* get_values */,

-             NULL /* value_free */,

-             slapu_get_values_len,

-             slapu_value_free_len};

-         ldapu_VTable_set(&vtable);

-     }

- 

-     /* Generate a component id for cert-based authentication */

-     generate_id();

- }

- 

- #include <ssl.h>

- #include "slapi-plugin.h"  /* SLAPI_BERVAL_EQ */

- #include "slapi-private.h" /* COMPONENT_CERT_AUTH */

- 

- static Slapi_ComponentId *auth_component_id = NULL;

- 

- static void

- generate_id(void)

- {

-     if (auth_component_id == NULL) {

-         auth_component_id = generate_componentid(NULL /* Not a plugin */, COMPONENT_CERT_AUTH);

-     }

- }

- 

- static Slapi_ComponentId *

- auth_get_component_id(void)

- {

-     return auth_component_id;

- }

- 

- 

- static char *

- subject_of(CERTCertificate *cert)

- {

-     char *dn = NULL;

-     if (cert != NULL) {

-         int err = ldapu_get_cert_subject_dn(cert, &dn);

-         if (err != LDAPU_SUCCESS) {

-             slapi_log_err(SLAPI_LOG_ERR, "subject_of", "ldapu_get_cert_subject_dn(%p) %i (%s)\n",

-                           (void *)cert, err, ldapu_err2string(err));

-         }

-     }

-     return dn;

- }

- 

- static char *

- issuer_of(CERTCertificate *cert)

- {

-     char *dn = NULL;

-     if (cert != NULL) {

-         int err = ldapu_get_cert_issuer_dn(cert, &dn);

-         if (err != LDAPU_SUCCESS) {

-             slapi_log_err(SLAPI_LOG_ERR, "issuer_of", "ldapu_get_cert_issuer_dn(%p) %i (%s)\n",

-                           (void *)cert, err, ldapu_err2string(err));

-         }

-     }

-     return dn;

- }

+ #include <slapi-internal-v4.h>

  

  /*

   * Log a certificate that was rejected because the client didn't
@@ -365,19 +38,22 @@ 

      CERTCertificate *clientCert = slapd_ssl_peerCertificate(prfd);

  

      PRErrorCode errorCode = PR_GetError();

-     char *subject = subject_of(clientCert);

-     char *issuer = issuer_of(clientCert);

+     char *subject = slapi_v4_cert_get_subjectdn(clientCert);

+     char *issuer = slapi_v4_cert_get_issuerdn(clientCert);

      slapi_log_access(LDAP_DEBUG_STATS,

                       "conn=%" PRIu64 " " SLAPI_COMPONENT_NAME_NSPR " error %i (%s); unauthenticated client %s; issuer %s\n",

                       conn->c_connid, errorCode, slapd_pr_strerror(errorCode),

                       subject ? escape_string(subject, sbuf) : "NULL",

                       issuer ? escape_string(issuer, ibuf) : "NULL");

-     if (issuer)

+     if (issuer) {

          free(issuer);

-     if (subject)

+     }

+     if (subject) {

          free(subject);

-     if (clientCert)

+     }

+     if (clientCert) {

          CERT_DestroyCertificate(clientCert);

+     }

      return -1; /* non-zero means reject this certificate */

  }

  
@@ -395,7 +71,6 @@ 

      Connection *conn = (Connection *)clientData;

      CERTCertificate *clientCert = slapd_ssl_peerCertificate(prfd);

  

-     char *clientDN = NULL;

      int keySize = 0;

      char *cipher = NULL;

      char *extraErrorMsg = "";
@@ -420,7 +95,7 @@ 

      }

  

      keySize = cipherInfo.effectiveKeyBits;

-     cipher = slapi_ch_strdup(cipherInfo.symCipherName);

+     cipher = strdup(cipherInfo.symCipherName);

  

      /* If inside an Start TLS operation, perform the privacy level discovery

       * and if the security degree achieved after the handshake is not reckoned
@@ -445,86 +120,66 @@ 

                           conn->c_connid,

                           sslversion, keySize, cipher ? cipher : "NULL");

      } else {

-         subject = subject_of(clientCert);

-         if (!subject) {

-             (void)slapi_getSSLVersion_str(channelInfo.protocolVersion,

-                                           sslversion, sizeof(sslversion));

-             slapi_log_access(LDAP_DEBUG_STATS,

-                              "conn=%" PRIu64 " %s %i-bit %s; missing subject\n",

-                              conn->c_connid,

-                              sslversion, keySize, cipher ? cipher : "NULL");

+ 

+         slapi_v4_certmap_pblock *pbc = slapi_v4_certmap_pblock_init();

+         /*

+          * Populate all the parameters to pbc that are needed.

+          *

+          * This is where we actually extract all the certificate details we'll need for

+          * the certmap bind process to operate.

+          *

+          * We need: issuer

+          *        : subject dn

+          *        : raw DER?

+          *        What if we just attach the cert to the pbc, then we can call as needed?

+          */

+         slapi_v4_certmap_pblock_set_clientcert(pbc, clientCert);

+ 

+         plugin_v4_result bind_certmap_result = plugin_v4_call_bind_certmap(pbc);

+         if (bind_certmap_result != PLUGIN_V4_SUCCESS) {

+             slapi_log_err(SLAPI_LOG_ERR, "handle_handshake_done", "Failed to execute bind_certmap plugins\n");

+             slapi_v4_certmap_pblock_destroy(pbc);

              goto done;

          }

-         {

-             char *issuer = issuer_of(clientCert);

-             char sbuf[BUFSIZ], ibuf[BUFSIZ];

-             (void)slapi_getSSLVersion_str(channelInfo.protocolVersion,

-                                           sslversion, sizeof(sslversion));

-             slapi_log_access(LDAP_DEBUG_STATS,

-                              "conn=%" PRIu64 " %s %i-bit %s; client %s; issuer %s\n",

-                              conn->c_connid,

-                              sslversion, keySize,

-                              cipher ? cipher : "NULL",

-                              subject ? escape_string(subject, sbuf) : "NULL",

-                              issuer ? escape_string(issuer, ibuf) : "NULL");

-             if (issuer)

-                 free(issuer);

+ 

+         Slapi_DN *client_dn = slapi_v4_certmap_pblock_get_clientdn(pbc);

+ 

+         if (client_dn == NULL) {

+             /*

+              * Given we got a SUCCESS from the plugin, this shouldn't happen, but

+              * who knows what kind of junk people write.

+              */

+             slapi_v4_certmap_pblock_destroy(pbc);

+             slapi_log_err(SLAPI_LOG_ERR, "handle_handshake_done", "bind_certmap plugins return NULL result, this is a mistake!!!!\n");

+             goto done;

          }

-         slapi_dn_normalize(subject);

-         {

-             LDAPMessage *chain = NULL;

-             char *basedn = config_get_basedn();

-             int err;

+         /* As pointless as this seems, I want to wait to change connection->c_dn to sdn */

+         char *binddn = strdup(slapi_sdn_get_dn(client_dn));

  

-             err = ldapu_cert_to_ldap_entry(clientCert, internal_ld, basedn ? basedn : "" /*baseDN*/, &chain);

-             if (err == LDAPU_SUCCESS && chain) {

-                 LDAPMessage *entry = slapu_first_entry(internal_ld, chain);

-                 if (entry) {

-                     /* clientDN is duplicated in slapu_get_dn */

-                     clientDN = slapu_get_dn(internal_ld, entry);

-                 } else {

+         (void)slapi_getSSLVersion_str(channelInfo.protocolVersion, sslversion, sizeof(sslversion));

  

-                     extraErrorMsg = "no entry";

-                     slapi_log_err(SLAPI_LOG_TRACE, "handle_handshake_done", "<= ldapu_cert_to_ldap_entry() %s\n",

-                                   extraErrorMsg);

-                 }

-             } else {

-                 extraErrorMsg = ldapu_err2string(err);

-                 slapi_log_err(SLAPI_LOG_TRACE, "handle_handshake_done", "<= ldapu_cert_to_ldap_entry() %i (%s)%s\n",

-                               err, extraErrorMsg, chain ? "" : " NULL");

-             }

-             slapi_ch_free_string(&basedn);

-             slapu_msgfree(internal_ld, chain);

+         if (client_dn != NULL) {

+             slapi_log_access(LDAP_DEBUG_STATS,

+                              "conn=%" PRIu64 " %s client bound as %s\n",

+                              conn->c_connid,

+                              sslversion, binddn);

+         } else if (clientCert != NULL) {

+             slapi_log_access(LDAP_DEBUG_STATS,

+                              "conn=%" PRIu64 " %s failed to map client "

+                              "certificate to LDAP DN (%s)\n",

+                              conn->c_connid,

+                              sslversion, extraErrorMsg);

          }

-     }

  

-     if (clientDN != NULL) {

-         Slapi_DN *sdn = NULL;

-         sdn = slapi_sdn_new_dn_passin(clientDN);

-         clientDN = slapi_ch_strdup(slapi_sdn_get_dn(sdn));

-         slapi_sdn_free(&sdn);

-         (void)slapi_getSSLVersion_str(channelInfo.protocolVersion,

-                                       sslversion, sizeof(sslversion));

-         slapi_log_access(LDAP_DEBUG_STATS,

-                          "conn=%" PRIu64 " %s client bound as %s\n",

-                          conn->c_connid,

-                          sslversion, clientDN);

-     } else if (clientCert != NULL) {

-         (void)slapi_getSSLVersion_str(channelInfo.protocolVersion,

-                                       sslversion, sizeof(sslversion));

-         slapi_log_access(LDAP_DEBUG_STATS,

-                          "conn=%" PRIu64 " %s failed to map client "

-                          "certificate to LDAP DN (%s)\n",

-                          conn->c_connid,

-                          sslversion, extraErrorMsg);

+         /*

+          * Associate the new credentials with the connection.  Note that

+          * clientDN and clientCert may be NULL.

+          */

+         bind_credentials_set_nolock(conn, SLAPD_AUTH_SSL, binddn, SLAPD_AUTH_SSL, binddn, clientCert, NULL);

+ 

+         slapi_v4_certmap_pblock_destroy(pbc);

      }

  

-     /*

-      * Associate the new credentials with the connection.  Note that

-      * clientDN and clientCert may be NULL.

-      */

-     bind_credentials_set_nolock(conn, SLAPD_AUTH_SSL, clientDN,

-                                 SLAPD_AUTH_SSL, clientDN, clientCert, NULL);

  done:

      slapi_ch_free_string(&subject);

      slapi_ch_free_string(&cipher);

@@ -0,0 +1,60 @@ 

+ /** BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK **/

+ 

+ #ifdef HAVE_CONFIG_H

+ #include <config.h>

+ #endif

+ 

+ #include <slapi-internal-v4.h>

+ 

+ void

+ slapi_v4_bv_free(struct berval *v) {

+     if (v != NULL) {

+         spal_free(v->bv_val);

+         spal_free(v);

+     }

+ }

+ 

+ /* Create a bvarray */

+ struct berval **

+ slapi_v4_bvarray_create() {

+     /* Allocate a default size. */

+     return (struct berval **)spal_calloc(sizeof(struct berval *));

+ }

+ 

+ /* Destroy it */

+ void

+ slapi_v4_bvarray_destroy(struct berval **array) {

+     for(size_t i = 0; array[i] != NULL; i++) {

+         slapi_ch_bvfree(&(array[i]));

+     }

+     spal_free(array);

+ }

+ 

+ /* Push back */

+ struct berval **

+ slapi_v4_bvarray_append(struct berval **array, struct berval *bv) {

+     size_t i= 0;

+     for(; array[i] != NULL; i++) {

+     }

+ 

+     array = (struct berval **)spal_realloc((char *)array, sizeof(struct berval *) * (i + 2));

+ 

+     array[i] = bv;

+     array[i + 1] = NULL;

+ 

+     return array;

+ }

+ 

+ /* fold */

+ void

+ slapi_v4_bvarray_fold(struct berval **array, void (*fn)(struct berval *bv, void *acc, void *arg), void *acc, void *arg){

+     for(size_t i = 0; array[i] != NULL; i++) {

+         fn(array[i], acc, arg);

+     }

+ }

@@ -0,0 +1,128 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ /* For NSS certificate parsing */

+ #include <cert.h>

+ 

+ /*

+  * To fix a compiler warning here: cert.h pulls

+  * in prcpucfg.h which defines LINUX as empty.

+  * However, config.h defines it to 1, so we need

+  * to undefined it after cert.h to let config.h

+  * do it's job.

+  */

+ 

+ #undef LINUX

+ 

+ #include <slapi-internal-v4.h>

+ 

+ static const int SEC_OID_AVA_UNKNOWN = 0; /* unknown OID */

+ 

+ char *

+ slapi_v4_cert_get_subjectdn(slapi_v4_cert *cert) {

+     return CERT_NameToAscii(&cert->subject);

+ }

+ 

+ char *

+ slapi_v4_cert_get_issuerdn(slapi_v4_cert *cert) {

+     return CERT_NameToAscii(&cert->issuer);

+ }

+ 

+ struct berval *

+ slapi_v4_cert_get_der_berval(slapi_v4_cert *cert) {

+     /* Construct a berval and return it. */

+     struct berval *bp = (struct berval *)spal_calloc(sizeof(struct berval));

+ 

+     SECItem derCert = cert->derCert;

+ 

+     bp->bv_len = derCert.len;

+     bp->bv_val = spal_calloc(derCert.len);

+ 

+     memcpy(bp->bv_val, derCert.data, derCert.len);

+     return bp;

+ }

+ 

+ static int

+ slapi_v4_cert_name_to_secoid(const char *attr) {

+     if (!strcasecmp(attr, "c")) {

+         return SEC_OID_AVA_COUNTRY_NAME;

+     } else if (!strcasecmp(attr, "o")) {

+         return SEC_OID_AVA_ORGANIZATION_NAME;

+     } else if (!strcasecmp(attr, "cn")) {

+         return SEC_OID_AVA_COMMON_NAME;

+     } else if (!strcasecmp(attr, "l")) {

+         return SEC_OID_AVA_LOCALITY;

+     } else if (!strcasecmp(attr, "st")) {

+         return SEC_OID_AVA_STATE_OR_PROVINCE;

+     } else if (!strcasecmp(attr, "ou")) {

+         return SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME;

+     } else if (!strcasecmp(attr, "uid")) {

+         return SEC_OID_RFC1274_UID;

+     } else if (!strcasecmp(attr, "e")) {

+         return SEC_OID_PKCS9_EMAIL_ADDRESS;

+     } else if (!strcasecmp(attr, "mail")) {

+         return SEC_OID_RFC1274_MAIL;

+     } else if (!strcasecmp(attr, "dc")) {

+         return SEC_OID_AVA_DC;

+     }

+ 

+     return SEC_OID_AVA_UNKNOWN;

+ }

+ 

+ static char **

+ slapi_v4_cert_get_ava_val(CERTName *dn, const char *attr) {

+     int attr_tag = slapi_v4_cert_name_to_secoid(attr);

+     char **result = NULL;

+ 

+     if (attr_tag == SEC_OID_AVA_UNKNOWN) {

+         return NULL;

+     }

+ 

+     CERTRDN **rdns = dn->rdns;

+     if (rdns == NULL) {

+         return NULL;

+     }

+ 

+     for (size_t i = 0; rdns[i] != NULL; i++) {

+         CERTRDN *rdn = rdns[i];

+         CERTAVA **avas = rdn->avas;

+ 

+         for (size_t j = 0; avas[j] != NULL; j++) {

+             CERTAVA *ava = avas[j];

+             if (attr_tag == CERT_GetAVATag(ava)) {

+                 /*

+                  * In the original implementation we need to trim

+                  * the ava value here else it will fail to be parsed.

+                  */

+                 size_t datalen = ava->value.len + 4;

+                 char *data = spal_calloc(datalen);

+ 

+                 int offset = 2;

+                 if (ava->value.len >= 128) {

+                     offset = 3;

+                 }

+ 

+                 int rv = CERT_RFC1485_EscapeAndQuote(data, datalen, (char *)(ava->value.data + offset), ava->value.len - offset);

+                 if (rv == SECSuccess) {

+                     slapi_ch_array_add(&result, data);

+                 }

+                 break;

+             }

+         }

+ 

+     }

+ 

+     return result;

+ }

+ 

+ char **

+ slapi_v4_cert_get_subject_ava_val(slapi_v4_cert *cert, const char *attr) {

+     CERTName *dn = &(cert->subject);

+     return slapi_v4_cert_get_ava_val(dn, attr);

+ }

+ 

@@ -158,7 +158,8 @@ 

  char *

  slapi_ch_calloc(

      unsigned long nelem,

-     unsigned long size)

+     unsigned long size

+ )

  {

      char *newmem;

  

file modified
+14 -2
@@ -62,6 +62,13 @@ 

      return n;

  }

  

+ char **

+ slapi_v4_charray_append(char **a, char *s) {

+     char **ptr = a;

+     charray_add(&ptr, s);

+     return ptr;

+ }

+ 

  void

  charray_merge(

      char ***a,
@@ -201,11 +208,13 @@ 

  

      for (a = array; *a != NULL; a++) {

          char *tmp = *a;

-         slapi_ch_free((void **)&tmp);

+         spal_free(tmp);

      }

-     slapi_ch_free((void **)&array);

+     spal_free(array);

  }

  

+ void slapi_v4_charray_free(char **array) __attribute__((weak, alias("charray_free")));

+ 

  /*

   * charray_free version for plugins: there is a need for plugins to free

   * the ch_arrays returned by functions like:
@@ -322,6 +331,9 @@ 

      return (slapi_str2charray_ext(str, brkstr, 1));

  }

  

+ char **

+ slapi_v4_charray_from_str(char *str, char *brkstr) __attribute__((weak, alias("slapi_str2charray")));

+ 

  /*

   * extended version of str2charray lets you disallow

   * duplicate values into the array.

file modified
+15 -9
@@ -27,7 +27,7 @@ 

  #include <sys/stat.h>

  #include <prio.h>

  

- #define MAXARGS 1000

+ #include <slapi-internal-v4.h>

  

  extern int should_detach;

  extern Slapi_PBlock *repl_pb;
@@ -334,14 +334,10 @@ 

                  }

  #endif

                  /* see if the entry is a child of the plugin base dn */

-                 if (slapi_sdn_isparent(&plug_dn,

-                                        slapi_entry_get_sdn_const(e))) {

-                     if (entry_has_attr_and_value(e, "objectclass",

-                                                  "nsSlapdPlugin", 0) &&

-                         (entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,

-                                                   "syntax", 0) ||

-                          entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,

-                                                   "matchingrule", 0))) {

+                 if (slapi_sdn_isparent(&plug_dn, slapi_entry_get_sdn_const(e))) {

+                     if (entry_has_attr_and_value(e, "objectclass", "nsSlapdPlugin", 0) &&

+                         (entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE, "syntax", 0) ||

+                          entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE, "matchingrule", 0))) {

                          /* add the syntax/matching scheme rule plugin */

                          if (plugin_setup(e, 0, 0, 1, returntext)) {

                              slapi_log_err(SLAPI_LOG_ERR, "slapd_bootstrap_config",
@@ -351,6 +347,16 @@ 

                              slapi_sdn_done(&plug_dn);

                              goto bail;

                          }

+                     } else if (entry_has_attr_and_value(e, "objectclass", "nsDylibPlugin4", 0)) {

+                         plugin_v4_result p_result = plugin_v4_setup(e);

+                         if (p_result != PLUGIN_V4_SUCCESS) {

+                             slapi_log_err(SLAPI_LOG_ERR, "slapd_bootstrap_config",

+                                 "The plugin entry [%s] in the configfile %s was invalid. %d\n",

+                                 slapi_entry_get_dn(e), configfile, p_result);

+                             rc = 0;

+                             slapi_sdn_done(&plug_dn);

+                             goto bail;

+                         }

                      }

                  }

  

@@ -22,6 +22,7 @@ 

  #include "log.h"

  #include "slap.h"

  #include "pw.h"

+ #include <slapi-internal-v4.h>

  

  static int check_all_maxdiskspace_and_mlogsize(Slapi_PBlock *pb, LDAPMod **mod, char *returntext);

  static int is_delete_a_replace(LDAPMod **mods, int mod_count);
@@ -368,6 +369,26 @@ 

  }

  

  int

+ load_plugin_v4_entry(Slapi_PBlock *pb __attribute__((unused)),

+                   Slapi_Entry* e,

+                   Slapi_Entry* ignored __attribute__((unused)),

+                   int *returncode,

+                   char *returntext __attribute__((unused)),

+                   void *arg __attribute__((unused)))

+ {

+     plugin_v4_result p_result = plugin_v4_setup(e);

+     if (p_result != PLUGIN_V4_SUCCESS) {

+         slapi_log_err(SLAPI_LOG_ERR, "load_plugin_v4_entry",

+             "The plugin entry [%s] is invalid. %d\n",

+             slapi_entry_get_dn(e), p_result);

+         exit(1);

+     }

+ 

+     *returncode = (int)p_result;

+     return SLAPI_DSE_CALLBACK_OK;

+ }

+ 

+ int

  modify_config_dse(Slapi_PBlock *pb,

                    Slapi_Entry *entryBefore __attribute__((unused)),

                    Slapi_Entry *e,

@@ -27,6 +27,8 @@ 

  #include <netinet/tcp.h> /* for TCP_CORK */

  #endif

  

+ #include <slapi-internal-v4.h>

+ 

  typedef Connection work_q_item;

  static void connection_threadmain(void);

  static void connection_add_operation(Connection *conn, Operation *op);
@@ -1594,7 +1596,14 @@ 

              g_decr_active_threadcnt();

              return;

          }

+         /* Get our plugins ready. */

+         if (plugin_v4_start_operation() != PLUGIN_V4_SUCCESS) {

+             slapi_log_err(SLAPI_LOG_CRIT, "connection_threadmain", "Failed to init plugins for operation\n");

+             goto done;

+         }

+ 

          maxthreads = conn->c_max_threads_per_conn;

+ 

          more_data = 0;

          ret = connection_read_operation(conn, op, &tag, &more_data);

          if ((ret == CONN_DONE) || (ret == CONN_TIMEDOUT)) {
@@ -1753,6 +1762,15 @@ 

          connection_dispatch_operation(conn, op, pb);

  

      done:

+         /*

+          * Operation is complete, yield the plugin list.

+          * Future william: Should plugin tls be part of operation instead?

+          */

+         if (plugin_v4_close_operation() != PLUGIN_V4_SUCCESS) {

+             /* This is a recoverable error, but may leak memory. */

+             slapi_log_err(SLAPI_LOG_CRIT, "connection_threadmain", "closing plugin after operation failed!\n");

+         }

+ 

          if (doshutdown) {

              pthread_mutex_lock(&(conn->c_mutex));

              connection_remove_operation_ext(pb, conn, op);

@@ -56,6 +56,8 @@ 

  #include <ssl.h>

  #include "fe.h"

  

+ #include <slapi-internal-v4.h>

+ 

  #if defined(ENABLE_LDAPI)

  #include "getsocketpeer.h"

  #endif /* ENABLE_LDAPI */
@@ -1228,6 +1230,13 @@ 

       */

      connection_table_free(the_connection_table);

      the_connection_table = NULL;

+     /*

+      * Shutdown all plugin_v4 components.

+      */

+     if (plugin_v4_shutdown() != PLUGIN_V4_SUCCESS) {

+         slapi_log_err(SLAPI_LOG_WARNING, "slapd_daemon",

+             "Unable to cleanly stop plugin v4 subsystem. Some resources may leak ...\n");

+     }

  

      if (!in_referral_mode) {

          /* Close SNMP collator after the plugins closed...

file modified
+20 -7
@@ -2010,6 +2010,9 @@ 

  }

  

  Slapi_DN *

+ slapi_v4_sdn_new_from_char_dn(const char *dn) __attribute__((weak, alias("slapi_sdn_new_dn_byval")));

+ 

+ Slapi_DN *

  slapi_sdn_new_ndn_byval(const char *ndn)

  {

      Slapi_DN *sdn = slapi_sdn_new();
@@ -2322,21 +2325,28 @@ 

  }

  

  void

- slapi_sdn_free(Slapi_DN **sdn)

- {

-     if (sdn != NULL && *sdn != NULL) {

+ slapi_v4_sdn_free(Slapi_DN *sdn) {

+     if (sdn != NULL) {

          int is_allocated = 0;

-         SDN_DUMP(*sdn, "slapi_sdn_free");

-         is_allocated = slapi_isbitset_uchar((*sdn)->flag, FLAG_ALLOCATED);

-         slapi_sdn_done(*sdn);

+         SDN_DUMP(sdn, "slapi_sdn_free");

+         is_allocated = slapi_isbitset_uchar(sdn->flag, FLAG_ALLOCATED);

+         slapi_sdn_done(sdn);

          if (is_allocated) {

-             slapi_ch_free((void **)sdn);

+             spal_free(sdn);

              PR_INCREMENT_COUNTER(slapi_sdn_counter_deleted);

              PR_DECREMENT_COUNTER(slapi_sdn_counter_exist);

          }

      }

  }

  

+ void

+ slapi_sdn_free(Slapi_DN **sdn)

+ {

+     if (sdn != NULL) {

+         slapi_v4_sdn_free(*sdn);

+     }

+ }

+ 

  const char *

  slapi_sdn_get_dn(const Slapi_DN *sdn)

  {
@@ -2471,6 +2481,9 @@ 

      return tmp;

  }

  

+ Slapi_DN *

+ slapi_v4_sdn_dup(const Slapi_DN *sdn) __attribute__((weak, alias("slapi_sdn_dup")));

+ 

  void

  slapi_sdn_copy(const Slapi_DN *from, Slapi_DN *to)

  {

file modified
+22 -15
@@ -44,6 +44,8 @@ 

  

  #include <unistd.h> /* provides fsync/close */

  

+ #include <slapi-internal-v4.h>

+ 

  /* #define SLAPI_DSE_DEBUG */ /* define this to force trace log    */

                                /* messages to always be logged        */

  
@@ -1940,6 +1942,10 @@ 

                          goto done;

                      }

                  }

+             } else if (slapi_entry_attr_hasvalue(ecc, SLAPI_ATTR_OBJECTCLASS, "nsDylibPlugin4")) {

+                 /* Let the plugin know it's being modified. */

+                 /* It will work out what actions need to be taken. */

+                 plugin_v4_modify(ecc);

              }

          }

      }
@@ -2156,14 +2162,15 @@ 

  {

      int rc = LDAP_SUCCESS;

  

-     if (!slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsSlapdPlugin") ||

-         !config_get_dynamic_plugins()) {

-         /*

-          * This is not a plugin, or we are not allowing dynamic updates.

-          */

-         return rc;

+     if (slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsSlapdPlugin") &&

+         config_get_dynamic_plugins()) {

+         rc = plugin_add(entry, returntext, 0 /* not locked */);

+     } else if (slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsDylibPlugin4")) {

+         plugin_v4_result result = plugin_v4_add(entry);

+         if (result != PLUGIN_V4_SUCCESS) {

+             rc = LDAP_UNWILLING_TO_PERFORM;

+         }

      }

-     rc = plugin_add(entry, returntext, 0 /* not locked */);

  

      return rc;

  }
@@ -2176,16 +2183,16 @@ 

  {

      int rc = LDAP_SUCCESS;

  

-     if (!slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsSlapdPlugin") ||

-         slapi_entry_attr_hasvalue(entry, "nsslapd-PluginEnabled", "off") ||

+     if (slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsSlapdPlugin") &&

+         slapi_entry_attr_hasvalue(entry, "nsslapd-PluginEnabled", "off") &&

          !config_get_dynamic_plugins()) {

-         /*

-          * This is not a plugin, this plugin was not enabled to begin with, or we

-          * are not allowing dynamic updates .

-          */

-         return rc;

+         rc = plugin_delete(entry, returntext, 0 /* not locked */);

+     } else if (slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, "nsDylibPlugin4")) {

+         plugin_v4_result result = plugin_v4_delete(entry);

+         if (result != PLUGIN_V4_SUCCESS) {

+             rc = LDAP_UNWILLING_TO_PERFORM;

+         }

      }

-     rc = plugin_delete(entry, returntext, 0 /* not locked */);

  

      return rc;

  }

@@ -22,6 +22,8 @@ 

  #include <prcountr.h>

  #include "slap.h"

  

+ #include <slapi-internal-v4.h>

+ 

  #undef ENTRY_DEBUG

  

  #define DELETED_ATTR_STRING ";deletedattribute"
@@ -2085,6 +2087,9 @@ 

      return &e->e_sdn;

  }

  

+ const Slapi_DN *

+ slapi_v4_entry_get_sdn(Slapi_Entry *e) __attribute__((weak, alias("slapi_entry_get_sdn_const")));

+ 

  Slapi_DN *

  slapi_entry_get_sdn(Slapi_Entry *e)

  {
@@ -2698,6 +2703,9 @@ 

      return slapi_entry_attr_get_charray_ext(e, type, &ignore);

  }

  

+ char **

+ slapi_v4_entry_attr_get_charray(const Slapi_Entry *e, const char *type) __attribute__((weak, alias("slapi_entry_attr_get_charray")));

+ 

  /*

   * The extension also gathers the number of values.

   * The caller must free with slapi_ch_array_free
@@ -2755,6 +2763,27 @@ 

      return p;

  }

  

+ struct berval **

+ slapi_v4_entry_attr_get_bervals(const Slapi_Entry *e, const char *type) {

+ 

+     struct berval **bervals = {0};

+     Slapi_Attr *attr = NULL;

+     slapi_entry_attr_find(e, type, &attr);

+ 

+     if (attr != NULL) {

+         bervals = slapi_v4_bvarray_create();

+         int hint;

+         Slapi_Value *v = NULL;

+ 

+         for (hint = slapi_attr_first_value(attr, &v); hint != -1; hint = slapi_attr_next_value(attr, hint, &v)) {

+             struct berval *bvp = slapi_ch_bvdup(slapi_value_get_berval(v));

+             bervals = slapi_v4_bvarray_append(bervals, bvp);

+         }

+     }

+ 

+     return bervals;

+ }

+ 

  /* returned value: attribute value as an integer type */

  int

  slapi_entry_attr_get_int(const Slapi_Entry *e, const char *type)

@@ -42,6 +42,7 @@ 

  #include "slap.h"

  #include "fe.h"

  #include <pwd.h>

+ #include <slapi-internal-v4.h>

  

  extern char **getSupportedCiphers(void);

  extern char **getEnabledCiphers(void);
@@ -2535,6 +2536,7 @@ 

  static struct dse *pfedse = NULL;

  

  static int check_plugin_path(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg);

+ static int check_plugin_v4(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg);

  

  static void

  internal_add_helper(Slapi_Entry *e, int dont_write_file)
@@ -2582,6 +2584,9 @@ 

          dse_register_callback(pfedse, DSE_OPERATION_READ, DSE_FLAG_PREOP, config,

                                LDAP_SCOPE_BASE, "(objectclass=*)",

                                load_config_dse, NULL, NULL);

+         dse_register_callback(pfedse, DSE_OPERATION_READ, DSE_FLAG_PREOP, config,

+                               LDAP_SCOPE_SUBTREE, "(objectclass=nsDylibPlugin4)",

+                               load_plugin_v4_entry, NULL, NULL);

  

          slapi_pblock_set(pb, SLAPI_CONFIG_DIRECTORY, (void *)configdir);

          /* don't write out the file when reading */
@@ -2865,6 +2870,7 @@ 

          dse_register_callback(pfedse, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, &root, LDAP_SCOPE_BASE, "(objectclass=*)", modify_root_dse, NULL, NULL);

          dse_register_callback(pfedse, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, &saslmapping, LDAP_SCOPE_SUBTREE, "(objectclass=nsSaslMapping)", sasl_map_config_modify, NULL, NULL);

          dse_register_callback(pfedse, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsSlapdPlugin)", check_plugin_path, NULL, NULL);

+         dse_register_callback(pfedse, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsDylibPlugin4)", check_plugin_v4, NULL, NULL);

  

          /* Delete */

          dse_register_callback(pfedse, SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, &config, LDAP_SCOPE_BASE, "(objectclass=*)", dont_allow_that, NULL, NULL);
@@ -2881,6 +2887,7 @@ 

          /* Add */

          dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &saslmapping, LDAP_SCOPE_SUBTREE, "(objectclass=nsSaslMapping)", sasl_map_config_add, NULL, NULL);

          dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsSlapdPlugin)", check_plugin_path, NULL, NULL);

+         dse_register_callback(pfedse, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, &plugins, LDAP_SCOPE_SUBTREE, "(objectclass=nsDylibPlugin4)", check_plugin_v4, NULL, NULL);

  

          be = be_new_internal(pfedse, "DSE", DSE_BACKEND, &fedse_plugin);

          be_addsuffix(be, &root);
@@ -3026,3 +3033,32 @@ 

  

      return rc;

  }

+ 

+ static int

+ check_plugin_v4(Slapi_PBlock *pb __attribute__((unused)),

+                   Slapi_Entry* entryBefore,

+                   Slapi_Entry* e,

+                   int *returncode,

+                   char *returntext,

+                   void *arg __attribute__((unused)))

+ {

+     int rc = SLAPI_DSE_CALLBACK_OK;

+ 

+     plugin_v4_result result = {0};

+ 

+     if (e == NULL) {

+         /* The add case uses entryBefore */

+         result = plugin_v4_validate(entryBefore);

+     } else {

+         result = plugin_v4_validate(e);

+     }

+     /* Validate logs it's own error message for admin. */

+ 

+     if (result != PLUGIN_V4_SUCCESS) {

+         *returncode = LDAP_UNWILLING_TO_PERFORM;

+         PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid plugin configuration");

+         rc = SLAPI_DSE_CALLBACK_ERROR;

+     }

+     return rc;

+ }

+ 

@@ -693,8 +693,8 @@ 

      {CONFIG_SECUREPORT_ATTRIBUTE, config_set_secureport,

       NULL, 0,

       (void **)&global_slapdFrontendConfig.secureport,

-      CONFIG_INT, NULL, NULL, NULL},

-     {CONFIG_BASEDN_ATTRIBUTE, config_set_basedn,

+      CONFIG_INT, NULL, NULL},

+     {CONFIG_BASEDN_ATTRIBUTE, config_set_certmap_basedn,

       NULL, 0,

       (void **)&global_slapdFrontendConfig.certmap_basedn,

       CONFIG_STRING, NULL, NULL, NULL /* deletion is not allowed */},
@@ -6611,7 +6611,7 @@ 

  }

  

  char *

- config_get_basedn(void)

+ config_get_certmap_basedn(void)

  {

      slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();

      char *retVal;
@@ -6624,7 +6624,7 @@ 

  }

  

  int

- config_set_basedn(const char *attrname, char *value, char *errorbuf, int apply)

+ config_set_certmap_basedn(const char *attrname, char *value, char *errorbuf, int apply)

  {

      int retVal = LDAP_SUCCESS;

      slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();

file modified
+25 -44
@@ -29,6 +29,10 @@ 

  #include "log.h"

  #include "fe.h"

  #include <pwd.h> /* getpwnam */

+ 

+ /* Access the log levels enum. */

+ #include <slapi-internal-v4.h>

+ 

  #define _PSEP '/'

  

  #ifdef SYSTEMTAP
@@ -2462,17 +2466,9 @@ 

      return (0);

  }

  

- /*

-  * Log a message to the errors log

-  *

-  * loglevel - The logging level:  replication, plugin, etc

-  * severity - LOG_ERR, LOG_WARNING, LOG_INFO, etc

-  */

- int

- slapi_log_error(int loglevel, char *subsystem, char *fmt, ...)

+ int32_t

+ slapi_log_error_ext(slapi_log_level loglevel, char *subsystem, char *fmt, va_list ap_err, va_list ap_file)

  {

-     va_list ap_err;

-     va_list ap_file;

      int rc = LDAP_SUCCESS;

      int lbackend = loginfo.log_backend; /* We copy this to make these next checks atomic */

  
@@ -2485,33 +2481,19 @@ 

  

      if (slapd_ldap_debug & slapi_log_map[loglevel]) {

          if (lbackend & LOGGING_BACKEND_INTERNAL) {

-             va_start(ap_err, fmt);

-             va_start(ap_file, fmt);

              rc = slapd_log_error_proc_internal(loglevel, subsystem, fmt, ap_err, ap_file);

-             va_end(ap_file);

-             va_end(ap_err);

          }

          if (rc != LDAP_SUCCESS) {

              return (rc);

          }

          if (lbackend & LOGGING_BACKEND_SYSLOG) {

-             va_start(ap_err, fmt);

-             /* va_start( ap_file, fmt ); */

              /* This returns void, so we hope it worked */

              vsyslog(get_syslog_loglevel(loglevel), fmt, ap_err);

-             /* vsyslog(LOG_ERROR, fmt, ap_file); */

-             /* va_end(ap_file); */

-             va_end(ap_err);

          }

  #ifdef HAVE_JOURNALD

          if (lbackend & LOGGING_BACKEND_JOURNALD) {

-             va_start(ap_err, fmt);

-             /* va_start( ap_file, fmt ); */

              /* This isn't handling RC nicely ... */

              rc = sd_journal_printv(get_syslog_loglevel(loglevel), fmt, ap_err);

-             /* rc = sd_journal_printv(LOG_ERROR, fmt, ap_file); */

-             /* va_end(ap_file); */

-             va_end(ap_err);

          }

  #endif

      } else {
@@ -2521,28 +2503,27 @@ 

      return (rc);

  }

  

- int

- slapi_log_error_ext(int loglevel, char *subsystem, char *fmt, va_list varg1, va_list varg2)

- {

-     int rc = 0;

- 

-     if (loglevel < SLAPI_LOG_MIN || loglevel > SLAPI_LOG_MAX) {

-         (void)slapd_log_error_proc(loglevel, subsystem, "slapi_log_error: invalid severity %d (message %s)\n",

-                                    loglevel, fmt);

-         return (-1);

-     }

- 

-     if (slapd_ldap_debug & slapi_log_map[loglevel]) {

-         rc = slapd_log_error_proc_internal(loglevel, subsystem, fmt, varg1, varg2);

-     } else {

-         rc = 0; /* nothing to be logged --> always return success */

-     }

- 

-     return (rc);

+ /*

+  * Log a message to the errors log

+  *

+  * loglevel - The logging level:  replication, plugin, etc

+  * severity - LOG_ERR, LOG_WARNING, LOG_INFO, etc

+  */

+ int32_t

+ slapi_log_error(slapi_log_level loglevel, char *subsystem, char *fmt, ...) {

+     int32_t rc = 0;

+     va_list ap_err;

+     va_list ap_file;

+     va_start(ap_err, fmt);

+     va_start(ap_file, fmt);

+     rc = slapi_log_error_ext(loglevel, subsystem, fmt, ap_err, ap_file);

+     va_end(ap_file);

+     va_end(ap_err);

+     return rc;

  }

  

- int

- slapi_is_loglevel_set(const int loglevel)

+ int32_t

+ slapi_is_loglevel_set(const slapi_log_level loglevel)

  {

      return (slapd_ldap_debug & slapi_log_map[loglevel] ? 1 : 0);

  }

file modified
+28 -5
@@ -54,12 +54,14 @@ 

  #include "slapi-plugin.h"

  #include "prinit.h"

  #include "snmp_collator.h"

- #include "fe.h" /* client_auth_init() */

+ #include "fe.h"

  #include "protect_db.h"

  #include "getopt_ext.h"

  #include "fe.h"

  #include <nss.h>

  

+ #include <slapi-internal-v4.h>

+ 

  #ifdef LINUX

  /* For mallopt. Should be removed soon. */

  #include <malloc.h>
@@ -686,6 +688,15 @@ 

          global_plugin_init();

  

          /*

+          * Initialise the plugin v4 structures and values.

+          */

+         if (plugin_v4_init() != PLUGIN_V4_SUCCESS) {

+             slapi_log_err(SLAPI_LOG_EMERG, "main",

+                 "Unable to initialise plugin v4 subsystem\n");

+             exit(1);

+         }

+ 

+         /*

           * Process the config files.

           */

          if (0 == slapd_bootstrap_config(slapdFrontendConfig->configdir)) {
@@ -1020,6 +1031,17 @@ 

          task_cleanup();

  

          /*

+          * This step checks for any updates and changes on upgrade

+          * specifically, it manages assumptions about what plugins should exist, and their

+          * configurations, and potentially even the state of configurations on the server

+          * and their removal and deprecation.

+          */

+         if (upgrade_server() != UPGRADE_SUCCESS) {

+             return_value = 1;

+             goto cleanup;

+         }

+ 

+         /*

           * Initialize password storage in entry extension.

           * Need to be initialized before plugin_startall in case stucked

           * changes are replicated as soon as the replication plugin is started.
@@ -1028,6 +1050,10 @@ 

  

          plugin_print_lists();

          plugin_startall(argc, argv, NULL /* specific plugin list */);

+         if (plugin_v4_startall() != PLUGIN_V4_SUCCESS) {

+             return_value = 1;

+             goto cleanup;

+         }

          compute_plugins_started();

          (void) rewriters_init();

          if (housekeeping_start((time_t)0, NULL) == NULL) {
@@ -1097,6 +1123,7 @@ 

      reslimit_cleanup();

      vattr_cleanup();

      sasl_map_done();

+     plugin_v4_destroy();

  cleanup:

      slapi_ch_free_string(&(mcfg.myname));

      compute_terminate();
@@ -2894,10 +2921,6 @@ 

          }

      }

  

-     if (slapd_exemode == SLAPD_EXEMODE_SLAPD) {

-         client_auth_init();

-     }

- 

      if (init_ssl && slapd_ssl_init()) {

          if (force_to_disable_security("SSL", &init_ssl, ports_info)) {

              return 1;

@@ -209,6 +209,7 @@ 

          factory_destroy_extension(get_operation_object_type(), *op, conn, &((*op)->o_extension));

          slapi_sdn_done(&(*op)->o_sdn);

          slapi_sdn_free(&(*op)->o_target_spec);

+         (*op)->o_target_spec = NULL;

          slapi_ch_free_string(&(*op)->o_authtype);

          if ((*op)->o_searchattrs != NULL) {

              charray_free((*op)->o_searchattrs);

@@ -3956,6 +3956,9 @@ 

          if (pblock->pb_op != NULL) {

              pblock->pb_op->o_results.r.r_search.nentries = *((int *)value);

          }

+         _pblock_assert_pb_intop(pblock);

+         /* We are given an int, need to extend it */

+         pblock->pb_intop->pb_plugin_internal_search_num_entries = (uint64_t)(*((int *)value));

          break;

      /* Referrals encountered while iterating over the result set */

      case SLAPI_SEARCH_REFERRALS:

@@ -134,6 +134,7 @@ 

  

      /* pointer to array of results returned on search */

      Slapi_Entry **pb_plugin_internal_search_op_entries;

+     uint64_t pb_plugin_internal_search_num_entries;

      char **pb_plugin_internal_search_op_referrals;

      LDAPControl **pb_search_ctrls; /* for search operations, allows plugins to provide

                                        controls to pass for each entry or referral returned */

@@ -0,0 +1,173 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ /*

+  * Replacement of the monolithic pblock into smaller focused

+  * versions.

+  *

+  * Basically the extension of the pblock_v3 breakup and hiding work, but

+  * without needing a super structure wrapper in front.

+  */

+ 

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ 

+ #include "pblock_v3.h"

+ #include <slapi-private-v4.h>

+ 

+ /* NSS cert includes for certcertificate */

+ #include <cert.h>

+ 

+ typedef struct _slapi_v4_certmap_pblock {

+     slapi_v4_dn *sdn;

+     slapi_v4_cert *clientcert;

+ } slapi_v4_certmap_pblock;

+ 

+ slapi_v4_certmap_pblock *

+ slapi_v4_certmap_pblock_init(void) {

+     slapi_v4_certmap_pblock *pbc = (slapi_v4_certmap_pblock *)spal_calloc(sizeof(slapi_v4_certmap_pblock));

+     return pbc;

+ }

+ 

+ slapi_v4_dn *

+ slapi_v4_certmap_pblock_get_clientdn(slapi_v4_certmap_pblock *pbc) {

+     return pbc->sdn;

+ }

+ 

+ void

+ slapi_v4_certmap_pblock_set_clientdn(slapi_v4_certmap_pblock *pbc, slapi_v4_dn *sdn) {

+     pbc->sdn = sdn;

+ }

+ 

+ slapi_v4_cert *

+ slapi_v4_certmap_pblock_get_clientcert(slapi_v4_certmap_pblock *pbc) {

+     return pbc->clientcert;

+ }

+ 

+ void

+ slapi_v4_certmap_pblock_set_clientcert(slapi_v4_certmap_pblock *pbc, slapi_v4_cert *clientcert) {

+     pbc->clientcert = clientcert;

+ }

+ 

+ void

+ slapi_v4_certmap_pblock_destroy(slapi_v4_certmap_pblock *pbc) {

+     slapi_sdn_free(&(pbc->sdn));

+     spal_free(pbc);

+ }

+ 

+ 

+ /*

+  * Search pblock functions.

+  */

+ 

+ /*

+  * To the external world we present a simple api of get/set same as pblock

+  *

+  * But when we go to commit a search, we actually alloc a v3 pblock, and push

+  * this as the intop pblock into it.

+  *

+  * This abstraction means that later we can later remove the v3 layer from the middle

+  * and just go full v4 for search pblock access.

+  */

+ 

+ slapi_v4_search_pblock *

+ slapi_v4_search_pblock_create(void) {

+     slapi_v4_search_pblock *pbs = (slapi_v4_search_pblock *)spal_calloc(sizeof(slapi_v4_search_pblock));

+     return pbs;

+ }

+ 

+ slapi_v4_search_pblock *

+ slapi_v4_search_pblock_extract(Slapi_PBlock *pb) {

+     slapi_v4_search_pblock *pbs = pb->pb_intop;

+     pb->pb_intop = NULL;

+     return pbs;

+ }

+ 

+ void

+ slapi_v4_search_pblock_destroy(slapi_v4_search_pblock *pbs) {

+ 

+     Slapi_Entry **op_entries = pbs->pb_plugin_internal_search_op_entries;

+ 

+     if (op_entries != NULL) {

+         for (size_t i = 0; op_entries[i] != NULL; i++) {

+             slapi_entry_free(op_entries[i]);

+         }

+         spal_free(op_entries);

+     }

+ 

+     char **op_referrals = pbs->pb_plugin_internal_search_op_referrals;

+ 

+     if (op_referrals != NULL) {

+         for (size_t i = 0; op_referrals[i] != NULL; i++) {

+             spal_free(op_referrals[i]);

+         }

+         spal_free(op_referrals);

+     }

+ 

+     if (pbs != NULL) {

+         delete_passwdPolicy(&pbs->pwdpolicy);

+         spal_free(pbs->pb_result_text);

+     }

+     spal_free(pbs);

+ }

+ 

+ uint64_t

+ slapi_v4_search_pblock_get_num_results(slapi_v4_search_pblock *pbs) {

+     return pbs->pb_plugin_internal_search_num_entries;

+ }

+ 

+ Slapi_Entry **

+ slapi_v4_search_pblock_get_entries(slapi_v4_search_pblock *pbs) {

+     return pbs->pb_plugin_internal_search_op_entries;

+ }

+ 

+ char **

+ slapi_v4_search_pblock_get_referrals(slapi_v4_search_pblock *pbs) {

+     return pbs->pb_plugin_internal_search_op_referrals;

+ }

+ 

+ int

+ slapi_v4_search_pblock_get_ldapresult(slapi_v4_search_pblock *pbs) {

+     return pbs->pb_internal_op_result;

+ }

+ 

+ void

+ slapi_v4_search_pblock_merge(slapi_v4_search_pblock *pbs_a, slapi_v4_search_pblock *pbs_b) {

+     /* Check the a and b are valid */

+     if (pbs_a == NULL || pbs_b == NULL) {

+         return;

+     }

+     /* Check the search results of b exist. */

+ 

+     if (pbs_b->pb_plugin_internal_search_num_entries > 0) {

+         /* Merge the content of B into A if any */

+         uint64_t total_entries = pbs_a->pb_plugin_internal_search_num_entries + pbs_b->pb_plugin_internal_search_num_entries;

+         /* Realloc the entry array space. */

+         pbs_a->pb_plugin_internal_search_op_entries = (Slapi_Entry **)spal_realloc((char *)pbs_a->pb_plugin_internal_search_op_entries,

+                                                                        sizeof(Slapi_Entry *) * (total_entries + 1));

+ 

+         for(size_t i = 0; i < pbs_b->pb_plugin_internal_search_num_entries; i++) {

+             /*

+              * This works as if pbs_a->num_ent == 0, we get 0 with i== 0. If we have 1

+              * we get 1, and the entry is at 0. Etc.

+              */

+             size_t offset_a = pbs_a->pb_plugin_internal_search_num_entries + i;

+             pbs_a->pb_plugin_internal_search_op_entries[offset_a] = pbs_b->pb_plugin_internal_search_op_entries[i];

+             pbs_b->pb_plugin_internal_search_op_entries[i] = NULL;

+         }

+         /* Ensure the last slot is null. */

+         pbs_a->pb_plugin_internal_search_op_entries[total_entries] = NULL;

+ 

+         pbs_a->pb_plugin_internal_search_num_entries = total_entries;

+     }

+ 

+     /* Finally, destroy b. */

+     slapi_v4_search_pblock_destroy(pbs_b);

+ }

+ 

+ 

@@ -18,6 +18,9 @@ 

  #include <plhash.h>

  #include "slap.h"

  

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ #include <slapi-private-v4.h>

+ 

  /* this defines are used for plugin configuration */

  #define LOCAL_DATA "local data"

  #define REMOTE_DATA "remote data"

@@ -55,8 +55,8 @@ 

  

  /* forward declarations */

  static int seq_internal_callback_pb(Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc, plugin_search_entry_callback psec, plugin_referral_entry_callback prec);

- static int search_internal_pb(Slapi_PBlock *pb);

  static int search_internal_callback_pb(Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc, plugin_search_entry_callback psec, plugin_referral_entry_callback prec);

+ int search_internal_pb(Slapi_PBlock *pb);

  

  void

  internal_getresult_callback(struct conn *unused1 __attribute__((unused)),
@@ -564,7 +564,7 @@ 

      ((plugin_search_internal_data *)callback_data)->rc = rc;

  }

  

- static int

+ int

  search_internal_pb(Slapi_PBlock *pb)

  {

      plugin_search_internal_data psid;

The added file is too large to be shown here, see it at: ldap/servers/slapd/plugin_v4.c
@@ -349,7 +349,7 @@ 

  int config_set_maxsasliosize(const char *attrname, char *value, char *errorbuf, int apply);

  int config_set_versionstring(const char *attrname, char *versionstring, char *errorbuf, int apply);

  int config_set_enquote_sup_oc(const char *attrname, char *value, char *errorbuf, int apply);

- int config_set_basedn(const char *attrname, char *value, char *errorbuf, int apply);

+ int config_set_certmap_basedn(const char *attrname, char *value, char *errorbuf, int apply);

  int config_set_configdir(const char *attrname, char *value, char *errorbuf, int apply);

  int config_set_instancedir(const char *attrname, char *value, char *errorbuf, int apply);

  int config_set_schemadir(const char *attrname, char *value, char *errorbuf, int apply);
@@ -509,8 +509,7 @@ 

  char *config_get_versionstring(void);

  char *config_get_buildnum(void);

  int config_get_enquote_sup_oc(void);

- char *config_get_basedn(void);

- char *config_get_configdir(void);

+ char *config_get_certmap_basedn(void);

  char *config_get_schemadir(void);

  char *config_get_lockdir(void);

  char *config_get_tmpdir(void);
@@ -621,6 +620,7 @@ 

  int postop_modify_config_dse(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);

  int add_root_dse(Slapi_PBlock *pb);

  int load_plugin_entry(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);

+ int load_plugin_v4_entry(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);

  

  

  /*

@@ -0,0 +1,127 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #pragma once

+ 

+ #include <slap.h>

+ 

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ 

+ #include <slapi-private-v4.h>

+ 

+ /**

+  * Internal implementation details of the slapi-plugin v4 call system

+  *

+  * This is how the server INTERNALLY manages plugins. Unless you are working

+  * inside of ns-slapd, libslapd, you will *never* need to include this file.

+  */

+ 

+ typedef enum _plugin_v4_result {

+     PLUGIN_V4_SUCCESS,

+     PLUGIN_V4_INVALID_CONFIG,

+     PLUGIN_V4_NULL_POINTER,

+     PLUGIN_V4_DUPLICATE,

+     PLUGIN_V4_RESOURCE,

+     PLUGIN_V4_INVALID_PLUGIN,

+     PLUGIN_V4_UNKNOWN,

+     PLUGIN_V4_INVALID_STATE,

+ } plugin_v4_result;

+ 

+ /*

+  * I think we need a result -> str table.

+  */

+ 

+ plugin_v4_result plugin_v4_init();

+ plugin_v4_result plugin_v4_shutdown();

+ void plugin_v4_destroy();

+ 

+ plugin_v4_result plugin_v4_validate(struct slapi_entry *plugin_entry);

+ 

+ /**

+  * This is called with an entry to setup a plugin

+  */

+ plugin_v4_result plugin_v4_startall();

+ plugin_v4_result plugin_v4_stopall();

+ 

+ plugin_v4_result plugin_v4_modify(struct slapi_entry *plugin_entry);

+ plugin_v4_result plugin_v4_add(struct slapi_entry *plugin_entry);

+ plugin_v4_result plugin_v4_setup(struct slapi_entry *plugin_entry);

+ plugin_v4_result plugin_v4_delete(struct slapi_entry *plugin_entry);

+ 

+ typedef struct _slapi_v4_plugin_registration {

+     /*

+      * The name of the plugin. We will enforce this matches

+      * the cn.

+      */

+     char *sv4_name;

+     /*

+      * Plugin order of operation precedence.

+      */

+     uint64_t precedence;

+     /*

+      * This function is called *before* the plugin starts

+      * and guarantees no operations will start until

+      * this function is completed. It's guaranteed that

+      * close will not run until start is complete.

+      */

+     slapi_v4_plugin_result *(*sv4_start_fn)(void **ctx);

+     /*

+      * This function is called *after* the plugin has stopped

+      * processing any operations. This allows you to free and

+      * stop and resources from your operation. It's guaranteed

+      * that no other plugin fn will run at the same time as this.

+      */

+     slapi_v4_plugin_result *(*sv4_close_fn)(void **ctx);

+     /*

+      * Map certificate details to an entry for bind.

+      */

+     slapi_v4_plugin_result *(*sv4_bind_certmap_fn)(void *ctx, slapi_v4_certmap_pblock *pbc);

+ 

+ } slapi_v4_plugin_registration;

+ 

+ slapi_v4_plugin_registration * slapi_v4_plugin_registration_create();

+ void slapi_v4_plugin_registration_destroy(slapi_v4_plugin_registration *pr);

+ 

+ /*

+  * Internal result handling from operations.

+  */

+ int64_t slapi_v4_plugin_result_is_ok(slapi_v4_plugin_result *result);

+ 

+ /*

+  * PLUGIN CALLBACK HOOKS

+  *

+  * These are the functions that we call to trigger plugin operations.

+  */

+ plugin_v4_result plugin_v4_start_operation();

+ plugin_v4_result plugin_v4_close_operation();

+ plugin_v4_result plugin_v4_call_bind_certmap();

+ 

+ /*

+  * Internal pblock operations

+  */

+ 

+ slapi_v4_search_pblock * slapi_v4_search_pblock_extract(Slapi_PBlock *pb);

+ slapi_v4_search_pblock * slapi_v4_search_pblock_create();

+ /* Merge the results of B into A */

+ void slapi_v4_search_pblock_merge(slapi_v4_search_pblock *pbs_a, slapi_v4_search_pblock *pbs_b);

+ 

+ /* from plugin-internal-op */

+ int search_internal_pb(Slapi_PBlock *pb);

+ 

+ 

+ /*

+  * SERVER UPGRADE INTERNALS

+  */

+ typedef enum _upgrade_status {

+     UPGRADE_SUCCESS = 0,

+     UPGRADE_FAILURE = 1,

+ } upgrade_status;

+ 

+ upgrade_status upgrade_server(void);

+ 

@@ -0,0 +1,70 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ 

+ #include <slapi-internal-v4.h>

+ #include <string.h>

+ 

+ slapi_v4_plugin_result *

+ slapi_v4_plugin_result_ok(void) {

+     /*

+      * A potential (and premature, and probably silly)

+      * optimisation here is OK is == NULL, to avoid an alloc / free.

+      *

+      * However, this may interfere with FFI which may expect a value.

+      * provided we *don't* offer an api that allows modification of a

+      * result post creation, it's a possibility.

+      */

+     slapi_v4_plugin_result *res = (slapi_v4_plugin_result *)spal_calloc(sizeof(slapi_v4_plugin_result));

+     res->result = SLAPI_V4_PLUGIN_SUCCESS;

+     return res;

+ }

+ 

+ slapi_v4_plugin_result *

+ slapi_v4_plugin_result_err(SV4_PLUGIN_RESULT_CODE result, int ldap_code, char *msg) {

+     slapi_v4_plugin_result *res = (slapi_v4_plugin_result *)spal_calloc(sizeof(slapi_v4_plugin_result));

+     res->result = result;

+     res->ldap_code = ldap_code;

+     res->msg = msg;

+     return res;

+ }

+ 

+ void

+ slapi_v4_plugin_result_destroy(slapi_v4_plugin_result *r) {

+     if (r != NULL) {

+         spal_free(r->msg);

+         spal_free(r);

+     }

+ }

+ 

+ void

+ slapi_v4_plugin_register_name(slapi_v4_plugin_registration *pr, char *name) {

+     pr->sv4_name = strdup(name);

+ }

+ 

+ void

+ slapi_v4_plugin_register_precedence(slapi_v4_plugin_registration *pr, uint64_t order) {

+     pr->precedence = order;

+ }

+ 

+ void

+ slapi_v4_plugin_register_start_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_start_fn)(void **ctx)) {

+     pr->sv4_start_fn = sv4_start_fn;

+ }

+ 

+ void

+ slapi_v4_plugin_register_close_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_close_fn)(void **ctx)) {

+     pr->sv4_close_fn = sv4_close_fn;

+ }

+ 

+ void

+ slapi_v4_plugin_register_bind_certmap_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_bind_certmap_fn)(void *ctx, slapi_v4_certmap_pblock *pbc)) {

+     pr->sv4_bind_certmap_fn = sv4_bind_certmap_fn;

+ }

@@ -0,0 +1,74 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #pragma once

+ 

+ #ifndef SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #error slapi plugin v4 is *not* stabilised for release. DO NOT USE IT.

+ #endif

+ 

+ #include <slapi_pal.h>

+ 

+ #include <stdlib.h>

+ #include <ldap.h>

+ 

+ /* Provides va_list */

+ #include <stdarg.h>

+ 

+ 

+ /*

+  * Logging

+  */

+ 

+ /* allowed values for the "severity" parameter */

+ /* THESE MUST MATCH SLAPI-PLUGIN.h */

+ typedef enum _slapi_log_level {

+     SLAPI_LOG_FATAL =       0,

+     SLAPI_LOG_TRACE =       1,

+     SLAPI_LOG_PACKETS =     2,

+     SLAPI_LOG_ARGS =        3,

+     SLAPI_LOG_CONNS =       4,

+     SLAPI_LOG_BER =         5,

+     SLAPI_LOG_FILTER =      6,

+     SLAPI_LOG_CONFIG =      7,

+     SLAPI_LOG_ACL =         8,

+     SLAPI_LOG_SHELL =       9,

+     SLAPI_LOG_PARSE =      10,

+     SLAPI_LOG_HOUSE =      11,

+     SLAPI_LOG_REPL =       12,

+     SLAPI_LOG_CACHE =      13,

+     SLAPI_LOG_PLUGIN =     14,

+     SLAPI_LOG_TIMING  =    15,

+     SLAPI_LOG_BACKLDBM =   16,

+     SLAPI_LOG_ACLSUMMARY = 17,

+     SLAPI_LOG_NUNCSTANS =  18,

+     SLAPI_LOG_EMERG =      19,

+     SLAPI_LOG_ALERT =      20,

+     SLAPI_LOG_CRIT =       21,

+     SLAPI_LOG_ERR =        22,

+     SLAPI_LOG_WARNING =    23,

+     SLAPI_LOG_NOTICE =     24,

+     SLAPI_LOG_INFO =       25,

+     SLAPI_LOG_DEBUG =      26,

+ } slapi_log_level;

+ 

+ /* The last level must be set in log.c: SLAPI_LOG_MAX */

+ 

+ int32_t slapi_log_error(slapi_log_level loglevel, char *subsystem, char *fmt, ...)

+ #ifdef __GNUC__

+     __attribute__((format(printf, 3, 4)));

+ #else

+     ;

+ #endif

+ 

+ int32_t slapi_log_error_ext(slapi_log_level loglevel, char *subsystem, char *fmt, va_list varg1, va_list varg2);

+ 

+ 

+ int32_t slapi_is_loglevel_set(const slapi_log_level loglevel);

+ 

+ 

@@ -27,6 +27,9 @@ 

  extern "C" {

  #endif

  

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #include <slapi-plugin-v4.h>

+ 

  /* Provides our int types and platform specific requirements. */

  #include "slapi_pal.h"

  #include "prtypes.h"
@@ -6023,51 +6026,6 @@ 

  int slapi_register_plugin_ext(const char *plugintype, int enabled, const char *initsymbol, slapi_plugin_init_fnptr initfunc, const char *name, char **argv, void *group_identity, int precedence);

  

  /*

-  * logging

-  */

- int slapi_log_error(int loglevel, char *subsystem, char *fmt, ...)

- #ifdef __GNUC__

-     __attribute__((format(printf, 3, 4)));

- #else

-     ;

- #endif

- 

- int slapi_log_error_ext(int loglevel, char *subsystem, char *fmt, va_list varg1, va_list varg2);

- 

- /* allowed values for the "severity" parameter */

- #define SLAPI_LOG_FATAL       0

- #define SLAPI_LOG_TRACE       1

- #define SLAPI_LOG_PACKETS     2

- #define SLAPI_LOG_ARGS        3

- #define SLAPI_LOG_CONNS       4

- #define SLAPI_LOG_BER         5

- #define SLAPI_LOG_FILTER      6

- #define SLAPI_LOG_CONFIG      7

- #define SLAPI_LOG_ACL         8

- #define SLAPI_LOG_SHELL       9

- #define SLAPI_LOG_PARSE      10

- #define SLAPI_LOG_HOUSE      11

- #define SLAPI_LOG_REPL       12

- #define SLAPI_LOG_CACHE      13

- #define SLAPI_LOG_PLUGIN     14

- #define SLAPI_LOG_TIMING     15

- #define SLAPI_LOG_BACKLDBM   16

- #define SLAPI_LOG_ACLSUMMARY 17

- #define SLAPI_LOG_NUNCSTANS  18

- /* Severity levels */

- #define SLAPI_LOG_EMERG      19

- #define SLAPI_LOG_ALERT      20

- #define SLAPI_LOG_CRIT       21

- #define SLAPI_LOG_ERR        22

- #define SLAPI_LOG_WARNING    23

- #define SLAPI_LOG_NOTICE     24

- #define SLAPI_LOG_INFO       25

- #define SLAPI_LOG_DEBUG      26 /* The last level must be set in log.c: SLAPI_LOG_MAX */

- 

- int slapi_is_loglevel_set(const int loglevel);

- 

- 

- /*

   * locks and synchronization

   */

  typedef struct slapi_mutex Slapi_Mutex;

@@ -0,0 +1,131 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #include <slapi-internal-v4.h>

+ 

+ slapi_v4_plugin_registration *

+ slapi_v4_plugin_registration_create() {

+     slapi_v4_plugin_registration *pr = (slapi_v4_plugin_registration *)spal_calloc(sizeof(slapi_v4_plugin_registration));

+     return pr;

+ }

+ 

+ void

+ slapi_v4_plugin_registration_destroy(slapi_v4_plugin_registration *pr) {

+     spal_free(pr->sv4_name);

+     spal_free(pr);

+ }

+ 

+ 

+ /* Internal search helper functions. */

+ 

+ slapi_v4_search_pblock *

+ slapi_v4_search_internal(Slapi_DN *basedn,

+                          int32_t scope,

+                          const char *filter,

+                          char **attrs,

+                          int32_t attrsonly,

+                          LDAPControl **controls,

+                          const char *uniqueid,

+                          int32_t operation_flags)

+ {

+     /*

+      * This setups the search pblock similar to slapi_search_internal_set_pb_ext

+      * followed by calling search_internal_pb

+      */

+ 

+     Slapi_PBlock *int_pbs = slapi_pblock_new();

+     /* Allocate a new operation */

+     Operation *op = internal_operation_new(SLAPI_OPERATION_SEARCH, operation_flags);

+     slapi_pblock_set(int_pbs, SLAPI_OPERATION, op);

+ 

+     /* Setup the search pb */

+     slapi_pblock_set(int_pbs, SLAPI_ORIGINAL_TARGET_DN, (void *)slapi_sdn_get_udn(basedn));

+     slapi_pblock_set(int_pbs, SLAPI_TARGET_SDN, (void *)basedn);

+     slapi_pblock_set(int_pbs, SLAPI_SEARCH_SCOPE, &scope);

+     slapi_pblock_set(int_pbs, SLAPI_SEARCH_STRFILTER, (void *)filter);

+     slapi_pblock_set(int_pbs, SLAPI_CONTROLS_ARG, controls);

+     /* forbidden attrs could be removed in slapi_pblock_set. */

+     char **tmp_attrs = slapi_ch_array_dup(attrs);

+     slapi_pblock_set(int_pbs, SLAPI_SEARCH_ATTRS, tmp_attrs);

+     slapi_pblock_set(int_pbs, SLAPI_SEARCH_ATTRSONLY, &attrsonly);

+     slapi_pblock_set(int_pbs, SLAPI_TARGET_UNIQUEID, (void *)uniqueid);

+ 

+     /* Do the search */

+     search_internal_pb(int_pbs);

+     /* Check the result. */

+ 

+     /* Now undefined the pb_search from pb so we can free pb*/

+     slapi_v4_search_pblock *pbs = slapi_v4_search_pblock_extract(int_pbs);

+     slapi_pblock_destroy(int_pbs);

+     return pbs;

+ }

+ 

+ slapi_v4_search_pblock *

+ slapi_v4_search_internal_all_contexts(int32_t scope,

+                          const char *filter,

+                          char **attrs,

+                          int32_t attrsonly,

+                          LDAPControl **controls,

+                          const char *uniqueid,

+                          int32_t operation_flags)

+ {

+     /* We can use mapping tree to iterate over the suffixes. */

+     void *mt_node = NULL;

+     /* Create a new result */

+     slapi_v4_search_pblock *pbs = slapi_v4_search_pblock_create();

+     /* Search each of them, building a result set, */

+ 

+     slapi_v4_dn *basedn = slapi_get_first_suffix(&mt_node, 0);

+     while (basedn != NULL) {

+         /* Search it! */

+         slapi_log_error(SLAPI_LOG_DEBUG, "slapi_v4_search_internal_all_contexts", "Searching %s ...\n", slapi_sdn_get_dn(basedn));

+         slapi_v4_search_pblock *pbs_inner = slapi_v4_search_internal(basedn, scope, filter, attrs, attrsonly, controls, uniqueid, operation_flags);

+         slapi_v4_search_pblock_merge(pbs, pbs_inner);

+ 

+         basedn = slapi_get_next_suffix(&mt_node, 0);

+     }

+     /* Return it! */

+     return pbs;

+ }

+ 

+ slapi_v4_plugin_result *

+ slapi_v4_entry_exists_or_create(Slapi_DN *dn, const char *filter, const char *entry, const char *modifier_name) {

+ 

+     /* Search for the entry */

+     int32_t attrsonly = 0;

+     char **attrs = NULL;

+ 

+     slapi_v4_search_pblock *pb_search_result = slapi_v4_search_internal(dn, LDAP_SCOPE_BASE, filter, attrs, attrsonly, NULL, NULL, 0);

+ 

+     uint64_t num_results = slapi_v4_search_pblock_get_num_results(pb_search_result);

+     slapi_v4_search_pblock_destroy(pb_search_result);

+ 

+     if (num_results == 0) {

+         slapi_log_error(SLAPI_LOG_DEBUG, "slapi_v4_entry_exists_or_create", "creating entry:\n%s\n", entry);

+         /* Create the entry */

+ 

+         Slapi_Entry *certmap_entry = slapi_str2entry((char *)entry, 0);

+         if (certmap_entry == NULL) {

+             return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, strdup("Failed to parse entry"));

+         }

+         slapi_v4_search_pblock *pb_add_result = slapi_v4_add_internal_entry(certmap_entry, modifier_name);

+ 

+         if (pb_add_result == NULL) {

+             return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, LDAP_OPERATIONS_ERROR, strdup("Failed to create entry, missing modifier name?"));

+         }

+ 

+         int opresult = slapi_v4_search_pblock_get_ldapresult(pb_add_result);

+         slapi_v4_search_pblock_destroy(pb_add_result);

+ 

+         if (opresult != LDAP_SUCCESS) {

+             return slapi_v4_plugin_result_err(SLAPI_V4_PLUGIN_FAILURE, opresult, strdup("Failed to create entry"));

+         }

+     }

+     return slapi_v4_plugin_result_ok();

+ }

+ 

@@ -0,0 +1,198 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #pragma once

+ 

+ #ifndef SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ #error slapi private v4 is *not* a guaranteed api. It may change between minor releases.

+ #endif

+ 

+ /*

+  * If you're using the internal private header, you know

+  * what you're getting into.

+  */

+ #define SLAPI_PLUGIN_V4_PRERELEASE_ACKNOWLEDGE

+ #include <slapi-plugin-v4.h>

+ 

+ /* Could be SLAPI_V4_PLUGIN_RESULT_CODE? */

+ /* We *must* define these values for FFI */

+ typedef enum {

+     SLAPI_V4_PLUGIN_SUCCESS = 0,

+     SLAPI_V4_PLUGIN_FAILURE = 1

+ } SV4_PLUGIN_RESULT_CODE;

+ 

+ typedef struct _slapi_v4_plugin_result {

+     SV4_PLUGIN_RESULT_CODE result;

+     /* Should we have an LDAP response code here? */

+     /* Will allow sending back responses easily. */

+     int ldap_code;

+     char *msg;

+ } slapi_v4_plugin_result;

+ 

+ /*

+  * Low level berval manipulation

+  */

+ 

+ void slapi_v4_bv_free(struct berval *v);

+ 

+ struct berval **slapi_v4_bvarray_create();

+ void slapi_v4_bvarray_destroy(struct berval **array);

+ struct berval **slapi_v4_bvarray_append(struct berval **array, struct berval *bv);

+ void slapi_v4_bvarray_fold(struct berval **array, void (*fn)(struct berval *bv, void *acc, void *arg), void *acc, void *arg);

+ 

+ /*

+  * Slapi_DN types

+  */

+ 

+ /**

+  * Represents a distinguished name in a directory entry.

+  *

+  * #Slapi_DN is the data type for an opaque structure that represents a distinguished

+  * name in the server plug-in.

+  */

+ typedef struct slapi_dn slapi_v4_dn;

+ void slapi_v4_sdn_free(slapi_v4_dn *sdn);

+ slapi_v4_dn * slapi_v4_sdn_new_from_char_dn(const char *dn);

+ slapi_v4_dn * slapi_v4_sdn_dup(const slapi_v4_dn *sdn);

+ 

+ /*

+  * TLS and certificate handling.

+  */

+ 

+ typedef struct CERTCertificateStr slapi_v4_cert;

+ char * slapi_v4_cert_get_subjectdn(slapi_v4_cert *cert);

+ char * slapi_v4_cert_get_issuerdn(slapi_v4_cert *cert);

+ struct berval *slapi_v4_cert_get_der_berval(slapi_v4_cert *cert);

+ char ** slapi_v4_cert_get_subject_ava_val(slapi_v4_cert *cert, const char *attr);

+ 

+ /*

+  * PBLOCKS and related option passing code

+  */

+ 

+ /* We only have empty pblock declarations */

+ 

+ typedef struct _slapi_v4_certmap_pblock slapi_v4_certmap_pblock;

+ 

+ slapi_v4_certmap_pblock * slapi_v4_certmap_pblock_init(void);

+ void slapi_v4_certmap_pblock_destroy(slapi_v4_certmap_pblock *pbc);

+ 

+ void slapi_v4_certmap_pblock_set_clientdn(slapi_v4_certmap_pblock *pbc, slapi_v4_dn *sdn);

+ slapi_v4_dn * slapi_v4_certmap_pblock_get_clientdn(slapi_v4_certmap_pblock *pbc);

+ 

+ slapi_v4_cert * slapi_v4_certmap_pblock_get_clientcert(slapi_v4_certmap_pblock *pbc);

+ void slapi_v4_certmap_pblock_set_clientcert(slapi_v4_certmap_pblock *pbc, slapi_v4_cert *clientcert);

+ 

+ /*

+  * Entry interaction code.

+  */

+ typedef struct slapi_entry Slapi_Entry;

+ 

+ const slapi_v4_dn * slapi_v4_entry_get_sdn(Slapi_Entry *e);

+ 

+ char **slapi_v4_entry_attr_get_charray(const Slapi_Entry *e, const char *type);

+ 

+ struct berval **slapi_v4_entry_attr_get_bervals(const Slapi_Entry *e, const char *type);

+ 

+ /*

+  * Search pblock. This is based on the v3 search pblock.

+  */

+ typedef struct _slapi_pblock_intop slapi_v4_search_pblock;

+ 

+ void slapi_v4_search_pblock_destroy(slapi_v4_search_pblock *pbs);

+ /* execute a search, and result the result pb */

+ slapi_v4_search_pblock * slapi_v4_search_internal(slapi_v4_dn *basedn,

+                          int scope,

+                          const char *filter,

+                          char **attrs,

+                          int attrsonly,

+                          LDAPControl **controls,

+                          const char *uniqueid,

+                          int operation_flags);

+ 

+ slapi_v4_search_pblock * slapi_v4_search_internal_all_contexts(int scope,

+                          const char *filter,

+                          char **attrs,

+                          int attrsonly,

+                          LDAPControl **controls,

+                          const char *uniqueid,

+                          int operation_flags);

+ 

+ slapi_v4_search_pblock * slapi_v4_add_internal_entry(Slapi_Entry *entry, const char *modifier_name);

+ 

+ slapi_v4_plugin_result * slapi_v4_entry_exists_or_create(slapi_v4_dn *dn, const char *filter, const char *entry, const char *modifier_name);

+ 

+ uint64_t slapi_v4_search_pblock_get_num_results(slapi_v4_search_pblock *pbs);

+ Slapi_Entry **slapi_v4_search_pblock_get_entries(slapi_v4_search_pblock *pbs);

+ char **slapi_v4_search_pblogk_get_referrals(slapi_v4_search_pblock *pbs);

+ 

+ int slapi_v4_search_pblock_get_ldapresult(slapi_v4_search_pblock *pbs);

+ 

+ 

+ 

+ /*

+  * PLUGIN REGISTRATION COMPONENTS

+  */

+ 

+ /* Forward declare this empty type */

+ typedef struct _slapi_v4_plugin_registration slapi_v4_plugin_registration;

+ 

+ #define SV4_PLUGIN_PRECEDENCE_DEFAULT 50

+ 

+ void slapi_v4_plugin_register_name(slapi_v4_plugin_registration *pr, char *name);

+ void slapi_v4_plugin_register_precedence(slapi_v4_plugin_registration *pr, uint64_t order);

+ void slapi_v4_plugin_register_start_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_start_fn)(void **ctx));

+ void slapi_v4_plugin_register_close_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_close_fn)(void **ctx));

+ void slapi_v4_plugin_register_bind_certmap_fn(slapi_v4_plugin_registration *pr, slapi_v4_plugin_result *(*sv4_bind_certmap_fn)(void *ctx, slapi_v4_certmap_pblock *pbc));

+ 

+ /*

+  * RESULT MANAGEMENT

+  */

+ 

+ slapi_v4_plugin_result *slapi_v4_plugin_result_ok(void);

+ slapi_v4_plugin_result *slapi_v4_plugin_result_err(SV4_PLUGIN_RESULT_CODE result, int ldap_code, char *msg);

+ void slapi_v4_plugin_result_destroy(slapi_v4_plugin_result *r);

+ 

+ /*

+  * CONFIGURATION

+  * Access to configurations. These should always stay private as plugins should

+  * never need to access this content.

+  */

+ 

+ char *config_get_configdir(void);

+ 

+ char *config_get_certmap_basedn(void);

+ 

+ /*

+  * Filter management

+  */

+ 

+ char * slapi_v4_escape_filter_value(char *filter_str, int len);

+ 

+ /*

+  * Char arrays and manipulation.

+  */

+ 

+ char ** slapi_v4_charray_from_str(char *str, char *brkstr, int allow_dups);

+ char ** slapi_v4_charray_append(char **a, char *s);

+ void slapi_v4_charray_free(char **array);

+ 

+ /*

+  * BORROW FROM V3

+  *

+  * YOU MUST NOT CHANGE THESE LINES, AND THEY MAY NOT REMAIN STABLE

+  */

+ 

+ /*

+  * UTF8 string handling

+  */

+ 

+ unsigned char * slapi_utf8StrToLower(unsigned char *s);

+ unsigned char * ldap_utf8strip(unsigned char *s);

+ char * ldap_utf8strtok_r(char *sp, const char *brk, char **next);

+ 

+ 

@@ -46,6 +46,84 @@ 

  #define CG2_HEADER_FORMAT "0::"

  #define CG2_HEADER_LEN strlen(CG2_HEADER_FORMAT)

  

+ /*

+  * Memory allocation wrappers

+  *

+  * Why do we use these instead of slapi_ch_* types?

+  *

+  * The problems that existed that slapi_ch_* were trying to solve don't

+  * exist anymore.

+  *

+  * First, we don't have our memory allocator - no matter what, we can't write

+  * something better than jemalloc, so don't.

+  *

+  * Second, linux lies. while we tried to check for null on ptr return

+  * and then handle the situation, the situation handlers were broken and

+  * didn't work, and the check doesn't matter anyway, because linux *always*

+  * returns a valid pointer to a zero page and it's only on write do we actually

+  * discover OOM. OOPs!

+  *

+  * Third, we tried to wrap calloc to have a number * size, but this means

+  * that the compiler can't pre-compute values, so we should just use size.

+  *

+  * Fourth, even in an OOM scenario, all past experiences and examples show

+  * we *never* get to this scenario where we can safely handle this, and infact

+  * we are OOM killed by the kernel first.

+  *

+  * Fifth, the slapi_ch types use ulongs not size_t.

+  *

+  * Finally, We spent so much time with free (&type) and then checking nulls

+  * and setting nulls that doesn't matter. free literally handles ptr == null as

+  * a no-op, and the setting of a pointer to null *does not* help us beside a tiny

+  * set of datastructure scenarios that we *don't use*.

+  *

+  * Thus, we should stop messing about and make these interfaces much lighter

+  * and simpler.

+  */

+ 

+ void *

+ spal_calloc(size_t size) {

+ #ifdef LINUX

+     return calloc(1, size);

+ #else

+     void *ptr = calloc(1, size);

+     if (ptr == NULL) {

+         /*

+          * Just abort - the core will tell us where and why, and there

+          * is no safe way to shutdown in OOM anyway.

+          */

+         abort();

+     }

+     return ptr;

+ #endif

+ }

+ 

+ void *

+ spal_realloc(void *ptr, size_t size) {

+ #ifdef LINUX

+     return realloc(ptr, size);

+ #else

+     void *ptr = realloc(ptr, size);

+     if (ptr == NULL) {

+         /*

+          * Just abort - the core will tell us where and why, and there

+          * is no safe way to shutdown in OOM anyway.

+          */

+         abort();

+     }

+     return ptr;

+ #endif

+ }

+ 

+ void

+ spal_free(void *ptr) {

+     free(ptr);

+ }

+ 

+ /*

+  * Limit management.

+  */

+ 

  static int_fast32_t

  _spal_rlimit_get(int resource, uint64_t *soft_limit, uint64_t *hard_limit)

  {

@@ -20,6 +20,12 @@ 

  #pragma once

  

  #include <inttypes.h>

+ /* malloc and size_t */

+ #include <stdlib.h>

+ 

+ void * spal_calloc(size_t size);

+ void * spal_realloc(void *ptr, size_t size);

+ void spal_free(void *ptr);

  

  /**

   * Structure that contains our system memory information in bytes and pages.

@@ -31,6 +31,9 @@ 

  #include "prcvar.h"

  #include "plstr.h"

  

+ #define SLAPI_PRIVATE_V4_ACKNOWLEDGE

+ #include <slapi-private-v4.h>

+ 

  #ifdef HPUX

  /* HP-UX doesn't define SEM_FAILED like other platforms, so

   * we define it ourselves. */

@@ -0,0 +1,60 @@ 

+ /* BEGIN COPYRIGHT BLOCK

+  * Copyright (C) 2017 Red Hat, Inc.

+  * All rights reserved.

+  *

+  * License: GPL (version 3 or any later version).

+  * See LICENSE for details.

+  * END COPYRIGHT BLOCK */

+ 

+ #include <slapi-internal-v4.h>

+ 

+ /*

+  * This is called on server startup *before* plugins start

+  * but after config dse is read for operations. This allows

+  * us to make internal assertions about the state of the configuration

+  * at start up, enable plugins, and more.

+  */

+ 

+ static char *modifier_name = "cn=upgrade internal,cn=config";

+ 

+ /*

+  * Ensure that the certmap plugin object exists. If not,

+  * create and enable it. If it exists and is disabled,

+  * ignore it.

+  */

+ static upgrade_status

+ upgrade_137_certmap_exists(void) {

+     /* Does it exist? */

+     char *certmap = strdup("dn: cn=certmap plugin,cn=plugins,cn=config\n"

+                     "objectClass: top\n"

+                     "objectClass: nsDylibPlugin4\n"

+                     "cn: certmap plugin\n"

+                     "nsslapd-pluginpath: libcertmap\n"

+                     "nsslapd-plugininitfunc: certmap_init_fn\n"

+                     "nsslapd-pluginenabled: on");

+ 

+     slapi_v4_dn *base_sdn = slapi_v4_sdn_new_from_char_dn("cn=certmap plugin,cn=plugins,cn=config");

+     /* If not, create it. */

+     slapi_v4_plugin_result *result = slapi_v4_entry_exists_or_create(base_sdn, "(cn=certmap plugin)", certmap, modifier_name);

+     upgrade_status uresult = UPGRADE_SUCCESS;

+ 

+     if (result->result != SLAPI_V4_PLUGIN_SUCCESS) {

+         slapi_log_error(SLAPI_LOG_FATAL, "upgrade_137_certmap_exists", "Failed to create certmap entry: %"PRId32": %s\n", result->ldap_code, result->msg);

+         uresult = UPGRADE_FAILURE;

+     }

+     spal_free(certmap);

+     slapi_v4_sdn_free(base_sdn);

+     slapi_v4_plugin_result_destroy(result);

+     return uresult;

+ }

+ 

+ upgrade_status

+ upgrade_server(void) {

+     /* Could this iterate over an array of function pointers? */

+     if (upgrade_137_certmap_exists() != UPGRADE_SUCCESS) {

+         return UPGRADE_FAILURE;

+     }

+     return UPGRADE_SUCCESS;

+ }

+ 

+ 

file modified
+27
@@ -408,3 +408,30 @@ 

      /* should never reach here */

      return 0;

  }

+ 

+ unsigned char *

+ ldap_utf8strip(unsigned char *s) {

+     /* First find the first non-whitespace char */

+     size_t first = 0;

+     size_t last = strlen((char *)s);

+ 

+     for(; ldap_utf8isspace((char *)(s + first)); first++) {

+     }

+     for(; ldap_utf8isspace((char *)(s + last)); last--) {

+     }

+ 

+     /* You are so screwed if this is true. */

+     if (last <= first) {

+         return NULL;

+     }

+     size_t size = last - first + 1;

+     if (size == 0) {

+         return NULL;

+     }

+ 

+     unsigned char *out = spal_calloc(size * sizeof(unsigned char));

+     snprintf(out, size, "%s", (char *)(s + first));

+ 

+     return out;

+ }

+ 

@@ -479,6 +479,9 @@ 

      }

  }

  

+ char *

+ slapi_v4_escape_filter_value(char *filter_str, int len) __attribute__((weak, alias("slapi_escape_filter_value")));

+ 

  /*

  ** This function takes a quoted attribute value of the form "abc",

  ** and strips off the enclosing quotes.  It also deals with quoted

@@ -1,1 +0,0 @@ 

- .depends

file removed
-504
@@ -1,504 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <string.h>

- /* This was malloc.h - but it's moved to stdlib.h on most platforms, and FBSD is strict */

- /* Make it stdlib.h, and revert to malloc.h with ifdefs if we have issues here. WB 2016 */

- #include <stdlib.h>

- 

- /* removed for ns security integration

- #include <sec.h>

- */

- #include "prmem.h"

- #include <keyhi.h>

- #include <cert.h>

- #include <nss.h>

- #include <ldaputil/certmap.h>

- #include <ldaputil/errors.h>

- #include <ldaputil/cert.h>

- #include "ldaputili.h"

- 

- #include "slapi-plugin.h"

- 

- NSAPI_PUBLIC int

- ldapu_get_cert(void *SSLendpoint __attribute__((unused)), void **cert __attribute__((unused)))

- {

-     /* TEMPORARY  -- not implemented yet*/

-     return LDAPU_FAILED;

- }

- 

- 

- NSAPI_PUBLIC int

- ldapu_get_cert_subject_dn(void *cert_in, char **subjectDN)

- {

-     CERTCertificate *cert = (CERTCertificate *)cert_in;

-     char *cert_subject = CERT_NameToAscii(&cert->subject);

- 

-     if (cert_subject != NULL)

-         *subjectDN = strdup(cert_subject);

-     else

-         *subjectDN = NULL;

- 

-     PR_Free(cert_subject);

-     return *subjectDN ? LDAPU_SUCCESS : LDAPU_ERR_EXTRACT_SUBJECTDN_FAILED;

- }

- 

- /*

-  * Return the Issuer DN as a CERTName.

-  * The CERTName is owned by the CERTCertificate.

-  */

- NSAPI_PUBLIC CERTName *

- ldapu_get_cert_issuer_dn_as_CERTName(CERTCertificate *cert_in)

- {

-     return &cert_in->issuer;

- }

- 

- /*

-  * Return the Issuer DN as a string.

-  * The string should be freed by the caller.

-  */

- NSAPI_PUBLIC int

- ldapu_get_cert_issuer_dn(void *cert_in, char **issuerDN)

- {

-     *issuerDN = NULL;

-     CERTName *dn = ldapu_get_cert_issuer_dn_as_CERTName((CERTCertificate *)cert_in);

-     if (dn != NULL) {

-         char *cert_issuer = CERT_NameToAscii(dn);

-         *issuerDN = strdup(cert_issuer);

-         PR_Free(cert_issuer);

-     }

-     return *issuerDN ? LDAPU_SUCCESS : LDAPU_ERR_EXTRACT_ISSUERDN_FAILED;

- }

- 

- NSAPI_PUBLIC int

- ldapu_get_cert_der(void *cert_in, unsigned char **der, unsigned int *len)

- {

-     CERTCertificate *cert = (CERTCertificate *)cert_in;

-     SECItem derCert = ((CERTCertificate *)cert)->derCert;

-     unsigned char *data = derCert.data;

- 

-     *len = derCert.len;

-     *der = (unsigned char *)malloc(*len);

- 

-     if (!*der)

-         return LDAPU_ERR_OUT_OF_MEMORY;

- 

-     memcpy(*der, data, *len);

- 

-     return *len ? LDAPU_SUCCESS : LDAPU_ERR_EXTRACT_DERCERT_FAILED;

- }

- 

- static int

- certmap_name_to_secoid(const char *str)

- {

-     if (!ldapu_strcasecmp(str, "c"))

-         return SEC_OID_AVA_COUNTRY_NAME;

-     if (!ldapu_strcasecmp(str, "o"))

-         return SEC_OID_AVA_ORGANIZATION_NAME;

-     if (!ldapu_strcasecmp(str, "cn"))

-         return SEC_OID_AVA_COMMON_NAME;

-     if (!ldapu_strcasecmp(str, "l"))

-         return SEC_OID_AVA_LOCALITY;

-     if (!ldapu_strcasecmp(str, "st"))

-         return SEC_OID_AVA_STATE_OR_PROVINCE;

-     if (!ldapu_strcasecmp(str, "ou"))

-         return SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME;

-     if (!ldapu_strcasecmp(str, "uid"))

-         return SEC_OID_RFC1274_UID;

-     if (!ldapu_strcasecmp(str, "e"))

-         return SEC_OID_PKCS9_EMAIL_ADDRESS;

-     if (!ldapu_strcasecmp(str, "mail"))

-         return SEC_OID_RFC1274_MAIL;

-     if (!ldapu_strcasecmp(str, "dc"))

-         return SEC_OID_AVA_DC;

- 

-     return SEC_OID_AVA_UNKNOWN; /* return invalid OID */

- }

- 

- NSAPI_PUBLIC int

- ldapu_get_cert_ava_val(void *cert_in, int which_dn, const char *attr, char ***val_out)

- {

-     CERTCertificate *cert = (CERTCertificate *)cert_in;

-     CERTName *cert_dn;

-     CERTRDN **rdns;

-     CERTRDN **rdn;

-     CERTAVA **avas;

-     CERTAVA *ava;

-     int attr_tag = certmap_name_to_secoid(attr);

-     char **val;

-     char **ptr;

-     int rv;

- 

-     *val_out = 0;

- 

-     if (attr_tag == SEC_OID_AVA_UNKNOWN) {

-         return LDAPU_ERR_INVALID_ARGUMENT;

-     }

- 

-     if (which_dn == LDAPU_SUBJECT_DN)

-         cert_dn = &cert->subject;

-     else if (which_dn == LDAPU_ISSUER_DN)

-         cert_dn = &cert->issuer;

-     else

-         return LDAPU_ERR_INVALID_ARGUMENT;

- 

-     val = (char **)malloc(32 * sizeof(char *));

- 

-     if (!val)

-         return LDAPU_ERR_OUT_OF_MEMORY;

- 

-     ptr = val;

- 

-     rdns = cert_dn->rdns;

- 

-     if (rdns) {

-         for (rdn = rdns; *rdn; rdn++) {

-             avas = (*rdn)->avas;

-             while ((ava = *avas++) != NULL) {

-                 int tag = CERT_GetAVATag(ava);

- 

-                 if (tag == attr_tag) {

-                     char buf[BIG_LINE];

-                     int lenLen;

-                     int vallen;

-                     /* Found it */

- 

-                     /* Copied from ns/lib/libsec ...

-              * XXX this code is incorrect in general

-              * -- should use a DER template.

-              */

-                     lenLen = 2;

-                     if (ava->value.len >= 128)

-                         lenLen = 3;

-                     vallen = ava->value.len - lenLen;

- 

-                     rv = CERT_RFC1485_EscapeAndQuote(buf,

-                                                      BIG_LINE,

-                                                      (char *)ava->value.data + lenLen,

-                                                      vallen);

- 

-                     if (rv == SECSuccess) {

-                         *ptr++ = strdup(buf);

-                     }

-                     break;

-                 }

-             }

-         }

-     }

- 

-     *ptr = 0;

- 

-     if (*val) {

-         /* At least one value found */

-         *val_out = val;

-         rv = LDAPU_SUCCESS;

-     } else {

-         free(val);

-         rv = LDAPU_FAILED;

-     }

- 

-     return rv;

- }

- 

- static void

- _rdns_free(char ***rdns)

- {

-     auto char ***rdn;

-     for (rdn = rdns; *rdn; ++rdn) {

-         slapi_ldap_value_free(*rdn);

-     }

-     free(rdns);

- }

- 

- static char ***

- _explode_dn(const char *dn)

- {

-     auto char ***exp = NULL;

-     if (dn && *dn) {

-         auto char **rdns = slapi_ldap_explode_dn(dn, 0);

-         if (rdns) {

-             auto size_t expLen = 0;

-             auto char **rdn;

-             for (rdn = rdns; *rdn; ++rdn) {

-                 auto char **avas = slapi_ldap_explode_rdn(*rdn, 0);

-                 if (avas && *avas) {

-                     exp = (char ***)ldapu_realloc(exp, sizeof(char **) * (expLen + 2));

-                     if (exp) {

-                         exp[expLen++] = avas;

-                     } else {

-                         slapi_ldap_value_free(avas);

-                         break;

-                     }

-                 } else { /* parse error */

-                     if (avas) {

-                         slapi_ldap_value_free(avas);

-                     }

-                     if (exp) {

-                         exp[expLen] = NULL;

-                         _rdns_free(exp);

-                         exp = NULL;

-                     }

-                     break;

-                 }

-             }

-             if (exp) {

-                 exp[expLen] = NULL;

-             }

-             slapi_ldap_value_free(rdns);

-         }

-     }

-     return exp;

- }

- 

- static size_t

- _rdns_count(char ***rdns)

- {

-     auto size_t count = 0;

-     auto char ***rdn;

-     for (rdn = rdns; *rdn; ++rdn) {

-         auto char **ava;

-         for (ava = *rdn; *ava; ++ava) {

-             ++count;

-         }

-     }

-     return count;

- }

- 

- static int

- _replaceAVA(char *attr, char **avas)

- {

-     if (attr && avas) {

-         for (; *avas; ++avas) {

-             if (!ldapu_strcasecmp(*avas, attr)) {

-                 *avas = attr;

-                 return 1;

-             }

-         }

-     }

-     return 0;

- }

- 

- struct _attr_getter_pair

- {

- #if NSS_VMAJOR < 3 || (NSS_VMAJOR == 3 && NSS_VMINOR < 15)

-     char *(*getter)(CERTName *dn);

- #else

-     /* in 3.15.x "const" was added to the declarations */

-     char *(*getter)(const CERTName *dn);

- #endif

-     const char *name1;

-     const char *name2;

- } _attr_getter_table[] =

-     {

-         {NULL, "OU", "organizationalUnitName"},

-         {CERT_GetOrgName, "O", "organizationName"},

-         {CERT_GetCommonName, "CN", "commonName"},

-         {CERT_GetCertEmailAddress, "E", NULL},

-         {CERT_GetCertEmailAddress, "MAIL", "rfc822mailbox"},

-         {CERT_GetCertUid, "uid", NULL},

-         {CERT_GetCountryName, "C", "country"},

-         {CERT_GetStateName, "ST", "state"},

-         {CERT_GetLocalityName, "L", "localityName"},

-         {CERT_GetDomainComponentName, "DC", "dc"},

-         {NULL, NULL, NULL}};

- 

- static int

- _is_OU(const char *attr)

- {

-     auto struct _attr_getter_pair *descAttr;

-     for (descAttr = _attr_getter_table; descAttr->name1; ++descAttr) {

-         if (descAttr->getter == NULL) { /* OU attribute */

-             if (!ldapu_strcasecmp(attr, descAttr->name1) || (descAttr->name2 &&

-                                                              !ldapu_strcasecmp(attr, descAttr->name2))) {

-                 return 1;

-             }

-             break;

-         }

-     }

-     return 0;

- }

- 

- static char **

- _previous_OU(char **ava, char **avas)

- {

-     while (ava != avas) {

-         --ava;

-         if (_is_OU(*ava)) {

-             return ava;

-         }

-     }

-     return NULL;

- }

- 

- static char *

- _value_normalize(char *value)

- /* Remove leading and trailing spaces, and

-        change consecutive spaces to a single space.

-     */

- {

-     auto char *t;

-     auto char *f;

-     t = f = value;

-     while (*f == ' ')

-         ++f; /* ignore leading spaces */

-     for (; *f; ++f) {

-         if (*f != ' ' || t[-1] != ' ') {

-             *t++ = *f; /* no consecutive spaces */

-         }

-     }

-     if (t > value && t[-1] == ' ') {

-         --t; /* ignore trailing space */

-     }

-     *t = '\0';

-     return value;

- }

- 

- static int

- _explode_AVA(char *AVA)

- /* Change an attributeTypeAndValue a la <draft-ietf-asid-ldapv3-dn>,

-        to the type name, followed immediately by the attribute value,

-        both normalized.

-      */

- {

-     auto char *value = strchr(AVA, '=');

-     if (!value)

-         return LDAPU_FAILED;

-     *value++ = '\0';

-     _value_normalize(AVA);

-     _value_normalize(value);

-     {

-         auto char *typeEnd = AVA + strlen(AVA);

-         if ((typeEnd + 1) != value) {

-             memmove(typeEnd + 1, value, strlen(value) + 1);

-         }

-     }

-     return LDAPU_SUCCESS;

- }

- 

- static char *

- _AVA_value(char *AVA)

- {

-     return (AVA + strlen(AVA) + 1);

- }

- 

- static int

- _value_match(char *value, char *desc)

- {

-     auto const int result =

-         !ldapu_strcasecmp(_value_normalize(value), desc);

-     return result;

- }

- 

- int

- ldapu_member_certificate_match(void *cert, const char *desc)

- /*

-  *    Return Values: (same as ldapu_find)

-  *        LDAPU_SUCCESS    cert matches desc

-  *        LDAPU_FAILED    cert doesn't match desc

-  *        <rv>        Something went wrong.

-  */

- {

-     auto int err = LDAPU_FAILED;

-     auto char ***descRDNs;

-     if (!cert || !desc || desc[0] != '{')

-         return LDAPU_FAILED;

-     if (desc[1] == '\0')

-         return LDAPU_SUCCESS; /* no AVAs */

-     descRDNs = _explode_dn(desc + 1);

-     if (descRDNs) {

-         auto char **descAVAs = (char **)ldapu_malloc(sizeof(char *) * (_rdns_count(descRDNs) + 1));

-         if (!descAVAs) {

-             err = LDAPU_ERR_OUT_OF_MEMORY;

-         } else {

-             auto CERTName *subject = &(((CERTCertificate *)cert)->subject);

-             auto char **descAVA;

- 

-             err = LDAPU_SUCCESS;

-             { /* extract all the AVAs, but not duplicate types, except OU */

-                 auto size_t descAVAsLen = 0;

-                 auto char ***descRDN;

-                 descAVAs[0] = NULL;

-                 for (descRDN = descRDNs; err == LDAPU_SUCCESS && *descRDN; ++descRDN) {

-                     for (descAVA = *descRDN; err == LDAPU_SUCCESS && *descAVA; ++descAVA) {

-                         err = _explode_AVA(*descAVA);

-                         if (err == LDAPU_SUCCESS) {

-                             if (_is_OU(*descAVA) ||

-                                 !_replaceAVA(*descAVA, descAVAs)) {

-                                 descAVAs[descAVAsLen++] = *descAVA;

-                                 descAVAs[descAVAsLen] = NULL;

-                             }

-                         }

-                     }

-                 }

-             }

- 

-             /* match all the attributes except OU */

-             for (descAVA = descAVAs; err == LDAPU_SUCCESS && *descAVA; ++descAVA) {

-                 auto struct _attr_getter_pair *descAttr;

-                 err = LDAPU_FAILED; /* if no match */

-                 for (descAttr = _attr_getter_table; descAttr->name1; ++descAttr) {

-                     if (!ldapu_strcasecmp(*descAVA, descAttr->name1) || (descAttr->name2 &&

-                                                                          !ldapu_strcasecmp(*descAVA, descAttr->name2))) {

-                         if (descAttr->getter == NULL) { /* OU attribute */

-                             err = LDAPU_SUCCESS;        /* for now */

-                         } else {

-                             auto char *certVal = (*(descAttr->getter))(subject);

-                             if (certVal && _value_match(certVal, _AVA_value(*descAVA))) {

-                                 err = LDAPU_SUCCESS;

-                             }

-                             PR_Free(certVal);

-                         }

-                         break;

-                     }

-                 }

-             }

- 

-             /* match the OU attributes */

-             if (err == LDAPU_SUCCESS && descAVA != descAVAs) {

-                 /* Iterate over the OUs in the certificate subject */

-                 auto CERTRDN **certRDN = subject->rdns;

-                 descAVA = _previous_OU(descAVA, descAVAs);

-                 for (; descAVA && *certRDN; ++certRDN) {

-                     auto CERTAVA **certAVA = (*certRDN)->avas;

-                     for (; descAVA && *certAVA; ++certAVA) {

-                         auto const int tag = CERT_GetAVATag(*certAVA);

-                         if (tag == SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME) {

-                             auto const size_t certValLen = (*certAVA)->value.len;

-                             auto const size_t lenLen = (certValLen < 128) ? 2 : 3;

-                             auto const size_t buflen = certValLen - lenLen;

-                             auto char *buf = (char *)ldapu_malloc(buflen + 1);

-                             if (!buf) {

-                                 err = LDAPU_ERR_OUT_OF_MEMORY;

-                                 descAVA = NULL;

-                             } else {

-                                 memcpy(buf, (*certAVA)->value.data + lenLen, buflen);

-                                 buf[buflen] = 0;

-                                 if (_value_match(buf, _AVA_value(*descAVA))) {

-                                     descAVA = _previous_OU(descAVA, descAVAs);

-                                 }

-                                 free(buf);

-                             }

-                         }

-                     }

-                 }

-                 if (descAVA) {

-                     err = LDAPU_FAILED; /* no match for descAVA in subject */

-                 }

-             }

-             free(descAVAs);

-         }

-         _rdns_free(descRDNs);

-     }

-     return err;

- }

file removed
-1612
@@ -1,1612 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <stdio.h>

- #include <string.h>

- #include <ctype.h>

- /* This was malloc.h - but it's moved to stdlib.h on most platforms, and FBSD is strict */

- /* Make it stdlib.h, and revert to malloc.h with ifdefs if we have issues here. WB 2016 */

- #include <stdlib.h>

- 

- /* removed for ns security integration

- #include <sec.h>

- */

- #include <plstr.h>

- #include <prlink.h>

- #include <prprf.h>

- 

- #include <keyhi.h>

- #include <cert.h>

- #define DEFINE_LDAPU_STRINGS 1

- #include <ldaputil/certmap.h>

- #include <ldaputil/ldapauth.h>

- #include <ldaputil/errors.h>

- #include <ldaputil/ldaputil.h>

- #include "ldaputili.h"

- 

- #ifndef BIG_LINE

- #define BIG_LINE 1024

- #endif

- 

- /* This is hack, the function is defined in cert/alg1485.c */

- #ifdef __cplusplus

- extern "C" {

- #endif

- 

- #ifdef __cplusplus

- }

- #endif

- 

- static char this_dllname[256];

- static const char *LIB_DIRECTIVE = "certmap";

- static const int LIB_DIRECTIVE_LEN = 7; /* strlen("LIB_DIRECTIVE") */

- 

- static void *ldapu_propval_free(void *propval_in, void *arg);

- 

- typedef struct

- {

-     FILE *fp;

-     void *arg;

- } LDAPUPrintInfo_t;

- 

- static LDAPUCertMapListInfo_t *certmap_listinfo = 0;

- static LDAPUCertMapInfo_t *default_certmap_info = 0;

- 

- static const char *certmap_attrs[] = {

-     0,

-     0,

-     0,

-     0};

- 

- const long CERTMAP_BIT_POS_UNKNOWN = 0;    /* unknown OID */

- const long CERTMAP_BIT_POS_CN = 1L << 1;   /* Common Name */

- const long CERTMAP_BIT_POS_OU = 1L << 2;   /* Organization unit */

- const long CERTMAP_BIT_POS_O = 1L << 3;    /* Organization */

- const long CERTMAP_BIT_POS_C = 1L << 4;    /* Country */

- const long CERTMAP_BIT_POS_L = 1L << 5;    /* Locality */

- const long CERTMAP_BIT_POS_ST = 1L << 6;   /* State or Province */

- const long CERTMAP_BIT_POS_MAIL = 1L << 7; /* E-mail Address */

- const long CERTMAP_BIT_POS_UID = 1L << 8;  /* UID */

- const long CERTMAP_BIT_POS_DC = 1L << 9;   /* DC */

- 

- const int SEC_OID_AVA_UNKNOWN = 0; /* unknown OID */

- 

- static long

- certmap_secoid_to_bit_pos(int oid)

- {

-     switch (oid) {

-     case SEC_OID_AVA_COUNTRY_NAME:

-         return CERTMAP_BIT_POS_C;

-     case SEC_OID_AVA_ORGANIZATION_NAME:

-         return CERTMAP_BIT_POS_O;

-     case SEC_OID_AVA_COMMON_NAME:

-         return CERTMAP_BIT_POS_CN;

-     case SEC_OID_AVA_LOCALITY:

-         return CERTMAP_BIT_POS_L;

-     case SEC_OID_AVA_STATE_OR_PROVINCE:

-         return CERTMAP_BIT_POS_ST;

-     case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:

-         return CERTMAP_BIT_POS_OU;

-     case SEC_OID_RFC1274_UID:

-         return CERTMAP_BIT_POS_UID;

-     /* Map "E" and "MAIL" to the same bit position */

-     case SEC_OID_PKCS9_EMAIL_ADDRESS:

-         return CERTMAP_BIT_POS_MAIL;

-     case SEC_OID_RFC1274_MAIL:

-         return CERTMAP_BIT_POS_MAIL;

-     case SEC_OID_AVA_DC:

-         return CERTMAP_BIT_POS_DC;

-     default:

-         return CERTMAP_BIT_POS_UNKNOWN;

-     }

- }

- 

- static const char *

- certmap_secoid_to_name(int oid)

- {

-     switch (oid) {

-     case SEC_OID_AVA_COUNTRY_NAME:

-         return "C";

-     case SEC_OID_AVA_ORGANIZATION_NAME:

-         return "O";

-     case SEC_OID_AVA_COMMON_NAME:

-         return "CN";

-     case SEC_OID_AVA_LOCALITY:

-         return "L";

-     case SEC_OID_AVA_STATE_OR_PROVINCE:

-         return "ST";

-     case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:

-         return "OU";

-     case SEC_OID_RFC1274_UID:

-         return "UID";

-     /* Map both 'e' and 'mail' to 'mail' in LDAP */

-     case SEC_OID_PKCS9_EMAIL_ADDRESS:

-         return "MAIL";

-     case SEC_OID_RFC1274_MAIL:

-         return "MAIL";

-     case SEC_OID_AVA_DC:

-         return "DC";

-     default:

-         return 0;

-     }

- }

- 

- static void

- tolower_string(char *str)

- {

-     if (str) {

-         while (*str) {

-             *str = tolower(*str);

-             str++;

-         }

-     }

- }

- 

- static long

- certmap_name_to_bit_pos(const char *str)

- {

-     if (!ldapu_strcasecmp(str, "c"))

-         return CERTMAP_BIT_POS_C;

-     if (!ldapu_strcasecmp(str, "o"))

-         return CERTMAP_BIT_POS_O;

-     if (!ldapu_strcasecmp(str, "cn"))

-         return CERTMAP_BIT_POS_CN;

-     if (!ldapu_strcasecmp(str, "l"))

-         return CERTMAP_BIT_POS_L;

-     if (!ldapu_strcasecmp(str, "st"))

-         return CERTMAP_BIT_POS_ST;

-     if (!ldapu_strcasecmp(str, "ou"))

-         return CERTMAP_BIT_POS_OU;

-     if (!ldapu_strcasecmp(str, "uid"))

-         return CERTMAP_BIT_POS_UID;

-     /* Map "E" and "MAIL" to the same bit position */

-     if (!ldapu_strcasecmp(str, "e"))

-         return CERTMAP_BIT_POS_MAIL;

-     if (!ldapu_strcasecmp(str, "mail"))

-         return CERTMAP_BIT_POS_MAIL;

-     if (!ldapu_strcasecmp(str, "dc"))

-         return CERTMAP_BIT_POS_DC;

- 

-     return CERTMAP_BIT_POS_UNKNOWN;

- }

- 

- #if 0 /* may need this in the future */

- static int certmap_name_to_secoid (const char *str)

- {

-     if (!ldapu_strcasecmp(str, "c")) return SEC_OID_AVA_COUNTRY_NAME;

-     if (!ldapu_strcasecmp(str, "o")) return SEC_OID_AVA_ORGANIZATION_NAME;

-     if (!ldapu_strcasecmp(str, "cn")) return SEC_OID_AVA_COMMON_NAME;

-     if (!ldapu_strcasecmp(str, "l")) return SEC_OID_AVA_LOCALITY;

-     if (!ldapu_strcasecmp(str, "st")) return SEC_OID_AVA_STATE_OR_PROVINCE;

-     if (!ldapu_strcasecmp(str, "ou")) return SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME;

-     if (!ldapu_strcasecmp(str, "uid")) return SEC_OID_RFC1274_UID;

-     if (!ldapu_strcasecmp(str, "e")) return SEC_OID_PKCS9_EMAIL_ADDRESS;

-     if (!ldapu_strcasecmp(str, "mail")) return SEC_OID_RFC1274_MAIL;

-     if (!ldapu_strcasecmp(str, "dc")) return SEC_OID_AVA_DC;

- 

-     return SEC_OID_AVA_UNKNOWN;    /* return invalid OID */

- }

- #endif

- 

- NSAPI_PUBLIC int

- ldapu_list_alloc(LDAPUList_t **list)

- {

-     *list = (LDAPUList_t *)calloc(1, sizeof(LDAPUList_t));

- 

-     if (!*list)

-         return LDAPU_ERR_OUT_OF_MEMORY;

- 

-     return LDAPU_SUCCESS;

- }

- 

- static int

- ldapu_list_add_node(LDAPUList_t *list, LDAPUListNode_t *node)

- {

-     if (list->head) {

-         node->prev = list->tail;

-         list->tail->next = node;

-     } else {

-         node->prev = 0;

-         list->head = node;

-     }

- 

-     node->next = 0;

-     list->tail = node;

-     return LDAPU_SUCCESS;

- }

- 

- NSAPI_PUBLIC int

- ldapu_list_add_info(LDAPUList_t *list, void *info)

- {

-     LDAPUListNode_t *node;

- 

-     /* Allocate the list node and set info in the node. */

-     node = (LDAPUListNode_t *)calloc(1, sizeof(LDAPUListNode_t));

- 

-     if (!node) {

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- 

-     node->info = info;

- 

-     return ldapu_list_add_node(list, node);

- }

- 

- 

- static void

- ldapu_list_free(LDAPUList_t *list, LDAPUListNodeFn_t free_fn)

- {

-     if (list) {

-         auto LDAPUListNode_t *node = list->head;

-         while (node) {

-             auto LDAPUListNode_t *next = node->next;

-             if (free_fn) {

-                 (*free_fn)(node->info, 0);

-                 node->info = 0;

-             }

-             node->info = 0;

-             free(node);

-             node = next;

-         }

-         list->head = 0;

-         list->tail = 0;

-     }

-     return;

- }

- 

- NSAPI_PUBLIC int

- ldapu_propval_alloc(const char *prop, const char *val, LDAPUPropVal_t **propval)

- {

-     *propval = (LDAPUPropVal_t *)malloc(sizeof(LDAPUPropVal_t));

- 

-     if (!*propval)

-         return LDAPU_ERR_OUT_OF_MEMORY;

- 

-     (*propval)->prop = prop ? strdup(prop) : 0;

-     (*propval)->val = val ? strdup(val) : 0;

- 

-     if ((!prop || (*propval)->prop) && (!val || (*propval)->val)) {

-         /* strdup worked */

-         return LDAPU_SUCCESS;

-     } else {

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- }

- 

- 

- static int

- PresentInComps(long comps_bitmask, int tag)

- {

-     long bit = certmap_secoid_to_bit_pos(tag);

- 

-     if (comps_bitmask & bit)

-         return 1;

-     else

-         return 0;

- }

- 

- 

- static int

- dbconf_to_certmap_err(int err)

- {

-     switch (err) {

-     case LDAPU_ERR_DBNAME_IS_MISSING:

-         return LDAPU_ERR_CANAME_IS_MISSING;

-     case LDAPU_ERR_PROP_IS_MISSING:

-         return LDAPU_ERR_CAPROP_IS_MISSING;

-     default:

-         return err;

-     }

- }

- 

- /* CAUTION: this function hijacks some substructures from db_info and make

-  * the pointers to it NULL in the db_info.  It is safe to deallocate db_info.

-  */

- static int

- dbinfo_to_certinfo(DBConfDBInfo_t *db_info,

-                    LDAPUCertMapInfo_t **certinfo_out)

- {

-     LDAPUCertMapInfo_t *certinfo = NULL;

-     LDAPUPropValList_t *propval_list = NULL;

-     int rv = LDAPU_SUCCESS;

- 

-     *certinfo_out = 0;

- 

-     certinfo = (LDAPUCertMapInfo_t *)calloc(1, sizeof(LDAPUCertMapInfo_t));

- 

-     if (!certinfo) {

-         rv = LDAPU_ERR_OUT_OF_MEMORY;

-         goto error;

-     }

- 

-     /* hijack few structures rather then copy.  Make the pointers to the

-        structures NULL in the original structure so that they don't freed up

-        when db_info is freed. */

-     certinfo->issuerName = db_info->dbname;

-     db_info->dbname = 0;

- 

-     /* Parse the Issuer DN. */

-     certinfo->issuerDN = CERT_AsciiToName(db_info->url);

-     if (NULL == certinfo->issuerDN                            /* invalid DN */

-             && ldapu_strcasecmp(db_info->url, "default") != 0 /* not "default" */) {

-         rv = LDAPU_ERR_MALFORMED_SUBJECT_DN;

-         goto error;

-     }

- 

-     /* hijack actual prop-vals from dbinfo -- to avoid strdup calls */

-     if (db_info->firstprop) {

-         LDAPUPropVal_t *propval;

-         DBPropVal_t *dbpropval;

- 

-         dbpropval = db_info->firstprop;

- 

-         rv = ldapu_list_alloc(&propval_list);

- 

-         if (rv != LDAPU_SUCCESS) {

-             goto error;

-         }

- 

-         while (dbpropval) {

-             propval = (LDAPUPropVal_t *)malloc(sizeof(LDAPUPropVal_t));

- 

-             if (!propval) {

-                 rv = LDAPU_ERR_OUT_OF_MEMORY;

-                 goto error;

-             }

- 

-             propval->prop = dbpropval->prop;

-             dbpropval->prop = 0;

- 

-             propval->val = dbpropval->val;

-             dbpropval->val = 0;

- 

-             rv = ldapu_list_add_info(propval_list, propval);

- 

-             if (rv != LDAPU_SUCCESS) {

-                 ldapu_propval_free((void *)propval, (void *)propval);

-                 goto error;

-             }

- 

-             dbpropval = dbpropval->next;

-         }

- 

-         certinfo->propval = propval_list;

-     }

- 

-     *certinfo_out = certinfo;

-     goto done;

- 

- error:

-     if (propval_list)

-         ldapu_propval_list_free(propval_list);

-     if (certinfo)

-         free(certinfo);

- 

- done:

-     return rv;

- }

- 

- static int

- ldapu_binary_cmp_certs(void *subject_cert,

-                        void *entry_cert_binary,

-                        unsigned long entry_cert_len)

- {

-     SECItem derCert = ((CERTCertificate *)subject_cert)->derCert;

-     int rv;

- 

-     /* binary compare the two certs */

-     if (derCert.len == entry_cert_len &&

-         !memcmp(derCert.data, entry_cert_binary, entry_cert_len)) {

-         rv = LDAPU_SUCCESS;

-     } else {

-         rv = LDAPU_ERR_CERT_VERIFY_FAILED;

-     }

- 

-     return rv;

- }

- 

- 

- static int

- ldapu_cert_verifyfn_default(void *subject_cert, LDAP *ld, void *certmap_info __attribute__((unused)), LDAPMessage *res, LDAPMessage **entry_out)

- {

-     LDAPMessage *entry;

-     struct berval **bvals;

-     int i;

-     int rv = LDAPU_ERR_CERT_VERIFY_FAILED;

-     char *cert_attr = ldapu_strings[LDAPU_STR_ATTR_CERT];

-     char *cert_attr_nosubtype = ldapu_strings[LDAPU_STR_ATTR_CERT_NOSUBTYPE];

- 

-     *entry_out = 0;

- 

-     for (entry = ldapu_first_entry(ld, res); entry != NULL;

-          entry = ldapu_next_entry(ld, entry)) {

-         if (((bvals = ldapu_get_values_len(ld, entry, cert_attr)) == NULL) &&

-             ((bvals = ldapu_get_values_len(ld, entry, cert_attr_nosubtype)) == NULL)) {

-             rv = LDAPU_ERR_CERT_VERIFY_NO_CERTS;

-             continue;

-         }

- 

-         for (i = 0; bvals[i] != NULL; i++) {

-             rv = ldapu_binary_cmp_certs(subject_cert,

-                                         bvals[i]->bv_val,

-                                         bvals[i]->bv_len);

- 

-             if (rv == LDAPU_SUCCESS) {

-                 break;

-             }

-         }

- 

-         ldapu_value_free_len(ld, bvals);

- 

-         if (rv == LDAPU_SUCCESS) {

-             *entry_out = entry;

-             break;

-         }

-     }

- 

-     return rv;

- }

- 

- static int

- parse_into_bitmask(const char *comps_in, long *bitmask_out, long default_val)

- {

-     long bitmask;

-     char *comps = comps_in ? strdup(comps_in) : 0;

- 

-     if (!comps) {

-         /* Not present in the config file */

-         bitmask = default_val;

-     } else if (!*comps) {

-         /* present but empty */

-         bitmask = 0;

-     } else {

-         char *ptr = comps;

-         char *name = comps;

-         long bit;

-         int break_loop = 0;

- 

-         bitmask = 0;

- 

-         while (*name) {

-             /* advance ptr to delimeter */

-             while (*ptr && !isspace(*ptr) && *ptr != ',')

-                 ptr++;

- 

-             if (!*ptr)

-                 break_loop = 1;

-             else

-                 *ptr++ = 0;

- 

-             bit = certmap_name_to_bit_pos(name);

-             bitmask |= bit;

- 

-             if (break_loop)

-                 break;

-             /* skip delimeters */

-             while (*ptr && (isspace(*ptr) || *ptr == ','))

-                 ptr++;

-             name = ptr;

-         }

-     }

- 

-     if (comps)

-         free(comps);

-     *bitmask_out = bitmask;

-     /*     print_oid_bitmask(bitmask); */

-     return LDAPU_SUCCESS;

- }

- 

- static int

- process_certinfo(LDAPUCertMapInfo_t *certinfo)

- {

-     int rv = LDAPU_SUCCESS;

-     char *dncomps = 0;

-     char *filtercomps = 0;

-     char *libname = 0;

-     char *verify = 0;

-     char *fname = 0;

-     char *searchAttr = 0;

- 

-     if (!ldapu_strcasecmp(certinfo->issuerName, "default")) {

-         default_certmap_info = certinfo;

-     } else if (!certinfo->issuerDN) {

-         return LDAPU_ERR_NO_ISSUERDN_IN_CONFIG_FILE;

-     } else {

-         rv = ldapu_list_add_info(certmap_listinfo, certinfo);

-     }

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* look for dncomps property and parse it into the dncomps bitmask */

-     rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_DNCOMPS, &dncomps);

- 

-     if (rv == LDAPU_SUCCESS && dncomps) {

-         certinfo->dncompsState = COMPS_HAS_ATTRS;

-         tolower_string(dncomps);

-     } else if (rv == LDAPU_FAILED) {

-         certinfo->dncompsState = COMPS_COMMENTED_OUT;

-         rv = LDAPU_SUCCESS;

-     } else if (rv == LDAPU_SUCCESS && !dncomps) {

-         certinfo->dncompsState = COMPS_EMPTY;

-         dncomps = strdup(""); /* present but empty */

-     }

- 

-     rv = parse_into_bitmask(dncomps, &certinfo->dncomps, -1);

- 

-     free(dncomps);

-     dncomps = NULL;

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* look for filtercomps property and parse it into the filtercomps bitmask */

-     rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_FILTERCOMPS,

-                                     &filtercomps);

- 

-     if (rv == LDAPU_SUCCESS && filtercomps) {

-         certinfo->filtercompsState = COMPS_HAS_ATTRS;

-         tolower_string(filtercomps);

-     } else if (rv == LDAPU_FAILED) {

-         certinfo->filtercompsState = COMPS_COMMENTED_OUT;

-         rv = LDAPU_SUCCESS;

-     } else if (rv == LDAPU_SUCCESS && !filtercomps) {

-         certinfo->filtercompsState = COMPS_EMPTY;

-         filtercomps = strdup(""); /* present but empty */

-     }

- 

-     rv = parse_into_bitmask(filtercomps, &certinfo->filtercomps, 0);

- 

-     free(filtercomps);

-     filtercomps = NULL;

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* look for "CmapLdapAttr" property and store it into searchAttr */

-     rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_CERTMAP_LDAP_ATTR,

-                                     &searchAttr);

- 

-     if (rv == LDAPU_FAILED || !searchAttr) {

-         rv = LDAPU_SUCCESS;

-     } else {

-         certinfo->searchAttr = searchAttr;

- 

-         if (searchAttr && !certinfo->searchAttr)

-             rv = LDAPU_ERR_OUT_OF_MEMORY;

-         else

-             rv = LDAPU_SUCCESS;

-     }

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* look for verifycert property and set the default verify function */

-     /* The value of the verifycert property is ignored */

-     rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_VERIFYCERT, &verify);

- 

-     if (rv == LDAPU_SUCCESS) {

-         if (!ldapu_strcasecmp(verify, "on"))

-             certinfo->verifyCert = 1;

-         else if (!ldapu_strcasecmp(verify, "off"))

-             certinfo->verifyCert = 0;

-         else if (!verify || !*verify) /* for mail/news backward compatibilty */

-             certinfo->verifyCert = 1; /* otherwise, this should be an error */

-         else

-             rv = LDAPU_ERR_MISSING_VERIFYCERT_VAL;

-     } else if (rv == LDAPU_FAILED)

-         rv = LDAPU_SUCCESS;

- 

-     if (verify)

-         free(verify);

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     {

-         PRLibrary *lib = 0;

- 

-         /* look for the library property and load it */

-         rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_LIBRARY, &libname);

- 

-         if (rv == LDAPU_SUCCESS) {

-             if (libname && *libname) {

-                 lib = PR_LoadLibrary(libname);

-                 if (!lib)

-                     rv = LDAPU_ERR_UNABLE_TO_LOAD_PLUGIN;

-             } else {

-                 rv = LDAPU_ERR_MISSING_LIBNAME;

-             }

-         } else if (rv == LDAPU_FAILED)

-             rv = LDAPU_SUCCESS;

- 

-         if (libname)

-             free(libname);

-         if (rv != LDAPU_SUCCESS)

-             return rv;

- 

-         /* look for the InitFn property, find it in the libray and call it */

-         rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_INITFN, &fname);

- 

-         if (rv == LDAPU_SUCCESS) {

-             if (fname && *fname) {

-                 /* If lib is NULL, PR_FindSymbol will search all libs loaded

-                  * through PR_LoadLibrary.

-                  */

-                 CertMapInitFn_t fn = (CertMapInitFn_t)PR_FindSymbol(lib, fname);

- 

-                 if (!fn) {

-                     rv = LDAPU_ERR_MISSING_INIT_FN_IN_LIB;

-                 } else {

-                     rv = (*fn)(certinfo, certinfo->issuerName,

-                                certinfo->issuerDN, this_dllname);

-                 }

-             } else {

-                 rv = LDAPU_ERR_MISSING_INIT_FN_NAME;

-             }

-         } else if (lib) {

-             /* If library is specified, init function must be specified */

-             /* If init fn is specified, library may not be specified */

-             rv = LDAPU_ERR_MISSING_INIT_FN_IN_CONFIG;

-         } else if (rv == LDAPU_FAILED) {

-             rv = LDAPU_SUCCESS;

-         }

- 

-         if (fname)

-             free(fname);

- 

-         if (rv != LDAPU_SUCCESS)

-             return rv;

-     }

- 

-     return rv;

- }

- 

- /* This function will read multiple certmap directives and set the information

-  * in the global certmap_listinfo structure.

-  */

- int

- certmap_read_certconfig_file(const char *file)

- {

-     DBConfInfo_t *conf_info = 0;

-     int rv;

- 

-     /* Read the config file */

-     rv = dbconf_read_config_file_sub(file, LIB_DIRECTIVE, LIB_DIRECTIVE_LEN,

-                                      &conf_info);

- 

-     /* Convert the conf_info into certmap_listinfo.  Some of the

-      * sub-structures are simply hijacked rather than copied since we are

-      * going to (carefully) free the conf_info anyway.

-      */

- 

-     if (rv == LDAPU_SUCCESS && conf_info) {

-         DBConfDBInfo_t *nextdb;

-         DBConfDBInfo_t *curdb;

-         LDAPUCertMapInfo_t *certinfo;

- 

-         curdb = conf_info->firstdb;

- 

-         while (curdb) {

-             nextdb = curdb->next;

-             rv = dbinfo_to_certinfo(curdb, &certinfo);

-             if (rv != LDAPU_SUCCESS) {

-                 dbconf_free_confinfo(conf_info);

-                 return rv;

-             }

- 

-             rv = process_certinfo(certinfo);

-             if (rv != LDAPU_SUCCESS) {

-                 ldapu_certinfo_free(certinfo);

-                 dbconf_free_confinfo(conf_info);

-                 return rv;

-             }

- 

-             curdb = nextdb;

-         }

- 

-         dbconf_free_confinfo(conf_info);

-     } else {

-         rv = dbconf_to_certmap_err(rv);

-     }

- 

-     return rv;

- }

- 

- /* This function will read the "certmap default" directive from the config

-  * file and set the information in the global certmap_info.

-  */

- int

- certmap_read_default_certinfo(const char *file)

- {

-     DBConfDBInfo_t *db_info = 0;

-     int rv;

- 

-     rv = dbconf_read_default_dbinfo_sub(file, LIB_DIRECTIVE, LIB_DIRECTIVE_LEN,

-                                         &db_info);

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     rv = dbinfo_to_certinfo(db_info, &default_certmap_info);

- 

-     dbconf_free_dbinfo(db_info);

-     return rv;

- }

- 

- static int

- ldapu_cert_searchfn_default(void *cert, LDAP *ld, void *certmap_info_in, const char *basedn, const char *dn, const char *filter, const char **attrs, LDAPMessage ***res)

- {

-     int rv = LDAPU_FAILED;

-     const char *ldapdn;

-     LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;

-     LDAPMessage *single_res = NULL;

-     LDAPMessage **multiple_res = NULL;

- 

- 

-     if (certmap_info && certmap_info->searchAttr) {

-         char *subjectDN = 0;

-         char *certFilter = 0;

-         int len;

- 

-         rv = ldapu_get_cert_subject_dn(cert, &subjectDN);

- 

-         if (rv != LDAPU_SUCCESS || !subjectDN) {

-             return rv;

-         }

-         len = strlen(certmap_info->searchAttr) + strlen(subjectDN) +

-               strlen("=") + 1;

-         certFilter = (char *)ldapu_malloc(len * sizeof(char));

-         if (!certFilter) {

-             free(subjectDN);

-             return LDAPU_ERR_OUT_OF_MEMORY;

-         }

-         sprintf(certFilter, "%s=%s", certmap_info->searchAttr, subjectDN);

-         free(subjectDN);

-         if (ldapu_strcasecmp(basedn, "")) {

-             rv = ldapu_find(ld, basedn, LDAP_SCOPE_SUBTREE, certFilter, attrs, 0, &single_res);

-             ldapu_free((void *)certFilter);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));

-                 (*res)[0] = single_res;

-                 (*res)[1] = NULL;

-                 return rv;

-             } else if (single_res) {

-                 ldapu_msgfree(ld, single_res);

-                 single_res = 0;

-             }

-         } else {

-             rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, certFilter, attrs, 0, &multiple_res);

-             ldapu_free((void *)certFilter);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = multiple_res;

-                 return rv;

-             } else if (multiple_res) {

-                 int n;

-                 for (n = 0; multiple_res[n] != NULL; n++)

-                     ldapu_msgfree(ld, multiple_res[n]);

-                 ldapu_memfree(ld, multiple_res);

-             }

-         }

-     }

- 

-     if (dn && *dn) {

-         /* First do the base level search --- NOT ANY MORE!! */

-         /* We actually do the search on the whole subtree hanging from "ldapdn" since we want to

-      * find all the entries that match the filter.

-      * If we get more than one matching entry in return, it'll be at verify time that we'll

-      * choose the correct one among them all.

-      * However, if certificate verify is not active, certificate mapping will fail and will

-      * consequently display an error message (something done at 'handle_handshake_done' level,

-      * for instance). */

-         ldapdn = dn;

- 

-         if (ldapu_strcasecmp(ldapdn, "")) {

-             rv = ldapu_find(ld, ldapdn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &single_res);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));

-                 (*res)[0] = single_res;

-                 (*res)[1] = NULL;

-                 return rv;

-             } else if (single_res) {

-                 ldapu_msgfree(ld, single_res);

-                 single_res = 0;

-             }

-         } else {

-             rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &multiple_res);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = multiple_res;

-                 return rv;

-             } else if (multiple_res) {

-                 int n;

-                 for (n = 0; multiple_res[n] != NULL; n++)

-                     ldapu_msgfree(ld, multiple_res[n]);

-                 ldapu_memfree(ld, multiple_res);

-             }

-         }

-     } else {

-         /* default the dn and filter for subtree search */

-         ldapdn = basedn;

-         if (!filter || !*filter) {

-             if (certmap_info && certmap_info->searchAttr) {

-                 /* dn & filter returned by the mapping function are both NULL

-            and 'searchAttr' based search has failed.  Don't do brute

-            force search if 'searchAttr' is being used.  Otherwise,

-            this search will result in all LDAP entries being

-            returned.

-            */

-             } else {

-                 filter = "objectclass=*";

-             }

-         }

-     }

- 

-     /* For local LDAP DB, the LDAP_SCOPE_BASE search may fail for dn == basedn

-      * since that object doesn't actually exists.

-      */

-     if ((rv == LDAPU_FAILED || rv == LDAP_NO_SUCH_OBJECT) && filter && (!dn || !*dn)) {

- 

-         /* Try the subtree search only if the filter is non-NULL */

-         if (ldapu_strcasecmp(ldapdn, "")) {

-             rv = ldapu_find(ld, ldapdn, LDAP_SCOPE_SUBTREE, filter, 0, 0, &single_res);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));

-                 (*res)[0] = single_res;

-                 (*res)[1] = NULL;

-                 return rv;

-             } else if (single_res) {

-                 ldapu_msgfree(ld, single_res);

-                 single_res = 0;

-             }

-         } else {

-             rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, filter, 0, 0, &multiple_res);

-             if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                 *res = multiple_res;

-                 return rv;

-             } else if (multiple_res) {

-                 int n;

-                 for (n = 0; multiple_res[n] != NULL; n++)

-                     ldapu_msgfree(ld, multiple_res[n]);

-                 ldapu_memfree(ld, multiple_res);

-             }

-         }

-     }

- 

-     if (rv == LDAPU_FAILED) {

-         /* Not an error but couldn't map the cert */

-         rv = LDAPU_ERR_MAPPED_ENTRY_NOT_FOUND;

-     } else if ((!dn || !*dn) && (rv == LDAP_NO_SUCH_OBJECT)) {

-         rv = LDAPU_ERR_INVALID_SUFFIX;

-     }

- 

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- ldapu_issuer_certinfo(const CERTName *issuerDN, void **certmap_info)

- {

-     *certmap_info = 0;

- 

-     if (certmap_listinfo) {

-         LDAPUListNode_t *cur = certmap_listinfo->head;

-         while (cur) {

-             LDAPUCertMapInfo_t *info = (LDAPUCertMapInfo_t *)cur->info;

- 

-             if (NULL == info->issuerDN) {

-                 /* no DN to compare to (probably the default certmap info) */

-                 continue;

-             }

- 

-             if (CERT_CompareName(issuerDN, info->issuerDN) == SECEqual) {

-                 *certmap_info = cur->info;

-                 break;

-             }

-             cur = cur->next;

-         }

-     }

-     return *certmap_info ? LDAPU_SUCCESS : LDAPU_FAILED;

- }

- 

- NSAPI_PUBLIC int

- ldapu_certmap_info_attrval(void *certmap_info_in,

-                            const char *attr,

-                            char **val)

- {

-     /* Look for given attr in the certmap_info and return its value */

-     LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;

-     LDAPUListNode_t *curprop = certmap_info->propval ? certmap_info->propval->head : 0;

-     LDAPUPropVal_t *propval;

-     int rv = LDAPU_FAILED;

- 

-     *val = 0;

-     while (curprop) {

-         propval = (LDAPUPropVal_t *)curprop->info;

-         if (!ldapu_strcasecmp(propval->prop, attr)) {

-             *val = propval->val ? strdup(propval->val) : 0;

-             rv = LDAPU_SUCCESS;

-             break;

-         }

-         curprop = curprop->next;

-     }

- 

-     return rv;

- }

- 

- static int

- AddAVAToBuf(char *buf, int size, int *len, const char *tagName, CERTAVA *ava)

- {

-     int lenLen;

-     int taglen;

-     SECStatus rv;

- 

-     buf += *len;

- 

-     /* Copied from ns/lib/libsec ...

-      * XXX this code is incorrect in general

-      * -- should use a DER template.

-      */

-     lenLen = 2;

-     if (ava->value.len >= 128)

-         lenLen = 3;

- 

-     taglen = PL_strlen(tagName);

-     memcpy(buf, tagName, taglen);

-     buf[taglen++] = '=';

- 

-     rv = CERT_RFC1485_EscapeAndQuote(buf + taglen,

-                                      size - taglen,

-                                      (char *)ava->value.data + lenLen,

-                                      ava->value.len - lenLen);

- 

-     *len += strlen(buf);

- 

-     return (rv == SECSuccess ? LDAPU_SUCCESS : LDAPU_FAILED);

- }

- 

- static int

- AddToLdapDN(char *ldapdn, int size, int *dnlen, const char *tagName, CERTAVA *ava)

- {

-     char *dn = ldapdn + *dnlen;

- 

-     if (*dnlen) {

-         strcat(dn, ", ");

-         dn += 2;

-         *dnlen += 2;

-     }

-     return AddAVAToBuf(ldapdn, size, dnlen, tagName, ava);

- }

- 

- static int

- AddToFilter(char *filter, int size, int *flen, const char *tagName, CERTAVA *ava)

- {

-     int rv;

- 

-     /* Append opening parenthesis */

-     strcat(filter + *flen, " (");

-     *flen += 2;

-     rv = AddAVAToBuf(filter, size, flen, tagName, ava);

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* Append closing parenthesis */

-     strcat(filter + *flen, ")");

-     (*flen)++;

- 

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- ldapu_free_cert_ava_val(char **val)

- {

-     char **ptr = val;

- 

-     if (!val)

-         return LDAPU_SUCCESS;

- 

-     while (*ptr)

-         free(*ptr++);

-     free(val);

- 

-     return LDAPU_SUCCESS;

- }

- 

- static int

- ldapu_cert_mapfn_default(void *cert_in, LDAP *ld __attribute__((unused)), void *certmap_info_in, char **ldapDN_out, char **filter_out)

- {

-     CERTCertificate *cert = (CERTCertificate *)cert_in;

-     LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;

-     int rv = LDAPU_SUCCESS;

- 

-     *ldapDN_out = *filter_out = 0;

- 

-     if (!certmap_info) {

-         /* Use subject DN as is -- identity mapping function */

-         rv = ldapu_get_cert_subject_dn(cert, ldapDN_out);

- 

-         return rv;

-     } else {

-         /*

-      * Iterate over rdns from the subject and collect AVAs depending on

-      * dnComps and filtercomps to form ldapDN and filter respectively.

-      * certmap_info->dncomps

-      */

-         CERTName *subject = &cert->subject;

-         CERTRDN **rdns = subject->rdns;

-         CERTRDN **lastRdn;

-         CERTRDN **rdn;

-         CERTAVA **avas;

-         CERTAVA *ava;

-         char ldapdn[BIG_LINE];

-         char filter[BIG_LINE];

-         int dnlen = 0;    /* ldap DN length */

-         int flen = 0;     /* filter length */

-         int numfavas = 0; /* no of avas added to filter */

- 

-         if (rdns == NULL) {

-             /* error */

-             return LDAPU_ERR_INTERNAL;

-         }

- 

-         /* find last RDN */

-         lastRdn = rdns;

-         while (*lastRdn)

-             lastRdn++;

-         lastRdn--;

- 

-         /* Initialize filter to "(&" */

-         strcpy(filter, "(&");

-         flen = 2;

- 

-         /*

-      * Loop over subject rdns in the _reverse_ order while forming ldapDN

-      * and filter.

-      */

-         for (rdn = lastRdn; rdn >= rdns; rdn--) {

-             avas = (*rdn)->avas;

-             while ((ava = *avas++) != NULL) {

-                 int tag = CERT_GetAVATag(ava);

-                 const char *tagName = certmap_secoid_to_name(tag);

- 

-                 if (PresentInComps(certmap_info->dncomps, tag)) {

-                     rv = AddToLdapDN(ldapdn, BIG_LINE, &dnlen, tagName, ava);

-                     if (rv != LDAPU_SUCCESS)

-                         return rv;

-                 }

- 

-                 if (PresentInComps(certmap_info->filtercomps, tag)) {

-                     rv = AddToFilter(filter, BIG_LINE, &flen, tagName, ava);

-                     if (rv != LDAPU_SUCCESS)

-                         return rv;

-                     numfavas++;

-                 }

-             }

-         }

- 

-         if (numfavas == 0) {

-             /* nothing added to filter */

-             *filter = 0;

-         } else if (numfavas == 1) {

-             /* one ava added to filter -- remove "(& (" from the front and ")"

-          * from the end.

-          */

-             *filter_out = strdup(filter + 4);

-             if (!*filter_out)

-                 return LDAPU_ERR_OUT_OF_MEMORY;

-             (*filter_out)[strlen(*filter_out) - 1] = 0;

-         } else {

-             /* Add the closing parenthesis to filter */

-             strcat(filter + flen, ")");

-             *filter_out = strdup(filter);

-         }

- 

-         if (dnlen >= BIG_LINE)

-             return LDAPU_FAILED;

-         ldapdn[dnlen] = 0;

-         *ldapDN_out = *ldapdn ? strdup(ldapdn) : 0;

- 

-         if ((numfavas && !*filter_out) || (dnlen && !*ldapDN_out)) {

-             /* strdup failed */

-             return LDAPU_ERR_OUT_OF_MEMORY;

-         }

- 

-         if ((certmap_info->dncompsState == COMPS_HAS_ATTRS && dnlen == 0) ||

-             (certmap_info->filtercompsState == COMPS_HAS_ATTRS &&

-              numfavas == 0)) {

-             /* At least one attr in DNComps should be present in the cert */

-             /* Same is true for FilterComps */

-             rv = LDAPU_ERR_MAPPED_ENTRY_NOT_FOUND;

-         }

-     }

- 

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- ldapu_set_cert_mapfn(const CERTName *issuerDN,

-                      CertMapFn_t mapfn)

- {

-     LDAPUCertMapInfo_t *certmap_info;

-     int rv;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

- 

-     /* Don't set the mapping function if certmap_info doesen't exist */

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     certmap_info->mapfn = mapfn;

-     return LDAPU_SUCCESS;

- }

- 

- static CertMapFn_t

- ldapu_get_cert_mapfn_sub(LDAPUCertMapInfo_t *certmap_info)

- {

-     CertMapFn_t mapfn;

- 

-     if (certmap_info && certmap_info->mapfn)

-         mapfn = certmap_info->mapfn;

-     else if (default_certmap_info && default_certmap_info->mapfn)

-         mapfn = default_certmap_info->mapfn;

-     else

-         mapfn = ldapu_cert_mapfn_default;

- 

-     return mapfn;

- }

- 

- NSAPI_PUBLIC CertMapFn_t

- ldapu_get_cert_mapfn(const CERTName *issuerDN)

- {

-     LDAPUCertMapInfo_t *certmap_info = 0;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

-     /* certmap_info may be NULL -- use the default */

- 

-     return ldapu_get_cert_mapfn_sub(certmap_info);

- }

- 

- NSAPI_PUBLIC int

- ldapu_set_cert_searchfn(const CERTName *issuerDN,

-                         CertSearchFn_t searchfn)

- {

-     LDAPUCertMapInfo_t *certmap_info;

-     int rv;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

- 

-     /* Don't set the mapping function if certmap_info doesen't exist */

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     certmap_info->searchfn = searchfn;

-     return LDAPU_SUCCESS;

- }

- 

- static CertSearchFn_t

- ldapu_get_cert_searchfn_sub(LDAPUCertMapInfo_t *certmap_info)

- {

-     CertSearchFn_t searchfn;

- 

-     if (certmap_info && certmap_info->searchfn)

-         searchfn = certmap_info->searchfn;

-     else if (default_certmap_info && default_certmap_info->searchfn)

-         searchfn = default_certmap_info->searchfn;

-     else

-         searchfn = ldapu_cert_searchfn_default;

- 

-     return searchfn;

- }

- 

- NSAPI_PUBLIC CertSearchFn_t

- ldapu_get_cert_searchfn(const CERTName *issuerDN)

- {

-     LDAPUCertMapInfo_t *certmap_info = 0;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

-     /* certmap_info may be NULL -- use the default */

- 

-     return ldapu_get_cert_searchfn_sub(certmap_info);

- }

- 

- NSAPI_PUBLIC int

- ldapu_set_cert_verifyfn(const CERTName *issuerDN,

-                         CertVerifyFn_t verifyfn)

- {

-     LDAPUCertMapInfo_t *certmap_info;

-     int rv;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

- 

-     /* Don't set the verify function if certmap_info doesen't exist */

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     certmap_info->verifyfn = verifyfn;

-     return LDAPU_SUCCESS;

- }

- 

- static CertVerifyFn_t

- ldapu_get_cert_verifyfn_sub(LDAPUCertMapInfo_t *certmap_info)

- {

-     CertVerifyFn_t verifyfn;

- 

-     if (certmap_info && certmap_info->verifyfn)

-         verifyfn = certmap_info->verifyfn;

-     else if (default_certmap_info && default_certmap_info->verifyfn)

-         verifyfn = default_certmap_info->verifyfn;

-     else

-         verifyfn = ldapu_cert_verifyfn_default;

- 

-     return verifyfn;

- }

- 

- NSAPI_PUBLIC CertVerifyFn_t

- ldapu_get_cert_verifyfn(const CERTName *issuerDN)

- {

-     LDAPUCertMapInfo_t *certmap_info = 0;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

-     /* certmap_info may be NULL -- use the default */

- 

-     return ldapu_get_cert_verifyfn_sub(certmap_info);

- }

- 

- #if 0 /* may need this in the future */

- static int ldapu_certinfo_copy (const LDAPUCertMapInfo_t *from,

-                 const char *newIssuerName,

-                 const char *newIssuerDN,

-                 LDAPUCertMapInfo_t *to)

- {

-     /* This function is not tested and is not used */

-     int rv;

- 

-     to->issuerName = newIssuerName ? strdup(newIssuerName) : 0;

-     to->issuerDN = newIssuerDN ? strdup(newIssuerDN) : 0;

-     if (from->propval) {

-     rv = ldapu_list_copy(from->propval, &to->propval, ldapu_propval_copy);

-     if (rv != LDAPU_SUCCESS) return rv;

-     }

-     else {

-     to->propval = 0;

-     }

- 

-     return process_certinfo(to);

- }

- #endif

- 

- NSAPI_PUBLIC int

- ldapu_cert_to_ldap_entry(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res)

- {

-     char *ldapDN = 0;

-     char *filter = 0;

-     LDAPUCertMapInfo_t *certmap_info;

-     LDAPMessage **res_array = NULL;

-     CertMapFn_t mapfn;

-     CertVerifyFn_t verifyfn;

-     CertSearchFn_t searchfn;

-     int rv, i, j;

- 

-     *res = 0;

- 

-     if (!certmap_attrs[0]) {

-         /* Initialize certmap_attrs */

-         certmap_attrs[0] = ldapu_strings[LDAPU_STR_ATTR_USER];

-         certmap_attrs[1] = ldapu_strings[LDAPU_STR_ATTR_CERT];

-         certmap_attrs[2] = ldapu_strings[LDAPU_STR_ATTR_CERT_NOSUBTYPE];

-         certmap_attrs[3] = 0;

-     }

- 

-     CERTName *issuerDN = ldapu_get_cert_issuer_dn_as_CERTName(cert);

-     /*        ^ don't need to free this; it will be freed with ^ the cert */

- 

-     if (NULL == issuerDN)

-         return LDAPU_ERR_NO_ISSUERDN_IN_CERT;

- 

-     /* don't free the certmap_info -- its a pointer to an internal structure */

-     rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);

- 

-     if (!certmap_info)

-         certmap_info = default_certmap_info;

- 

-     /* Get the mapping function from the certmap_info */

-     mapfn = ldapu_get_cert_mapfn_sub(certmap_info);

- 

-     rv = (*mapfn)(cert, ld, certmap_info, &ldapDN, &filter);

- 

-     if (rv != LDAPU_SUCCESS) {

-         free(ldapDN);

-         free(filter);

-         return rv;

-     }

- 

-     /* Get the search function from the certmap_info - certinfo maybe NULL */

-     searchfn = ldapu_get_cert_searchfn_sub(certmap_info);

- 

-     rv = (*searchfn)(cert, ld, certmap_info, basedn, ldapDN, filter,

-                      certmap_attrs, &res_array);

- 

-     free(ldapDN);

-     free(filter);

- 

-     /*

-      * Get the verify cert function & call it.

-      */

-     j = 0;

-     if ((rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) &&

-         (certmap_info ? certmap_info->verifyCert : 0)) {

-         verifyfn = ldapu_get_cert_verifyfn_sub(certmap_info);

- 

-         if (verifyfn) {

-             int verify_rv;

- 

-             i = 0;

-             do {

-                 LDAPMessage *entry;

-                 verify_rv = (*verifyfn)(cert, ld, certmap_info, res_array[i], &entry);

- 

-                 if (rv == LDAPU_ERR_MULTIPLE_MATCHES) {

-                     if (verify_rv == LDAPU_SUCCESS) {

-                         /* 'entry' points to the matched entry */

-                         /* Get the 'res' which only contains this entry */

-                         char *dn = ldapu_get_dn(ld, entry);

-                         if (*res)

-                             ldapu_msgfree(ld, *res);

-                         rv = ldapu_find(ld, dn, LDAP_SCOPE_BASE, 0, certmap_attrs, 0, res);

-                         ldapu_memfree(ld, dn);

-                     } else {

-                         /* Verify failed for multiple matches -- keep rv */

-                         /* multiple matches err is probably more interesting to

-                the caller then any other error returned by the verify

-                fn */

-                     }

-                 } else /* rv == LDAPU_SUCCESS */ {

-                     if (verify_rv == LDAPU_SUCCESS) {

-                         *res = res_array[0];

-                         j = 1;

-                     } else {

-                         rv = verify_rv;

-                     }

-                 }

-             } while ((verify_rv != LDAPU_SUCCESS) && (res_array[++i] != NULL));

-         }

-     } else {

-         if (rv == LDAPU_SUCCESS) {

-             *res = res_array[0];

-             j = 1;

-         }

-     }

- 

- 

-     if (rv != LDAPU_SUCCESS) {

-         if (*res) {

-             ldapu_msgfree(ld, *res);

-             *res = 0;

-         }

-     }

- 

-     i = j; /* ugaston - if the search had been successful, despite verifyCert being "off",

-          * mapping is considered successful, so we keep the first (and only) response message.

-          * If, on the other hand, the search had returned multiple matches, the fact

-          * of having verifyCert "off" automatically turns the mapping faulty, so we

-          * don't need to care about keeping any response at all.

-          */

- 

-     if (res_array) {

-         while (res_array[i] != NULL) {

-             ldapu_msgfree(ld, res_array[i]);

-             res_array[i++] = 0;

-         }

-         ldapu_memfree(ld, res_array);

-     }

-     return rv;

- }

- 

- /* The caller shouldn't free the entry */

- NSAPI_PUBLIC int

- ldapu_cert_to_user(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res_out, char **user)

- {

-     int rv;

-     LDAPMessage *res;

-     LDAPMessage *entry;

-     int numEntries;

-     char **attrVals = NULL;

- 

-     *res_out = 0;

-     *user = 0;

- 

-     rv = ldapu_cert_to_ldap_entry(cert, ld, basedn, &res);

- 

-     if (rv != LDAPU_SUCCESS) {

-         goto done;

-     }

- 

-     if (!res) {

-         rv = LDAPU_ERR_EMPTY_LDAP_RESULT;

-         goto done;

-     }

- 

-     /* Extract user login (the 'uid' attr) from 'res' */

-     numEntries = ldapu_count_entries(ld, res);

- 

-     if (numEntries != 1) {

-         rv = LDAPU_ERR_MULTIPLE_MATCHES;

-         goto done;

-     }

- 

-     entry = ldapu_first_entry(ld, res);

- 

-     if (!entry) {

-         rv = LDAPU_ERR_MISSING_RES_ENTRY;

-         goto done;

-     }

- 

-     attrVals = ldapu_get_values(ld, entry,

-                                 ldapu_strings[LDAPU_STR_ATTR_USER]);

- 

-     if (!attrVals || !attrVals[0]) {

-         rv = LDAPU_ERR_MISSING_UID_ATTR;

-         goto done;

-     }

- 

-     *user = strdup(attrVals[0]);

- 

-     /*     ldapu_msgfree(res); */

- 

-     if (!*user) {

-         rv = LDAPU_ERR_OUT_OF_MEMORY;

-         goto done;

-     }

- 

-     *res_out = res;

- 

- done:

-     if (attrVals) {

-         ldapu_value_free(ld, attrVals);

-     }

- 

-     return rv;

- }

- 

- static void *

- ldapu_propval_free(void *propval_in, void *arg __attribute__((unused)))

- {

-     LDAPUPropVal_t *propval = (LDAPUPropVal_t *)propval_in;

- 

-     if (propval->prop)

-         free(propval->prop);

-     if (propval->val)

-         free(propval->val);

-     memset((void *)propval, 0, sizeof(LDAPUPropVal_t));

-     free(propval);

-     return 0;

- }

- 

- void

- ldapu_certinfo_free(void *info_in)

- {

-     LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)info_in;

- 

-     if (certmap_info->issuerName)

-         free(certmap_info->issuerName);

-     if (certmap_info->issuerDN)

-         free(certmap_info->issuerDN);

-     if (certmap_info->propval)

-         ldapu_list_free(certmap_info->propval, ldapu_propval_free);

-     if (certmap_info->searchAttr)

-         free(certmap_info->searchAttr);

-     memset((void *)certmap_info, 0, sizeof(LDAPUCertMapInfo_t));

-     free(certmap_info);

- }

- 

- static void *

- ldapu_certinfo_free_helper(void *info, void *arg __attribute__((unused)))

- {

-     ldapu_certinfo_free(info);

-     return (void *)LDAPU_SUCCESS;

- }

- 

- void

- ldapu_certmap_listinfo_free(void *_certmap_listinfo)

- {

-     LDAPUCertMapListInfo_t *list = (LDAPUCertMapListInfo_t *)_certmap_listinfo;

-     ldapu_list_free(list, ldapu_certinfo_free_helper);

- }

- 

- void

- ldapu_propval_list_free(void *propval_list)

- {

-     LDAPUPropValList_t *list = (LDAPUPropValList_t *)propval_list;

-     ldapu_list_free(list, ldapu_propval_free);

-     free(list);

- }

- 

- int

- ldapu_certmap_init(const char *config_file,

-                    const char *dllname,

-                    LDAPUCertMapListInfo_t **certmap_list,

-                    LDAPUCertMapInfo_t **certmap_default)

- {

-     int rv;

-     certmap_listinfo = (LDAPUCertMapListInfo_t *)calloc(1, sizeof(LDAPUCertMapListInfo_t));

- 

-     *certmap_list = 0;

-     *certmap_default = 0;

-     PR_snprintf(this_dllname, sizeof(this_dllname), "%s", dllname);

- 

-     if (!certmap_listinfo)

-         return LDAPU_ERR_OUT_OF_MEMORY;

- 

-     rv = certmap_read_certconfig_file(config_file);

- 

-     if (rv == LDAPU_SUCCESS) {

-         *certmap_list = certmap_listinfo;

-         *certmap_default = default_certmap_info;

-     }

- 

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- ldaputil_exit()

- {

-     if (default_certmap_info) {

-         ldapu_certinfo_free(default_certmap_info);

-         default_certmap_info = 0;

-     }

- 

-     if (certmap_listinfo) {

-         ldapu_certmap_listinfo_free(certmap_listinfo);

-         certmap_listinfo = 0;

-     }

- 

-     return LDAPU_SUCCESS;

- }

- 

- 

- NSAPI_PUBLIC void

- ldapu_free(void *ptr)

- {

-     if (ptr)

-         free(ptr);

- }

- 

- NSAPI_PUBLIC void

- ldapu_free_old(char *ptr)

- {

-     free((void *)ptr);

- }

- 

- NSAPI_PUBLIC void *

- ldapu_malloc(int size)

- {

-     return malloc(size);

- }

- 

- NSAPI_PUBLIC char *

- ldapu_strdup(const char *ptr)

- {

-     return strdup(ptr);

- }

- 

- NSAPI_PUBLIC void *

- ldapu_realloc(void *ptr, int size)

- {

-     return realloc(ptr, size);

- }

file modified
+9 -6
@@ -41,11 +41,14 @@ 

  #	empty         - set the filter to "objectclass=*"

  #	attr names    - a comma separated list of attributes to form the filter

  #

+ # 7. basedn is the basedn to search rather than using dncomps. If dncomps

+ #    is specified, basedn is ignored. If basedn is not specified, we use

+ #    nsslapd-certmap-basedn

+ #

  

- certmap default		default

+ certmap default     default

+ #default:basedn  ou=People,dc=example,dc=com

  #default:DNComps

- #default:FilterComps	e, uid

- #default:verifycert	on

- #default:CmapLdapAttr	certSubjectDN

- #default:library	<path_to_shared_lib_or_dll>

- #default:InitFn		<Init function's name>

+ #default:FilterComps    e, uid

+ #default:verifycert on

+ #default:CmapLdapAttr   nsCertSubjectDN

file removed
-686
@@ -1,686 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <string.h>

- /* This was malloc.h - but it's moved to stdlib.h on most platforms, and FBSD is strict */

- /* Make it stdlib.h, and revert to malloc.h with ifdefs if we have issues here. WB 2016 */

- #include <stdlib.h>

- #include <ctype.h>

- 

- #include <ldaputil/errors.h>

- #include <ldaputil/certmap.h>

- #include <ldaputil/encode.h>

- #include <ldaputil/dbconf.h>

- 

- #define BIG_LINE 1024

- 

- static const char *DB_DIRECTIVE = "directory";

- static const int DB_DIRECTIVE_LEN = 9; /* strlen("DB_DIRECTIVE") */

- 

- static const char *ENCODED = "encoded";

- 

- static void

- insert_dbinfo_propval(DBConfDBInfo_t *db_info,

-                       DBPropVal_t *propval)

- {

-     if (db_info->lastprop) {

-         db_info->lastprop->next = propval;

-     } else {

-         db_info->firstprop = propval;

-     }

- 

-     db_info->lastprop = propval;

- }

- 

- static void

- insert_dbconf_dbinfo(DBConfInfo_t *conf_info,

-                      DBConfDBInfo_t *db_info)

- {

-     if (conf_info->lastdb) {

-         conf_info->lastdb->next = db_info;

-     } else {

-         conf_info->firstdb = db_info;

-     }

- 

-     conf_info->lastdb = db_info;

- }

- 

- void

- dbconf_free_propval(DBPropVal_t *propval)

- {

-     if (propval) {

-         if (propval->prop)

-             free(propval->prop);

-         if (propval->val)

-             free(propval->val);

-         memset((void *)propval, 0, sizeof(DBPropVal_t));

-         free(propval);

-     }

- }

- 

- NSAPI_PUBLIC void

- dbconf_free_dbinfo(DBConfDBInfo_t *db_info)

- {

-     if (db_info) {

-         DBPropVal_t *next;

-         DBPropVal_t *cur;

- 

-         if (db_info->dbname)

-             free(db_info->dbname);

-         if (db_info->url)

-             free(db_info->url);

- 

-         cur = db_info->firstprop;

- 

-         while (cur) {

-             next = cur->next;

-             dbconf_free_propval(cur);

-             cur = next;

-         }

- 

-         memset((void *)db_info, 0, sizeof(DBConfDBInfo_t));

-         free(db_info);

-     }

- }

- 

- NSAPI_PUBLIC void

- dbconf_free_confinfo(DBConfInfo_t *conf_info)

- {

-     DBConfDBInfo_t *next;

-     DBConfDBInfo_t *cur;

- 

-     if (conf_info) {

-         cur = conf_info->firstdb;

- 

-         while (cur) {

-             next = cur->next;

-             dbconf_free_dbinfo(cur);

-             cur = next;

-         }

- 

-         memset((void *)conf_info, 0, sizeof(DBConfInfo_t));

-         free(conf_info);

-     }

- }

- 

- static int

- skip_blank_lines_and_spaces(FILE *fp, char *buf, char **ptr_out, int *eof)

- {

-     char *ptr = buf;

-     char *end;

- 

-     while (buf && (*buf || fgets(buf, BIG_LINE, fp))) {

-         ptr = buf;

- 

-         /* skip leading whitespace */

-         while (*ptr && isspace(*ptr))

-             ++ptr;

- 

-         /* skip blank line or comment */

-         if (!*ptr || *ptr == '#') {

-             *buf = 0; /* to force reading of next line */

-             continue;

-         }

- 

-         /* Non-blank line found */

-         break;

-     }

- 

-     *ptr_out = ptr;

-     if (!*ptr) {

-         *eof = 1;

-     } else {

-         /* skip trailing whitespace */

-         end = ptr + strlen(ptr) - 1;

-         while (isspace(*end))

-             *end-- = 0;

-     }

- 

-     return LDAPU_SUCCESS;

- }

- 

- static int

- dbconf_parse_propval(char *buf, char *ptr, DBConfDBInfo_t *db_info)

- {

-     char *dbname = db_info->dbname;

-     int dbname_len = strlen(dbname);

-     char *prop;

-     char *val;

-     DBPropVal_t *propval;

-     char *delimeter_chars = " \t";

-     char *lastchar;

-     int end_of_prop;

-     char *encval = 0; /* encoded value */

-     char *origprop = 0;

- 

-     if ((ptr - buf + dbname_len > BIG_LINE) ||

-         strncmp(ptr, dbname, dbname_len) ||

-         !(ptr[dbname_len] == ':' || isspace(ptr[dbname_len]))) {

-         /* Not a prop-val for the current db but not an error */

-         return LDAPU_ERR_NOT_PROPVAL;

-     }

- 

-     /* remove the last char if it is newline */

-     lastchar = strrchr(buf, '\n');

-     if (lastchar)

-         *lastchar = '\0';

- 

-     prop = ptr + dbname_len + 1;

- 

-     while (*prop && (isspace(*prop) || *prop == ':'))

-         ++prop;

- 

-     if (!*prop) {

-         return LDAPU_ERR_PROP_IS_MISSING;

-     }

- 

-     end_of_prop = strcspn(prop, delimeter_chars);

- 

-     if (prop[end_of_prop] != '\0') {

-         /* buf doesn't end here -- val is present */

-         prop[end_of_prop] = '\0';

-         val = &prop[end_of_prop + 1];

- 

-         while (*val && isspace(*val))

-             ++val;

-         if (*val == '\0')

-             val = 0;

-     } else {

-         val = 0;

-     }

- 

-     /*

-      * The prop-val line could be one of the following:

-      * "<dbname>:prop val" OR "<dbname>:encoded prop encval"

-      * If (prop == "encoded") then the val has "prop encval".

-      * Get the actual prop from val and get encval (i.e. encoded value)

-      * and decode it.  If it is encoded then the val part must be non-NULL.

-      */

-     if (val && *val && !strcmp(prop, ENCODED)) {

-         /* val has the actual prop followed by the encoded value */

-         origprop = prop;

-         prop = val;

-         while (*prop && (isspace(*prop) || *prop == ':'))

-             ++prop;

- 

-         if (!*prop) {

-             return LDAPU_ERR_PROP_IS_MISSING;

-         }

- 

-         end_of_prop = strcspn(prop, delimeter_chars);

- 

-         if (prop[end_of_prop] != '\0') {

-             /* buf doesn't end here -- encval is present */

-             prop[end_of_prop] = '\0';

-             encval = &prop[end_of_prop + 1];

- 

-             while (*encval && isspace(*encval))

-                 ++encval;

-             if (*encval == '\0')

-                 encval = 0;

-         } else {

-             encval = 0;

-         }

- 

-         if (!encval) {

-             /* special case - if encval is null, "encoded" itself is a

-          * property and what we have in prop now is the value. */

-             val = prop;

-             prop = origprop;

-         } else {

-             /* decode the value */

-             val = dbconf_decodeval(encval);

-         }

-     }

- 

-     /* Success - we have prop & val */

-     propval = (DBPropVal_t *)malloc(sizeof(DBPropVal_t));

- 

-     if (!propval) {

-         if (encval && val)

-             free(val);

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

-     memset((void *)propval, 0, sizeof(DBPropVal_t));

-     propval->prop = strdup(prop);

-     propval->val = val ? strdup(val) : 0;

- 

-     if (encval && val)

-         free(val); /* val was allocated by dbconf_decodeval */

- 

-     if (!propval->prop || (val && !propval->val)) {

-         dbconf_free_propval(propval);

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- 

-     insert_dbinfo_propval(db_info, propval);

-     return LDAPU_SUCCESS;

- }

- 

- static int

- dbconf_read_propval(FILE *fp, char *buf, DBConfDBInfo_t *db_info, int *eof)

- {

-     int rv;

-     char *ptr = buf;

- 

-     while (buf && (*buf || fgets(buf, BIG_LINE, fp))) {

-         ptr = buf;

- 

-         rv = skip_blank_lines_and_spaces(fp, buf, &ptr, eof);

- 

-         if (rv != LDAPU_SUCCESS || *eof)

-             return rv;

- 

-         /* We have a non-blank line which could be prop-val pair for the

-      * dbname in the db_info. parse the prop-val pair and continue.

-      */

-         rv = dbconf_parse_propval(buf, ptr, db_info);

- 

-         if (rv == LDAPU_ERR_NOT_PROPVAL)

-             return LDAPU_SUCCESS;

-         if (rv != LDAPU_SUCCESS)

-             return rv;

- 

-         *buf = 0; /* to force reading of next line */

-     }

- 

-     if (!*buf)

-         *eof = 1;

- 

-     return LDAPU_SUCCESS;

- }

- 

- static int

- parse_directive(char *buf, const char *directive, const int directive_len, DBConfDBInfo_t **db_info_out)

- {

-     DBConfDBInfo_t *db_info;

-     char *dbname;

-     char *url;

-     int end_of_dbname;

-     char *delimeter_chars = " \t";

-     char *lastchar;

- 

-     /* remove the last char if it is newline */

-     lastchar = strrchr(buf, '\n');

-     if (lastchar)

-         *lastchar = '\0';

- 

-     if (strncmp(buf, directive, directive_len) ||

-         !isspace(buf[directive_len])) {

-         return LDAPU_ERR_DIRECTIVE_IS_MISSING;

-     }

- 

-     dbname = buf + directive_len + 1;

- 

-     while (*dbname && isspace(*dbname))

-         ++dbname;

- 

-     if (!*dbname) {

-         return LDAPU_ERR_DBNAME_IS_MISSING;

-     }

- 

-     end_of_dbname = strcspn(dbname, delimeter_chars);

- 

-     if (dbname[end_of_dbname] != '\0') {

-         /* buf doesn't end here -- url is present */

-         dbname[end_of_dbname] = '\0';

-         url = &dbname[end_of_dbname + 1];

- 

-         while (*url && isspace(*url))

-             ++url;

- 

-         if (*url == '\0')

-             url = 0;

-     } else {

-         url = 0;

-     }

- 

-     /* Success - we have dbname & url */

-     db_info = (DBConfDBInfo_t *)malloc(sizeof(DBConfDBInfo_t));

- 

-     if (!db_info)

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     memset((void *)db_info, 0, sizeof(DBConfDBInfo_t));

-     db_info->dbname = strdup(dbname);

-     db_info->url = url ? strdup(url) : 0;

- 

-     if (!db_info->dbname || (url && !db_info->url)) {

-         dbconf_free_dbinfo(db_info);

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- 

-     *db_info_out = db_info;

-     return LDAPU_SUCCESS;

- }

- 

- /* Read the next database info from the file and put it in db_info_out.  The

-  * buf may contain first line of the database info.  When this function

-  * finishes, the buf may contain unprocessed information (which should be

-  * passed to the next call to read_db_info).

-  */

- static int

- read_db_info(FILE *fp, char *buf, DBConfDBInfo_t **db_info_out, const char *directive, const int directive_len, int *eof)

- {

-     char *ptr;

-     DBConfDBInfo_t *db_info;

-     int rv;

- 

-     *db_info_out = 0;

- 

-     rv = skip_blank_lines_and_spaces(fp, buf, &ptr, eof);

- 

-     if (rv != LDAPU_SUCCESS || *eof)

-         return rv;

- 

-     /* We possibly have a directive of the form "directory <name> <url>" */

-     rv = parse_directive(ptr, directive, directive_len, &db_info);

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     /* We have parsed the directive successfully -- lets look for additional

-      * property-value pairs for the database.

-      */

-     if (!fgets(buf, BIG_LINE, fp)) {

-         *eof = 1;

-         rv = LDAPU_SUCCESS;

-     } else {

-         rv = dbconf_read_propval(fp, buf, db_info, eof);

-     }

- 

-     if (rv != LDAPU_SUCCESS) {

-         dbconf_free_dbinfo(db_info);

-         *db_info_out = 0;

-     } else {

-         *db_info_out = db_info;

-     }

- 

-     return rv;

- }

- 

- int

- dbconf_read_config_file_sub(const char *file,

-                             const char *directive,

-                             const int directive_len,

-                             DBConfInfo_t **conf_info_out)

- {

-     FILE *fp;

-     DBConfInfo_t *conf_info;

-     DBConfDBInfo_t *db_info;

-     char buf[BIG_LINE];

-     int rv;

-     int eof;

- 

-     buf[0] = 0;

- 

-     if ((fp = fopen(file, "r")) == NULL) {

-         return LDAPU_ERR_CANNOT_OPEN_FILE;

-     }

- 

-     /* Allocate DBConfInfo_t */

-     conf_info = (DBConfInfo_t *)malloc(sizeof(DBConfInfo_t));

- 

-     if (!conf_info) {

-         fclose(fp);

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- 

-     memset((void *)conf_info, 0, sizeof(DBConfInfo_t));

- 

-     /* Read each db info */

-     eof = 0;

-     while (!eof &&

-            ((rv = read_db_info(fp, buf, &db_info, directive, directive_len, &eof)) == LDAPU_SUCCESS)) {

-         insert_dbconf_dbinfo(conf_info, db_info);

-     }

- 

-     if (rv != LDAPU_SUCCESS) {

-         dbconf_free_confinfo(conf_info);

-         *conf_info_out = 0;

-     } else {

-         *conf_info_out = conf_info;

-     }

- 

-     fclose(fp);

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- dbconf_read_config_file(const char *file, DBConfInfo_t **conf_info_out)

- {

-     return dbconf_read_config_file_sub(file, DB_DIRECTIVE, DB_DIRECTIVE_LEN,

-                                        conf_info_out);

- }

- 

- int

- dbconf_read_default_dbinfo_sub(const char *file,

-                                const char *directive,

-                                const int directive_len,

-                                DBConfDBInfo_t **db_info_out)

- {

-     FILE *fp;

-     DBConfDBInfo_t *db_info;

-     char buf[BIG_LINE];

-     int rv;

-     int eof;

- 

-     buf[0] = 0;

- 

-     if ((fp = fopen(file, "r")) == NULL) {

-         return LDAPU_ERR_CANNOT_OPEN_FILE;

-     }

- 

-     /* Read each db info until eof or dbname == default*/

-     eof = 0;

- 

-     while (!eof &&

-            ((rv = read_db_info(fp, buf, &db_info, directive, directive_len, &eof)) == LDAPU_SUCCESS)) {

-         if (!strcmp(db_info->dbname, DBCONF_DEFAULT_DBNAME))

-             break;

-         dbconf_free_dbinfo(db_info);

-         db_info = NULL;

-     }

- 

-     if (rv != LDAPU_SUCCESS) {

-         *db_info_out = 0;

-     } else {

-         *db_info_out = db_info;

-     }

- 

-     fclose(fp);

-     return rv;

- }

- 

- 

- NSAPI_PUBLIC int

- dbconf_read_default_dbinfo(const char *file,

-                            DBConfDBInfo_t **db_info_out)

- {

-     return dbconf_read_default_dbinfo_sub(file, DB_DIRECTIVE, DB_DIRECTIVE_LEN,

-                                           db_info_out);

- }

- 

- /*

-  * ldapu_strcasecmp - is like strcasecmp on UNIX but also accepts null strings.

-  */

- int

- ldapu_strcasecmp(const char *s1, const char *s2)

- {

- 

-     if (!s1)

-         return !s2 ? 0 : 0 - tolower(*s2);

-     else if (!s2)

-         return tolower(*s1);

- 

-     return strcasecmp(s1, s2);

- }

- 

- NSAPI_PUBLIC int

- ldapu_dbinfo_attrval(DBConfDBInfo_t *db_info,

-                      const char *attr,

-                      char **val)

- {

-     /* Look for given attr in the db_info and return its value */

-     int rv = LDAPU_ATTR_NOT_FOUND;

-     DBPropVal_t *next;

- 

-     *val = 0;

- 

-     if (db_info) {

-         next = db_info->firstprop;

-         while (next) {

-             rv = ldapu_strcasecmp(attr, next->prop);

-             if (!rv) {

-                 /* Found the property */

-                 *val = next->val ? strdup(next->val) : 0;

- 

-                 if (next->val && !*val) {

-                     rv = LDAPU_ERR_OUT_OF_MEMORY;

-                 } else {

-                     rv = LDAPU_SUCCESS;

-                 }

-                 break;

-             }

-             next = next->next;

-         }

-     }

- 

-     return rv;

- }

- 

- void

- dbconf_print_propval(DBPropVal_t *propval)

- {

-     if (propval) {

-         fprintf(stderr, "\tprop: \"%s\"\tval: \"%s\"\n", propval->prop,

-                 propval->val ? propval->val : "");

-     } else {

-         fprintf(stderr, "Null propval\n");

-     }

- }

- 

- void

- dbconf_print_dbinfo(DBConfDBInfo_t *db_info)

- {

-     DBPropVal_t *next;

- 

-     if (db_info) {

-         fprintf(stderr, "dbname: \"%s\"\n", db_info->dbname);

-         fprintf(stderr, "url: \t\"%s\"\n", db_info->url ? db_info->url : "");

-         next = db_info->firstprop;

-         while (next) {

-             dbconf_print_propval(next);

-             next = next->next;

-         }

-     } else {

-         fprintf(stderr, "Null db_info\n");

-     }

- }

- 

- void

- dbconf_print_confinfo(DBConfInfo_t *conf_info)

- {

-     DBConfDBInfo_t *next;

- 

-     if (conf_info) {

-         next = conf_info->firstdb;

-         while (next) {

-             dbconf_print_dbinfo(next);

-             next = next->next;

-         }

-     } else {

-         fprintf(stderr, "Null conf_info\n");

-     }

- }

- 

- 

- NSAPI_PUBLIC int

- dbconf_output_db_directive(FILE *fp, const char *dbname, const char *url)

- {

-     fprintf(fp, "%s %s %s\n", DB_DIRECTIVE, dbname, url);

-     return LDAPU_SUCCESS;

- }

- 

- NSAPI_PUBLIC int

- dbconf_output_propval(FILE *fp, const char *dbname, const char *prop, const char *val, const int encoded)

- {

-     if (encoded && val && *val) {

-         char *new_val = dbconf_encodeval(val);

- 

-         if (!new_val)

-             return LDAPU_ERR_OUT_OF_MEMORY;

-         fprintf(fp, "%s:%s %s %s\n", dbname, ENCODED,

-                 prop, new_val);

-         free(new_val);

-     } else {

-         fprintf(fp, "%s:%s %s\n", dbname, prop, val ? val : "");

-     }

- 

-     return LDAPU_SUCCESS;

- }

- 

- 

- NSAPI_PUBLIC int

- dbconf_get_dbnames(const char *dbmap, char ***dbnames_out, int *cnt_out)

- {

-     DBConfInfo_t *conf_info = 0;

-     DBConfDBInfo_t *db = 0;

-     int cnt = 0;

-     char **dbnames = 0;

-     char *heap = 0;

-     int rv;

- 

-     *dbnames_out = 0;

-     *cnt_out = 0;

- 

-     rv = dbconf_read_config_file(dbmap, &conf_info);

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     db = conf_info->firstdb;

- 

- 

-     dbnames = (char **)malloc(32 * 1024);

-     heap = (char *)dbnames + 2 * 1024;

- 

-     if (!dbnames) {

-         dbconf_free_confinfo(conf_info);

-         return LDAPU_ERR_OUT_OF_MEMORY;

-     }

- 

-     *dbnames_out = dbnames;

- 

-     while (db) {

-         *dbnames++ = heap;

-         strcpy(heap, db->dbname);

-         heap += strlen(db->dbname) + 1;

-         db = db->next;

-         cnt++;

-     }

- 

-     *dbnames = NULL;

-     *cnt_out = cnt;

-     dbconf_free_confinfo(conf_info);

- 

-     return LDAPU_SUCCESS;

- }

- 

- NSAPI_PUBLIC int

- dbconf_free_dbnames(char **dbnames)

- {

-     if (dbnames)

-         free(dbnames);

- 

-     return LDAPU_SUCCESS;

- }

file removed
-151
@@ -1,151 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- /* This was malloc.h - but it's moved to stdlib.h on most platforms, and FBSD is strict */

- /* Make it stdlib.h, and revert to malloc.h with ifdefs if we have issues here. WB 2016 */

- #include <stdlib.h>

- #include <string.h>

- #include <ldaputil/certmap.h>

- #include <ldaputil/encode.h>

- 

- /* The magic set of 64 chars in the uuencoded data */

- static unsigned char uuset[] = {

-     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',

-     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',

-     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',

-     '8', '9', '+', '/'};

- 

- static int

- do_uuencode(unsigned char *src, unsigned char *dst, int srclen)

- {

-     int i, r;

-     unsigned char *p;

- 

-     /* To uuencode, we snip 8 bits from 3 bytes and store them as

- 6 bits in 4 bytes.   6*4 == 8*3 (get it?) and 6 bits per byte

- yields nice clean bytes

- 

- It goes like this:

-         AAAAAAAA BBBBBBBB CCCCCCCC

- turns into the standard set of uuencode ascii chars indexed by numbers:

-         00AAAAAA 00AABBBB 00BBBBCC 00CCCCCC

- 

- Snip-n-shift, snip-n-shift, etc....

- 

- */

- 

-     for (p = dst, i = 0; i < srclen; i += 3) {

-         /* Do 3 bytes of src */

-         register char b0, b1, b2;

- 

-         b0 = src[0];

-         if (i == srclen - 1)

-             b1 = b2 = '\0';

-         else if (i == srclen - 2) {

-             b1 = src[1];

-             b2 = '\0';

-         } else {

-             b1 = src[1];

-             b2 = src[2];

-         }

- 

-         *p++ = uuset[b0 >> 2];

-         *p++ = uuset[(((b0 & 0x03) << 4) | ((b1 & 0xf0) >> 4))];

-         *p++ = uuset[(((b1 & 0x0f) << 2) | ((b2 & 0xc0) >> 6))];

-         *p++ = uuset[b2 & 0x3f];

-         src += 3;

-     }

-     *p = 0;                                        /* terminate the string */

-     r = (unsigned char *)p - (unsigned char *)dst; /* remember how many we did */

- 

-     /* Always do 4-for-3, but if not round threesome, have to go

-           clean up the last extra bytes */

- 

-     for (; i != srclen; i--)

-         *--p = '=';

- 

-     return r;

- }

- 

- const unsigned char pr2six[256] = {

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,

-     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

-     10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27,

-     28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,

-     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};

- 

- static char *

- _uudecode(const char *bufcoded)

- {

-     register const char *bufin = bufcoded;

-     register unsigned char *bufout;

-     register int nprbytes;

-     unsigned char *bufplain;

-     int nbytesdecoded;

- 

-     /* Find the length */

-     while (pr2six[(int)*(bufin++)] <= 63)

-         ;

-     nprbytes = bufin - bufcoded - 1;

-     nbytesdecoded = ((nprbytes + 3) / 4) * 3;

- 

-     bufout = (unsigned char *)malloc(nbytesdecoded + 1);

-     bufplain = bufout;

- 

-     bufin = bufcoded;

- 

-     while (nprbytes > 0) {

-         *(bufout++) = (unsigned char)(pr2six[(int)(*bufin)] << 2 | pr2six[(int)bufin[1]] >> 4);

-         *(bufout++) = (unsigned char)(pr2six[(int)bufin[1]] << 4 | pr2six[(int)bufin[2]] >> 2);

-         *(bufout++) = (unsigned char)(pr2six[(int)bufin[2]] << 6 | pr2six[(int)bufin[3]]);

-         bufin += 4;

-         nprbytes -= 4;

-     }

- 

-     if (nprbytes & 03) {

-         if (pr2six[(int)bufin[-2]] > 63)

-             nbytesdecoded -= 2;

-         else

-             nbytesdecoded -= 1;

-     }

-     bufplain[nbytesdecoded] = '\0';

- 

-     return (char *)bufplain;

- }

- 

- 

- char *

- dbconf_encodeval(const char *val)

- {

-     int len = strlen(val);

-     char *dst = (char *)malloc(2 * len);

- 

-     if (dst) {

-         do_uuencode((unsigned char *)val, (unsigned char *)dst, len);

-     }

- 

-     return dst;

- }

- 

- char *

- dbconf_decodeval(const char *val)

- {

-     return _uudecode(val);

- }

file removed
-210
@@ -1,210 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <ldaputil/errors.h>

- #include <ldaputil/certmap.h>

- 

- NSAPI_PUBLIC char *

- ldapu_err2string(int err)

- {

-     char *rv;

- 

-     switch (err) {

- 

-     /* Error codes defined in certmap.h */

-     case LDAPU_SUCCESS:

-         rv = "success";

-         break;

-     case LDAPU_FAILED:

-         rv = "ldap search didn't find an ldap entry";

-         break;

-     case LDAPU_CERT_MAP_FUNCTION_FAILED:

-         rv = "Cert mapping function failed";

-         break;

-     case LDAPU_CERT_SEARCH_FUNCTION_FAILED:

-         rv = "Cert search function failed";

-         break;

-     case LDAPU_CERT_VERIFY_FUNCTION_FAILED:

-         rv = "Cert verify function failed";

-         break;

-     case LDAPU_CERT_MAP_INITFN_FAILED:

-         rv = "Certmap InitFn function failed";

-         break;

- 

- 

-     /* Error codes returned by ldapdb.c */

-     case LDAPU_ERR_URL_INVALID_PREFIX:

-         rv = "invalid local ldap database url prefix -- must be ldapdb://";

-         break;

-     case LDAPU_ERR_URL_NO_BASEDN:

-         rv = "base dn is missing in ldapdb url";

-         break;

-     case LDAPU_ERR_OUT_OF_MEMORY:

-         rv = "out of memory";

-         break;

-     case LDAPU_ERR_LDAP_INIT_FAILED:

-         rv = "Couldn't initialize connection to the ldap directory server";

-         break;

-     case LDAPU_ERR_LCACHE_INIT_FAILED:

-         rv = "Couldn't initialize connection to the local ldap directory";

-         break;

-     case LDAPU_ERR_LDAP_SET_OPTION_FAILED:

-         rv = "ldap_set_option failed for local ldap database";

-         break;

-     case LDAPU_ERR_NO_DEFAULT_CERTDB:

-         rv = "default cert database not initialized when using LDAP over SSL";

-         break;

- 

- 

-     /* Errors returned by ldapauth.c */

-     case LDAPU_ERR_CIRCULAR_GROUPS:

-         rv = "Circular groups were detected during group membership check";

-         break;

-     case LDAPU_ERR_INVALID_STRING:

-         rv = "Invalid string";

-         break;

-     case LDAPU_ERR_INVALID_STRING_INDEX:

-         rv = "Invalid string index";

-         break;

-     case LDAPU_ERR_MISSING_ATTR_VAL:

-         rv = "Missing attribute value from the search result";

-         break;

- 

- 

-     /* Errors returned by dbconf.c */

-     case LDAPU_ERR_CANNOT_OPEN_FILE:

-         rv = "cannot open the config file";

-         break;

-     case LDAPU_ERR_DBNAME_IS_MISSING:

-         rv = "database name is missing";

-         break;

-     case LDAPU_ERR_PROP_IS_MISSING:

-         rv = "database property is missing";

-         break;

-     case LDAPU_ERR_DIRECTIVE_IS_MISSING:

-         rv = "illegal directive in the config file";

-         break;

-     case LDAPU_ERR_NOT_PROPVAL:

-         rv = "internal error - LDAPU_ERR_NOT_PROPVAL";

-         break;

- 

- 

-     /* Error codes returned by certmap.c */

-     case LDAPU_ERR_NO_ISSUERDN_IN_CERT:

-         rv = "cannot extract issuer DN from the cert";

-         break;

-     case LDAPU_ERR_NO_ISSUERDN_IN_CONFIG_FILE:

-         rv = "issuer DN missing for non-default certmap";

-         break;

-     case LDAPU_ERR_CERTMAP_INFO_MISSING:

-         rv = "cert to ldap entry mapping information is missing";

-         break;

-     case LDAPU_ERR_MALFORMED_SUBJECT_DN:

-         rv = "Found malformed subject DN in the certificate";

-         break;

-     case LDAPU_ERR_MAPPED_ENTRY_NOT_FOUND:

-         rv = "Certificate couldn't be mapped to an ldap entry";

-         break;

-     case LDAPU_ERR_UNABLE_TO_LOAD_PLUGIN:

-         rv = "Unable to load certmap plugin library";

-         break;

-     case LDAPU_ERR_MISSING_INIT_FN_IN_CONFIG:

-         rv = "InitFn must be provided when using certmap plugin library";

-         break;

-     case LDAPU_ERR_MISSING_INIT_FN_IN_LIB:

-         rv = "Could not find InitFn in the certmap plugin library";

-         break;

-     case LDAPU_ERR_CERT_VERIFY_FAILED:

-         rv = "Could not matching certificate in User's LDAP entry";

-         break;

-     case LDAPU_ERR_CERT_VERIFY_NO_CERTS:

-         rv = "User's LDAP entry doesn't have any certificates to compare";

-         break;

-     case LDAPU_ERR_MISSING_LIBNAME:

-         rv = "Library name is missing in the config file";

-         break;

-     case LDAPU_ERR_MISSING_INIT_FN_NAME:

-         rv = "Init function name is missing in the config file";

-         break;

-     case LDAPU_ERR_WRONG_ARGS:

-         rv = "ldaputil API function called with wrong arguments";

-         break;

-     case LDAPU_ERR_RENAME_FILE_FAILED:

-         rv = "Renaming of file failed";

-         break;

-     case LDAPU_ERR_MISSING_VERIFYCERT_VAL:

-         rv = "VerifyCert property value must be on or off";

-         break;

-     case LDAPU_ERR_CANAME_IS_MISSING:

-         rv = "Cert issuer name is missing";

-         break;

-     case LDAPU_ERR_CAPROP_IS_MISSING:

-         rv = "property name is missing";

-         break;

-     case LDAPU_ERR_UNKNOWN_CERT_ATTR:

-         rv = "unknown cert attribute";

-         break;

- 

- 

-     case LDAPU_ERR_EMPTY_LDAP_RESULT:

-         rv = "ldap search returned empty result";

-         break;

-     case LDAPU_ERR_MULTIPLE_MATCHES:

-         rv = "ldap search returned multiple matches when one expected";

-         break;

-     case LDAPU_ERR_MISSING_RES_ENTRY:

-         rv = "Could not extract entry from the ldap search result";

-         break;

-     case LDAPU_ERR_MISSING_UID_ATTR:

-         rv = "ldap entry is missing the 'uid' attribute value";

-         break;

-     case LDAPU_ERR_INVALID_ARGUMENT:

-         rv = "invalid argument passed to the certmap API function";

-         break;

-     case LDAPU_ERR_INVALID_SUFFIX:

-         rv = "invalid LDAP directory suffix";

-         break;

- 

- 

-     /* Error codes returned by cert.c */

-     case LDAPU_ERR_EXTRACT_SUBJECTDN_FAILED:

-         rv = "Couldn't extract the subject DN from the certificate";

-         break;

-     case LDAPU_ERR_EXTRACT_ISSUERDN_FAILED:

-         rv = "Couldn't extract the issuer DN from the certificate";

-         break;

-     case LDAPU_ERR_EXTRACT_DERCERT_FAILED:

-         rv = "Couldn't extract the original DER encoding from the certificate";

-         break;

- 

- 

-     case LDAPU_ERR_NOT_IMPLEMENTED:

-         rv = "function not implemented yet";

-         break;

-     case LDAPU_ERR_INTERNAL:

-         rv = "ldaputil internal error";

-         break;

- 

-     default:

-         if (err > 0) {

-             /* LDAP errors are +ve */

-             rv = ldap_err2string(err);

-         } else {

-             rv = "internal error - unknown error code";

-         }

-         break;

-     }

- 

-     return rv;

- }

@@ -1,89 +0,0 @@ 

- #

- # BEGIN COPYRIGHT BLOCK

- # Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

- # Copyright (C) 2005 Red Hat, Inc.

- # All rights reserved.

- #

- # License: GPL (version 3 or any later version).

- # See LICENSE for details. 

- # END COPYRIGHT BLOCK

- #

- #

- # Makefile for certmap example program.

- #

- 

- #

- # Please set the ARCH variable to one of the following:

- # SOLARIS, IRIX, HPUX

- #

- ARCH = 

- 

- 

- #

- # Please set the SROOT to be same as your server root

- #

- SROOT = 

- 

- #

- # Uncomment the following if you need the debug build

- #

- #COMMON_DEFS = -g

- 

- ifndef ARCH

- arch:

- 	@echo "Please edit the Makefile and set the variable: ARCH"

- 	@exit 1

- endif

- 

- ifndef SROOT

- sroot:

- 	@echo "Please edit the Makefile and set the server root variable: SROOT"

- 	@exit 1

- endif

- 

- ifeq ($(ARCH), SOLARIS)

- CC_CMD = cc -DSOLARIS -D_REENTRANT

- LD_SHAREDCMD = ld -G

- endif

- 

- ifeq ($(ARCH), HPUX)

-   BIN = certmap.sl

- else

-   BIN = certmap.so

- endif

- 

- OBJS = init.o plugin.o

- 

- INCLUDE_FLAGS=-I. -I$(SROOT)/include

- 

- INC_FILES = \

- 	$(SROOT)/include/certmap.h \

- 	$(SROOT)/include/ldap.h \

- 	$(SROOT)/include/lber.h

- 

- all: $(BIN)

- 

- $(INC_FILES):

- 	@echo

- 	@echo "To extend the Certificate to LDAP entry mapping by"

- 	@echo "writing your own functions, you need to download the"

- 	@echo "Certmap API (version 1.0) and LDAP SDK (version 1.0)."

- 	@echo "Please download these from http://???"

- 	@echo "Make sure the following files exist:"

- 	@echo "\t$(SROOT)/include/certmap.h"

- 	@echo "\t$(SROOT)/include/ldap.h"

- 	@echo "\t$(SROOT)/include/lber.h"

- 	@echo

- 	@exit 1

- 

- $(BIN):	$(INC_FILES) $(OBJS)

- 	$(LD_SHAREDCMD) $(OBJS) -o $@ $(EXTRA_LDDEFINES)

- 

- certmap.dll: $(OBJS)

- 	$(LD_SHAREDCMD) $(OBJS) -o $@ $(EXTRA_LDDEFINES)

- 

- .c.o:

- 	$(CC_CMD) $(COMMON_DEFS) $(INCLUDE_FLAGS) -c $< 

- 

- clean:

- 	rm -f $(OBJS) certmap.so $(EXTRA_CLEAN)

@@ -1,100 +0,0 @@ 

- # BEGIN COPYRIGHT BLOCK

- # Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

- # Copyright (C) 2005 Red Hat, Inc.

- # All rights reserved.

- #

- # License: GPL (version 3 or any later version).

- # See LICENSE for details. 

- # END COPYRIGHT BLOCK

- #

- 

- This directory contains an example program to demonstrate

- writing plugins using the "Certificate to LDAP Mapping" API.

- Please read the "Managing Servers" manual to find out

- about how certificate to ldap mapping can be configured using

- the <ServerRoot>/userdb/certmap.conf file.  Also refer to the

- "Certificate to LDAP Mapping API" documentation to find out

- about the various API functions and how you can write your

- plugin.

- 

- This example demonstrate use of most of the API functions.  It

- defines a mapping function, a search function, and a verify

- function.  Read the API doc to learn about these functions.

- The init.c file also contains an init function which sets the

- mapping, search and verify functions.

- 

- The Mapping Function 

- -------------------- 

- 

- The mapping function extracts the attributes "CN", "E", "O" and

- "C" from the certificate's subject DN using the function

- ldapu_get_cert_ava_val.  If the attributes "C" doesn't exists

- then it defaults to "US".  It then gets the value of a custom

- certmap.conf property "defaultOU" using the function

- ldapu_certmap_info_attrval.  This demonstrates how you can have

- your own custom properties defined in the certmap.conf file.

- The mapping function then returns an ldapdn of the form:

- "cn=<name>, ou=<defaultOU>, o=<o>, c=<c>".

- 

- If the "E" attribute has a value, it returns a filter

- "mail=<e>".  Finally, the mapping function frees the structures

- returned by some of the API functions it called.

- 

- 

- The Search Function

- -------------------

- 

- The search function calls a dummy function to get the

- certificate's serial number.  It then does a subtree search in

- the entire directory for the filter 

- "certSerialNumber=<serial No.>".  If this fails, it calls the

- default search function.  This demonstrates how you can use the

- default functions in your custom functions.

- 

- The Verify Function

- -------------------

- 

- The verify function returns LDAPU_SUCCESS if only one entry was

- returned by the search function.  Otherwise, it returns

- LDAPU_CERT_VERIFY_FUNCTION_FAILED.

- 

- 

- Error Reporting

- ---------------

- 

- To report errors/warning, there is a function defined called

- plugin_ereport.  This function demonstrates how to get the

- subject DN and the issuer DN from the certificate.

- 

- Build Procedure

- ---------------

- On UNIX: Edit the Makefile, and set the variables ARCH & SROOT

- according to the comments in the Makefile.  Download LDAP C SDK

- from the mozilla.org site and make the ldap include

- files available in <SROOT>/include.  Copy the

- ../include/certmap.h file to the <SROOT>/include directory.

- Use 'gmake' to build the plugin.  A shared library plugin.so

- (plugin.sl on HP) will be created in the current directory.

- 

- On NT:  Execute the following command:

- NMAKE /f "Certmap.mak" CFG="Certmap - Win32 Debug"

- Certmap.dll will be created in the Debug subdirectory.

- 

- Certmap.conf Configuration

- --------------------------

- Save a copy of certmap.conf file.

- Change the certmap.conf file as follows:

- 

- certmap default default

- default:defaultOU   marketing

- default:library	    <path to the shared library>

- default:InitFn	    plugin_init_fn

- 

- 

- After experimenting with this example, restore the old copy of

- certmap.conf file.  Or else, set the certmap.conf file as follows:

- 

- certmap default default

- default:DNComps	    

- default:FilterComps	e, mail, uid

- default:VerifyCert	on

@@ -1,44 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <stdio.h>

- #include <string.h>

- #include <ctype.h>

- #include <cert.h>

- #include "certmap.h" /* Public Certmap API */

- #include "plugin.h"  /* must define extern "C" functions */

- 

- 

- NSAPI_PUBLIC int

- plugin_init_fn(void *certmap_info, const char *issuerName, const CERTName *issuerDN, const char *libname)

- {

-     static int initialized = 0;

-     int rv;

- 

-     /* Make sure CertmapDLLInit is initialized only once */

-     if (!initialized) {

- 

-         initialized = 1;

-     }

- 

-     fprintf(stderr, "plugin_init_fn called.\n");

-     ldapu_set_cert_mapfn(issuerDN, plugin_mapping_fn);

-     ldapu_set_cert_verifyfn(issuerDN, plugin_verify_fn);

- 

-     if (!default_searchfn)

-         default_searchfn = ldapu_get_cert_searchfn(issuerDN);

- 

-     ldapu_set_cert_searchfn(issuerDN, plugin_search_fn);

-     return LDAPU_SUCCESS;

- }

@@ -1,240 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <stdio.h>

- #include <string.h>

- #include <ctype.h>

- #include "certmap.h" /* Public Certmap API */

- #include "plugin.h"  /* must define extern "C" functions */

- 

- 

- CertSearchFn_t default_searchfn = 0;

- 

- 

- /* plugin_ereport -

-    This function prints an error message to stderr.  It prints the issuerDN

-    and subjectDN alongwith the given message.

-    */

- static void

- plugin_ereport(const char *msg, void *cert)

- {

-     int rv;

-     char *subjectDN;

-     char *issuerDN;

-     char *default_subjectDN = "Failed to get the subject DN";

-     char *default_issuerDN = "Failed to get the issuer DN";

- 

-     rv = ldapu_get_cert_subject_dn(cert, &subjectDN);

- 

-     if (rv != LDAPU_SUCCESS || !subjectDN) {

-         subjectDN = default_subjectDN;

-     }

- 

-     rv = ldapu_get_cert_issuer_dn(cert, &issuerDN);

- 

-     if (rv != LDAPU_SUCCESS || !issuerDN) {

-         issuerDN = default_issuerDN;

-     }

- 

-     fprintf(stderr, "%s. Issuer: %s, Subject: %s\n", msg, issuerDN,

-             subjectDN);

- 

-     if (default_subjectDN != subjectDN)

-         ldapu_free(subjectDN);

-     if (default_issuerDN != issuerDN)

-         ldapu_free(issuerDN);

- }

- 

- 

- /* plugin_mapping_fn -

-    This mapping function extracts "CN", "O" and "C" attributes from the

-    subject DN to form ldapDN.  It inserts "ou=<defaultOU>" between the

-    "CN" and the "O" attr-value pair.  The <defaultOU> can be configured in

-    the certmap.conf config file.

-    If the "C" attr is absent, it defaults to "US".

-    It extracts the "E" attribute to form the filter.

-    */

- int

- plugin_mapping_fn(void *cert, LDAP *ld, void *certmap_info, char **ldapDN, char **filter)

- {

-     char **cn_val; /* get this from the cert */

-     char **o_val;  /* get this from the cert */

-     char **c_val;  /* get this from the cert */

-     char **e_val;  /* get this from the cert */

-     char *ou_val;  /* get this from the config file */

-     int len;

-     int rv;

- 

-     fprintf(stderr, "plugin_mapping_fn called.\n");

- 

-     rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "CN", &cn_val);

- 

-     if (rv != LDAPU_SUCCESS || !cn_val) {

-         plugin_ereport("plugin_mapping_fn: Failed to extract \"CN\" from the cert", cert);

-         return LDAPU_CERT_MAP_FUNCTION_FAILED;

-     }

- 

-     rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "O", &o_val);

- 

-     if (rv != LDAPU_SUCCESS || !o_val) {

-         plugin_ereport("plugin_mapping_fn: Failed to extract \"O\" from the cert", cert);

-         return LDAPU_CERT_MAP_FUNCTION_FAILED;

-     }

- 

-     rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "C", &c_val);

- 

-     if (rv != LDAPU_SUCCESS || !c_val) {

-         plugin_ereport("plugin_mapping_fn: Failed to extract \"C\" from the cert", cert);

-     }

- 

-     rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "E", &e_val);

- 

-     if (rv != LDAPU_SUCCESS || !e_val) {

-         /* Don't return error -- just print the warning */

-         plugin_ereport("plugin_mapping_fn: Failed to extract \"E\" from the cert", cert);

-     }

- 

-     /* Get the "OU" from the "defaultOU" property from the config file */

-     rv = ldapu_certmap_info_attrval(certmap_info, "defaultOU", &ou_val);

- 

-     if (rv != LDAPU_SUCCESS || !ou_val) {

-         plugin_ereport("plugin_mapping_fn: Failed to get \"defaultOU\" from the configuration", cert);

-         return LDAPU_CERT_MAP_FUNCTION_FAILED;

-     }

- 

-     len = strlen("cn=, ou=, o=, c=") + strlen(cn_val[0]) + strlen(ou_val) +

-           strlen(o_val[0]) + (c_val ? strlen(c_val[0]) : strlen("US")) + 1;

-     *ldapDN = (char *)ldapu_malloc(len);

- 

-     if (!*ldapDN) {

-         plugin_ereport("plugin_mapping_fn: Ran out of memory", cert);

-         return LDAPU_CERT_MAP_FUNCTION_FAILED;

-     }

- 

-     if (e_val) {

-         len = strlen("mail=") + strlen(e_val[0]) + 1;

-         *filter = (char *)ldapu_malloc(len);

- 

-         if (!*filter) {

-             free(*ldapDN);

-             plugin_ereport("plugin_mapping_fn: Ran out of memory", cert);

-             return LDAPU_CERT_MAP_FUNCTION_FAILED;

-         }

-         sprintf(*filter, "mail=%s", e_val[0]);

-     } else {

-         *filter = 0;

-     }

- 

-     sprintf(*ldapDN, "cn=%s, ou=%s, o=%s, c=%s", cn_val[0], ou_val,

-             o_val[0], c_val ? c_val[0] : "US");

- 

-     ldapu_free_cert_ava_val(cn_val);

-     ldapu_free_cert_ava_val(o_val);

-     ldapu_free_cert_ava_val(c_val);

-     ldapu_free_cert_ava_val(e_val);

-     ldapu_free(ou_val);

- 

-     fprintf(stderr, "plugin_mapping_fn Returned:\n\tldapDN: \"%s\"\n\tfilter: \"%s\"\n",

-             *ldapDN, *filter ? *filter : "<NULL>");

- 

-     return LDAPU_SUCCESS;

- }

- 

- 

- int

- plugin_cert_serial_number(void *cert)

- {

-     /* Just a stub function.  You can get the DER encoded cert by using the

-        function ldapu_get_cert_der:

-        */

-     unsigned char *derCert;

-     unsigned int len;

-     int rv;

-     int sno;

- 

-     rv = ldapu_get_cert_der(cert, &derCert, &len);

- 

-     /* extract the serial number from derCert */

-     sno = 43534754; /* a fake value for now */

- 

-     ldapu_free((char *)derCert);

- 

-     return sno;

- }

- 

- /* plugin_search_fn -

-    This function first does a search based on the cert's serial number.

-    If that fails, it calls the default search function.

-    */

- int

- plugin_search_fn(void *cert, LDAP *ld, void *certmap_info, const char *suffix, const char *ldapdn, const char *filter, const char **attrs, LDAPMessage **res)

- {

-     int rv;

-     char snoFilter[256];

- 

-     fprintf(stderr, "plugin_search_fn called.\n");

-     sprintf(snoFilter, "certSerialNumber=%d",

-             plugin_cert_serial_number(cert));

- 

-     /* Search the entire LDAP tree for "certSerialNumber=<serial No.>" */

-     rv = ldap_search_s(ld, suffix, LDAP_SCOPE_SUBTREE, snoFilter,

-                        (char **)attrs, 0, res);

- 

-     /* ldap_search_s returns LDAP_SUCCESS (rather than LDAPU_SUCCESS)

-        if there is no error but there may not be any matching entries.

-        */

-     if (rv == LDAP_SUCCESS) {

-         /* There was no error but check if any entries matched */

-         int numEntries = ldap_count_entries(ld, *res);

- 

-         if (numEntries > 0) {

-             /* at least one entry matched */

-             /* change the return value to LDAPU_SUCCESS from LDAP_SUCCESS */

-             rv = LDAPU_SUCCESS;

-         } else {

-             /* Try the default search function */

-             rv = (*default_searchfn)(cert, ld, certmap_info, suffix, ldapdn,

-                                      filter, attrs, res);

-         }

-     }

- 

-     /* It's ok to return the error code from ldap_search_s */

-     return rv;

- }

- 

- /*

-   plugin_verify_fn -

-   This function returns success if only one entry exists in 'res'.

-   */

- int

- plugin_verify_fn(void *cert, LDAP *ld, void *certmap_info, LDAPMessage *res, LDAPMessage **entry)

- {

-     int rv;

-     int numEntries;

- 

-     fprintf(stderr, "plugin_verify_fn called.\n");

-     numEntries = ldap_count_entries(ld, res);

- 

-     if (numEntries == 1) {

-         *entry = ldap_first_entry(ld, res);

-         rv = LDAPU_SUCCESS;

-     } else {

-         plugin_ereport("plugin_verify_fn: Failing because multiple entries matched.",

-                        cert);

-         *entry = 0;

-         rv = LDAPU_CERT_VERIFY_FUNCTION_FAILED;

-     }

- 

-     return rv;

- }

@@ -1,35 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- #ifndef _CERTMAP_PLUGIN_H

- #define _CERTMAP_PLUGIN_H

- 

- extern CertSearchFn_t default_searchfn;

- 

- #ifdef __cplusplus

- extern "C" {

- #endif

- 

- extern int plugin_mapping_fn(void *cert, LDAP *ld, void *certmap_info, char **ldapDN, char **filter);

- 

- extern int plugin_search_fn(void *cert, LDAP *ld, void *certmap_info, const char *basedn, const char *dn, const char *filter, const char **attrs, LDAPMessage **res);

- 

- extern int plugin_verify_fn(void *cert, LDAP *ld, void *certmap_info, LDAPMessage *res, LDAPMessage **entry);

- 

- NSAPI_PUBLIC int plugin_init_fn(void *certmap_info, const char *issuerName, const char *issuerDN, const char *dllname);

- 

- #ifdef __cplusplus

- }

- #endif

- 

- #endif /* _CERTMAP_PLUGIN_H */

file removed
-138
@@ -1,138 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- 

- #include <string.h>

- #include <prlink.h>

- #include <prio.h>

- #include <prprf.h>

- 

- /*#include "base/file.h"*/

- #include "ldaputil/certmap.h"

- /*#include "ldaputil/ldapdb.h"*/

- #include "ldaputil/ldaputil.h"

- #include "ldaputil/cert.h"

- #include "ldaputil/errors.h"

- #include "ldaputil/init.h"

- 

- #include "slapi-plugin.h"

- 

- #ifndef FILE_PATHSEP

- #define FILE_PATHSEP '/'

- #endif

- #ifdef HPUX

- #ifdef __ia64

- #define DLL_SUFFIX ".so"

- #else

- #define DLL_SUFFIX ".sl"

- #endif

- #else

- #define DLL_SUFFIX ".so"

- #endif

- 

- static int

- load_server_libs(const char *dir)

- {

-     int rv = LDAPU_SUCCESS;

-     PRDir *ds;

-     int suffix_len = strlen(DLL_SUFFIX);

- 

-     if ((ds = PR_OpenDir(dir)) != NULL) {

-         PRDirEntry *d;

- 

-         /* Dir exists */

-         while ((d = PR_ReadDir(ds, PR_SKIP_BOTH))) {

-             PRLibrary *lib = 0;

-             const char *libname = d->name;

-             int len = strlen(libname);

-             int is_lib;

- 

-             is_lib = (len > suffix_len && !strcmp(libname + len - suffix_len, DLL_SUFFIX));

- 

-             if (is_lib) {

-                 char path[1024];

- 

-                 PR_snprintf(path, sizeof(path), "%s%c%s", dir, FILE_PATHSEP, libname);

-                 lib = PR_LoadLibrary(path);

-                 if (!lib)

-                     rv = LDAPU_ERR_UNABLE_TO_LOAD_PLUGIN;

-             }

-         }

-     } else {

-         /* It's ok if dir doesn't exists */

-     }

- 

-     return rv;

- }

- 

- NSAPI_PUBLIC int

- ldaputil_init(const char *config_file,

-               const char *dllname,

-               const char *serv_root,

-               const char *serv_type,

-               const char *serv_id)

- {

-     int rv = LDAPU_SUCCESS;

-     static int initialized = 0;

- 

-     /* If already initialized, cleanup the old structures */

-     if (initialized)

-         ldaputil_exit();

- 

-     if (config_file && *config_file) {

-         char dir[1024];

- 

-         LDAPUCertMapListInfo_t *certmap_list;

-         LDAPUCertMapInfo_t *certmap_default;

- 

-         if (serv_root && *serv_root) {

-             /* Load common libraries */

-             PR_snprintf(dir, sizeof(dir), "%s%clib%c%s", serv_root, FILE_PATHSEP,

-                         FILE_PATHSEP, "common");

-             rv = load_server_libs(dir);

- 

-             if (rv != LDAPU_SUCCESS)

-                 return rv;

- 

-             if (serv_type && *serv_type) {

-                 /* Load server type specific libraries */

-                 sprintf(dir, "%s%clib%c%s", serv_root, FILE_PATHSEP,

-                         FILE_PATHSEP, serv_type);

-                 rv = load_server_libs(dir);

- 

-                 if (rv != LDAPU_SUCCESS)

-                     return rv;

- 

-                 if (serv_id && *serv_id) {

-                     /* Load server instance specific libraries */

-                     sprintf(dir, "%s%clib%c%s", serv_root, FILE_PATHSEP,

-                             FILE_PATHSEP, serv_id);

-                     rv = load_server_libs(dir);

- 

-                     if (rv != LDAPU_SUCCESS)

-                         return rv;

-                 }

-             }

-         }

- 

-         rv = ldapu_certmap_init(config_file, dllname, &certmap_list,

-                                 &certmap_default);

-     }

- 

-     initialized = 1;

- 

-     if (rv != LDAPU_SUCCESS)

-         return rv;

- 

-     return rv;

- }

file removed
-214
@@ -1,214 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- /*

-  * ldapauth.cpp: Implements LDAP integration in the web server.

-  *

-  * Nitin More, John Kristian

-  */

- 

- /* #define DBG_PRINT */

- 

- #include <stdio.h>  /* for BUFSIZ */

- #include <string.h> /* for strncpy, strcat */

- #include <ldap.h>

- #include <prprf.h>

- 

- #define DEFINE_LDAPU_STRINGS 1

- #include <ldaputil/certmap.h>

- #include <ldaputil/errors.h>

- #include <ldaputil/ldapauth.h>

- 

- #include <ldaputili.h>

- 

- #include "slapi-plugin.h"

- 

- /*

-  * ldapu_find

-  *   Description:

-  *    Caller should free res if it is not NULL.

-  *   Arguments:

-  *    ld        Pointer to LDAP (assumes connection has been

-  *                established and the client has called the

-  *                appropriate bind routine)

-  *    base        basedn (where to start the search)

-  *    scope        scope for the search.  One of

-  *                LDAP_SCOPE_SUBTREE, LDAP_SCOPE_ONELEVEL, and

-  *                LDAP_SCOPE_BASE

-  *    filter        LDAP filter

-  *    attrs        A NULL-terminated array of strings indicating which

-  *                attributes to return for each matching entry.  Passing

-  *                NULL for this parameter causes all available

-  *                attributes to be retrieved.

-  *    attrsonly    A boolean value that should be zero if both attribute

-  *                types and values are to be returned, non-zero if only

-  *                types are wanted.

-  *    res        A result parameter which will contain the results of

-  *            the search upon completion of the call.

-  *   Return Values:

-  *    LDAPU_SUCCESS    if entry is found

-  *    LDAPU_FAILED    if entry is not found

-  *    <rv>        if error, where <rv> can be passed to

-  *            ldap_err2string to get an error string.

-  */

- int

- ldapu_find(LDAP *ld, const char *base, int scope, const char *filter, const char **attrs, int attrsonly, LDAPMessage **res)

- {

-     int retval;

- #ifdef USE_THIS_CODE /* ASYNCHRONOUS */

-     int msgid;

- #endif

-     int numEntries;

- 

-     *res = 0;

- 

-     /* If base is NULL set it to null string */

-     if (!base) {

-         DBG_PRINT1("ldapu_find: basedn is missing -- assuming null string\n");

-         base = "";

-     }

- 

-     if (!filter || !*filter) {

-         DBG_PRINT1("ldapu_find: filter is missing -- assuming objectclass=*\n");

-         filter = ldapu_strings[LDAPU_STR_FILTER_DEFAULT];

-     }

- 

-     DBG_PRINT2("\tbase:\t\"%s\"\n", base);

-     DBG_PRINT2("\tfilter:\t\"%s\"\n", filter ? filter : "<NULL>");

-     DBG_PRINT2("\tscope:\t\"%s\"\n",

-                (scope == LDAP_SCOPE_SUBTREE ? "LDAP_SCOPE_SUBTREE"

-                                             : (scope == LDAP_SCOPE_ONELEVEL ? "LDAP_SCOPE_ONELEVEL"

-                                                                             : "LDAP_SCOPE_BASE")));

- 

-     retval = ldapu_search_s(ld, base, scope, filter, (char **)attrs,

-                             attrsonly, res);

- 

-     if (retval != LDAP_SUCCESS) {

-         /* retval = ldap_result2error(ld, *res, 0); */

-         DBG_PRINT2("ldapu_search_s: %s\n", ldapu_err2string(retval));

-         return (retval);

-     }

- 

-     numEntries = ldapu_count_entries(ld, *res);

- 

-     if (numEntries == 1) {

-         /* success */

-         return LDAPU_SUCCESS;

-     } else if (numEntries == 0) {

-         /* not found -- but not an error */

-         DBG_PRINT1("ldapu_search_s: Entry not found\n");

-         return LDAPU_FAILED;

-     } else if (numEntries > 0) {

-         /* Found more than one entry! */

-         DBG_PRINT1("ldapu_search_s: Found more than one entry\n");

-         return LDAPU_ERR_MULTIPLE_MATCHES;

-     } else {

-         /* should never get here */

-         DBG_PRINT1("ldapu_search_s: should never reach here\n");

-         ldapu_msgfree(ld, *res);

-         return LDAP_OPERATIONS_ERROR;

-     }

- }

- 

- 

- /* Search function for the cases where base = "" = NULL suffix, that is, search to

-  * be performed on the entire DIT tree.

-  * We actually do various searches taking a naming context at a time as the base for

-  * the search. */

- 

- int

- ldapu_find_entire_tree(LDAP *ld, int scope, const char *filter, const char **attrs, int attrsonly, LDAPMessage ***res)

- {

-     int retval = LDAPU_FAILED;

-     int rv, i, num_namingcontexts;

-     LDAPMessage *result_entry, *result = NULL;

-     const char *suffix_attr[2] = {"namingcontexts", NULL};

-     /* these are private suffixes that may contain pseudo users

-        e.g. replication manager that may have certs */

-     int num_private_suffix = 1;

-     const char *private_suffix_list[2] = {"cn=config", NULL};

-     char **suffix_list, **suffix = NULL;

- 

-     rv = ldapu_find(ld, "", LDAP_SCOPE_BASE, "objectclass=*", suffix_attr, 0, &result);

-     if (rv != LDAP_SUCCESS) {

-         if (result)

-             ldapu_msgfree(ld, result);

-         return rv;

-     }

- 

-     result_entry = ldapu_first_entry(ld, result);

-     suffix = ldapu_get_values(ld, result_entry, suffix_attr[0]);

-     suffix_list = suffix;

-     num_namingcontexts = slapi_ldap_count_values(suffix);

-     /* add private suffixes to our list of suffixes to search */

-     if (num_private_suffix) {

-         suffix_list = ldapu_realloc(suffix_list,

-                                     sizeof(char *) * (num_namingcontexts + num_private_suffix + 1));

-         if (!suffix_list) {

-             if (result) {

-                 ldapu_msgfree(ld, result);

-             }

-             retval = LDAPU_FAILED;

-             return retval;

-         }

-         for (i = num_namingcontexts; i < (num_namingcontexts + num_private_suffix); ++i) {

-             suffix_list[i] = strdup(private_suffix_list[i - num_namingcontexts]);

-         }

-         suffix_list[i] = NULL;

-         num_namingcontexts += num_private_suffix;

-         suffix = suffix_list;

-     }

-     if (result)

-         ldapu_msgfree(ld, result);

-     result = 0;

-     i = 0;

- 

-     /* ugaston - the caller function must remember to free the memory allocated here */

-     *res = (LDAPMessage **)ldapu_malloc((num_namingcontexts + 1) * sizeof(LDAPMessage *));

-     while (suffix && *suffix) {

-         rv = ldapu_find(ld, *suffix, scope, filter, attrs, attrsonly, &result);

-         if (scope == LDAP_SCOPE_BASE && rv == LDAP_SUCCESS) {

-             retval = rv;

-             (*res)[i++] = result;

-             break;

-         }

- 

-         switch (rv) {

-         case LDAP_SUCCESS:

-             if (retval == LDAP_SUCCESS) {

-                 retval = LDAPU_ERR_MULTIPLE_MATCHES;

-                 (*res)[i++] = result;

-                 break;

-             }

-         /* FALLTHROUGH */

-         case LDAPU_ERR_MULTIPLE_MATCHES:

-             retval = rv;

-             (*res)[i++] = result;

-             break;

-         default:

-             if (retval != LDAP_SUCCESS && retval != LDAPU_ERR_MULTIPLE_MATCHES) {

-                 retval = rv;

-             }

-             if (result)

-                 ldapu_msgfree(ld, result);

-             result = 0;

-             break;

-         }

- 

-         suffix++;

-     }

- 

-     (*res)[i] = NULL;

-     ldapu_value_free(ld, suffix_list);

-     return retval;

- }

@@ -1,406 +0,0 @@ 

- <!-- BEGIN COPYRIGHT BLOCK

-  Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  Copyright (C) 2005 Red Hat, Inc.

-  All rights reserved.

-  

-  License: GPL (version 3 or any later version).

-  See LICENSE for details. 

-  END COPYRIGHT BLOCK -->

- <HTML>

- <HEAD>

-    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">

-    <META NAME="Author" CONTENT="Nitin More">

-    <META NAME="GENERATOR" CONTENT="Mozilla/4.01 [en] (WinNT; U) [Netscape]">

- </HEAD>

- <BODY>

- 

- <CENTER>

- <H1>

- Change Log for the ldaputil library</H1></CENTER>

- 

- <DT>

- Author: Nitin More</DT>

- 

- <DT>

- E-mail:&nbsp; <A HREF="mailto:nitin@netscape.com">nitin@netscape.com</A></DT>

- 

- <DT>

- Phone: (415) 937-4240</DT>

- 

- <CENTER></CENTER>

- 

- <CENTER>

- <HR WIDTH="100%"></CENTER>

- 

- <CENTER></CENTER>

- 

- <CENTER><B><FONT SIZE=+1>Changes since Apr 17, 1997</FONT></B></CENTER>

- 

- 

- <P>Last Update: Aug 25, 1997

- 

- <P>All the new changes have been checked into the server3_tier_branch.&nbsp;

- The server3_branch is frozen &amp; contains the version of 'ldaputil' for

- the SuiteSpot 3.0 release.

- <H2>

- Changed:</H2>

- Several bug fixes went in since I last modified this file.&nbsp; The important

- ones are:

- <UL>

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=79373">79373</A>: Attributes

- listed multiple times in certmap.conf were turining that attribute off

- and enabling some other attribute.&nbsp; (For example, if you have "E"

- as well as "MAIL" in FilterComps, they cancelled each other).</LI>

- 

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=58474">58474</A>: If nested

- group checks goes on for 30 recursions, a circular groups error is returned.</LI>

- 

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=80004">80004</A>: after

- thoroughly testing the certmap utility, several (mostly minor) oddities

- were found &amp; fixed.</LI>

- </UL>

- 

- <H2>

- Added:</H2>

- 

- <UL>

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=79370">79370</A>: Group

- membership check is optimized now through the new function <B>ldapu_auth_userdn_groupids</B>.&nbsp;

- Use this new function to get the optimization.&nbsp; This function's algorithm

- is as follows:</LI>

- 

- <BR>The first search uses the following filter (w/o the group names!):

- <OL><TT>(| (&amp; (objectclass=groupofuniquenames)</TT>

- <BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (uniquemember=&lt;userDN>))</TT>

- <BR><TT>&nbsp;&nbsp; (&amp; (objectclass=groupofnames)(member=&lt;userDN>)))</TT>

- <BR>&nbsp;</OL>

- This gives us all the groups the user is member of.&nbsp; We ask for only

- the "CN" attributes of the returned groups.&nbsp; We check if "CN" of any

- of the returned groups is one of the groups we have.&nbsp; If yes, we have

- succeeded.&nbsp; If there are no groups returned then we have failed.&nbsp;

- Otherwise, we continue with the nested group check.&nbsp; To perform that

- check, we need DNs of all the groups the user is member of, which we already

- have from the previous search.&nbsp; Now we repeat the search as follows:

- <OL><TT>(| (&amp; (objectclass=groupofuniquenames)</TT>

- <BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (| (uniquemember=&lt;grp1DN>)...

- (uniquemember=&lt;grpNDN>))</TT>

- <BR><TT>&nbsp;&nbsp; (&amp; (objectclass=groupofnames)</TT>

- <BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (| (member=&lt;grp1DN>)... (member=&lt;grpNDN>))</TT></OL>

- We check the list of groups returned by this search with the groups in

- the ACL and recursively continue until we succeed or no more groups are

- returned from the searches.

- 

- <P>Advantages of this new function is it checks multiple groups at the

- same time.&nbsp; Previously we were performing 2 ldap lookups per group.&nbsp;

- Now we achieve this in a single ldap lookup!

- 

- <P><B><BLINK>Caution</BLINK></B>: this function allows multiple groups

- with the same "CN".

- 

- <P>To use this function, you need to provide a list of group names in any

- form (e.g comma separated string, a hash table, array of strings, etc.)

- and a function to compare the name returned by the ldap lookup with your

- group names.</UL>

- 

- <CENTER><B><FONT SIZE=+1>Changes since Mar 22, 1997</FONT></B></CENTER>

- 

- 

- <P>Last Update: Apr 17, 1997

- 

- <P>Now that all beta releases are out for servers using this library, I

- could do some incompatible changes to make this library more flexible.

- No more incompatible changes are planned (except for possibly one: see

- http://scopus/bugsplat/show_bug.cgi?id=58482). <B><BLINK>All 3.0 SuiteSpot

- servers supporting client auth need to upgrade to this version.</BLINK></B>

- <H2>

- Changed:</H2>

- 

- <UL>

- <LI>

- <B>Exchanged certmap.h &amp; ldaputil.h: </B>ldaputil.h had public API

- but when the file was installed on the server root, it was called certmap.h.

- Since we already had a certmap.h, this was causing lot of confusion. If

- you were including "certmap.h", now include "ldaputil.h" and vice versa.</LI>

- 

- <LI>

- <B>Renamed 'SearchComps' to 'FilterComps'</B>: Shouldn't affect your code

- but may affect tests and documentation.</LI>

- 

- <LI>

- <B>'VerifyCert' must be either "on" or "off"</B>: VerifyCert didn't have

- a value. Now it must have a value. If it has a value of "on" then the "verification"

- step is on, otherwise it is off.</LI>

- 

- <LI>

- <B>Important bug fixes</B>: One bug was causing stack corruption &amp;

- weird unpredictable results. The other important bug was to map 'E' in

- cert to 'MAIL' in LDAP.</LI>

- </UL>

- 

- <H2>

- Added:</H2>

- 

- <UL>

- <LI>

- <B>Settable 'search function'</B>: User defined search function can be

- set for cert to ldap mapping.</LI>

- 

- <LI>

- <B>ldapu_get_cert_ava_val &amp; ldapu_free_cert_ava_val</B>: API functions

- to get &amp; free an attribute's value(s) from either the subject DN or

- the issuer DN from a cert.</LI>

- </UL>

- 

- <H2>

- Open Bugs:</H2>

- 

- <UL>Following bugs may not get fixed by RTM.</UL>

- 

- <UL>

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=51279">51279</A>: 'uniquemember'

- bug</LI>

- 

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=58474">58474</A>:&nbsp;

- 'circular groups' results in infinite loop</LI>

- 

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=58478">58478</A>: Don't

- allow a space as a valid delimeter for DNComps &amp; FilterComps.</LI>

- 

- <LI>

- <A HREF="http://scopus/bugsplat/show_bug.cgi?id=58482">58482</A>: Make

- the 'search function' configurable.</LI>

- 

- <BR>

- <HR WIDTH="100%"></UL>

- 

- <CENTER>

- <H3>

- Changes since Mar 18, 1997</H3></CENTER>

- 

- <DT>

- Last Update: Mar 22, 1997</DT>

- 

- <DT>

- A query on how to map a verisign certificate prompted these changes.&nbsp;

- I was hoping I don't have to do any major changes when I wrote this document

- on Mar 18. These are incompatible changes -- please review them before

- you upgrade.&nbsp; I have checked in this file in CVS under "ns/netsite/lib/ldaputil/ldapu-changes.html".

- I have added all the "XYZ_branch" and "XYZ_point" tags to this file so

- that you can easily see this file in your tree.&nbsp; When I make significant

- changes to this file/library, I will retag this file for your branch to

- make it same as the server3_branch. [Let me know if I shouldn't do it for

- your branch].</DT>

- 

- <H2>

- Changed:</H2>

- 

- <UL>

- <LI>

- <B>ldapu_cert_to_ldap_entry</B>: The major change was to allow for the

- mapped DN to be NULL and in that case, start the search from the basedn

- of the LDAP server. This required API change so that the basedn can be

- passed to the ldapu_cert_to_ldap_entry function. This change was required

- for correctly mapping certs from verisign w/o writing plugins. The Verisign

- certs can be mapped correctly using the following setting in the &lt;ServerRoot>/userdb/certmap.conf

- file:</LI>

- 

- <UL><TT><FONT SIZE=+1>certmap verisign &lt;verisign's DN></FONT></TT>

- <BR><TT><FONT SIZE=+1>verisign:dncomps</FONT></TT>

- <BR><TT><FONT SIZE=+1>verisign:searchcomps cn, e</FONT></TT></UL>

- The mapped DN will be NULL so basedn will be used.&nbsp; The filter will

- be

- <BR>(&amp; (cn="&lt;user's CN>") (mail="&lt;user's mail>")).&nbsp; The

- new signature of ldapu_cert_to_ldap_entry is as follows:

- <BR>&nbsp;&nbsp;&nbsp; int ldapu_cert_to_ldap_entry(void *cert, LDAP *ld,

- const char *basedn, LDAPMessage **res);

- <LI>

- <B>verify cert functions</B>: A major change in how verify cert functions

- work.&nbsp; This is function is now called even when multiple potential

- matches are found for the cert.&nbsp; The mapping is successful if the

- verify function can reduce the number of matches to exactly one.&nbsp;

- For example, if there are multiple "Joe Smith" entries, at most one of

- those will have the cert in it's "userCertificate" attr.&nbsp; The verify

- function will select that entry.&nbsp; The verify function is called with

- "LDAPMessage *res" containing all the potential matches.&nbsp; It should

- return a pointer to the matched entry in the new "LDAPMessage **entry"

- parameter.&nbsp; The new signature for CertVerifyFn_t is as follows:</LI>

- 

- <BR>&nbsp;&nbsp;&nbsp; typedef int (*CertVerifyFn_t)(void *cert, LDAP *ld,

- LDAPMessage *res,

- <BR>&nbsp;

- 

- <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

- LDAPMessage **entry);

- <LI>

- typedef int (*<B>CertMapInitiFn_t)</B>: Renamed from CertmapInitFn_t.&nbsp;

- Now this has two extra parameters to make it easy to use it in a plugin.

- Other API functions require "issuerDN" but this function was called with

- "LDAPUCertMapInfo_t *certinfo".&nbsp; There was no public API function

- to get the issuerDN from "certinfo". The new signature for CertMapInitFn_t

- is as follows:</LI>

- 

- <BR>&nbsp;&nbsp;&nbsp; typedef int (*CertMapInitFn_t)(void *certmap_info,

- const char *issuerName,

- <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

- const char *issuerDN);

- <LI>

- (ldapauth.h) <B>ldapu_auth_* functions:</B> For multiple matches, these

- functions now return LDAPU_ERR_MULTIPLE_MATCHES instead of LDAPU_FAILED.

- This change was required to make nested group membership work efficiently

- and enable the new functionality of verify cert function.</LI>

- </UL>

- 

- <DT>

- 

- <HR WIDTH="100%"></DT>

- 

- <CENTER>

- <H3>

- Changes since Feb 1, 1997</H3></CENTER>

- 

- <DT>

- Last Update: Mar 18, 1997</DT>

- 

- <DT>

- There have been several changes to the netsite/lib/ldaputil recently. If

- you use this library, please start using the latest version of ldaputil

- on the server3_branch so that all the servers go out with the same API

- and behavior. Review the changes before you upgrade. If you don't plan

- to upgrade, please let me know.</DT>

- 

- <H2>

- Renamed:</H2>

- Following structures and functions are renamed. But this shouldn't affect

- you unless you have written a certmap plugin.

- <DD>

- <TT><FONT SIZE=+1>struct CertMappingFunction_t ---> CertMapFn_t</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>struct CertVerifyFunction_t ---> CertVerifyFn_t</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_set_cert_mapping_function ---> ldapu_set_cert_mapfn</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_get_cert_mapping_function ---> ldapu_get_cert_mapfn</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_set_cert_verify_function ---> ldapu_set_cert_verifyfn</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_get_cert_verify_function ---> ldapu_get_cert_verifyfn</FONT></TT></DD>

- 

- <H2>

- Removed: (from .h)</H2>

- Removed the following functions from .h files. They are still in the .c

- file as static functions. I don't think these should be public. If you

- think otherwise, let me know.

- <DD>

- <TT><FONT SIZE=+1>ldapu_cert_mapping_function_default</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_cert_verify_function_default</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_search_cert_dn</FONT></TT></DD>

- 

- <DD>

- <TT><FONT SIZE=+1>ldapu_subject_dn_to_ldap_dn</FONT></TT></DD>

- 

- <H2>

- Changed:</H2>

- The following changes may affect you. Please review them carefully before

- you upgrade to the latest version of ldaputil.

- <UL>

- <LI>

- <TT>ldapu_auth_userdn_groupdn</TT> -- added <TT>const char *base</TT> argument

- for group within group membership check</LI>

- 

- <LI>

- ldap_init and bind calls using <TT>LDAPDatabase_t *ldb</TT> retry once

- if the LDAP server is/went down.</LI>

- 

- <LI>

- <TT>typedef CertVerifyFn_t</TT> has different arguments.</LI>

- 

- <LI>

- DNs from cert with escaped/quoted characters are correctly handled now.</LI>

- 

- <LI>

- cert to ldap entry mapping is optimized by not using string comparisons

- during thruntime. A bitmask is created when the config file is read, cert

- data is mapped to bits and compared against the bitmask.</LI>

- 

- <LI>

- Only the required attrs are retrieved in most <TT>ldap_search_s </TT>calls

- from ldaputil. Some new functions were added to keep older functions the

- same.</LI>

- 

- <LI>

- Fixed a core dump in ldapu_free_LDAPDatabase_t when using the local db.</LI>

- 

- <LI>

- ldaputil functions for initializing connection to the LDAP server and binding

- to the server are thread-safe now. This requires linking to netsite/lib/base.

- If you don't use libbase, you can turn off the thread-safe code using a

- compile time option.</LI>

- </UL>

- 

- <H2>

- Added:</H2>

- 

- <UL>

- <LI>

- Documentation to functions in ldaputil.h (customer API) - ldaputil.h is

- the external public API for customers to write there plugins.</LI>

- 

- <LI>

- <TT>ldapu_get_cert_der</TT> - returns raw DER encoded cert data</LI>

- 

- <LI>

- <TT>ldapu_cert_to_user</TT> - Similar to ldapu_cert_to_ldap_entry but only

- retrieves the 'uid' and 'userCertificate' attributes from LDAP and also

- extracts the user id.</LI>

- 

- <LI>

- <TT>ldapu_find_uid_attrs</TT> and <TT>ldapu_find_group_attrs</TT> - Similar

- to ldapu_find_uid and ldapu_find_group resp., but only retrieves the specified

- attributes. Internally used during password verification and group membership

- checks.</LI>

- 

- <LI>

- <TT>ldapu_certinfo_delete, ldapu_certinfo_modify and ldapu_certinfo_save</TT>

- - API for the certmap config file GUI tool which is not yet developed.

- Any volunteers?</LI>

- </UL>

- 

- <H2>

- <FONT SIZE=+1>TODO/Bugs:</FONT></H2>

- 

- <UL>

- <LI>

- uniquemember attribute is not handled correctly in the group membership

- check. If the user's entry has 'x500UniqueIdentifier' attribute populated,

- the group could refer to the user entry by the user's dn followed by '#'

- and an unique identifier. For example, the group entry could have:</LI>

- 

- <DD>

- uniquemember: cn=Joe Smith,o=Netscape,c=US#jsmith</DD>

- 

- <DT>

- where, 'jsmith' is one of the values of the 'x500UniqueIdentifier' attribute

- for the Joe Smith entry.</DT>

- 

- <DT>

- </DT>

- </UL>

- 

- </BODY>

- </HTML>

@@ -1,68 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- #ifndef _LDAPU_LDAPUTILI_H

- #define _LDAPU_LDAPUTILI_H

- 

- #include <ldaputil/ldaputil.h>

- 

- #include <ssl.h>

- 

- #define BIG_LINE 1024

- 

- extern const int SEC_OID_AVA_UNKNOWN; /* unknown OID */

- 

- #ifdef __cplusplus

- extern "C" {

- #endif

- 

- SECStatus CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen);

- 

- extern void *ldapu_list_empty(LDAPUList_t *list, LDAPUListNodeFn_t free_fn, void *arg);

- extern void ldapu_list_move(LDAPUList_t *from, LDAPUList_t *into);

- 

- extern int ldapu_get_cert_ava_val(void *cert_in, int which_dn, const char *attr, char ***val_out);

- 

- extern int ldapu_member_certificate_match(void *cert, const char *desc);

- 

- /* Each of several LDAP API functions has a counterpart here.

-  * They behave the same, but their implementation may be replaced

-  * by calling ldapu_VTable_set(); as Directory Server does.

-  */

- #ifdef USE_LDAP_SSL

- extern LDAP *ldapu_ssl_init(const char *host, int port, int encrypted);

- #else

- extern LDAP *ldapu_init(const char *host, int port);

- #endif

- extern int ldapu_set_option(LDAP *ld, int opt, void *val);

- extern int ldapu_simple_bind_s(LDAP *ld, const char *username, const char *passwd);

- extern int ldapu_unbind(LDAP *ld);

- extern int ldapu_search_s(LDAP *ld, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPMessage **res);

- extern int ldapu_count_entries(LDAP *ld, LDAPMessage *chain);

- extern LDAPMessage *ldapu_first_entry(LDAP *ld, LDAPMessage *chain);

- extern LDAPMessage *ldapu_next_entry(LDAP *ld, LDAPMessage *entry);

- extern int ldapu_msgfree(LDAP *ld, LDAPMessage *chain);

- extern char *ldapu_get_dn(LDAP *ld, LDAPMessage *entry);

- extern void ldapu_memfree(LDAP *ld, void *dn);

- extern char *ldapu_first_attribute(LDAP *ld, LDAPMessage *entry, BerElement **ber);

- extern char *ldapu_next_attribute(LDAP *ld, LDAPMessage *entry, BerElement *ber);

- extern void ldapu_ber_free(LDAP *ld, BerElement *ber, int freebuf);

- extern char **ldapu_get_values(LDAP *ld, LDAPMessage *entry, const char *target);

- extern struct berval **ldapu_get_values_len(LDAP *ld, LDAPMessage *entry, const char *target);

- extern void ldapu_value_free(LDAP *ld, char **vals);

- extern void ldapu_value_free_len(LDAP *ld, struct berval **vals);

- 

- #ifdef __cplusplus

- }

- #endif

- #endif

file removed
-210
@@ -1,210 +0,0 @@ 

- /** BEGIN COPYRIGHT BLOCK

-  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.

-  * Copyright (C) 2005 Red Hat, Inc.

-  * All rights reserved.

-  *

-  * License: GPL (version 3 or any later version).

-  * See LICENSE for details.

-  * END COPYRIGHT BLOCK **/

- 

- #ifdef HAVE_CONFIG_H

- #include <config.h>

- #endif

- 

- #include "ldaputili.h"

- #include <ldap.h>

- 

- static LDAPUVTable_t ldapu_VTable = {0};

- 

- /* Replace ldapu_VTable.  Subsequently, ldaputil will call the

-    functions in 'from' (not the LDAP API) to access the directory.

-  */

- void

- ldapu_VTable_set(LDAPUVTable_t *from)

- {

-     if (from) {

-         memcpy(&ldapu_VTable, from, sizeof(LDAPUVTable_t));

-     }

- }

- 

- int

- ldapu_set_option(LDAP *ld, int option, void *optdata)

- {

-     if (ldapu_VTable.ldapuV_set_option) {

-         return ldapu_VTable.ldapuV_set_option(ld, option, optdata);

-     }

-     return LDAP_LOCAL_ERROR;

- }

- 

- int

- ldapu_simple_bind_s(LDAP *ld, const char *who, const char *passwd)

- {

-     if (ldapu_VTable.ldapuV_simple_bind_s) {

-         return ldapu_VTable.ldapuV_simple_bind_s(ld, who, passwd);

-     }

-     return LDAP_LOCAL_ERROR;

- }

- 

- int

- ldapu_unbind(LDAP *ld)

- {

-     if (ldapu_VTable.ldapuV_unbind) {

-         return ldapu_VTable.ldapuV_unbind(ld);

-     }

-     return LDAP_LOCAL_ERROR;

- }

- 

- int

- ldapu_search_s(LDAP *ld, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPMessage **res)

- {

-     if (ldapu_VTable.ldapuV_search_s) {

-         return ldapu_VTable.ldapuV_search_s(ld, base, scope, filter, attrs, attrsonly, res);

-     }

-     return LDAP_LOCAL_ERROR;

- }

- 

- int

- ldapu_count_entries(LDAP *ld, LDAPMessage *chain)

- {

-     if (ldapu_VTable.ldapuV_count_entries) {

-         return ldapu_VTable.ldapuV_count_entries(ld, chain);

-     }

-     return 0;

- }

- 

- LDAPMessage *

- ldapu_first_entry(LDAP *ld, LDAPMessage *chain)

- {

-     if (ldapu_VTable.ldapuV_first_entry) {

-         return ldapu_VTable.ldapuV_first_entry(ld, chain);

-     }

-     return NULL;

- }

- 

- LDAPMessage *

- ldapu_next_entry(LDAP *ld, LDAPMessage *entry)

- {

-     if (ldapu_VTable.ldapuV_next_entry) {

-         return ldapu_VTable.ldapuV_next_entry(ld, entry);

-     }

-     return NULL;

- }

- 

- int

- ldapu_msgfree(LDAP *ld, LDAPMessage *chain)

- {

-     if (ldapu_VTable.ldapuV_msgfree) {

-         return ldapu_VTable.ldapuV_msgfree(ld, chain);

-     }

-     return LDAP_SUCCESS;

- }

- 

- char *

- ldapu_get_dn(LDAP *ld, LDAPMessage *entry)

- {

-     if (ldapu_VTable.ldapuV_get_dn) {

-         return ldapu_VTable.ldapuV_get_dn(ld, entry);

-     }

-     return NULL;

- }

- 

- void

- ldapu_memfree(LDAP *ld, void *p)

- {

-     if (ldapu_VTable.ldapuV_memfree) {

-         ldapu_VTable.ldapuV_memfree(ld, p);

-     }

- }

- 

- char *

- ldapu_first_attribute(LDAP *ld, LDAPMessage *entry, BerElement **ber)

- {

-     if (ldapu_VTable.ldapuV_first_attribute) {

-         return ldapu_VTable.ldapuV_first_attribute(ld, entry, ber);

-     }

-     return NULL;

- }

- 

- char *

- ldapu_next_attribute(LDAP *ld, LDAPMessage *entry, BerElement *ber)

- {

-     if (ldapu_VTable.ldapuV_next_attribute) {

-         return ldapu_VTable.ldapuV_next_attribute(ld, entry, ber);

-     }

-     return NULL;

- }

- 

- void

- ldapu_ber_free(LDAP *ld, BerElement *ber, int freebuf)

- {

-     if (ldapu_VTable.ldapuV_ber_free) {

-         ldapu_VTable.ldapuV_ber_free(ld, ber, freebuf);

-     }

- }

- 

- char **

- ldapu_get_values(LDAP *ld, LDAPMessage *entry, const char *desc)

- {

-     if (ldapu_VTable.ldapuV_get_values) {

-         return ldapu_VTable.ldapuV_get_values(ld, entry, desc);

-     } else if (!ldapu_VTable.ldapuV_value_free && ldapu_VTable.ldapuV_get_values_len) {

-         auto struct berval **bvals =

-             ldapu_VTable.ldapuV_get_values_len(ld, entry, desc);

-         if (bvals) {

-             auto char **vals = (char **)

-                 ldapu_malloc((ldap_count_values_len(bvals) + 1) * sizeof(char *));

-             if (vals) {

-                 auto char **val;

-                 auto struct berval **bval;

-                 for (val = vals, bval = bvals; *bval; ++val, ++bval) {

-                     auto const size_t len = (*bval)->bv_len;

-                     *val = (char *)ldapu_malloc(len + 1);

-                     memcpy(*val, (*bval)->bv_val, len);

-                     (*val)[len] = '\0';

-                 }

-                 *val = NULL;

-                 ldapu_value_free_len(ld, bvals);

-                 return vals;

-             }

-         }

-         ldapu_value_free_len(ld, bvals);

-     }

-     return NULL;

- }

- 

- void

- ldapu_value_free(LDAP *ld, char **vals)

- {

-     if (ldapu_VTable.ldapuV_value_free) {

-         ldapu_VTable.ldapuV_value_free(ld, vals);

-     } else if (!ldapu_VTable.ldapuV_get_values && vals) {

-         auto char **val;

-         for (val = vals; *val; ++val) {

-             free(*val);

-         }

-         free(vals);

-     }

- }

- 

- struct berval **

- ldapu_get_values_len(LDAP *ld, LDAPMessage *entry, const char *desc)

- {

-     if (ldapu_VTable.ldapuV_get_values_len) {

-         return ldapu_VTable.ldapuV_get_values_len(ld, entry, desc);

-     }

-     return NULL;

- }

- 

- void

- ldapu_value_free_len(LDAP *ld, struct berval **vals)

- {

-     if (ldapu_VTable.ldapuV_value_free_len) {

-         ldapu_VTable.ldapuV_value_free_len(ld, vals);

-     } else if (!ldapu_VTable.ldapuV_get_values_len && vals) {

-         auto struct berval **val;

-         for (val = vals; *val; ++val) {

-             free(*val);

-         }

-         free(vals);

-     }

- }

@@ -789,6 +789,10 @@ 

              self.log.error("Can't find file: %r, removing extension", prog)

              prog = prog[:-3]

  

+         # We need to tuck the SSLport away because we need to connect

+         hidden_ssl_port = self.sslport

+         self.sslport = None

+ 

          # Create and extract a service keytab

          args = {SER_HOST: self.host,

                  SER_PORT: self.port,

@@ -175,7 +175,6 @@ 

  

          return super(UserAccount, self)._validate(rdn, properties, basedn)

  

- 

  class UserAccounts(DSLdapObjects):

      """DSLdapObjects that represents all User Account entries in suffix.

      By default it uses 'ou=People' as rdn.

file modified
+7 -5
@@ -401,7 +401,6 @@ 

              '%s/%s' % (self._certdb, PWD_TXT),

          ]

          result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))

- 

          # We can skip the first few lines. They are junk

          # IE ['',

          #     'Certificate Nickname                                         Trust Attributes',
@@ -466,10 +465,13 @@ 

          Detect if a self-signed ca exists

          """

          have_ca = False

-         cert_list = self._rsa_cert_list()

-         for cert in cert_list:

-             if self._rsa_cert_key_exists(cert) and self._rsa_cert_is_catrust(cert):

-                 have_ca = True

+         try:

+             cert_list = self._rsa_cert_list()

+             for cert in cert_list:

+                 if self._rsa_cert_key_exists(cert) and self._rsa_cert_is_catrust(cert):

+                     have_ca = True

+         except subprocess.CalledProcessError:

+             pass

          return have_ca

  

      def _rsa_key_and_cert_exists(self):

@@ -0,0 +1,62 @@ 

+ # --- BEGIN COPYRIGHT BLOCK ---

+ # Copyright (C) 2017 Red Hat, Inc.

+ # All rights reserved.

+ #

+ # License: GPL (version 3 or any later version).

+ # See LICENSE for details.

+ # --- END COPYRIGHT BLOCK ---

+ 

+ import copy

+ 

+ from lib389._mapped_object import DSLdapObjects, DSLdapObject

+ 

+ class DylibPlugin4(DSLdapObject):

+     _plugin_properties = {

+         'nsslapd-pluginEnabled' : 'off',

+         'nsslapd-pluginInitfunc' : 'NONE',

+         'nsslapd-pluginPath': 'NONE',

+     }

+ 

+     def __init__(self, instance, dn=None):

+         super(DylibPlugin4, self).__init__(instance, dn)

+         self._rdn_attribute = 'cn'

+         self._must_attributes = [

+             'cn',

+             'nsslapd-pluginPath',

+             'nsslapd-pluginInitfunc',

+             'nsslapd-pluginEnabled',

+         ]

+         self._create_objectclasses = ['top', 'nsDylibPlugin4']

+         # We'll mark this protected, and people can just disable the plugins.

+         self._protected = True

+ 

+     def enable(self):

+         self.set('nsslapd-pluginEnabled', 'on')

+ 

+     def disable(self):

+         self.set('nsslapd-pluginEnabled', 'off')

+ 

+     def status(self):

+         return self.get_attr_val_utf8('nsslapd-pluginEnabled') == 'on'

+ 

+     def create(self, rdn=None, properties=None, basedn=None):

+         # When we create plugins, we don't want people to have to consider all

+         # the little details. Plus, the server during creation needs to be able

+         # to create these from nothing.

+         # As a result, all the named plugins carry a default properties

+         # dictionary that can be used.

+ 

+         # Copy the plugin internal properties.

+         internal_properties = copy.deepcopy(self._plugin_properties)

+         if properties is not None:

+             internal_properties.update(properties)

+         return super(DylibPlugin4, self).create(rdn, internal_properties, basedn)

+ 

+ class CertmapPlugin(DylibPlugin4):

+     def __init__(self, instance, dn="cn=certmap plugin,cn=plugins,cn=config"):

+         super(CertmapPlugin, self).__init__(instance, dn)

+ 

+ 

+ 

+ 

+ 

@@ -88,7 +88,6 @@ 

          assert(ssca._rsa_user_exists(user) is True)

      assert(ssca._rsa_user_exists('non_existen') is False)

  

- 

  if __name__ == "__main__":

      CURRENT_FILE = os.path.realpath(__file__)

      pytest.main("-s -vv %s" % CURRENT_FILE)

@@ -8,53 +8,103 @@ 

  #

  

  import ldap

+ import pytest

  

+ from lib389 import DirSrv

+ from lib389.utils import ds_is_older

  from lib389.topologies import topology_st

  from lib389.utils import logging

+ from lib389.nss_ssl import NssSsl, CERT_SUFFIX

  from lib389.idm.user import UserAccounts

- from lib389._constants import DEFAULT_SUFFIX, SECUREPORT_STANDALONE1

+ from lib389.plugins_v4 import CertmapPlugin

+ from lib389.backend import Backends, BACKEND_SAMPLE_ENTRIES

+ from lib389._constants import DEFAULT_SUFFIX, SECUREPORT_STANDALONE1, INSTALL_LATEST_CONFIG

  

  from lib389.config import CertmapLegacy

  

  log = logging.getLogger(__name__)

  

+ def _check_bind(inst, dn, tls_locs):

+ 

+     inst_clone = inst.clone()

+     inst_clone.open(saslmethod='EXTERNAL',

+                                connOnly=True,

+                                certdir=inst.get_ssca_dir(),

+                                userkey=tls_locs['key'],

+                                usercert=tls_locs['crt'])

+     assert(inst_clone.whoami_s().lower() == "dn: %s" % dn.lower())

+     inst_clone.close()

+     log.debug("PASS: bound as %s" % dn)

+ 

+ @pytest.mark.skipif(ds_is_older('1.4.0'), reason="Not implemented in 1.4.0")

+ def test_certmap_plugin_upgrade(topology_st):

+     standalone = topology_st.standalone

+ 

+     certmap = CertmapPlugin(standalone)

+     # Now, reach in and allow deletion!

+     certmap._protected = False

+     certmap.delete()

+ 

+     # Restart the server

+     standalone.restart()

+ 

+     # Now assert that the item exists again.

+     certmap_reload = CertmapPlugin(standalone)

+     assert certmap_reload.status() == True

+ 

+ @pytest.mark.skipif(ds_is_older('1.4.0'), reason="Not implemented in 1.4.0")

  def test_tls_external(topology_st):

  

      standalone = topology_st.standalone

+     standalone.enable_tls()

+ 

+     ssca = NssSsl(dbpath=topology_st.standalone.get_ssca_dir())

+     assert(ssca._rsa_ca_exists() is True)

+ 

+     inst_db = NssSsl(dirsrv=topology_st.standalone)

+     assert(inst_db._db_exists() is True)

+     assert(inst_db._rsa_key_and_cert_exists() is True)

  

-     # SETUP TLS

-     standalone.stop()

-     assert(standalone.nss_ssl.reinit() is True)

-     assert(standalone.nss_ssl.create_rsa_ca() is True)

-     assert(standalone.nss_ssl.create_rsa_key_and_cert() is True)

      # Create a user

-     assert(standalone.nss_ssl.create_rsa_user('testuser') is True)

+     assert(ssca.create_rsa_user('testuser_a') is not None)

      # Now get the details of where the key and crt are.

-     tls_locs = standalone.nss_ssl.get_rsa_user('testuser')

-     #  {'ca': ca_path, 'key': key_path, 'crt': crt_path}

+     testuser_a_tls_locs = ssca.get_rsa_user('testuser_a')

+ 

+     # This user is added to a different backend to test "without" dncomps

+     # IE we try to bind to the DN in the cert.

+     backends = Backends(standalone)

+     backends.create(properties={

+         'cn': 'certRoot',

+         'nsslapd-suffix': CERT_SUFFIX,

+         BACKEND_SAMPLE_ENTRIES: INSTALL_LATEST_CONFIG

+     })

  

-     # Start again

-     standalone.start()

+     # Manual testing: sudo LDAPTLS_KEY=/opt/dirsrv/etc/dirsrv/ssca/user-testuser_a.key LDAPTLS_CERT=/opt/dirsrv/etc/dirsrv/ssca/user-testuser_a.crt LDAPTLS_CACERT=/opt/dirsrv/etc/dirsrv/ssca/ca.crt ldapwhoami -H ldaps://localhost:63601/

  

-     users = UserAccounts(standalone, DEFAULT_SUFFIX)

-     user = users.create(properties={

-         'uid': 'testuser',

-         'cn' : 'testuser',

+     c_users = UserAccounts(standalone, CERT_SUFFIX, rdn=None)

+     testuser_a = c_users.create(rdn='cn=testuser_a', properties={

+         'uid': 'testuser_a',

+         'cn' : 'testuser_a',

+         'o': 'testing',

          'sn' : 'user',

-         'uidNumber' : '1000',

-         'gidNumber' : '2000',

-         'homeDirectory' : '/home/testuser'

+         'uidNumber' : '1001',

+         'gidNumber' : '2001',

+         'homeDirectory' : '/home/testuser_a',

+         'nsCertSubjectDn': 'CN=testuser_a,%s' % CERT_SUFFIX,

      })

+     testuser_a.enroll_certificate(testuser_a_tls_locs['crt_der_path'])

+ 

+     ## REMEMBER the bind logic is in this order:

+     # If dncomps == None: bind to subject DN in cert

+     # If dncomps == None, cmapattr set, search object with cmap attr. nsCertSubjectDN

+     # if dncomps == '', use filter comps ot search an entyr below basedn

+     # if dncomps == 'attr',  use these to construct a DN

  

-     standalone.rsa.create()

-     # Set the secure port and nsslapd-security

-     standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1 )

-     standalone.config.set('nsslapd-security', 'on')

-     standalone.sslport = SECUREPORT_STANDALONE1

      # Now turn on the certmap.

      cm = CertmapLegacy(standalone)

      certmaps = cm.list()

-     certmaps['default']['DNComps'] = ''

+     # This means to use filter comps instead of dn comps

+     certmaps['default']['DNComps'] = None

      certmaps['default']['FilterComps'] = ['cn']

      certmaps['default']['VerifyCert'] = 'off'

      cm.set(certmaps)
@@ -66,17 +116,43 @@ 

      standalone.restart(post_open=False)

  

      # Now attempt a bind with TLS external

-     conn = standalone.openConnection(saslmethod='EXTERNAL', connOnly=True, certdir=standalone.get_cert_dir(), userkey=tls_locs['key'], usercert=tls_locs['crt'])

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

+ 

+     # Change the certmap and try and verify the certificate

+     certmaps['default']['CmapLdapAttr'] = 'nsCertSubjectDN'

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

+ 

+     # Change the basedn and check it works.

+     certmaps['default']['basedn'] = 'o=testing,l=lib389,st=Queensland,c=AU'

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

+ 

+     # Change the certmap and try and verify the certificate

+     certmaps['default']['VerifyCert'] = 'on'

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

  

-     assert(conn.whoami_s() == "dn: uid=testuser,ou=People,dc=example,dc=com")

+     # Check filter comps

+     certmaps['default']['DNComps'] = ''

+     certmaps['default']['CmapLdapAttr'] = None

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

  

-     # Backup version of the code:

-     # ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)

-     # ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, tls_locs['ca'])

-     # ldap.set_option(ldap.OPT_X_TLS_KEYFILE, tls_locs['key'])

-     # ldap.set_option(ldap.OPT_X_TLS_CERTFILE, tls_locs['crt'])

-     # conn = ldap.initialize(standalone.toLDAPURL())

+     # Change the filter comps to check o and cn

+     certmaps['default']['FilterComps'] = ['cn', 'o']

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

  

-     # sasl_auth = ldap.sasl.external()

-     # conn.sasl_interactive_bind_s("", sasl_auth)

+     # Finally, check the dncomps

+     # The order of these matter as they are extract and appended in *this* order.

+     certmaps['default']['DNComps'] = ['cn', 'o', 'l', 'st', 'c']

+     cm.set(certmaps)

+     standalone.restart(post_open=False)

+     _check_bind(standalone, 'cn=testuser_a,%s' % CERT_SUFFIX, testuser_a_tls_locs)

  

file modified
+21 -3
@@ -1079,7 +1079,7 @@ 

   * \param fn The function to be applied to each key-value pair.

   * \retval Result of the operation as sds_result.

   */

- sds_result sds_bptree_map(sds_bptree_instance *binst, void (*fn)(void *k, void *v));

+ sds_result sds_bptree_map(sds_bptree_instance *binst, void *arg, void (*fn)(void *k, void *v, void *arg));

  /**

   * From instance a, and instance b, create a new insance that contains the

   * keys and values where keys exist in a or b but not both.
@@ -1227,7 +1227,16 @@ 

   * \retval Result of the operation as sds_result.

   */

  sds_result sds_bptree_cow_wrtxn_commit(sds_bptree_transaction **btxn);

- 

+ /**

+  * Retrieve the current transaction's id. There is *no guarantee* that this

+  * id increments sequentially, or avoids any kind of int rollover. It's only

+  * purpose is to allow generational timestamping of external data to assert

+  * if a newer transaction has passed since.

+  *

+  * \param btxn The transaction from which you wish to retrieve the ID

+  * \retval The transaction ID.

+  */

+ uint64_t sds_bptree_txn_get_id(sds_bptree_transaction *btxn);

  /**

   * Search a tree with a valid transaction reference. This returns KEY_PRESENT

   * or KEY_NOT_PRESENT if the search suceeds or not. Search may operation on a valid
@@ -1288,10 +1297,19 @@ 

   * \param value The value to update. May be NULL.

   * \retval Result of the operation as sds_result.

   */

- 

  sds_result sds_bptree_cow_update(sds_bptree_transaction *btxn, void *key, void *value);

  

  /**

+  * Map over all key/values in the tree within this txn. If the transaction is readonly

+  * you should only read these values. If the txn is write, you may modify value.

+  *

+  * \param btxn The transaction to map over.

+  * \param arg A generic argument that will be passed to each invocation of fn.

+  * \param fn the function to apply to each key/value.

+  */

+ sds_result sds_bptree_cow_map(sds_bptree_transaction *btxn, void *arg, void (*fn)(void *k, void *v, void *arg));

+ 

+ /**

   * Search atomic functions as search, but implies a single short lived read transaction.

   *

   * If you have multiple searches to make, it is better to use a read transaction due to

@@ -384,6 +384,9 @@ 

  {

      // Remove all the other elements

      sds_result result = SDS_SUCCESS;

+     if (binst == NULL) {

+         return SDS_NULL_POINTER;

+     }

      result = sds_bptree_map_nodes(binst, binst->root, sds_bptree_node_destroy);

      // Finally remove the binst

      sds_free(binst);

file modified
+1 -1
@@ -522,7 +522,7 @@ 

  

      /* extract the contents (if any) */

      void *value = node->values[index];

-     if (value != NULL) {

+     if (value != NULL && binst->value_free_fn != NULL) {

          binst->value_free_fn(value);

      }

      /* Delete the key + value */

file modified
+2 -2
@@ -66,7 +66,7 @@ 

  /* Tree mapping functions */

  /* Shouldn't this make a set of results? */

  sds_result

- sds_bptree_map(sds_bptree_instance *binst, void (*fn)(void *k, void *v))

+ sds_bptree_map(sds_bptree_instance *binst, void *arg, void (*fn)(void *k, void *v, void *arg))

  {

      /* If this is the non-cow tree, this is easy. */

      /* Find the bottom left node, then iterate to the right! */
@@ -74,7 +74,7 @@ 

  

      while (work_node != NULL) {

          for (size_t index = 0; index < work_node->item_count; index++) {

-             fn(work_node->keys[index], work_node->values[index]);

+             fn(work_node->keys[index], work_node->values[index], arg);

          }

          work_node = (sds_bptree_node *)work_node->values[SDS_BPTREE_DEFAULT_CAPACITY];

      }

@@ -469,6 +469,51 @@ 

      return SDS_SUCCESS;

  }

  

+ sds_result

+ sds_bptree_cow_map(sds_bptree_transaction *btxn, void *arg, void (*fn)(void *k, void *v, void *arg)) {

+     /*

+      * For each leaf node, map fn to each value.

+      *

+      * This is really similar to map_nodes, but only applies fn at level == 0

+      */

+ 

+     if (btxn == NULL) {

+         return SDS_INVALID_TXN;

+     }

+ 

+     sds_bptree_node_list *cur = sds_malloc(sizeof(sds_bptree_node_list));

+     sds_bptree_node_list *prev = cur;

+     sds_bptree_node_list *tail = cur;

+ 

+     cur->node = btxn->root;

+     cur->next = NULL;

+     sds_result final_result = SDS_SUCCESS;

+ 

+     while (cur != NULL) {

+         if (cur->node->level > 0) {

+             /* Has to be <= here as this is access values, not keys! */

+             for (size_t i = 0; i <= cur->node->item_count; i++) {

+                 /* Alloc a new element, and shuffle along .... */

+                 if (cur->node->values[i] != NULL) {

+                     tail->next = sds_malloc(sizeof(sds_bptree_node_list));

+                     tail = tail->next;

+                     tail->node = (sds_bptree_node *)cur->node->values[i];

+                     tail->next = NULL;

+                 }

+             }

+         } else {

+             /* We have a leaf! map the fn over valid values. */

+             for (size_t index = 0; index < cur->node->item_count; index++) {

+                 fn(cur->node->keys[index], cur->node->values[index], arg);

+             }

+         }

+         prev = cur;

+         cur = cur->next;

+         free(prev);

+     }

+     return final_result;

+ }

+ 

  // Does this need to work on a transaction perhaps to verify the tree is "sane"?

  sds_result

  sds_bptree_cow_verify(sds_bptree_cow_instance *binst)

file modified
+22 -5
@@ -54,7 +54,7 @@ 

  

      // The initial ref count is 0, and we only up to 1 when we commit.

      // Atomically set this to 0.

-     __atomic_and_fetch(&(btxn->reference_count), 0, __ATOMIC_SEQ_CST);

+     __atomic_and_fetch(&(btxn->reference_count), 0, __ATOMIC_RELAXED);

  

  #ifdef SDS_DEBUG

      // Update our needed checksums
@@ -76,6 +76,23 @@ 

   * ==============================================================

   */

  

+ uint64_t

+ sds_bptree_txn_get_id(sds_bptree_transaction *btxn) {

+     if (btxn != NULL) {

+         return btxn->txn_id;

+     }

+     return 0;

+ }

+ 

+ /* ========================= WARNING ============================

+  * UNLESS YOU HAVE READ:

+  *  https://www.kernel.org/doc/Documentation/memory-barriers.txt

+  * and SERIOUSLY understand it, and how it works you *MUST* not

+  * edit this file. This section of the code relies on a deep

+  * understanding of locking and memory barriers.

+  * ==============================================================

+  */

+ 

  // Should be caled by txn decrement.

  static void

  sds_bptree_txn_free(sds_bptree_transaction *btxn)
@@ -111,7 +128,7 @@ 

  static void

  sds_bptree_txn_increment(sds_bptree_transaction *btxn)

  {

-     __atomic_add_fetch(&(btxn->reference_count), 1, __ATOMIC_SEQ_CST);

+     __atomic_add_fetch(&(btxn->reference_count), 1, __ATOMIC_RELAXED);

  

  // PR_AtomicIncrement(&(btxn->reference_count));

  #ifdef SDS_DEBUG
@@ -140,7 +157,7 @@ 

  

      // Atomic dec the counter.

      // PR_AtomicDecrement returns the set value.

-     uint32_t result = __atomic_sub_fetch(&(btxn->reference_count), 1, __ATOMIC_SEQ_CST);

+     uint32_t result = __atomic_sub_fetch(&(btxn->reference_count), 1, __ATOMIC_RELAXED);

  /* WARNING: After this point, another thread MAY free btxn under us.

       * You MUST *not* deref btxn after this point.

       */
@@ -169,7 +186,7 @@ 

              // * there are more parents left, so we are > 0

              // * there are still active holders left, so we are > 0

              if (btxn != NULL) {

-                 result = __atomic_sub_fetch(&(btxn->reference_count), 1, __ATOMIC_SEQ_CST);

+                 result = __atomic_sub_fetch(&(btxn->reference_count), 1, __ATOMIC_RELAXED);

              }

          }

      }
@@ -400,7 +417,7 @@ 

      // Say we are alive and commited - 2 means "our former transaction owns us"

      // and "we are the active root".

      uint32_t default_ref_count = 2;

-     __atomic_store(&((*btxn)->reference_count), &default_ref_count, __ATOMIC_SEQ_CST);

+     __atomic_store(&((*btxn)->reference_count), &default_ref_count, __ATOMIC_RELAXED);

      // Set it.

      (*btxn)->binst->txn = *btxn;

      // Update our parent to reference us.

@@ -562,6 +562,40 @@ 

      assert_int_equal(sds_bptree_cow_rotxn_close(&ro_btxn_b), SDS_SUCCESS);

  }

  

+ static void

+ test_cow_map_cb(void *key __attribute((unused)), void *value, void *arg __attribute((unused))) {

+     *(uint64_t *)value = 12345;

+ }

+ 

+ static void

+ test_cow_map(void **state)

+ {

+     sds_bptree_cow_instance *binst = *state;

+     sds_bptree_transaction *wr_btxn = NULL;

+     sds_result result = SDS_SUCCESS;

+ 

+     assert_int_equal(sds_bptree_cow_wrtxn_begin(binst, &wr_btxn), SDS_SUCCESS);

+ 

+     /* Insert a set of keys with values */

+     for (uint64_t i = 10; i < (10 + SDS_BPTREE_DEFAULT_CAPACITY); i++) {

+         result = sds_bptree_cow_insert(wr_btxn, (void *)&i, sds_uint64_t_dup((void *)&i));

+         assert_int_equal(result, SDS_SUCCESS);

+     }

+     /* Map and change the values */

+ 

+     assert_int_equal(sds_bptree_cow_map(wr_btxn, NULL, test_cow_map_cb), SDS_SUCCESS);

+ 

+     for (uint64_t i = 10; i < (10 + SDS_BPTREE_DEFAULT_CAPACITY); i++) {

+         uint64_t *output = NULL;

+         assert_int_equal(sds_bptree_cow_retrieve(wr_btxn, (void *)&i, (void **)&output), SDS_KEY_PRESENT);

+         assert_int_equal(result, SDS_SUCCESS);

+         assert_int_equal(*output, 12345);

+     }

+     /* Assert the values have changed. */

+ 

+     assert_int_equal(sds_bptree_cow_wrtxn_commit(&wr_btxn), SDS_SUCCESS);

+ }

+ 

  int

  run_cow_tests(void)

  {
@@ -627,6 +661,9 @@ 

          cmocka_unit_test_setup_teardown(test_cow_update,

                                          bptree_test_cow_setup,

                                          bptree_test_cow_teardown),

+         cmocka_unit_test_setup_teardown(test_cow_map,

+                                         bptree_test_cow_setup,

+                                         bptree_test_cow_teardown),

      };

      return cmocka_run_group_tests_name("bpt_cow", tests, NULL, NULL);

  }

@@ -16,7 +16,7 @@ 

  static int32_t cb_count = 0;

  

  static void

- test_31_map_cb(void *k __attribute__((unused)), void *v __attribute__((unused)))

+ test_31_map_cb(void *k __attribute__((unused)), void *v __attribute__((unused)), void *arg __attribute__((unused)))

  {

      cb_count++;

  }
@@ -39,7 +39,7 @@ 

          result = sds_bptree_verify(binst);

          assert_int_equal(result, SDS_SUCCESS);

      }

-     sds_bptree_map(binst, test_31_map_cb);

+     sds_bptree_map(binst, NULL, test_31_map_cb);

      assert_int_equal(cb_count, 199);

  }

  

https://pagure.io/389-ds-base/issue/49218

With FreeIPA 4.5 version it is possible to define certificate mappings using flexible rules. This mechanism is supported now in MIT Kerberos (to be released in 1.16, backported to Fedora 26/RHEL 7.4) with 'certauth' plugin which FreeIPA 4.5 implements and in SSSD (for local PKINIT authentication).

It would be nice to extend 389-ds to support the same certificate mapping rules. Right now certificate mapping in 389-ds is static and defined in a read-only configuration file. Aside from that, this file needs to be manually copied across all replicas to be consistent.

FreeIPA design page: http://www.freeipa.org/page/V4/Certificate_Identity_Mapping
SSSD design page: https://docs.pagure.org/SSSD.sssd/design_pages/matching_and_mapping_certificates.html
MIT Kerberos design page: https://k5wiki.kerberos.org/wiki/Projects/Certificate_authorization_pluggable_interface

We currently have a feature to track and report the bind dn even when plugins make updates

http://www.port389.org/docs/389ds/design/plugin-track-bind-dn.html

What impact is this going to have? Does it make that feature obsolete?

Okay, it doesn't make it obsolete persay, but "on by default". I think that's the best answer here.

So looking at the one design doc you mention a concern over use a version number in the function names, "_v4". To future proof this work I think we should create wrappers now, and start using the wrappers throughout the code, so when there is another version change the impact is minimal.

For example we have slapi_v4_bvarray_append() We should also create a wrapper called: slapi_bvarray_append() that will call whatever the current "versioned" function is. So we only need to update one function when we do a major version change, and not a 150 places in the code. This of course can be a separate patch, but I wanted to bring it up.

@mreynolds I think I did start adding this? And I did use them as much as possible? Did I miss some?

Because I think this is good so we can audit the API with the intent to clean our public interface in the next few years.

@mreynolds Hey mate, I think I updated this patch. Did I miss anything?

There's still some indentation issues, and I think you should add some logging in utf8.c (see comments). Otherwise looking good!

Thanks @mreynolds I hope to tidy this up and get it merged soon then :)

I think the cleanup was done, but not sure if pushed. Really, the enemy of this is "time", and I think I want to improve this patch some more (feature gate) before I really push it.

@firstyear, just curious does this patch address the annoying issues with plug-in memory leaks reported by ASAN?

Either way it would be nice to see this work continued :)

@mreynolds Very much yes :) It was one of the motivations for me to write this all that time ago, was that it made plugin structures on the server side much simpler, and with a better defined lifetime and lifecycle. It has no asan issues at all even with dynamic enable/disable. :)

edit: hit send to soon - anyway, my current plan is look at the follow ups on filter optimisation, logging, connections, then this. But I will come back to it.

@mreynolds I've revived this and got it running on master, but I think the strategy might be to break it down into smaller submissions, so that it's easier to review :)

rebased onto 9a852c9

3 years ago

Pull-Request has been closed by spichugi

3 years ago

Pull-Request has been reopened by spichugi

3 years ago

389-ds-base is moving from Pagure to Github. This means that new issues and pull requests
will be accepted only in 389-ds-base's github repository.

This pull request has been cloned to Github as issue and is available here:
- https://github.com/389ds/389-ds-base/issues/2638

If you want to continue to work on the PR, please navigate to the github issue,
download the patch from the attachments and file a new pull request.

Thank you for understanding. We apologize for all inconvenience.

Pull-Request has been closed by spichugi

3 years ago
Metadata
Changes Summary 72
+30 -31
file changed
Makefile.am
+1 -0
file changed
ldap/schema/01core389.ldif
+639
file added
ldap/servers/plugins/certmap/certmap.c
+5 -0
file changed
ldap/servers/plugins/rever/rever.h
+34 -0
file changed
ldap/servers/slapd/add.c
+61 -406
file changed
ldap/servers/slapd/auth.c
+60
file added
ldap/servers/slapd/bvarray_v4.c
+128
file added
ldap/servers/slapd/cert_v4.c
+2 -1
file changed
ldap/servers/slapd/ch_malloc.c
+14 -2
file changed
ldap/servers/slapd/charray.c
+15 -9
file changed
ldap/servers/slapd/config.c
+21 -0
file changed
ldap/servers/slapd/configdse.c
+18 -0
file changed
ldap/servers/slapd/connection.c
+9 -0
file changed
ldap/servers/slapd/daemon.c
+20 -7
file changed
ldap/servers/slapd/dn.c
+22 -15
file changed
ldap/servers/slapd/dse.c
+29 -0
file changed
ldap/servers/slapd/entry.c
+36 -0
file changed
ldap/servers/slapd/fedse.c
+4 -4
file changed
ldap/servers/slapd/libglobs.c
+25 -44
file changed
ldap/servers/slapd/log.c
+28 -5
file changed
ldap/servers/slapd/main.c
+1 -0
file changed
ldap/servers/slapd/operation.c
+3 -0
file changed
ldap/servers/slapd/pblock.c
+1 -0
file changed
ldap/servers/slapd/pblock_v3.h
+173
file added
ldap/servers/slapd/pblock_v4.c
+3 -0
file changed
ldap/servers/slapd/plugin.c
+2 -2
file changed
ldap/servers/slapd/plugin_internal_op.c
+1171
file added
ldap/servers/slapd/plugin_v4.c
+3 -3
file changed
ldap/servers/slapd/proto-slap.h
+127
file added
ldap/servers/slapd/slapi-internal-v4.h
+70
file added
ldap/servers/slapd/slapi-plugin-v4.c
+74
file added
ldap/servers/slapd/slapi-plugin-v4.h
+3 -45
file changed
ldap/servers/slapd/slapi-plugin.h
+131
file added
ldap/servers/slapd/slapi-private-v4.c
+198
file added
ldap/servers/slapd/slapi-private-v4.h
+78 -0
file changed
ldap/servers/slapd/slapi_pal.c
+6 -0
file changed
ldap/servers/slapd/slapi_pal.h
+3 -0
file changed
ldap/servers/slapd/snmp_collator.c
+60
file added
ldap/servers/slapd/upgrade.c
+27 -0
file changed
ldap/servers/slapd/utf8.c
+3 -0
file changed
ldap/servers/slapd/util.c
-1
file removed
lib/ldaputil/.cvsignore
-504
file removed
lib/ldaputil/cert.c
-1612
file removed
lib/ldaputil/certmap.c
+9 -6
file changed
lib/ldaputil/certmap.conf
-686
file removed
lib/ldaputil/dbconf.c
-151
file removed
lib/ldaputil/encode.c
-210
file removed
lib/ldaputil/errors.c
-89
file removed
lib/ldaputil/examples/Makefile
-100
file removed
lib/ldaputil/examples/README
-44
file removed
lib/ldaputil/examples/init.c
-240
file removed
lib/ldaputil/examples/plugin.c
-35
file removed
lib/ldaputil/examples/plugin.h
-138
file removed
lib/ldaputil/init.c
-214
file removed
lib/ldaputil/ldapauth.c
-406
file removed
lib/ldaputil/ldapu-changes.html
-68
file removed
lib/ldaputil/ldaputili.h
-210
file removed
lib/ldaputil/vtable.c
+4 -0
file changed
src/lib389/lib389/__init__.py
+0 -1
file changed
src/lib389/lib389/idm/user.py
+7 -5
file changed
src/lib389/lib389/nss_ssl.py
+62
file added
src/lib389/lib389/plugins_v4.py
+0 -1
file changed
src/lib389/lib389/tests/nss_ssl_test.py
+110 -34
file changed
src/lib389/lib389/tests/tls_external_test.py
+21 -3
file changed
src/libsds/include/sds.h
+3 -0
file changed
src/libsds/sds/bpt/bpt.c
+1 -1
file changed
src/libsds/sds/bpt/common.c
+2 -2
file changed
src/libsds/sds/bpt/set.c
+45 -0
file changed
src/libsds/sds/bpt_cow/bpt_cow.c
+22 -5
file changed
src/libsds/sds/bpt_cow/txn.c
+37 -0
file changed
src/libsds/test/test_sds_cow.c
+2 -2
file changed
src/libsds/test/test_sds_set.c