Changeset 32 in openpam


Ignore:
Timestamp:
Feb 4, 2002, 11:22:40 PM (16 years ago)
Author:
Dag-Erling Smørgrav
Message:

Add support for static linking. Also rename a handful of constants
to reduce the chance of every running into a naming conflict.

Sponsored by: DARPA, NAI Labs

Location:
trunk
Files:
3 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/security/openpam.h

    r23 r32  
    5656        ...);
    5757
    58 #ifdef __GNUC__
     58#if defined(__STDC__) && (__STDC_VERSION__ > 199901L)
     59#define openpam_log(lvl, fmt, ...) \
     60        _openpam_log((lvl), __func__, fmt, __VA_ARGS__)
     61#elif defined(__GNUC__)
    5962#define openpam_log(lvl, fmt...) \
    6063        _openpam_log((lvl), __func__, ##fmt)
    6164#else
    62 #define openpam_log(lvl, fmt, ...) \
    63         _openpam_log((lvl), __func__, fmt, __VA_ARGS__)
     65extern openpam_log(int _level, const char *_format, ...);
    6466#endif
    6567
     
    6769 * Generic conversation function
    6870 */
     71struct pam_message;
     72struct pam_response;
    6973int openpam_ttyconv(int _n,
    7074        const struct pam_message **_msg,
     
    7276        void *_data);
    7377
     78/*
     79 * PAM primitives
     80 */
     81enum {
     82        PAM_SM_AUTHENTICATE,
     83        PAM_SM_SETCRED,
     84        PAM_SM_ACCT_MGMT,
     85        PAM_SM_OPEN_SESSION,
     86        PAM_SM_CLOSE_SESSION,
     87        PAM_SM_CHAUTHTOK,
     88        /* keep this last */
     89        PAM_NUM_PRIMITIVES
     90};
     91
     92/*
     93 * Dummy service module function
     94 */
     95#define PAM_SM_DUMMY(type)                                              \
     96PAM_EXTERN int                                                          \
     97pam_sm_##type(pam_handle_t *pamh, int flags,                            \
     98    int argc, const char *argv[])                                       \
     99{                                                                       \
     100        return (PAM_IGNORE);                                            \
     101}
     102
     103/*
     104 * PAM service module functions match this typedef
     105 */
     106struct pam_handle;
     107typedef int (*pam_func_t)(struct pam_handle *, int, int, const char **);
     108
     109/*
     110 * A struct that describes a module.
     111 */
     112typedef struct pam_module pam_module_t;
     113struct pam_module {
     114        const char      *path;
     115        pam_func_t       func[PAM_NUM_PRIMITIVES];
     116        void            *dlh;
     117        int              refcount;
     118        pam_module_t    *prev;
     119        pam_module_t    *next;
     120};
     121
     122/*
     123 * Infrastructure for static modules using GCC linker sets.
     124 * You are not expected to understand this.
     125 */
     126#if defined(__GNUC__) && !defined(__PIC__)
     127#if defined(__FreeBSD__)
     128#define PAM_SOEXT ".so"
     129#else
     130#error Static linking is not supported on your platform
    74131#endif
     132/* gcc, static linking */
     133#include <sys/cdefs.h>
     134#include <linker_set.h>
     135#define OPENPAM_STATIC_MODULES
     136#define PAM_EXTERN static
     137#define PAM_MODULE_ENTRY(name)                                          \
     138static struct pam_module _pam_module = { name PAM_SOEXT, {              \
     139    pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt,              \
     140    pam_sm_open_session, pam_sm_close_session, pam_sm_chauthtok },      \
     141    NULL, 0, NULL, NULL };                                              \
     142DATA_SET(_openpam_modules, _pam_module)
     143#else
     144/* normal case */
     145#define PAM_EXTERN
     146#define PAM_MODULE_ENTRY(name)
     147#endif
     148
     149#endif
  • trunk/include/security/pam_modules.h

    r16 r32  
    4040#include <security/pam_types.h>
    4141#include <security/pam_constants.h>
     42#include <security/openpam.h>
    4243
    4344/*
     
    4546 */
    4647
    47 int
     48PAM_EXTERN int
    4849pam_sm_acct_mgmt(pam_handle_t *_pamh,
    4950        int _flags,
     
    5152        const char **_argv);
    5253
    53 int
     54PAM_EXTERN int
    5455pam_sm_authenticate(pam_handle_t *_pamh,
    5556        int _flags,
     
    5758        const char **_argv);
    5859
    59 int
     60PAM_EXTERN int
    6061pam_sm_chauthtok(pam_handle_t *_pamh,
    6162        int _flags,
     
    6364        const char **_argv);
    6465
    65 int
     66PAM_EXTERN int
    6667pam_sm_close_session(pam_handle_t *_pamh,
    6768        int _flags,
     
    6970        const char **_argv);
    7071
    71 int
     72PAM_EXTERN int
    7273pam_sm_open_session(pam_handle_t *_pamh,
    7374        int _flags,
     
    7576        const char **_argv);
    7677
    77 int
     78PAM_EXTERN int
    7879pam_sm_setcred(pam_handle_t *_pamh,
    7980        int _flags,
     
    8586 */
    8687#if 0
    87 int
     88PAM_EXTERN int
    8889pam_sm_authenticate_secondary(pam_handle_t *_pamh,
    8990        char *_target_username,
     
    9697        const char **_argv);
    9798
    98 int
     99PAM_EXTERN int
    99100pam_sm_get_mapped_authtok(pam_handle_t *_pamh,
    100101        char *_target_module_username,
     
    106107        char *_argv);
    107108
    108 int
     109PAM_EXTERN int
    109110pam_sm_get_mapped_username(pam_handle_t *_pamh,
    110111        char *_src_username,
     
    117118        const char **_argv);
    118119
    119 int
     120PAM_EXTERN int
    120121pam_sm_set_mapped_authtok(pam_handle_t *_pamh,
    121122        char *_target_module_username,
     
    127128        const char *_argv);
    128129
    129 int
     130PAM_EXTERN int
    130131pam_sm_set_mapped_username(pam_handle_t *_pamh,
    131132        char *_target_module_username,
  • trunk/lib/openpam_dispatch.c

    r25 r32  
    5656        int flags)
    5757{
    58         pam_chain_t *module;
     58        pam_chain_t *chain;
    5959        int err, fail, r;
    6060
     
    7070        /* pick a chain */
    7171        switch (primitive) {
    72         case PAM_AUTHENTICATE:
    73         case PAM_SETCRED:
    74                 module = pamh->chains[PAM_AUTH];
    75                 break;
    76         case PAM_ACCT_MGMT:
    77                 module = pamh->chains[PAM_ACCOUNT];
    78                 break;
    79         case PAM_OPEN_SESSION:
    80         case PAM_CLOSE_SESSION:
    81                 module = pamh->chains[PAM_SESSION];
    82                 break;
    83         case PAM_CHAUTHTOK:
    84                 module = pamh->chains[PAM_PASSWORD];
     72        case PAM_SM_AUTHENTICATE:
     73        case PAM_SM_SETCRED:
     74                chain = pamh->chains[PAM_AUTH];
     75                break;
     76        case PAM_SM_ACCT_MGMT:
     77                chain = pamh->chains[PAM_ACCOUNT];
     78                break;
     79        case PAM_SM_OPEN_SESSION:
     80        case PAM_SM_CLOSE_SESSION:
     81                chain = pamh->chains[PAM_SESSION];
     82                break;
     83        case PAM_SM_CHAUTHTOK:
     84                chain = pamh->chains[PAM_PASSWORD];
    8585                break;
    8686        default:
     
    8989
    9090        /* fail if the chain is empty */
    91         if (module == NULL)
     91        if (chain == NULL)
    9292                return (PAM_SYSTEM_ERR);
    9393
    9494        /* execute */
    95         for (err = fail = 0; module != NULL; module = module->next) {
    96                 if (module->primitive[primitive] == NULL) {
     95        for (err = fail = 0; chain != NULL; chain = chain->next) {
     96                if (chain->module->func[primitive] == NULL) {
    9797                        openpam_log(PAM_LOG_ERROR, "%s: no %s()",
    98                             module->modpath, _pam_sm_func_name[primitive]);
     98                            chain->module->path, _pam_sm_func_name[primitive]);
    9999                        r = PAM_SYMBOL_ERR;
    100100                } else {
    101                         pamh->current = module;
    102                         r = (module->primitive[primitive])(pamh, flags,
    103                             module->optc, (const char **)module->optv);
     101                        pamh->current = chain;
     102                        r = (chain->module->func[primitive])(pamh, flags,
     103                            chain->optc, (const char **)chain->optv);
    104104                        pamh->current = NULL;
    105105                        openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s",
    106                             module->modpath, _pam_sm_func_name[primitive],
     106                            chain->module->path, _pam_sm_func_name[primitive],
    107107                            pam_strerror(pamh, r));
    108108                }
     
    119119                         * previously failed.  I'm not sure why.
    120120                         */
    121                         if (module->flag == PAM_SUFFICIENT &&
    122                             primitive != PAM_SETCRED)
     121                        if (chain->flag == PAM_SUFFICIENT &&
     122                            primitive != PAM_SM_SETCRED)
    123123                                break;
    124124                }
     
    133133                if (err == 0)
    134134                        err = r;
    135                 if (module->flag == PAM_REQUIRED && !fail) {
     135                if (chain->flag == PAM_REQUIRED && !fail) {
    136136                        fail = 1;
    137137                        err = r;
     
    142142                 * immediately.
    143143                 */
    144                 if (module->flag == PAM_REQUISITE) {
     144                if (chain->flag == PAM_REQUISITE) {
    145145                        fail = 1;
    146146                        break;
     
    165165        /* specific error codes */
    166166        switch (primitive) {
    167         case PAM_AUTHENTICATE:
     167        case PAM_SM_AUTHENTICATE:
    168168                if (r == PAM_AUTH_ERR ||
    169169                    r == PAM_CRED_INSUFFICIENT ||
     
    173173                        return;
    174174                break;
    175         case PAM_SETCRED:
     175        case PAM_SM_SETCRED:
    176176                if (r == PAM_CRED_UNAVAIL ||
    177177                    r == PAM_CRED_EXPIRED ||
     
    180180                        return;
    181181                break;
    182         case PAM_ACCT_MGMT:
     182        case PAM_SM_ACCT_MGMT:
    183183                if (r == PAM_USER_UNKNOWN ||
    184184                    r == PAM_AUTH_ERR ||
     
    187187                        return;
    188188                break;
    189         case PAM_OPEN_SESSION:
    190         case PAM_CLOSE_SESSION:
     189        case PAM_SM_OPEN_SESSION:
     190        case PAM_SM_CLOSE_SESSION:
    191191                if (r == PAM_SESSION_ERR)
    192192                        return;
    193193                break;
    194         case PAM_CHAUTHTOK:
     194        case PAM_SM_CHAUTHTOK:
    195195                if (r == PAM_PERM_DENIED ||
    196196                    r == PAM_AUTHTOK_ERR ||
  • trunk/lib/openpam_impl.h

    r25 r32  
    4040#include <security/openpam.h>
    4141
     42extern const char *_pam_sm_func_name[PAM_NUM_PRIMITIVES];
     43
    4244/*
    4345 * Control flags
     
    5860#define PAM_NUM_CHAINS          4
    5961
    60 #define PAM_ACCT_MGMT           0
    61 #define PAM_AUTHENTICATE        1
    62 #define PAM_CHAUTHTOK           2
    63 #define PAM_CLOSE_SESSION       3
    64 #define PAM_OPEN_SESSION        4
    65 #define PAM_SETCRED             5
    66 #define PAM_NUM_PRIMITIVES      6
    67 
    68 extern const char *_pam_sm_func_name[PAM_NUM_PRIMITIVES];
    69 
    70 typedef int (*pam_func_t)(pam_handle_t *, int, int, const char **);
    71 
    7262typedef struct pam_chain pam_chain_t;
    7363struct pam_chain {
     64        pam_module_t    *module;
    7465        int              flag;
    75         char            *modpath;
    7666        int              optc;
    7767        char           **optv;
    7868        pam_chain_t     *next;
    79         void            *dlh;
    80         pam_func_t       primitive[PAM_NUM_PRIMITIVES];
    8169};
    8270
  • trunk/lib/openpam_load.c

    r25 r32  
    4343#include "openpam_impl.h"
    4444
     45#ifdef OPENPAM_STATIC_MODULES
     46SET_DECLARE(_openpam_modules, pam_module_t);
     47#endif
     48
    4549const char *_pam_sm_func_name[PAM_NUM_PRIMITIVES] = {
    4650        "pam_sm_acct_mgmt",
     
    5256};
    5357
     58static pam_module_t *modules;
     59
     60/*
     61 * Load a dynamic module, or locate a static one.  Keep a list of
     62 * previously found modules to speed up the process.
     63 */
     64
     65static pam_module_t *
     66openpam_load_module(const char *path)
     67{
     68        pam_module_t *module;
     69        void *dlh;
     70
     71        /* check cache first */
     72        for (module = modules; module != NULL; module = module->next)
     73                if (strcmp(module->path, path) == 0)
     74                        goto found;
     75
     76        /* nope; try to load */
     77        if ((dlh = dlopen(path, RTLD_NOW)) == NULL) {
     78                openpam_log(PAM_LOG_ERROR, "dlopen(): %s", dlerror());
     79        } else {
     80                if ((module = calloc(1, sizeof *module)) == NULL)
     81                        goto buf_err;
     82                if ((module->path = strdup(path)) == NULL)
     83                        goto buf_err;
     84                module->dlh = dlh;
     85        }
     86        openpam_log(PAM_LOG_DEBUG, "%s dynamic %s",
     87            (module == NULL) ? "no" : "using", path);
     88
     89#ifdef OPENPAM_STATIC_MODULES
     90        /* look for a static module */
     91        if (module == NULL && strchr(path, '/') == NULL) {
     92                pam_module_t **modp;
     93               
     94                SET_FOREACH(modp, _openpam_modules) {
     95                        if (strcmp((*modp)->path, path) == 0) {
     96                                module = *modp;
     97                                break;
     98                        }
     99                }
     100                openpam_log(PAM_LOG_DEBUG, "%s static %s",
     101                    (module == NULL) ? "no" : "using", path);
     102        }
     103#endif
     104        if (module == NULL)
     105                return (NULL);
     106        module->next = modules;
     107        module->prev = NULL;
     108        modules = module;
     109 found:
     110        ++module->refcount;
     111        return (module);
     112 buf_err:
     113        openpam_log(PAM_LOG_ERROR, "malloc(): %m");
     114        dlclose(dlh);
     115        free(module);
     116        return (NULL);
     117}
     118
     119
     120/*
     121 * Release a module.
     122 * XXX highly thread-unsafe
     123 */
     124
    54125static void
    55 openpam_destroy_module(pam_chain_t *module)
    56 {
    57         if (module->dlh != NULL)
    58                 dlclose(module->dlh);
    59         while (module->optc--)
    60                 free(module->optv[module->optc]);
    61         free(module->optv);
    62         free(module->modpath);
     126openpam_release_module(pam_module_t *module)
     127{
     128        if (module == NULL)
     129                return;
     130        --module->refcount;
     131        if (module->refcount > 0)
     132                /* still in use */
     133                return;
     134        if (module->refcount < 0) {
     135                openpam_log(PAM_LOG_ERROR, "module %s has negative refcount",
     136                    module->path);
     137                module->refcount = 0;
     138        }
     139        if (module->dlh == NULL)
     140                /* static module */
     141                return;
     142        dlclose(module->dlh);
     143        if (module->prev != NULL)
     144                module->prev->next = module->next;
     145        if (module->next != NULL)
     146                module->next->prev = module->prev;
    63147        free(module);
    64148}
     149
     150
     151/*
     152 * Destroy a chain, freeing all its links and releasing the modules
     153 * they point to.
     154 */
     155
     156static void
     157openpam_destroy_chain(pam_chain_t *chain)
     158{
     159        if (chain == NULL)
     160                return;
     161        openpam_destroy_chain(chain->next);
     162        chain->next = NULL;
     163        while (chain->optc--)
     164                free(chain->optv[chain->optc]);
     165        free(chain->optv);
     166        openpam_release_module(chain->module);
     167        free(chain);
     168}
     169
     170/*
     171 * Add a module to a chain.
     172 */
    65173
    66174int
     
    72180        const char *optv[])
    73181{
    74         pam_chain_t *module, *iterator;
    75         int i;
    76 
    77         /* fill in configuration data */
    78         if ((module = calloc(1, sizeof(*module))) == NULL)
     182        pam_chain_t *new, *iterator;
     183
     184        if ((new = calloc(1, sizeof(*new))) == NULL)
    79185                goto buf_err;
    80         if ((module->modpath = strdup(modpath)) == NULL)
    81                 goto buf_err;
    82         if ((module->optv = malloc(sizeof(char *) * (optc + 1))) == NULL)
     186        if ((new->optv = malloc(sizeof(char *) * (optc + 1))) == NULL)
    83187                goto buf_err;
    84188        while (optc--)
    85                 if ((module->optv[module->optc++] = strdup(*optv++)) == NULL)
     189                if ((new->optv[new->optc++] = strdup(*optv++)) == NULL)
    86190                        goto buf_err;
    87         module->optv[module->optc] = NULL;
    88         module->flag = flag;
    89         module->next = NULL;
    90 
    91         /* load module and resolve symbols */
    92         /*
    93          * Each module is dlopen()'d once for evey time it occurs in
    94          * any chain.  While the linker is smart enough to not load
    95          * the same module more than once, it does waste space in the
    96          * form of linker handles and pam_func structs.
    97          *
    98          * TODO: implement a central module cache and replace the
    99          * array of pam_func structs in struct pam_chain with pointers
    100          * to the appropriate entry in the module cache.
    101          */
    102         if ((module->dlh = dlopen(modpath, RTLD_NOW)) == NULL) {
    103                 openpam_log(PAM_LOG_ERROR, "dlopen(): %s", dlerror());
    104                 openpam_destroy_module(module);
     191        new->optv[new->optc] = NULL;
     192        new->flag = flag;
     193        if ((new->module = openpam_load_module(modpath)) == NULL) {
     194                openpam_destroy_chain(new);
    105195                return (PAM_OPEN_ERR);
    106196        }
    107         for (i = 0; i < PAM_NUM_PRIMITIVES; ++i)
    108                 module->primitive[i] =
    109                     dlsym(module->dlh, _pam_sm_func_name[i]);
    110 
    111197        if ((iterator = pamh->chains[chain]) != NULL) {
    112198                while (iterator->next != NULL)
    113199                        iterator = iterator->next;
    114                 iterator->next = module;
     200                iterator->next = new;
    115201        } else {
    116                 pamh->chains[chain] = module;
     202                pamh->chains[chain] = new;
    117203        }
    118204        return (PAM_SUCCESS);
     
    120206 buf_err:
    121207        openpam_log(PAM_LOG_ERROR, "%m");
    122         openpam_destroy_module(module);
     208        openpam_destroy_chain(new);
    123209        return (PAM_BUF_ERR);
    124210}
     211
    125212
    126213/*
     
    131218openpam_clear_chains(pam_handle_t *pamh)
    132219{
    133         pam_chain_t *module;
    134220        int i;
    135221
    136         for (i = 0; i < PAM_NUM_CHAINS; ++i) {
    137                 while (pamh->chains[i] != NULL) {
    138                         module = pamh->chains[i];
    139                         pamh->chains[i] = module->next;
    140                         openpam_destroy_module(module);
    141                 }
    142         }
    143 }
     222        for (i = 0; i < PAM_NUM_CHAINS; ++i)
     223                openpam_destroy_chain(pamh->chains[i]);
     224}
  • trunk/lib/pam_acct_mgmt.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_ACCT_MGMT, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_ACCT_MGMT, flags));
    5656}
  • trunk/lib/pam_authenticate.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_AUTHENTICATE, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_AUTHENTICATE, flags));
    5656}
  • trunk/lib/pam_chauthtok.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_CHAUTHTOK, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_CHAUTHTOK, flags));
    5656}
  • trunk/lib/pam_close_session.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_CLOSE_SESSION, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_CLOSE_SESSION, flags));
    5656}
  • trunk/lib/pam_open_session.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_OPEN_SESSION, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_OPEN_SESSION, flags));
    5656}
  • trunk/lib/pam_setcred.c

    r16 r32  
    5353{
    5454
    55         return (openpam_dispatch(pamh, PAM_SETCRED, flags));
     55        return (openpam_dispatch(pamh, PAM_SM_SETCRED, flags));
    5656}
  • trunk/modules/Makefile

    r16 r32  
    3737SUBDIR           =
    3838SUBDIR          += pam_deny
     39SUBDIR          += pam_dummy
    3940SUBDIR          += pam_permit
    4041
  • trunk/modules/pam_deny/pam_deny.c

    r16 r32  
    3535 */
    3636
     37#include <sys/param.h>
     38
    3739#include <security/pam_modules.h>
    3840
    39 int
     41PAM_EXTERN int
    4042pam_sm_authenticate(pam_handle_t *pamh, int flags,
    4143        int argc, const char *argv[])
     
    4547}
    4648
    47 int
     49PAM_EXTERN int
    4850pam_sm_setcred(pam_handle_t *pamh, int flags,
    4951        int argc, const char *argv[])
     
    5355}
    5456
    55 int
     57PAM_EXTERN int
    5658pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
    5759        int argc, const char *argv[])
     
    6163}
    6264
    63 int
     65PAM_EXTERN int
    6466pam_sm_open_session(pam_handle_t *pamh, int flags,
    6567        int argc, const char *argv[])
     
    6971}
    7072
    71 int
     73PAM_EXTERN int
    7274pam_sm_close_session(pam_handle_t *pamh, int flags,
    7375        int argc, const char *argv[])
     
    7779}
    7880
    79 int
     81PAM_EXTERN int
    8082pam_sm_chauthtok(pam_handle_t *pamh, int flags,
    8183        int argc, const char *argv[])
     
    8486        return (PAM_PERM_DENIED);
    8587}
     88
     89PAM_MODULE_ENTRY("pam_deny");
  • trunk/modules/pam_permit/pam_permit.c

    r16 r32  
    3535 */
    3636
     37#include <sys/param.h>
     38
    3739#include <security/pam_modules.h>
    3840
    39 int
     41PAM_EXTERN int
    4042pam_sm_authenticate(pam_handle_t *pamh, int flags,
    4143        int argc, const char *argv[])
     
    4547}
    4648
    47 int
     49PAM_EXTERN int
    4850pam_sm_setcred(pam_handle_t *pamh, int flags,
    4951        int argc, const char *argv[])
     
    5355}
    5456
    55 int
     57PAM_EXTERN int
    5658pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
    5759        int argc, const char *argv[])
     
    6163}
    6264
    63 int
     65PAM_EXTERN int
    6466pam_sm_open_session(pam_handle_t *pamh, int flags,
    6567        int argc, const char *argv[])
     
    6971}
    7072
    71 int
     73PAM_EXTERN int
    7274pam_sm_close_session(pam_handle_t *pamh, int flags,
    7375        int argc, const char *argv[])
     
    7779}
    7880
    79 int
     81PAM_EXTERN int
    8082pam_sm_chauthtok(pam_handle_t *pamh, int flags,
    8183        int argc, const char *argv[])
     
    8486        return (PAM_SUCCESS);
    8587}
     88
     89PAM_MODULE_ENTRY("pam_permit");
Note: See TracChangeset for help on using the changeset viewer.