openpam_load.c revision 116520
191094Sdes/*- 2115619Sdes * Copyright (c) 2002-2003 Networks Associates Technology, Inc. 391094Sdes * All rights reserved. 491094Sdes * 591094Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and 699158Sdes * Network Associates Laboratories, the Security Research Division of 799158Sdes * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 899158Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 991094Sdes * 1091094Sdes * Redistribution and use in source and binary forms, with or without 1191094Sdes * modification, are permitted provided that the following conditions 1291094Sdes * are met: 1391094Sdes * 1. Redistributions of source code must retain the above copyright 1491094Sdes * notice, this list of conditions and the following disclaimer. 1591094Sdes * 2. Redistributions in binary form must reproduce the above copyright 1691094Sdes * notice, this list of conditions and the following disclaimer in the 1791094Sdes * documentation and/or other materials provided with the distribution. 1891094Sdes * 3. The name of the author may not be used to endorse or promote 1991094Sdes * products derived from this software without specific prior written 2091094Sdes * permission. 2191094Sdes * 2291094Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2391094Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2491094Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2591094Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2691094Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2791094Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2891094Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2991094Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3091094Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3191094Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3291094Sdes * SUCH DAMAGE. 3391094Sdes * 34116520Sdes * $P4: //depot/projects/openpam/lib/openpam_load.c#20 $ 3591094Sdes */ 3691094Sdes 3791094Sdes#include <dlfcn.h> 3891094Sdes#include <stdlib.h> 3991094Sdes#include <string.h> 4091094Sdes 4191094Sdes#include <security/pam_appl.h> 4291094Sdes 4391094Sdes#include "openpam_impl.h" 4491094Sdes 45107937Sdesconst char *_pam_func_name[PAM_NUM_PRIMITIVES] = { 46107937Sdes "pam_authenticate", 47107937Sdes "pam_setcred", 48107937Sdes "pam_acct_mgmt", 49107937Sdes "pam_open_session", 50107937Sdes "pam_close_session", 51107937Sdes "pam_chauthtok" 52107937Sdes}; 53107937Sdes 5491094Sdesconst char *_pam_sm_func_name[PAM_NUM_PRIMITIVES] = { 5591097Sdes "pam_sm_authenticate", 5691097Sdes "pam_sm_setcred", 5791094Sdes "pam_sm_acct_mgmt", 5891097Sdes "pam_sm_open_session", 5991094Sdes "pam_sm_close_session", 6091097Sdes "pam_sm_chauthtok" 6191094Sdes}; 6291094Sdes 6391094Sdesstatic pam_module_t *modules; 6491094Sdes 6591094Sdes/* 6691684Sdes * Locate a matching dynamic or static module. Keep a list of previously 6791684Sdes * found modules to speed up the process. 6891094Sdes */ 6991094Sdes 70115619Sdespam_module_t * 7191094Sdesopenpam_load_module(const char *path) 7291094Sdes{ 7391094Sdes pam_module_t *module; 7491094Sdes 7591094Sdes /* check cache first */ 7691094Sdes for (module = modules; module != NULL; module = module->next) 7791094Sdes if (strcmp(module->path, path) == 0) 7891094Sdes goto found; 7991094Sdes 8091094Sdes /* nope; try to load */ 8191684Sdes module = openpam_dynamic(path); 8291094Sdes openpam_log(PAM_LOG_DEBUG, "%s dynamic %s", 8391094Sdes (module == NULL) ? "no" : "using", path); 8491094Sdes 8591094Sdes#ifdef OPENPAM_STATIC_MODULES 8691094Sdes /* look for a static module */ 8791094Sdes if (module == NULL && strchr(path, '/') == NULL) { 8891100Sdes module = openpam_static(path); 8991094Sdes openpam_log(PAM_LOG_DEBUG, "%s static %s", 9091094Sdes (module == NULL) ? "no" : "using", path); 9191094Sdes } 9291094Sdes#endif 9391830Sdes if (module == NULL) { 9491830Sdes openpam_log(PAM_LOG_ERROR, "no %s found", path); 9591094Sdes return (NULL); 9691830Sdes } 9791830Sdes openpam_log(PAM_LOG_DEBUG, "adding %s to cache", module->path); 9891094Sdes module->next = modules; 9991830Sdes if (module->next != NULL) 10091830Sdes module->next->prev = module; 10191094Sdes module->prev = NULL; 10291094Sdes modules = module; 10391094Sdes found: 10491094Sdes ++module->refcount; 10591094Sdes return (module); 10691094Sdes} 10791094Sdes 10891094Sdes 10991094Sdes/* 11091094Sdes * Release a module. 11191094Sdes * XXX highly thread-unsafe 11291094Sdes */ 11391094Sdes 11491094Sdesstatic void 11591094Sdesopenpam_release_module(pam_module_t *module) 11691094Sdes{ 11791094Sdes if (module == NULL) 11891094Sdes return; 11991094Sdes --module->refcount; 12091094Sdes if (module->refcount > 0) 12191094Sdes /* still in use */ 12291094Sdes return; 12391094Sdes if (module->refcount < 0) { 12491094Sdes openpam_log(PAM_LOG_ERROR, "module %s has negative refcount", 12591094Sdes module->path); 12691094Sdes module->refcount = 0; 12791094Sdes } 12891094Sdes if (module->dlh == NULL) 12991094Sdes /* static module */ 13091094Sdes return; 13191094Sdes dlclose(module->dlh); 13291094Sdes if (module->prev != NULL) 13391094Sdes module->prev->next = module->next; 13491094Sdes if (module->next != NULL) 13591094Sdes module->next->prev = module->prev; 13691830Sdes if (module == modules) 13791830Sdes modules = module->next; 13891830Sdes openpam_log(PAM_LOG_DEBUG, "releasing %s", module->path); 139115619Sdes FREE(module->path); 140115619Sdes FREE(module); 14191094Sdes} 14291094Sdes 14391094Sdes 14491094Sdes/* 14591094Sdes * Destroy a chain, freeing all its links and releasing the modules 14691094Sdes * they point to. 14791094Sdes */ 14891094Sdes 14991094Sdesstatic void 15091094Sdesopenpam_destroy_chain(pam_chain_t *chain) 15191094Sdes{ 15291094Sdes if (chain == NULL) 15391094Sdes return; 15491094Sdes openpam_destroy_chain(chain->next); 15591094Sdes chain->next = NULL; 156116520Sdes while (chain->optc) { 157116520Sdes --chain->optc; 158115619Sdes FREE(chain->optv[chain->optc]); 159116520Sdes } 160115619Sdes FREE(chain->optv); 16191094Sdes openpam_release_module(chain->module); 162116520Sdes chain->module = NULL; 163115619Sdes FREE(chain); 16491094Sdes} 16591094Sdes 16691094Sdes 16791094Sdes/* 16891094Sdes * Clear the chains and release the modules 16991094Sdes */ 17091094Sdes 17191094Sdesvoid 17295908Sdesopenpam_clear_chains(pam_chain_t *policy[]) 17391094Sdes{ 17491094Sdes int i; 17591094Sdes 176115619Sdes for (i = 0; i < PAM_NUM_FACILITIES; ++i) 17795908Sdes openpam_destroy_chain(policy[i]); 17891094Sdes} 17991100Sdes 18091100Sdes/* 18191100Sdes * NOPARSE 18291100Sdes */ 183