Changeset 662 in openpam for trunk/lib


Ignore:
Timestamp:
Mar 11, 2013, 4:33:27 PM (8 years ago)
Author:
Dag-Erling Smørgrav
Message:

Clean up the dynamic module loading code, and add support for the
module path which was added in r695.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/libpam/openpam_dynamic.c

    r660 r662  
    4040#endif
    4141
     42#include <sys/param.h>
     43
    4244#include <dlfcn.h>
     45#include <errno.h>
    4346#include <fcntl.h>
    44 #include <errno.h>
    4547#include <stdio.h>
    4648#include <stdlib.h>
     
    7173        int fd;
    7274
     75        openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
    7376        if ((fd = open(modfn, O_RDONLY)) < 0)
    7477                return (NULL);
     
    9497        void *dlh;
    9598
     99        openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
    96100        openpam_get_feature(OPENPAM_VERIFY_MODULE_FILE,
    97101            &check_module_file);
     
    109113
    110114/*
    111  * OpenPAM internal
    112  *
    113  * Locate a dynamically linked module
    114  */
    115 
    116 pam_module_t *
    117 openpam_dynamic(const char *path)
     115 * Try to load a module from the suggested location.
     116 */
     117static pam_module_t *
     118try_module(const char *modpath)
    118119{
    119120        const pam_module_t *dlmodule;
    120121        pam_module_t *module;
    121         const char *prefix;
    122         char *vpath;
    123         void *dlh;
    124122        int i, serrno;
    125123
    126         dlh = NULL;
    127 
    128         /* Prepend the standard prefix if not an absolute pathname. */
    129         if (path[0] != '/')
    130                 prefix = OPENPAM_MODULES_DIR;
    131         else
    132                 prefix = "";
    133 
    134         /* try versioned module first, then unversioned module */
    135         if (asprintf(&vpath, "%s%s.%d", prefix, path, LIB_MAJ) < 0)
     124        if ((module = calloc(1, sizeof *module)) == NULL ||
     125            (module->path = strdup(modpath)) == NULL ||
     126            (module->dlh = try_dlopen(modpath)) == NULL)
    136127                goto err;
    137         if ((dlh = try_dlopen(vpath)) == NULL && errno == ENOENT) {
    138                 *strrchr(vpath, '.') = '\0';
    139                 dlh = try_dlopen(vpath);
    140         }
    141         if (dlh == NULL)
    142                 goto err;
    143         if ((module = calloc(1, sizeof *module)) == NULL)
    144                 goto buf_err;
    145         if ((module->path = strdup(path)) == NULL)
    146                 goto buf_err;
    147         module->dlh = dlh;
    148         dlmodule = dlsym(dlh, "_pam_module");
     128        dlmodule = dlsym(module->dlh, "_pam_module");
    149129        for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) {
    150130                if (dlmodule) {
    151131                        module->func[i] = dlmodule->func[i];
    152132                } else {
    153                         module->func[i] =
    154                             (pam_func_t)dlfunc(dlh, pam_sm_func_name[i]);
     133                        module->func[i] = (pam_func_t)dlfunc(module->dlh,
     134                            pam_sm_func_name[i]);
    155135                        /*
    156136                         * This openpam_log() call is a major source of
     
    165145                        if (module->func[i] == NULL)
    166146                                openpam_log(PAM_LOG_LIBDEBUG, "%s: %s(): %s",
    167                                     path, pam_sm_func_name[i], dlerror());
    168 #endif
    169                 }
    170         }
    171         FREE(vpath);
     147                                    modpath, pam_sm_func_name[i], dlerror());
     148#endif
     149                }
     150        }
    172151        return (module);
    173 buf_err:
    174         serrno = errno;
    175         if (dlh != NULL)
    176                 dlclose(dlh);
    177         FREE(module);
    178         errno = serrno;
    179152err:
    180153        serrno = errno;
    181         if (errno != 0)
    182                 openpam_log(PAM_LOG_ERROR, "%s: %m", vpath);
    183         FREE(vpath);
     154        if (module != NULL) {
     155                if (module->dlh != NULL)
     156                        dlclose(module->dlh);
     157                if (module->path != NULL)
     158                        FREE(module->path);
     159                FREE(module);
     160        }
     161        errno = serrno;
     162        if (serrno != 0 && serrno != ENOENT)
     163                openpam_log(PAM_LOG_ERROR, "%s: %m", modpath);
    184164        errno = serrno;
    185165        return (NULL);
     
    187167
    188168/*
     169 * OpenPAM internal
     170 *
     171 * Locate a dynamically linked module
     172 */
     173
     174pam_module_t *
     175openpam_dynamic(const char *modname)
     176{
     177        pam_module_t *module;
     178        char modpath[PATH_MAX];
     179        const char **path;
     180        int dot, len;
     181
     182        /*
     183         * Simple case: module name contains path separator(s)
     184         */
     185        if (strchr(modname, '/') != NULL) {
     186                /*
     187                 * Absolute paths are not allowed if RESTRICT_MODULE_NAME
     188                 * is in effect.  Relative paths are never allowed.
     189                 */
     190                if (OPENPAM_FEATURE(RESTRICT_MODULE_NAME) ||
     191                    modname[0] != '/') {
     192                        openpam_log(PAM_LOG_ERROR,
     193                            "invalid module name: %s", modname);
     194                        return (NULL);
     195                }
     196                return (try_module(modname));
     197        }
     198
     199        /*
     200         * Complicated case: search for the module in the usual places.
     201         */
     202        for (path = openpam_module_path; *path != NULL; ++path) {
     203                /*
     204                 * Assemble the full path, including the version suffix.  Take
     205                 * note of where the suffix begins so we can cut it off later.
     206                 */
     207                len = snprintf(modpath, sizeof modpath, "%s/%s%n.%d",
     208                    *path, modname, &dot, LIB_MAJ);
     209                if (len < 0 || (unsigned int)len >= sizeof modpath) {
     210                        errno = ENOENT;
     211                        continue;
     212                }
     213                /* try the versioned path */
     214                if ((module = try_module(modpath)) != NULL)
     215                        return (module);
     216                if (errno == ENOENT) {
     217                        /* no luck, try the unversioned path */
     218                        modpath[dot] = '\0';
     219                        if ((module = try_module(modpath)) != NULL)
     220                                return (module);
     221                }
     222        }
     223
     224        /* :( */
     225        return (NULL);
     226}
     227
     228/*
    189229 * NOPARSE
    190230 */
Note: See TracChangeset for help on using the changeset viewer.