/* * Returns 0 if ok, -1 if not ok. */ static int __ivaliduser(FILE *hostf, unsigned raddr, const char *luser, const char *ruser) { char *user, *p; int ch; char buf[MaxHostNameLen + 128]; /* host + login */ char hname[MaxHostNameLen]; struct hostent *hp; /* Presumed guilty until proven innocent. */ int userok = 0, hostok = 0; #ifdef HAVE_YP_GET_DEFAULT_DOMAIN char *ypdomain; if (yp_get_default_domain(&ypdomain)) ypdomain = NULL; #else #define ypdomain NULL #endif /* We need to get the damn hostname back for netgroup matching. */ if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long), AF_INET)) == NULL) return (-1); strlcpy(hname, hp->h_name, sizeof(hname)); while (fgets(buf, sizeof(buf), hostf)) { p = buf; /* Skip lines that are too long. */ if (strchr(p, '\n') == NULL) { while ((ch = getc(hostf)) != '\n' && ch != EOF); continue; } if (*p == '\n' || *p == '#') { /* comment... */ continue; } while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { if (isupper((unsigned char)*p)) *p = tolower((unsigned char)*p); p++; } if (*p == ' ' || *p == '\t') { *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; user = p; while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') p++; } else user = p; *p = '\0'; /* * Do +/- and +@/-@ checking. This looks really nasty, * but it matches SunOS's behavior so far as I can tell. */ switch(buf[0]) { case '+': if (!buf[1]) { /* '+' matches all hosts */ hostok = 1; break; } if (buf[1] == '@') /* match a host by netgroup */ hostok = innetgr((char *)&buf[2], (char *)&hname, NULL, ypdomain); else /* match a host by addr */ hostok = __icheckhost(raddr,(char *)&buf[1]); break; case '-': /* reject '-' hosts and all their users */ if (buf[1] == '@') { if (innetgr((char *)&buf[2], (char *)&hname, NULL, ypdomain)) return(-1); } else { if (__icheckhost(raddr,(char *)&buf[1])) return(-1); } break; default: /* if no '+' or '-', do a simple match */ hostok = __icheckhost(raddr, buf); break; } switch(*user) { case '+': if (!*(user+1)) { /* '+' matches all users */ userok = 1; break; } if (*(user+1) == '@') /* match a user by netgroup */ userok = innetgr(user+2, NULL, (char *)ruser, ypdomain); else /* match a user by direct specification */ userok = !(strcmp(ruser, user+1)); break; case '-': /* if we matched a hostname, */ if (hostok) { /* check for user field rejections */ if (!*(user+1)) return(-1); if (*(user+1) == '@') { if (innetgr(user+2, NULL, (char *)ruser, ypdomain)) return(-1); } else { if (!strcmp(ruser, user+1)) return(-1); } } break; default: /* no rejections: try to match the user */ if (hostok) userok = !(strcmp(ruser,*user ? user : luser)); break; } if (hostok && userok) return(0); } return (-1); }
/* * 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') { /* <nul> 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'; /* <nul> 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; }
int __ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen, const char *luser, const char *ruser) { char *user, *p; char *buf; const char *auser, *ahost; int hostok, userok; char *rhost = (char *)-1; char domain[MAXHOSTNAMELEN]; size_t buflen; getdomainname(domain, sizeof(domain)); while ((buf = fgetln(hostf, &buflen))) { p = buf; if (*p == '#') continue; while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') { if (!isprint(*p)) goto bail; *p = isupper(*p) ? tolower(*p) : *p; p++; } if (p >= buf + buflen) continue; if (*p == ' ' || *p == '\t') { *p++ = '\0'; while (p < buf + buflen && (*p == ' ' || *p == '\t')) p++; if (p >= buf + buflen) continue; user = p; while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') { if (!isprint(*p)) goto bail; p++; } } else user = p; *p = '\0'; if (p == buf) continue; auser = *user ? user : luser; ahost = buf; if (strlen(ahost) >= MAXHOSTNAMELEN) continue; /* * innetgr() must lookup a hostname (we do not attempt * to change the semantics so that netgroups may have * #.#.#.# addresses in the list.) */ if (ahost[0] == '+') switch (ahost[1]) { case '\0': hostok = 1; break; case '@': if (rhost == (char *)-1) rhost = __gethostloop(raddr, salen); hostok = 0; if (rhost) hostok = innetgr(&ahost[2], rhost, NULL, domain); break; default: hostok = __icheckhost(raddr, salen, &ahost[1]); break; } else if (ahost[0] == '-') switch (ahost[1]) { case '\0': hostok = -1; break; case '@': if (rhost == (char *)-1) rhost = __gethostloop(raddr, salen); hostok = 0; if (rhost) hostok = -innetgr(&ahost[2], rhost, NULL, domain); break; default: hostok = -__icheckhost(raddr, salen, &ahost[1]); break; } else hostok = __icheckhost(raddr, salen, ahost); if (auser[0] == '+') switch (auser[1]) { case '\0': userok = 1; break; case '@': userok = innetgr(&auser[2], NULL, ruser, domain); break; default: userok = strcmp(ruser, &auser[1]) ? 0 : 1; break; } else if (auser[0] == '-') switch (auser[1]) { case '\0': userok = -1; break; case '@': userok = -innetgr(&auser[2], NULL, ruser, domain); break; default: userok = strcmp(ruser, &auser[1]) ? 0 : -1; break; } else userok = strcmp(ruser, auser) ? 0 : 1; /* Check if one component did not match */ if (hostok == 0 || userok == 0) continue; /* Check if we got a forbidden pair */ if (userok <= -1 || hostok <= -1) return (-1); /* Check if we got a valid pair */ if (hostok >= 1 && userok >= 1) return (0); } bail: return (-1); }
int __ivaliduser_sa(FILE *hostf, const struct sockaddr *raddr, socklen_t salen, const char *luser, const char *ruser) { char *user, *p; int ch; char buf[MAXHOSTNAMELEN + 128]; /* host + login */ char hname[MAXHOSTNAMELEN]; /* Presumed guilty until proven innocent. */ int userok = 0, hostok = 0; #ifdef YP char *ypdomain; if (yp_get_default_domain(&ypdomain)) ypdomain = NULL; #else #define ypdomain NULL #endif /* We need to get the damn hostname back for netgroup matching. */ if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0, NI_NAMEREQD) != 0) hname[0] = '\0'; while (fgets(buf, sizeof(buf), hostf)) { p = buf; /* Skip lines that are too long. */ if (strchr(p, '\n') == NULL) { while ((ch = getc(hostf)) != '\n' && ch != EOF); continue; } if (*p == '\n' || *p == '#') { /* comment... */ continue; } while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p; p++; } if (*p == ' ' || *p == '\t') { *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; user = p; while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') p++; } else user = p; *p = '\0'; /* * Do +/- and +@/-@ checking. This looks really nasty, * but it matches SunOS's behavior so far as I can tell. */ switch(buf[0]) { case '+': if (!buf[1]) { /* '+' matches all hosts */ hostok = 1; break; } if (buf[1] == '@') /* match a host by netgroup */ hostok = hname[0] != '\0' && innetgr(&buf[2], hname, NULL, ypdomain); else /* match a host by addr */ hostok = __icheckhost(raddr, salen, (char *)&buf[1]); break; case '-': /* reject '-' hosts and all their users */ if (buf[1] == '@') { if (hname[0] == '\0' || innetgr(&buf[2], hname, NULL, ypdomain)) return(-1); } else { if (__icheckhost(raddr, salen, (char *)&buf[1])) return(-1); } break; default: /* if no '+' or '-', do a simple match */ hostok = __icheckhost(raddr, salen, buf); break; } switch(*user) { case '+': if (!*(user+1)) { /* '+' matches all users */ userok = 1; break; } if (*(user+1) == '@') /* match a user by netgroup */ userok = innetgr(user+2, NULL, ruser, ypdomain); else /* match a user by direct specification */ userok = !(strcmp(ruser, user+1)); break; case '-': /* if we matched a hostname, */ if (hostok) { /* check for user field rejections */ if (!*(user+1)) return(-1); if (*(user+1) == '@') { if (innetgr(user+2, NULL, ruser, ypdomain)) return(-1); } else { if (!strcmp(ruser, user+1)) return(-1); } } break; default: /* no rejections: try to match the user */ if (hostok) userok = !(strcmp(ruser,*user ? user : luser)); break; } if (hostok && userok) return(0); } return (-1); }
static int __ivaliduser (pam_handle_t *pamh, struct _options *opts, FILE *hostf, U32 raddr, const char *luser, const char *ruser, const char *rhost) { register const char *user; register char *p; int hcheck, ucheck; char buf[MAXHOSTNAMELEN + 128]; /* host + login */ buf[sizeof (buf)-1] = '\0'; /* terminate line */ while (fgets(buf, sizeof(buf), hostf) != NULL) { /* hostf file line */ p = buf; /* from beginning of file.. */ /* Skip empty or comment lines */ if (__isempty(p)) { continue; } /* Skip lines that are too long. */ if (strchr(p, '\n') == NULL) { int ch = getc(hostf); while (ch != '\n' && ch != EOF) ch = getc(hostf); continue; } /* * If there is a hostname at the start of the line. Set it to * lower case. A leading ' ' or '\t' indicates no hostname */ for (;*p && !isspace(*p); ++p) { *p = tolower(*p); } /* * next we want to find the permitted name for the remote user */ if (*p == ' ' || *p == '\t') { /* <nul> 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'; /* <nul> terminate username (+host?) */ /* buf -> host(?) ; user -> username(?) */ /* First check host part */ hcheck=__icheckhost(pamh, opts, raddr, buf, rhost); if (hcheck<0) return(1); if (hcheck) { /* Then check user part */ if (! (*user)) user = luser; ucheck=__icheckuser(pamh, opts, user, ruser, rhost); /* Positive 'host user' match? */ if (ucheck>0) return(0); /* Negative 'host -user' match? */ if (ucheck<0) return(1); /* Neither, go on looking for match */ } } return (1); }