Tom Ryan wrote:
On 7/26/06 5:29 PM, "Richard Megginson" <rmeggins@xxxxxxxxxx> wrote: > pamMapMethod: ENTRY This should be pamIDMapMethod. The reason it always uses the RDN value is because that is the default if none is specified.Sweet! I wasn’t looking at the code, just the readme/etc which says pammapmethodRegardless, if I use that, it doesn’t start up now..I tried adjusting the schema files to state pamidmapmethod instead.. I’m getting nothing..
Congratulations - you are the first tester of the ENTRY method! :-) I've made some fixes to pam_ptconfig.c - try the attached file.
:) Tom ------------------------------------------------------------------------ -- Fedora-directory-users mailing list Fedora-directory-users@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-directory-users
/** BEGIN COPYRIGHT BLOCK * This Program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License. * * This Program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA. * * In addition, as a special exception, Red Hat, Inc. gives You the additional * right to link the code of this Program with code not covered under the GNU * General Public License ("Non-GPL Code") and to distribute linked combinations * including the two, subject to the limitations in this paragraph. Non-GPL Code * permitted under this exception must only link to the code of this Program * through those well defined interfaces identified in the file named EXCEPTION * found in the source code files (the "Approved Interfaces"). The files of * Non-GPL Code may instantiate templates or use macros or inline functions from * the Approved Interfaces without causing the resulting work to be covered by * the GNU General Public License. Only Red Hat, Inc. may make changes or * additions to the list of Approved Interfaces. You must obey the GNU General * Public License in all respects for all of the Program code and other code used * in conjunction with the Program except the Non-GPL Code covered by this * exception. If you modify this file, you may extend this exception to your * version of the file, but you are not obligated to do so. If you do not wish to * provide this exception without modification, you must delete this exception * statement from your version and license this file solely under the GPL without * exception. * * * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ /* * ptconfig.c - configuration-related code for Pass Through Authentication * */ #include <plstr.h> #include "pam_passthru.h" #define PAM_PT_CONFIG_FILTER "(objectclass=*)" /* * The configuration attributes are contained in the plugin entry e.g. * cn=PAM Pass Through,cn=plugins,cn=config * * Configuration is a two step process. The first pass is a validation step which * occurs pre-op - check inputs and error out if bad. The second pass actually * applies the changes to the run time config. */ /* * function prototypes */ static int pam_passthru_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg); static int pam_passthru_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg); static int pam_passthru_search (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { return SLAPI_DSE_CALLBACK_OK; } /* * static variables */ /* for now, there is only one configuration and it is global to the plugin */ static Pam_PassthruConfig theConfig; static int inited = 0; static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { *returncode = LDAP_UNWILLING_TO_PERFORM; return SLAPI_DSE_CALLBACK_ERROR; } /* * Read configuration and create a configuration data structure. * This is called after the server has configured itself so we can check * for things like collisions between our suffixes and backend's suffixes. * Returns an LDAP error code (LDAP_SUCCESS if all goes well). */ int pam_passthru_config(Slapi_Entry *config_e) { int returncode = LDAP_SUCCESS; char returntext[SLAPI_DSE_RETURNTEXT_SIZE]; if ( inited ) { slapi_log_error( SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "only one PAM pass through plugin instance can be used\n" ); return( LDAP_PARAM_ERROR ); } /* initialize fields */ if ((theConfig.lock = slapi_new_mutex()) == NULL) { return( LDAP_LOCAL_ERROR ); } /* do not fallback to regular bind */ theConfig.pamptconfig_fallback = PR_FALSE; /* require TLS/SSL security */ theConfig.pamptconfig_secure = PR_TRUE; /* use the RDN method to derive the PAM identity */ theConfig.pamptconfig_map_method1 = PAMPT_MAP_METHOD_RDN; theConfig.pamptconfig_map_method2 = PAMPT_MAP_METHOD_NONE; theConfig.pamptconfig_map_method3 = PAMPT_MAP_METHOD_NONE; if (SLAPI_DSE_CALLBACK_OK == pam_passthru_validate_config(NULL, NULL, config_e, &returncode, returntext, NULL)) { pam_passthru_apply_config(NULL, NULL, config_e, &returncode, returntext, NULL); } /* config DSE must be initialized before we get here */ if (returncode == LDAP_SUCCESS) { const char *config_dn = slapi_entry_get_dn_const(config_e); slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE, PAM_PT_CONFIG_FILTER, pam_passthru_validate_config,NULL); slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, config_dn, LDAP_SCOPE_BASE, PAM_PT_CONFIG_FILTER, pam_passthru_apply_config,NULL); slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE, PAM_PT_CONFIG_FILTER, dont_allow_that, NULL); slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE, PAM_PT_CONFIG_FILTER, dont_allow_that, NULL); slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, config_dn, LDAP_SCOPE_BASE, PAM_PT_CONFIG_FILTER, pam_passthru_search,NULL); } inited = 1; if (returncode != LDAP_SUCCESS) { slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "Error %d: %s\n", returncode, returntext); } return returncode; } static int missing_suffix_to_int(char *missing_suffix) { int retval = -1; /* -1 is error */ if (!PL_strcasecmp(missing_suffix, PAMPT_MISSING_SUFFIX_ERROR_STRING)) { retval = PAMPT_MISSING_SUFFIX_ERROR; } else if (!PL_strcasecmp(missing_suffix, PAMPT_MISSING_SUFFIX_ALLOW_STRING)) { retval = PAMPT_MISSING_SUFFIX_ALLOW; } else if (!PL_strcasecmp(missing_suffix, PAMPT_MISSING_SUFFIX_IGNORE_STRING)) { retval = PAMPT_MISSING_SUFFIX_IGNORE; } return retval; } static PRBool check_missing_suffix_flag(int val) { if (val == PAMPT_MISSING_SUFFIX_ERROR || val == PAMPT_MISSING_SUFFIX_ALLOW || val == PAMPT_MISSING_SUFFIX_IGNORE) { return PR_TRUE; } return PR_FALSE; } #define MAKE_STR(x) #x static char *get_missing_suffix_values() { return MAKE_STR(PAMPT_MISSING_SUFFIX_ERROR) ", " MAKE_STR(PAMPT_MISSING_SUFFIX_ALLOW) ", " MAKE_STR(PAMPT_MISSING_SUFFIX_IGNORE); } static char *get_map_method_values() { return PAMPT_MAP_METHOD_DN_STRING " or " PAMPT_MAP_METHOD_RDN_STRING " or " PAMPT_MAP_METHOD_ENTRY_STRING; } static int meth_to_int(char **map_method, int *err) { char *end; int len; int ret; *err = 0; if (!map_method || !*map_method) { return PAMPT_MAP_METHOD_NONE; } end = strchr(*map_method, ' '); if (!end) { len = strlen(*map_method); } else { len = end - *map_method; } if (!PL_strncasecmp(*map_method, PAMPT_MAP_METHOD_DN_STRING, len)) { ret = PAMPT_MAP_METHOD_DN; } else if (!PL_strncasecmp(*map_method, PAMPT_MAP_METHOD_RDN_STRING, len)) { ret = PAMPT_MAP_METHOD_RDN; } else if (!PL_strncasecmp(*map_method, PAMPT_MAP_METHOD_ENTRY_STRING, len)) { ret = PAMPT_MAP_METHOD_ENTRY; } else { *err = 1; } if (!*err) { if (end && *end) { *map_method = end + 1; } else { *map_method = NULL; } } return ret; } static int parse_map_method(char *map_method, int *one, int *two, int *three, char *returntext) { int err = 0; int extra; char **ptr = &map_method; *one = *two = *three = PAMPT_MAP_METHOD_NONE; *one = meth_to_int(ptr, &err); if (err) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The map method in the string [%s] is invalid: must be " "one of %s", map_method, get_map_method_values()); return LDAP_UNWILLING_TO_PERFORM; } *two = meth_to_int(ptr, &err); if (err) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The map method in the string [%s] is invalid: must be " "one of %s", map_method, get_map_method_values()); return LDAP_UNWILLING_TO_PERFORM; } *three = meth_to_int(ptr, &err); if (err) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The map method in the string [%s] is invalid: must be " "one of %s", map_method, get_map_method_values()); return LDAP_UNWILLING_TO_PERFORM; } if (((extra = meth_to_int(ptr, &err)) != PAMPT_MAP_METHOD_NONE) || err) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid extra text [%s] after last map method", ((ptr && *ptr) ? *ptr : "(null)")); return LDAP_UNWILLING_TO_PERFORM; } return err; } /* Validate the pending changes in the e entry. */ static int pam_passthru_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { char *missing_suffix_str = NULL; int missing_suffix; int ii; char **excludes = NULL; char **includes = NULL; char *pam_ident_attr = NULL; char *map_method = NULL; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* first, get the missing_suffix flag and validate it */ missing_suffix_str = slapi_entry_attr_get_charptr(e, PAMPT_MISSING_SUFFIX_ATTR); if ((missing_suffix = missing_suffix_to_int(missing_suffix_str)) < 0 || !check_missing_suffix_flag(missing_suffix)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: valid values for %s are %s", PAMPT_MISSING_SUFFIX_ATTR, get_missing_suffix_values()); goto done; } if (missing_suffix != PAMPT_MISSING_SUFFIX_IGNORE) { char **missing_list = NULL; Slapi_DN *comp_dn = slapi_sdn_new(); /* get the list of excluded suffixes */ excludes = slapi_entry_attr_get_charray(e, PAMPT_EXCLUDES_ATTR); for (ii = 0; excludes && excludes[ii]; ++ii) { slapi_sdn_init_dn_byref(comp_dn, excludes[ii]); if (!slapi_be_exist(comp_dn)) { charray_add(&missing_list, slapi_ch_strdup(excludes[ii])); } slapi_sdn_done(comp_dn); } /* get the list of included suffixes */ includes = slapi_entry_attr_get_charray(e, PAMPT_INCLUDES_ATTR); for (ii = 0; includes && includes[ii]; ++ii) { slapi_sdn_init_dn_byref(comp_dn, includes[ii]); if (!slapi_be_exist(comp_dn)) { charray_add(&missing_list, slapi_ch_strdup(includes[ii])); } slapi_sdn_done(comp_dn); } slapi_sdn_free(&comp_dn); if (missing_list) { PRUint32 size = PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The following suffixes listed in %s or %s are not present in this " "server: ", PAMPT_EXCLUDES_ATTR, PAMPT_INCLUDES_ATTR); for (ii = 0; missing_list[ii]; ++ii) { if (size < SLAPI_DSE_RETURNTEXT_SIZE) { size += PR_snprintf(returntext+size, SLAPI_DSE_RETURNTEXT_SIZE-size, "%s%s", (ii > 0) ? "; " : "", missing_list[ii]); } } slapi_ch_array_free(missing_list); missing_list = NULL; if (missing_suffix != PAMPT_MISSING_SUFFIX_ERROR) { slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, "Warning: %s\n", returntext); *returntext = 0; /* log error, don't report back to user */ } else { goto done; } } } pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR); map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR); if (map_method) { int one, two, three; *returncode = parse_map_method(map_method, &one, &two, &three, returntext); if (!pam_ident_attr && ((one == PAMPT_MAP_METHOD_ENTRY) || (two == PAMPT_MAP_METHOD_ENTRY) || (three == PAMPT_MAP_METHOD_ENTRY))) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: the %s method" " was specified, but no %s was given", PAMPT_MAP_METHOD_ENTRY_STRING, PAMPT_PAM_IDENT_ATTR); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } if ((one == PAMPT_MAP_METHOD_NONE) && (two == PAMPT_MAP_METHOD_NONE) && (three == PAMPT_MAP_METHOD_NONE)) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Error: no method(s)" " specified for %s, should be one or more of %s", PAMPT_MAP_METHOD_ATTR, get_map_method_values()); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } /* success */ *returncode = LDAP_SUCCESS; done: slapi_ch_free_string(&map_method); slapi_ch_free_string(&pam_ident_attr); slapi_ch_array_free(excludes); excludes = NULL; slapi_ch_array_free(includes); includes = NULL; slapi_ch_free_string(&missing_suffix_str); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } } static Pam_PassthruSuffix * New_Pam_PassthruSuffix(char *suffix) { Pam_PassthruSuffix *newone = NULL; if (suffix) { newone = (Pam_PassthruSuffix *)slapi_ch_malloc(sizeof(Pam_PassthruSuffix)); newone->pamptsuffix_dn = slapi_sdn_new(); slapi_sdn_init_dn_byval(newone->pamptsuffix_dn, suffix); newone->pamptsuffix_next = NULL; } return newone; } static Pam_PassthruSuffix * pam_ptconfig_add_suffixes(char **str_list) { Pam_PassthruSuffix *head = NULL; Pam_PassthruSuffix *suffixent = NULL; if (str_list && *str_list) { int ii; for (ii = 0; str_list[ii]; ++ii) { Pam_PassthruSuffix *tmp = New_Pam_PassthruSuffix(str_list[ii]); if (!suffixent) { head = suffixent = tmp; } else { suffixent->pamptsuffix_next = tmp; suffixent = suffixent->pamptsuffix_next; } } } return head; } static void Delete_Pam_PassthruSuffix(Pam_PassthruSuffix *one) { if (one) { slapi_sdn_free(&one->pamptsuffix_dn); slapi_ch_free((void **)&one); } } static void pam_ptconfig_free_suffixes(Pam_PassthruSuffix *list) { while (list) { Pam_PassthruSuffix *next = list->pamptsuffix_next; Delete_Pam_PassthruSuffix(list); list = next; } } /* Apply the pending changes in the e entry to our config struct. validate must have already been called */ static int pam_passthru_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { char **excludes = NULL; char **includes = NULL; char *new_service = NULL; char *pam_ident_attr = NULL; char *map_method = NULL; PRBool fallback; PRBool secure; *returncode = LDAP_SUCCESS; pam_ident_attr = slapi_entry_attr_get_charptr(e, PAMPT_PAM_IDENT_ATTR); map_method = slapi_entry_attr_get_charptr(e, PAMPT_MAP_METHOD_ATTR); new_service = slapi_entry_attr_get_charptr(e, PAMPT_SERVICE_ATTR); excludes = slapi_entry_attr_get_charray(e, PAMPT_EXCLUDES_ATTR); includes = slapi_entry_attr_get_charray(e, PAMPT_INCLUDES_ATTR); fallback = slapi_entry_attr_get_bool(e, PAMPT_FALLBACK_ATTR); secure = slapi_entry_attr_get_bool(e, PAMPT_SECURE_ATTR); /* lock config here */ slapi_lock_mutex(theConfig.lock); theConfig.pamptconfig_fallback = fallback; theConfig.pamptconfig_secure = secure; if (!theConfig.pamptconfig_service || (new_service && PL_strcmp(theConfig.pamptconfig_service, new_service))) { slapi_ch_free_string(&theConfig.pamptconfig_service); theConfig.pamptconfig_service = new_service; new_service = NULL; /* config now owns memory */ } /* get the list of excluded suffixes */ pam_ptconfig_free_suffixes(theConfig.pamptconfig_excludes); theConfig.pamptconfig_excludes = pam_ptconfig_add_suffixes(excludes); /* get the list of included suffixes */ pam_ptconfig_free_suffixes(theConfig.pamptconfig_includes); theConfig.pamptconfig_includes = pam_ptconfig_add_suffixes(includes); if (!theConfig.pamptconfig_pam_ident_attr || (pam_ident_attr && PL_strcmp(theConfig.pamptconfig_pam_ident_attr, pam_ident_attr))) { slapi_ch_free_string(&theConfig.pamptconfig_pam_ident_attr); theConfig.pamptconfig_pam_ident_attr = pam_ident_attr; pam_ident_attr = NULL; /* config now owns memory */ } if (map_method) { parse_map_method(map_method, &theConfig.pamptconfig_map_method1, &theConfig.pamptconfig_map_method2, &theConfig.pamptconfig_map_method3, NULL); } /* unlock config here */ slapi_unlock_mutex(theConfig.lock); slapi_ch_free_string(&new_service); slapi_ch_free_string(&map_method); slapi_ch_free_string(&pam_ident_attr); slapi_ch_array_free(excludes); slapi_ch_array_free(includes); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } } int pam_passthru_check_suffix(Pam_PassthruConfig *cfg, char *binddn) { Slapi_DN *comp_dn; Pam_PassthruSuffix *try; int ret = LDAP_SUCCESS; comp_dn = slapi_sdn_new(); slapi_sdn_init_dn_byref(comp_dn, binddn); slapi_lock_mutex(cfg->lock); if (!cfg->pamptconfig_includes && !cfg->pamptconfig_excludes) { goto done; /* NULL means allow */ } /* exclude trumps include - if suffix is on exclude list, then deny */ for (try = cfg->pamptconfig_excludes; try; try = try->pamptsuffix_next) { if (slapi_sdn_issuffix(comp_dn, try->pamptsuffix_dn)) { ret = LDAP_UNWILLING_TO_PERFORM; /* suffix is excluded */ goto done; } } /* ok, now flip it - deny access unless dn is on include list */ if (cfg->pamptconfig_includes) { ret = LDAP_UNWILLING_TO_PERFORM; /* suffix is excluded */ for (try = cfg->pamptconfig_includes; try; try = try->pamptsuffix_next) { if (slapi_sdn_issuffix(comp_dn, try->pamptsuffix_dn)) { ret = LDAP_SUCCESS; /* suffix is included */ goto done; } } } done: slapi_unlock_mutex(cfg->lock); slapi_sdn_free(&comp_dn); return ret; } /* * Get the pass though configuration data. For now, there is only one * configuration and it is global to the plugin. */ Pam_PassthruConfig * pam_passthru_get_config( void ) { return( &theConfig ); }
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature
-- Fedora-directory-users mailing list Fedora-directory-users@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-directory-users