📄 rcmd.c
字号:
return (s);}int __check_rhosts_file = 1;char *__rcmd_errstr;intruserok(rhost, superuser, ruser, luser) const char *rhost, *ruser, *luser; int superuser;{ struct addrinfo hints, *res, *r; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ error = getaddrinfo(rhost, "0", &hints, &res); if (error) return (-1); for (r = res; r; r = r->ai_next) { if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser, luser) == 0) { freeaddrinfo(res); return (0); } } freeaddrinfo(res); return (-1);}/* * New .rhosts strategy: We are passed an ip address. We spin through * hosts.equiv and .rhosts looking for a match. When the .rhosts only * has ip addresses, we don't have to trust a nameserver. When it * contains hostnames, we spin through the list of addresses the nameserver * gives us and look for a match. * * Returns 0 if ok, -1 if not ok. */intiruserok(raddr, superuser, ruser, luser) unsigned long raddr; int superuser; const char *ruser, *luser;{ struct sockaddr_in sin; int sin_len; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); return iruserok_sa((struct sockaddr *)&sin, sin_len, superuser, ruser, luser);}/* * AF independent extension of iruserok. * * Returns 0 if ok, -1 if not ok. */intiruserok_sa(ra, rlen, superuser, ruser, luser) const void *ra; int rlen; int superuser; const char *ruser, *luser;{ char *cp; struct stat sbuf; struct passwd *pwd; FILE *hostf; uid_t uid; int first; char pbuf[MAXPATHLEN]; const struct sockaddr *raddr; struct sockaddr_storage ss; /* avoid alignment issue */ if (rlen > sizeof(ss)) return(-1); memcpy(&ss, ra, rlen); raddr = (struct sockaddr *)&ss; first = 1; hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");again: if (hostf) { if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) { (void)fclose(hostf); return (0); } (void)fclose(hostf); } if (first == 1 && (__check_rhosts_file || superuser)) { first = 0; if ((pwd = getpwnam(luser)) == NULL) return (-1); (void)strcpy(pbuf, pwd->pw_dir); (void)strcat(pbuf, "/.rhosts"); /* * Change effective uid while opening .rhosts. If root and * reading an NFS mounted file system, can't read files that * are protected read/write owner only. */ uid = geteuid(); (void)seteuid(pwd->pw_uid); hostf = fopen(pbuf, "r"); (void)seteuid(uid); if (hostf == NULL) return (-1); /* * If not a regular file, or is owned by someone other than * user or root or if writeable by anyone but the owner, quit. */ cp = NULL; if (lstat(pbuf, &sbuf) < 0) cp = ".rhosts lstat failed"; else if (!S_ISREG(sbuf.st_mode)) cp = ".rhosts not regular file"; else if (fstat(fileno(hostf), &sbuf) < 0) cp = ".rhosts fstat failed"; else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) cp = "bad .rhosts owner"; else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) cp = ".rhosts writeable by other than owner"; /* If there were any problems, quit. */ if (cp) { __rcmd_errstr = cp; (void)fclose(hostf); return (-1); } goto again; } return (-1);}/* * XXX * Don't make static, used by lpd(8). * * Returns 0 if ok, -1 if not ok. */int__ivaliduser(hostf, raddr, luser, ruser) FILE *hostf; u_int32_t raddr; const char *luser, *ruser;{ struct sockaddr_in sin; int sin_len; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr)); return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin_len, luser, ruser);}/* * Returns 0 if ok, -1 if not ok. * * XXX obsolete API. */int__ivaliduser_af(hostf, raddr, luser, ruser, af, len) FILE *hostf; const void *raddr; const char *luser, *ruser; int af, len;{ struct sockaddr *sa = NULL; struct sockaddr_in *sin = NULL;#ifdef INET6 struct sockaddr_in6 *sin6 = NULL;#endif struct sockaddr_storage ss; memset(&ss, 0, sizeof(ss)); switch (af) { case AF_INET: if (len != sizeof(sin->sin_addr)) return -1; sin = (struct sockaddr_in *)&ss; sin->sin_family = AF_INET; memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr)); break;#ifdef INET6 case AF_INET6: if (len != sizeof(sin6->sin6_addr)) return -1; /* you will lose scope info */ sin6 = (struct sockaddr_in6 *)&ss; sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr)); break;#endif default: return -1; } sa = (struct sockaddr *)&ss; return __ivaliduser_sa(hostf, sa, 0, luser, ruser);}int__ivaliduser_sa(hostf, raddr, salen, luser, ruser) FILE *hostf; const struct sockaddr *raddr; socklen_t salen; const char *luser, *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) return (-1); 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 = innetgr((char *)&buf[2], (char *)&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 (innetgr((char *)&buf[2], (char *)&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);}/* * Returns "true" if match, 0 if no match. * * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion * if af == AF_INET6. */static int__icheckhost(raddr, salen, lhost) const struct sockaddr *raddr; socklen_t salen; const char *lhost;{ struct sockaddr_in sin; struct sockaddr_in6 *sin6; struct addrinfo hints, *res, *r; int error; char h1[NI_MAXHOST], h2[NI_MAXHOST]; if (raddr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)raddr; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], sizeof(sin.sin_addr)); raddr = (struct sockaddr *)&sin; salen = sizeof(struct sockaddr_in); } } h1[0] = '\0'; if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0) return (0); /* Resolve laddr into sockaddr */ memset(&hints, 0, sizeof(hints)); hints.ai_family = raddr->sa_family; hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/ res = NULL; error = getaddrinfo(lhost, "0", &hints, &res); if (error) return (0); for (r = res; r ; r = r->ai_next) { h2[0] = '\0'; if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0) continue; if (strcmp(h1, h2) == 0) { freeaddrinfo(res); return (1); } } /* No match. */ freeaddrinfo(res); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -