source: packages/libs/libpam/patches/005-fix_ruserok.patch @ 28317

Last change on this file since 28317 was 28317, checked in by acoul, 5 years ago

libs/libpam: make KanjiMonster happy

File size: 8.2 KB
  • modules/pam_rhosts/pam_rhosts.c

    a b  
    3434 
    3535#include <pwd.h> 
    3636#include <netdb.h> 
     37#include <stdio.h> 
    3738#include <string.h> 
    3839#include <syslog.h> 
     40#include <sys/stat.h> 
    3941 
    4042#define PAM_SM_AUTH  /* only defines this management group */ 
    4143 
     
    4345#include <security/pam_modutil.h> 
    4446#include <security/pam_ext.h> 
    4547 
     48int  __check_rhosts_file = 1; 
     49 
     50/* Extremely paranoid file open function. */ 
     51static FILE * 
     52iruserfopen (const char *file, uid_t okuser) 
     53{ 
     54  struct stat st; 
     55  char *cp = NULL; 
     56  FILE *res = NULL; 
     57 
     58  /* If not a regular file, if owned by someone other than user or 
     59     root, if writeable by anyone but the owner, or if hardlinked 
     60     anywhere, quit.  */ 
     61  if (lstat (file, &st)) 
     62    cp = "lstat failed"; 
     63  else if (!S_ISREG (st.st_mode)) 
     64    cp = "not regular file"; 
     65  else 
     66    { 
     67      res = fopen (file, "r"); 
     68      if (!res) 
     69        cp = "cannot open"; 
     70      else if (fstat (fileno (res), &st) < 0) 
     71        cp = "fstat failed"; 
     72      else if (st.st_uid && st.st_uid != okuser) 
     73        cp = "bad owner"; 
     74      else if (st.st_mode & (S_IWGRP|S_IWOTH)) 
     75        cp = "writeable by other than owner"; 
     76      else if (st.st_nlink > 1) 
     77        cp = "hard linked somewhere"; 
     78    } 
     79 
     80  /* If there were any problems, quit.  */ 
     81  if (cp != NULL) 
     82    { 
     83      if (res) 
     84        fclose (res); 
     85      return NULL; 
     86    } 
     87 
     88  return res; 
     89} 
     90 
     91/* 
     92 * Returns 1 for blank lines (or only comment lines) and 0 otherwise 
     93 */ 
     94static int 
     95__isempty(char *p) 
     96{ 
     97    while (*p && isspace (*p)) { 
     98        ++p; 
     99    } 
     100 
     101    return (*p == '\0' || *p == '#') ? 1 : 0 ; 
     102} 
     103 
     104/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */ 
     105static int 
     106__icheckhost (u_int32_t raddr, char *lhost, const char *rhost) 
     107{ 
     108        struct hostent *hp; 
     109        u_int32_t laddr; 
     110        int negate=1;    /* Multiply return with this to get -1 instead of 1 */ 
     111        char **pp; 
     112 
     113#ifdef __UCLIBC_HAS_REENTRANT_RPC__ 
     114        int save_errno; 
     115        size_t buflen; 
     116        char *buffer; 
     117        struct hostent hostbuf; 
     118        int herr; 
     119#endif 
     120 
     121#ifdef HAVE_NETGROUP 
     122        /* Check nis netgroup.  */ 
     123        if (strncmp ("+@", lhost, 2) == 0) 
     124                return innetgr (&lhost[2], rhost, NULL, NULL); 
     125 
     126        if (strncmp ("-@", lhost, 2) == 0) 
     127                return -innetgr (&lhost[2], rhost, NULL, NULL); 
     128#endif /* HAVE_NETGROUP */ 
     129 
     130        /* -host */ 
     131        if (strncmp ("-", lhost,1) == 0) { 
     132                negate = -1; 
     133                lhost++; 
     134        } else if (strcmp ("+",lhost) == 0) { 
     135                return 1;                    /* asking for trouble, but ok.. */ 
     136        } 
     137 
     138        /* Try for raw ip address first. */ 
     139        if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE) 
     140                return negate * (! (raddr ^ laddr)); 
     141 
     142        /* Better be a hostname. */ 
     143#ifdef __UCLIBC_HAS_REENTRANT_RPC__ 
     144        buflen = 1024; 
     145        buffer = malloc(buflen); 
     146        save_errno = errno; 
     147 
     148        while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) 
     149               != 0) { 
     150            free(buffer); 
     151            return (0); 
     152        } 
     153        free(buffer); 
     154        __set_errno (save_errno); 
     155#else 
     156        hp = gethostbyname(lhost); 
     157#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ 
     158 
     159        if (hp == NULL) 
     160                return 0; 
     161 
     162        /* Spin through ip addresses. */ 
     163        for (pp = hp->h_addr_list; *pp; ++pp) 
     164                if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) 
     165                        return negate; 
     166 
     167        /* No match. */ 
     168        return (0); 
     169} 
     170 
     171/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */ 
     172static int 
     173__icheckuser (const char *luser, const char *ruser) 
     174{ 
     175 
     176    /* 
     177      luser is user entry from .rhosts/hosts.equiv file 
     178      ruser is user id on remote host 
     179      */ 
     180 
     181#ifdef HAVE_NETGROUP 
     182    /* [-+]@netgroup */ 
     183    if (strncmp ("+@", luser, 2) == 0) 
     184        return innetgr (&luser[2], NULL, ruser, NULL); 
     185 
     186    if (strncmp ("-@", luser,2) == 0) 
     187        return -innetgr (&luser[2], NULL, ruser, NULL); 
     188#endif /* HAVE_NETGROUP */ 
     189 
     190    /* -user */ 
     191    if (strncmp ("-", luser, 1) == 0) 
     192        return -(strcmp (&luser[1], ruser) == 0); 
     193 
     194    /* + */ 
     195    if (strcmp ("+", luser) == 0) 
     196        return 1; 
     197 
     198    /* simple string match */ 
     199    return strcmp (ruser, luser) == 0; 
     200} 
     201 
     202/* 
     203 * Returns 0 if positive match, -1 if _not_ ok. 
     204 */ 
     205static int 
     206__ivaliduser2(FILE *hostf, u_int32_t raddr,     const char *luser, 
     207                          const char *ruser, const char *rhost) 
     208{ 
     209    register const char *user; 
     210    register char *p; 
     211    int hcheck, ucheck; 
     212    char *buf = NULL; 
     213    size_t bufsize = 0; 
     214    int retval = -1; 
     215 
     216    while (getline (&buf, &bufsize, hostf) > 0) { 
     217        buf[bufsize - 1] = '\0'; /* Make sure it's terminated.  */ 
     218        p = buf; 
     219 
     220        /* Skip empty or comment lines */ 
     221        if (__isempty (p)) { 
     222            continue; 
     223        } 
     224 
     225        /* Skip lines that are too long. */ 
     226        if (strchr (p, '\n') == NULL) { 
     227            int ch = getc_unlocked (hostf); 
     228 
     229            while (ch != '\n' && ch != EOF) 
     230              ch = getc_unlocked (hostf); 
     231            continue; 
     232        } 
     233 
     234        for (;*p && !isspace(*p); ++p) { 
     235            *p = tolower (*p); 
     236        } 
     237 
     238        /* Next we want to find the permitted name for the remote user.  */ 
     239        if (*p == ' ' || *p == '\t') { 
     240            /* <nul> terminate hostname and skip spaces */ 
     241            for (*p++='\0'; *p && isspace (*p); ++p); 
     242 
     243            user = p;                   /* this is the user's name */ 
     244            while (*p && !isspace (*p)) 
     245                ++p;                    /* find end of user's name */ 
     246        } else 
     247            user = p; 
     248 
     249        *p = '\0';              /* <nul> terminate username (+host?) */ 
     250 
     251        /* buf -> host(?) ; user -> username(?) */ 
     252 
     253        /* First check host part */ 
     254        hcheck = __icheckhost (raddr, buf, rhost); 
     255 
     256        if (hcheck < 0) 
     257            break; 
     258 
     259        if (hcheck) { 
     260            /* Then check user part */ 
     261            if (! (*user)) 
     262                user = luser; 
     263 
     264            ucheck = __icheckuser (user, ruser); 
     265 
     266            /* Positive 'host user' match? */ 
     267            if (ucheck > 0) { 
     268                retval = 0; 
     269                break; 
     270            } 
     271 
     272            /* Negative 'host -user' match? */ 
     273            if (ucheck < 0) 
     274                break; 
     275 
     276            /* Neither, go on looking for match */ 
     277        } 
     278    } 
     279 
     280    free (buf); 
     281 
     282    return retval; 
     283} 
     284 
     285static int 
     286iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, 
     287                   const char *rhost) 
     288{ 
     289        FILE *hostf = NULL; 
     290        int isbad = -1; 
     291 
     292        if (!superuser) 
     293                hostf = iruserfopen (_PATH_HEQUIV, 0); 
     294 
     295        if (hostf) { 
     296                isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); 
     297                fclose (hostf); 
     298 
     299                if (!isbad) 
     300                        return 0; 
     301        } 
     302 
     303        if (__check_rhosts_file || superuser) { 
     304                char *pbuf; 
     305                struct passwd *pwd; 
     306                size_t dirlen; 
     307                uid_t uid; 
     308 
     309#ifdef __UCLIBC_HAS_REENTRANT_RPC__ 
     310                size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 
     311                struct passwd pwdbuf; 
     312                char *buffer = stack_heap_alloc(buflen); 
     313 
     314                if (getpwnam_r (luser, &pwdbuf, buffer, 
     315                            buflen, &pwd) != 0 || pwd == NULL) 
     316                { 
     317                        stack_heap_free(buffer); 
     318                        return -1; 
     319                } 
     320                stack_heap_free(buffer); 
     321#else 
     322                if ((pwd = getpwnam(luser)) == NULL) 
     323                        return -1; 
     324#endif 
     325 
     326                dirlen = strlen (pwd->pw_dir); 
     327                pbuf = malloc (dirlen + sizeof "/.rhosts"); 
     328                strcpy (pbuf, pwd->pw_dir); 
     329                strcat (pbuf, "/.rhosts"); 
     330 
     331                /* Change effective uid while reading .rhosts.  If root and 
     332                   reading an NFS mounted file system, can't read files that 
     333                   are protected read/write owner only.  */ 
     334                uid = geteuid (); 
     335                seteuid (pwd->pw_uid); 
     336                hostf = iruserfopen (pbuf, pwd->pw_uid); 
     337                free(pbuf); 
     338 
     339                if (hostf != NULL) { 
     340                        isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); 
     341                        fclose (hostf); 
     342                } 
     343 
     344                seteuid (uid); 
     345                return isbad; 
     346        } 
     347        return -1; 
     348} 
     349 
     350int ruserok(const char *rhost, int superuser, const char *ruser, 
     351                        const char *luser) 
     352{ 
     353        struct hostent *hp; 
     354        u_int32_t addr; 
     355        char **ap; 
     356#ifdef __UCLIBC_HAS_REENTRANT_RPC__ 
     357        size_t buflen; 
     358        char *buffer; 
     359        int herr; 
     360        struct hostent hostbuf; 
     361#endif 
     362 
     363#ifdef __UCLIBC_HAS_REENTRANT_RPC__ 
     364        buflen = 1024; 
     365        buffer = stack_heap_alloc(buflen); 
     366 
     367        while (gethostbyname_r (rhost, &hostbuf, buffer, 
     368                    buflen, &hp, &herr) != 0 || hp == NULL) 
     369        { 
     370            if (herr != NETDB_INTERNAL || errno != ERANGE) { 
     371                stack_heap_free(buffer); 
     372                return -1; 
     373            } else 
     374            { 
     375                /* Enlarge the buffer.  */ 
     376                buflen *= 2; 
     377                stack_heap_free(buffer); 
     378                buffer = stack_heap_alloc(buflen); 
     379            } 
     380        } 
     381        stack_heap_free(buffer); 
     382#else 
     383        if ((hp = gethostbyname(rhost)) == NULL) { 
     384                return -1; 
     385        } 
     386#endif 
     387        for (ap = hp->h_addr_list; *ap; ++ap) { 
     388                memmove(&addr, *ap, sizeof(addr)); 
     389                if (iruserok2(addr, superuser, ruser, luser, rhost) == 0) 
     390                        return 0; 
     391        } 
     392        return -1; 
     393} 
     394 
    46395PAM_EXTERN 
    47396int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, 
    48397                         const char **argv) 
Note: See TracBrowser for help on using the repository browser.