From: acoul Date: Thu, 29 Sep 2011 12:03:36 +0000 (+0000) Subject: libs/libpam: make KanjiMonster happy X-Git-Url: http://207.154.207.93/?a=commitdiff_plain;h=38b2398307416b4cc76fdbc657ee52b5c9fa2ece;p=packages.git libs/libpam: make KanjiMonster happy git-svn-id: svn://svn.openwrt.org/openwrt/packages@28317 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/libs/libpam/patches/005-fix_ruserok.patch b/libs/libpam/patches/005-fix_ruserok.patch index 91a474160..1abd2d160 100644 --- a/libs/libpam/patches/005-fix_ruserok.patch +++ b/libs/libpam/patches/005-fix_ruserok.patch @@ -1,16 +1,367 @@ --- a/modules/pam_rhosts/pam_rhosts.c +++ b/modules/pam_rhosts/pam_rhosts.c -@@ -111,11 +111,13 @@ int pam_sm_authenticate (pam_handle_t *p - as_root = (lpwd->pw_uid == 0); - } +@@ -34,8 +34,10 @@ -+#if 0 - #ifdef HAVE_RUSEROK_AF - retval = ruserok_af (rhost, as_root, ruser, luser, PF_UNSPEC); - #else - retval = ruserok (rhost, as_root, ruser, luser); - #endif + #include + #include ++#include + #include + #include ++#include + + #define PAM_SM_AUTH /* only defines this management group */ + +@@ -43,6 +45,353 @@ + #include + #include + ++int __check_rhosts_file = 1; ++ ++/* Extremely paranoid file open function. */ ++static FILE * ++iruserfopen (const char *file, uid_t okuser) ++{ ++ struct stat st; ++ char *cp = NULL; ++ FILE *res = NULL; ++ ++ /* If not a regular file, if owned by someone other than user or ++ root, if writeable by anyone but the owner, or if hardlinked ++ anywhere, quit. */ ++ if (lstat (file, &st)) ++ cp = "lstat failed"; ++ else if (!S_ISREG (st.st_mode)) ++ cp = "not regular file"; ++ else ++ { ++ res = fopen (file, "r"); ++ if (!res) ++ cp = "cannot open"; ++ else if (fstat (fileno (res), &st) < 0) ++ cp = "fstat failed"; ++ else if (st.st_uid && st.st_uid != okuser) ++ cp = "bad owner"; ++ else if (st.st_mode & (S_IWGRP|S_IWOTH)) ++ cp = "writeable by other than owner"; ++ else if (st.st_nlink > 1) ++ cp = "hard linked somewhere"; ++ } ++ ++ /* If there were any problems, quit. */ ++ if (cp != NULL) ++ { ++ if (res) ++ fclose (res); ++ return NULL; ++ } ++ ++ return res; ++} ++ ++/* ++ * Returns 1 for blank lines (or only comment lines) and 0 otherwise ++ */ ++static int ++__isempty(char *p) ++{ ++ while (*p && isspace (*p)) { ++ ++p; ++ } ++ ++ return (*p == '\0' || *p == '#') ? 1 : 0 ; ++} ++ ++/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ ++static int ++__icheckhost (u_int32_t raddr, char *lhost, const char *rhost) ++{ ++ struct hostent *hp; ++ u_int32_t laddr; ++ int negate=1; /* Multiply return with this to get -1 instead of 1 */ ++ char **pp; ++ ++#ifdef __UCLIBC_HAS_REENTRANT_RPC__ ++ int save_errno; ++ size_t buflen; ++ char *buffer; ++ struct hostent hostbuf; ++ int herr; ++#endif ++ ++#ifdef HAVE_NETGROUP ++ /* Check nis netgroup. */ ++ if (strncmp ("+@", lhost, 2) == 0) ++ return innetgr (&lhost[2], rhost, NULL, NULL); ++ ++ if (strncmp ("-@", lhost, 2) == 0) ++ return -innetgr (&lhost[2], rhost, NULL, NULL); ++#endif /* HAVE_NETGROUP */ ++ ++ /* -host */ ++ if (strncmp ("-", lhost,1) == 0) { ++ negate = -1; ++ lhost++; ++ } else if (strcmp ("+",lhost) == 0) { ++ return 1; /* asking for trouble, but ok.. */ ++ } ++ ++ /* Try for raw ip address first. */ ++ if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE) ++ return negate * (! (raddr ^ laddr)); ++ ++ /* Better be a hostname. */ ++#ifdef __UCLIBC_HAS_REENTRANT_RPC__ ++ buflen = 1024; ++ buffer = malloc(buflen); ++ save_errno = errno; ++ ++ while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) ++ != 0) { ++ free(buffer); ++ return (0); ++ } ++ free(buffer); ++ __set_errno (save_errno); ++#else ++ hp = gethostbyname(lhost); ++#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ ++ ++ if (hp == NULL) ++ return 0; ++ ++ /* Spin through ip addresses. */ ++ for (pp = hp->h_addr_list; *pp; ++pp) ++ if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) ++ return negate; ++ ++ /* No match. */ ++ return (0); ++} ++ ++/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ ++static int ++__icheckuser (const char *luser, const char *ruser) ++{ ++ ++ /* ++ luser is user entry from .rhosts/hosts.equiv file ++ ruser is user id on remote host ++ */ ++ ++#ifdef HAVE_NETGROUP ++ /* [-+]@netgroup */ ++ if (strncmp ("+@", luser, 2) == 0) ++ return innetgr (&luser[2], NULL, ruser, NULL); ++ ++ if (strncmp ("-@", luser,2) == 0) ++ return -innetgr (&luser[2], NULL, ruser, NULL); ++#endif /* HAVE_NETGROUP */ ++ ++ /* -user */ ++ if (strncmp ("-", luser, 1) == 0) ++ return -(strcmp (&luser[1], ruser) == 0); ++ ++ /* + */ ++ if (strcmp ("+", luser) == 0) ++ return 1; ++ ++ /* simple string match */ ++ return strcmp (ruser, luser) == 0; ++} ++ ++/* ++ * Returns 0 if positive match, -1 if _not_ ok. ++ */ ++static int ++__ivaliduser2(FILE *hostf, u_int32_t raddr, const char *luser, ++ const char *ruser, const char *rhost) ++{ ++ register const char *user; ++ register char *p; ++ int hcheck, ucheck; ++ char *buf = NULL; ++ size_t bufsize = 0; ++ int retval = -1; ++ ++ while (getline (&buf, &bufsize, hostf) > 0) { ++ buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */ ++ p = buf; ++ ++ /* Skip empty or comment lines */ ++ if (__isempty (p)) { ++ continue; ++ } ++ ++ /* Skip lines that are too long. */ ++ if (strchr (p, '\n') == NULL) { ++ int ch = getc_unlocked (hostf); ++ ++ while (ch != '\n' && ch != EOF) ++ ch = getc_unlocked (hostf); ++ continue; ++ } ++ ++ for (;*p && !isspace(*p); ++p) { ++ *p = tolower (*p); ++ } ++ ++ /* Next we want to find the permitted name for the remote user. */ ++ if (*p == ' ' || *p == '\t') { ++ /* terminate hostname and skip spaces */ ++ for (*p++='\0'; *p && isspace (*p); ++p); ++ ++ user = p; /* this is the user's name */ ++ while (*p && !isspace (*p)) ++ ++p; /* find end of user's name */ ++ } else ++ user = p; ++ ++ *p = '\0'; /* terminate username (+host?) */ ++ ++ /* buf -> host(?) ; user -> username(?) */ ++ ++ /* First check host part */ ++ hcheck = __icheckhost (raddr, buf, rhost); ++ ++ if (hcheck < 0) ++ break; ++ ++ if (hcheck) { ++ /* Then check user part */ ++ if (! (*user)) ++ user = luser; ++ ++ ucheck = __icheckuser (user, ruser); ++ ++ /* Positive 'host user' match? */ ++ if (ucheck > 0) { ++ retval = 0; ++ break; ++ } ++ ++ /* Negative 'host -user' match? */ ++ if (ucheck < 0) ++ break; ++ ++ /* Neither, go on looking for match */ ++ } ++ } ++ ++ free (buf); ++ ++ return retval; ++} ++ ++static int ++iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, ++ const char *rhost) ++{ ++ FILE *hostf = NULL; ++ int isbad = -1; ++ ++ if (!superuser) ++ hostf = iruserfopen (_PATH_HEQUIV, 0); ++ ++ if (hostf) { ++ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); ++ fclose (hostf); ++ ++ if (!isbad) ++ return 0; ++ } ++ ++ if (__check_rhosts_file || superuser) { ++ char *pbuf; ++ struct passwd *pwd; ++ size_t dirlen; ++ uid_t uid; ++ ++#ifdef __UCLIBC_HAS_REENTRANT_RPC__ ++ size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); ++ struct passwd pwdbuf; ++ char *buffer = stack_heap_alloc(buflen); ++ ++ if (getpwnam_r (luser, &pwdbuf, buffer, ++ buflen, &pwd) != 0 || pwd == NULL) ++ { ++ stack_heap_free(buffer); ++ return -1; ++ } ++ stack_heap_free(buffer); ++#else ++ if ((pwd = getpwnam(luser)) == NULL) ++ return -1; ++#endif ++ ++ dirlen = strlen (pwd->pw_dir); ++ pbuf = malloc (dirlen + sizeof "/.rhosts"); ++ strcpy (pbuf, pwd->pw_dir); ++ strcat (pbuf, "/.rhosts"); ++ ++ /* Change effective uid while reading .rhosts. If root and ++ reading an NFS mounted file system, can't read files that ++ are protected read/write owner only. */ ++ uid = geteuid (); ++ seteuid (pwd->pw_uid); ++ hostf = iruserfopen (pbuf, pwd->pw_uid); ++ free(pbuf); ++ ++ if (hostf != NULL) { ++ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); ++ fclose (hostf); ++ } ++ ++ seteuid (uid); ++ return isbad; ++ } ++ return -1; ++} ++ ++int ruserok(const char *rhost, int superuser, const char *ruser, ++ const char *luser) ++{ ++ struct hostent *hp; ++ u_int32_t addr; ++ char **ap; ++#ifdef __UCLIBC_HAS_REENTRANT_RPC__ ++ size_t buflen; ++ char *buffer; ++ int herr; ++ struct hostent hostbuf; ++#endif ++ ++#ifdef __UCLIBC_HAS_REENTRANT_RPC__ ++ buflen = 1024; ++ buffer = stack_heap_alloc(buflen); ++ ++ while (gethostbyname_r (rhost, &hostbuf, buffer, ++ buflen, &hp, &herr) != 0 || hp == NULL) ++ { ++ if (herr != NETDB_INTERNAL || errno != ERANGE) { ++ stack_heap_free(buffer); ++ return -1; ++ } else ++ { ++ /* Enlarge the buffer. */ ++ buflen *= 2; ++ stack_heap_free(buffer); ++ buffer = stack_heap_alloc(buflen); ++ } ++ } ++ stack_heap_free(buffer); ++#else ++ if ((hp = gethostbyname(rhost)) == NULL) { ++ return -1; ++ } +#endif - if (retval != 0) { - if (!opt_silent || opt_debug) - pam_syslog(pamh, LOG_WARNING, "denied access to %s@%s as %s", ++ for (ap = hp->h_addr_list; *ap; ++ap) { ++ memmove(&addr, *ap, sizeof(addr)); ++ if (iruserok2(addr, superuser, ruser, luser, rhost) == 0) ++ return 0; ++ } ++ return -1; ++} ++ + PAM_EXTERN + int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, + const char **argv)