Changeset 493 in openpam


Ignore:
Timestamp:
Nov 20, 2011, 2:28:15 AM (6 years ago)
Author:
Dag-Erling Smørgrav
Message:

Refuse to load a module if it is owned by anyone else than root or the
arbitrator or it is writable by group or other.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/openpam_dynamic.c

    r460 r493  
    4040#endif
    4141
     42#include <sys/types.h>
     43#include <sys/stat.h>
     44
    4245#include <dlfcn.h>
     46#include <errno.h>
     47#include <libgen.h>
    4348#include <stdio.h>
    4449#include <stdlib.h>
    4550#include <string.h>
     51#include <unistd.h>
    4652
    4753#include <security/pam_appl.h>
     
    5359#endif
    5460
     61/*
     62 * OpenPAM internal
     63 *
     64 * Verify that a file or directory is owned by either root or the
     65 * arbitrator and that it is not writable by group or other.
     66 */
     67
     68static int
     69check_owner_perms(const char *path)
     70{
     71        struct stat sb;
     72
     73        if (stat(path, &sb) != 0)
     74                return (-1);
     75        if ((sb.st_uid != 0 && sb.st_uid != geteuid()) ||
     76            (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
     77                openpam_log(PAM_LOG_ERROR,
     78                    "%s: insecure ownership or permissions", path);
     79                errno = EPERM;
     80                return (-1);
     81        }
     82        return (0);
     83}
     84
     85/*
     86 * OpenPAM internal
     87 *
     88 * Perform sanity checks and attempt to load a module
     89 */
     90
     91static void *
     92try_dlopen(const char *modfn)
     93{
     94        char *moddn;
     95        int ok, serrno;
     96
     97        /*
     98         * BSD dirname(3) returns a pointer to a static buffer, while GNU
     99         * dirname(3) modifies the input string.  Use a copy of the string
     100         * so both cases work.
     101         */
     102        if ((moddn = strdup(modfn)) == NULL)
     103                return (NULL);
     104        ok = (check_owner_perms(dirname(moddn)) == 0 &&
     105            check_owner_perms(modfn) == 0);
     106        serrno = errno;
     107        free(moddn);
     108        errno = serrno;
     109        return (ok ? dlopen(modfn, RTLD_NOW) : NULL);
     110}
     111   
    55112/*
    56113 * OpenPAM internal
     
    67124        char *vpath;
    68125        void *dlh;
    69         int i;
     126        int i, serrno;
    70127
    71128        dlh = NULL;
     
    80137        if (asprintf(&vpath, "%s%s.%d", prefix, path, LIB_MAJ) < 0)
    81138                goto err;
    82         if ((dlh = dlopen(vpath, RTLD_NOW)) == NULL) {
    83                 openpam_log(PAM_LOG_DEBUG, "%s: %s", vpath, dlerror());
     139        if ((dlh = try_dlopen(vpath)) == NULL && errno == ENOENT) {
    84140                *strrchr(vpath, '.') = '\0';
    85                 if ((dlh = dlopen(vpath, RTLD_NOW)) == NULL) {
    86                         openpam_log(PAM_LOG_DEBUG, "%s: %s", vpath, dlerror());
    87                         FREE(vpath);
    88                         return (NULL);
    89                 }
     141                dlh = try_dlopen(vpath);
    90142        }
     143        serrno = errno;
    91144        FREE(vpath);
     145        errno = serrno;
     146        if (dlh == NULL)
     147                goto err;
    92148        if ((module = calloc(1, sizeof *module)) == NULL)
    93149                goto buf_err;
Note: See TracChangeset for help on using the changeset viewer.