Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- rshd.c.ori 2014-04-16 21:14:57.000000000 +0200
- +++ rshd.c 2022-07-10 23:14:08.444649863 +0200
- @@ -40,13 +40,14 @@
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- -
- +#include <sys/param.h>
- +#include <sys/stat.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/ip_var.h>
- #include <arpa/inet.h>
- -
- +#include <ctype.h>
- #include <err.h>
- #include <errno.h>
- #include <fcntl.h>
- @@ -63,7 +64,7 @@
- #include <stdarg.h>
- #include <login_cap.h>
- #include <bsd_auth.h>
- -
- +#include <netgroup.h>
- int keepalive = 1;
- int check_all;
- int log_success; /* If TRUE, log all successful accesses */
- @@ -83,7 +84,7 @@
- int
- main(int argc, char *argv[])
- {
- - extern int __check_rhosts_file;
- + //extern int __check_rhosts_file;
- struct linger linger;
- int ch, on = 1;
- socklen_t fromlen;
- @@ -101,7 +102,7 @@
- log_success = 1;
- break;
- case 'l':
- - __check_rhosts_file = 0;
- + //__check_rhosts_file = 0;
- break;
- case 'n':
- keepalive = 0;
- @@ -134,13 +135,332 @@
- exit(0);
- }
- +static int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
- + const char *, const char *);
- +static int __icheckhost(struct sockaddr *, socklen_t, const char *);
- +static char *__gethostloop(struct sockaddr *, socklen_t);
- +static int iruserok_sa(const void *, int, int, const char *, const char *);
- +
- +int
- +iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
- + const char *luser)
- +{
- + struct sockaddr *sa;
- + char *cp;
- + struct stat sbuf;
- + struct passwd pwstore, *pwd;
- + FILE *hostf;
- + uid_t uid;
- + int first;
- + char pbuf[PATH_MAX], pwbuf[_PW_BUF_LEN];
- +
- + sa = (struct sockaddr *)raddr;
- + first = 1;
- + hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "re");
- +again:
- + if (hostf) {
- + if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
- + (void)fclose(hostf);
- + return (0);
- + }
- + (void)fclose(hostf);
- + }
- + if (first == 1) {
- + int len;
- +
- + first = 0;
- + pwd = NULL;
- + getpwnam_r(luser, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
- + if (pwd == NULL)
- + return (-1);
- + len = snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
- + if (len < 0 || len >= sizeof pbuf)
- + return (-1);
- +
- + /*
- + * 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, "re");
- + (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) == -1)
- + cp = ".rhosts lstat failed";
- + else if (!S_ISREG(sbuf.st_mode))
- + cp = ".rhosts not regular file";
- + else if (fstat(fileno(hostf), &sbuf) == -1)
- + 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 writable by other than owner";
- + /* If there were any problems, quit. */
- + if (cp) {
- + (void)fclose(hostf);
- + return (-1);
- + }
- + goto again;
- + }
- + return (-1);
- +}
- +
- +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[HOST_NAME_MAX+1];
- + 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((unsigned char)*p))
- + goto bail;
- + *p = isupper((unsigned char)*p) ?
- + tolower((unsigned char)*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((unsigned char)*p))
- + goto bail;
- + p++;
- + }
- + } else
- + user = p;
- + *p = '\0';
- +
- + if (p == buf)
- + continue;
- +
- + auser = *user ? user : luser;
- + ahost = buf;
- +
- + if (strlen(ahost) > HOST_NAME_MAX)
- + 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);
- +}
- +
- +/*
- + * Returns "true" if match, 0 if no match. If we do not find any
- + * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
- + */
- +static int
- +__icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost)
- +{
- + struct addrinfo hints, *res, *r;
- + char h1[NI_MAXHOST], h2[NI_MAXHOST];
- + int error;
- + const int niflags = NI_NUMERICHOST;
- +
- + h1[0] = '\0';
- + if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
- + niflags) != 0)
- + return (0);
- +
- + /* Resolve laddr into sockaddr */
- + memset(&hints, 0, sizeof(hints));
- + hints.ai_family = raddr->sa_family;
- + hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- + res = NULL;
- + error = getaddrinfo(lhost, "0", &hints, &res);
- + if (error)
- + return (0);
- +
- + /*
- + * Try string comparisons between raddr and laddr.
- + */
- + for (r = res; r; r = r->ai_next) {
- + h2[0] = '\0';
- + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
- + NULL, 0, niflags) != 0)
- + continue;
- + if (strcmp(h1, h2) == 0) {
- + freeaddrinfo(res);
- + return (1);
- + }
- + }
- +
- + /* No match. */
- + freeaddrinfo(res);
- + return (0);
- +}
- +
- +/*
- + * Return the hostname associated with the supplied address.
- + * Do a reverse lookup as well for security. If a loop cannot
- + * be found, pack the result of inet_ntoa() into the string.
- + */
- +static char *
- +__gethostloop(struct sockaddr *raddr, socklen_t salen)
- +{
- + static char remotehost[NI_MAXHOST];
- + char h1[NI_MAXHOST], h2[NI_MAXHOST];
- + struct addrinfo hints, *res, *r;
- + int error;
- + const int niflags = NI_NUMERICHOST;
- +
- + h1[0] = remotehost[0] = '\0';
- + if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
- + NULL, 0, NI_NAMEREQD) != 0)
- + return (NULL);
- + if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
- + niflags) != 0)
- + return (NULL);
- +
- + /*
- + * Look up the name and check that the supplied
- + * address is in the list
- + */
- + memset(&hints, 0, sizeof(hints));
- + hints.ai_family = raddr->sa_family;
- + hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- + hints.ai_flags = AI_CANONNAME;
- + res = NULL;
- + error = getaddrinfo(remotehost, "0", &hints, &res);
- + if (error)
- + return (NULL);
- +
- + for (r = res; r; r = r->ai_next) {
- + h2[0] = '\0';
- + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
- + NULL, 0, niflags) != 0)
- + continue;
- + if (strcmp(h1, h2) == 0) {
- + freeaddrinfo(res);
- + return (remotehost);
- + }
- + }
- +
- + /*
- + * either the DNS adminstrator has made a configuration
- + * mistake, or someone has attempted to spoof us
- + */
- + freeaddrinfo(res);
- + return (NULL);
- +}
- +
- char *envinit[1] = { 0 };
- extern char **environ;
- void
- doit(struct sockaddr *fromp)
- {
- - extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
- + //extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
- struct addrinfo hints, *res, *res0;
- int gaierror;
- struct passwd *pwd;
- @@ -382,12 +702,12 @@
- (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
- iruserok_sa(fromp, fromp->sa_len, pwd->pw_uid == 0,
- remuser, locuser) < 0)) {
- - if (__rcmd_errstr)
- + /*if (__rcmd_errstr)
- syslog(LOG_INFO|LOG_AUTH,
- "%s@%s as %s: permission denied (%s). cmd='%.80s'",
- remuser, hostname, locuser, __rcmd_errstr,
- cmdbuf);
- - else
- + else*/
- syslog(LOG_INFO|LOG_AUTH,
- "%s@%s as %s: permission denied. cmd='%.80s'",
- remuser, hostname, locuser, cmdbuf);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement