1 --- a/modules/pam_rhosts/pam_rhosts.c
2 +++ b/modules/pam_rhosts/pam_rhosts.c
4 #include <security/pam_modutil.h>
5 #include <security/pam_ext.h>
10 +#include <sys/stat.h>
13 +int __check_rhosts_file = 1;
15 +/* Extremely paranoid file open function. */
17 +iruserfopen (const char *file, uid_t okuser)
23 + /* If not a regular file, if owned by someone other than user or
24 + root, if writeable by anyone but the owner, or if hardlinked
26 + if (lstat (file, &st))
27 + cp = "lstat failed";
28 + else if (!S_ISREG (st.st_mode))
29 + cp = "not regular file";
32 + res = fopen (file, "r");
35 + else if (fstat (fileno (res), &st) < 0)
36 + cp = "fstat failed";
37 + else if (st.st_uid && st.st_uid != okuser)
39 + else if (st.st_mode & (S_IWGRP|S_IWOTH))
40 + cp = "writeable by other than owner";
41 + else if (st.st_nlink > 1)
42 + cp = "hard linked somewhere";
45 + /* If there were any problems, quit. */
57 + * Returns 1 for blank lines (or only comment lines) and 0 otherwise
62 + while (*p && isspace (*p)) {
66 + return (*p == '\0' || *p == '#') ? 1 : 0 ;
69 +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
71 +__icheckhost (u_int32_t raddr, char *lhost, const char *rhost)
75 + int negate=1; /* Multiply return with this to get -1 instead of 1 */
78 +#ifdef __UCLIBC_HAS_REENTRANT_RPC__
82 + struct hostent hostbuf;
87 + /* Check nis netgroup. */
88 + if (strncmp ("+@", lhost, 2) == 0)
89 + return innetgr (&lhost[2], rhost, NULL, NULL);
91 + if (strncmp ("-@", lhost, 2) == 0)
92 + return -innetgr (&lhost[2], rhost, NULL, NULL);
93 +#endif /* HAVE_NETGROUP */
96 + if (strncmp ("-", lhost,1) == 0) {
99 + } else if (strcmp ("+",lhost) == 0) {
100 + return 1; /* asking for trouble, but ok.. */
103 + /* Try for raw ip address first. */
104 + if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE)
105 + return negate * (! (raddr ^ laddr));
107 + /* Better be a hostname. */
108 +#ifdef __UCLIBC_HAS_REENTRANT_RPC__
110 + buffer = malloc(buflen);
111 + save_errno = errno;
113 + while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr)
119 + __set_errno (save_errno);
121 + hp = gethostbyname(lhost);
122 +#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */
127 + /* Spin through ip addresses. */
128 + for (pp = hp->h_addr_list; *pp; ++pp)
129 + if (!memcmp (&raddr, *pp, sizeof (u_int32_t)))
136 +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */
138 +__icheckuser (const char *luser, const char *ruser)
142 + luser is user entry from .rhosts/hosts.equiv file
143 + ruser is user id on remote host
146 +#ifdef HAVE_NETGROUP
147 + /* [-+]@netgroup */
148 + if (strncmp ("+@", luser, 2) == 0)
149 + return innetgr (&luser[2], NULL, ruser, NULL);
151 + if (strncmp ("-@", luser,2) == 0)
152 + return -innetgr (&luser[2], NULL, ruser, NULL);
153 +#endif /* HAVE_NETGROUP */
156 + if (strncmp ("-", luser, 1) == 0)
157 + return -(strcmp (&luser[1], ruser) == 0);
160 + if (strcmp ("+", luser) == 0)
163 + /* simple string match */
164 + return strcmp (ruser, luser) == 0;
168 + * Returns 0 if positive match, -1 if _not_ ok.
171 +__ivaliduser2(FILE *hostf, u_int32_t raddr, const char *luser,
172 + const char *ruser, const char *rhost)
174 + register const char *user;
176 + int hcheck, ucheck;
178 + size_t bufsize = 0;
181 + while (getline (&buf, &bufsize, hostf) > 0) {
182 + buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */
185 + /* Skip empty or comment lines */
186 + if (__isempty (p)) {
190 + /* Skip lines that are too long. */
191 + if (strchr (p, '\n') == NULL) {
192 + int ch = getc_unlocked (hostf);
194 + while (ch != '\n' && ch != EOF)
195 + ch = getc_unlocked (hostf);
199 + for (;*p && !isspace(*p); ++p) {
203 + /* Next we want to find the permitted name for the remote user. */
204 + if (*p == ' ' || *p == '\t') {
205 + /* <nul> terminate hostname and skip spaces */
206 + for (*p++='\0'; *p && isspace (*p); ++p);
208 + user = p; /* this is the user's name */
209 + while (*p && !isspace (*p))
210 + ++p; /* find end of user's name */
214 + *p = '\0'; /* <nul> terminate username (+host?) */
216 + /* buf -> host(?) ; user -> username(?) */
218 + /* First check host part */
219 + hcheck = __icheckhost (raddr, buf, rhost);
225 + /* Then check user part */
229 + ucheck = __icheckuser (user, ruser);
231 + /* Positive 'host user' match? */
237 + /* Negative 'host -user' match? */
241 + /* Neither, go on looking for match */
251 +iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser,
254 + FILE *hostf = NULL;
258 + hostf = iruserfopen (_PATH_HEQUIV, 0);
261 + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
268 + if (__check_rhosts_file || superuser) {
270 + struct passwd *pwd;
274 +#ifdef __UCLIBC_HAS_REENTRANT_RPC__
275 + size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
276 + struct passwd pwdbuf;
277 + char *buffer = stack_heap_alloc(buflen);
279 + if (getpwnam_r (luser, &pwdbuf, buffer,
280 + buflen, &pwd) != 0 || pwd == NULL)
282 + stack_heap_free(buffer);
285 + stack_heap_free(buffer);
287 + if ((pwd = getpwnam(luser)) == NULL)
291 + dirlen = strlen (pwd->pw_dir);
292 + pbuf = malloc (dirlen + sizeof "/.rhosts");
293 + strcpy (pbuf, pwd->pw_dir);
294 + strcat (pbuf, "/.rhosts");
296 + /* Change effective uid while reading .rhosts. If root and
297 + reading an NFS mounted file system, can't read files that
298 + are protected read/write owner only. */
300 + seteuid (pwd->pw_uid);
301 + hostf = iruserfopen (pbuf, pwd->pw_uid);
304 + if (hostf != NULL) {
305 + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost);
315 +int ruserok(const char *rhost, int superuser, const char *ruser,
318 + struct hostent *hp;
321 +#ifdef __UCLIBC_HAS_REENTRANT_RPC__
325 + struct hostent hostbuf;
328 +#ifdef __UCLIBC_HAS_REENTRANT_RPC__
330 + buffer = stack_heap_alloc(buflen);
332 + while (gethostbyname_r (rhost, &hostbuf, buffer,
333 + buflen, &hp, &herr) != 0 || hp == NULL)
335 + if (herr != NETDB_INTERNAL || errno != ERANGE) {
336 + stack_heap_free(buffer);
340 + /* Enlarge the buffer. */
342 + stack_heap_free(buffer);
343 + buffer = stack_heap_alloc(buflen);
346 + stack_heap_free(buffer);
348 + if ((hp = gethostbyname(rhost)) == NULL) {
352 + for (ap = hp->h_addr_list; *ap; ++ap) {
353 + memmove(&addr, *ap, sizeof(addr));
354 + if (iruserok2(addr, superuser, ruser, luser, rhost) == 0)
360 +#endif /* __UCLIBC__ */
363 int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc,