ruserok.c

Go to the documentation of this file.
00001 /*      ruserok() - hosts.equiv and .rhosts check       Author: Kees J. Bot
00002  *                                                              25 May 2001
00003  *
00004  * Under Minix one can use IP addresses, CIDR network blocks, and hostnames
00005  * with wildcards in .rhosts files.  Only the iruserok() interface can be
00006  * used, and the IP address is reverse/forward crosschecked if a hostname
00007  * match is done.  Ruserok() is dead and buried.  The superuser parameter is
00008  * ignored, because it makes root too special.  Most users on Minix can be
00009  * root, so hosts.equiv would become useless if root can't use it.  Likewise
00010  * .rhosts isn't checked to be root or user owned and stuff, users have to
00011  * be careful themselves.
00012  */
00013 
00014 #include <sys/types.h>
00015 #include <string.h>
00016 #include <stdio.h>
00017 #include <ctype.h>
00018 #include <limits.h>
00019 #include <pwd.h>
00020 #include <net/hton.h>
00021 #include <net/gen/in.h>
00022 #include <net/gen/netdb.h>
00023 #include <net/gen/inet.h>
00024 #include <net/gen/socket.h>
00025 #include <net/gen/nameser.h>
00026 
00027 /* Odd global variable.  Seems to be used by lpd(8). */
00028 int     __check_rhosts_file = 1;
00029 
00030 static int cidr_aton(char *word, ipaddr_t *addr, ipaddr_t *mask)
00031 /* Try to interpret 'word' as an CIDR spec, e.g. 172.16.102.64/27. */
00032 {
00033     char *slash;
00034     int r;
00035     static char S32[]= "/32";
00036 
00037     if (*word == 0) return 0;
00038 
00039     if ((slash= strchr(word, '/')) == NULL) slash= S32;
00040 
00041     *slash= 0;
00042     r= inet_aton(word, addr);
00043     *slash++= '/';
00044     if (!r) return 0;
00045 
00046     r= 0;
00047     while ((*slash - '0') < 10u) {
00048         r= 10*r + (*slash++ - '0');
00049         if (r > 32) return 0;
00050     }
00051     if (*slash != 0 || slash[-1] == '/') return 0;
00052     *mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
00053     return 1;
00054 }
00055 
00056 static int match(const char *word, const char *pattern)
00057 /* Match word onto a pattern.  Pattern may contain the * wildcard. */
00058 {
00059     unsigned cw, cp;
00060 #define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
00061 
00062     for (;;) {
00063         lc(cw, *word);
00064         lc(cp, *pattern);
00065 
00066         if (cp == '*') {
00067             do pattern++; while (*pattern == '*');
00068             lc(cp, *pattern);
00069             if (cp == 0) return 1;
00070 
00071             while (cw != 0) {
00072                 if (cw == cp && match(word+1, pattern+1)) return 1;
00073                 word++;
00074                 lc(cw, *word);
00075             }
00076             return 0;
00077         } else
00078         if (cw == 0 || cp == 0) {
00079             return cw == cp;
00080         } else
00081         if (cw == cp) {
00082             word++;
00083             pattern++;
00084         } else {
00085             return 0;
00086         }
00087     }
00088 #undef lc
00089 }
00090 
00091 static int get_name(ipaddr_t addr, char *name)
00092 /* Do a reverse lookup on the remote IP address followed by a forward lookup
00093  * to check if the host has that address.  Return true if this is so, return
00094  * either the true name or the ascii IP address in name[].
00095  */
00096 {
00097     struct hostent *he;
00098     int ok, i;
00099 
00100     ok= 0;
00101     he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
00102     if (he != NULL) {
00103         strcpy(name, he->h_name);
00104         he= gethostbyname(name);
00105 
00106         if (he != NULL && he->h_addrtype == AF_INET) {
00107             for (i= 0; he->h_addr_list[i] != NULL; i++) {
00108                 if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
00109                     ok= 1;
00110                     break;
00111                 }
00112             }
00113         }
00114     }
00115     strcpy(name, ok ? he->h_name : inet_ntoa(addr));
00116     return ok;
00117 }
00118 
00119 int __ivaliduser(FILE *hostf, unsigned long raddr,
00120     const char *luser, const char *ruser)
00121 {
00122     register char *p;
00123     char buf[MAXDNAME + 128];           /* host + login */
00124     char rhost[MAXDNAME];               /* remote host */
00125     char *word[2];
00126     int i, ch, got_name;
00127     ipaddr_t addr, mask;
00128 
00129     got_name = -1;
00130 
00131     while (fgets(buf, sizeof(buf), hostf)) {
00132         /* Skip lines that are too long. */
00133         if (strchr(buf, '\n') == NULL) {
00134             while ((ch = fgetc(hostf)) != '\n' && ch != EOF);
00135             continue;
00136         }
00137         i = 0;
00138         p = buf;
00139         for (;;) {
00140             while (isspace(*p)) *p++ = '\0';
00141             if (*p == '\0') break;
00142             if (i < 2) word[i] = p;
00143             i++;
00144             while (*p != '\0' && !isspace(*p)) p++;
00145         }
00146         if (i != 1 && i != 2) continue;
00147         if (word[0][0] == '#') continue;
00148         if (strcmp(ruser, i == 2 ? word[1] : luser) != 0) continue;
00149 
00150         if (cidr_aton(word[0], &addr, &mask)) {
00151             if (((raddr ^ addr) & mask) == 0) return (0);
00152             continue;
00153         }
00154 
00155         if (got_name == -1) got_name = get_name(raddr, rhost);
00156         if (match(rhost, word[0])) return (0);
00157     }
00158     return (-1);
00159 }
00160 
00161 int iruserok(unsigned long raddr, int superuser,
00162     const char *ruser, const char *luser)
00163 {
00164     /* Returns 0 if ok, -1 if not ok. */
00165     struct passwd *pwd;
00166     FILE *hostf;
00167     int i, r;
00168     char pbuf[PATH_MAX];
00169 
00170     for (i = 0; i < 2; i++) {
00171         if (i == 0) {
00172             strcpy(pbuf, _PATH_HEQUIV);
00173         } else {
00174             if (!__check_rhosts_file) return (-1);
00175             if ((pwd = getpwnam(luser)) == NULL) return (-1);
00176             (void)strcpy(pbuf, pwd->pw_dir);
00177             (void)strcat(pbuf, "/.rhosts");
00178         }
00179 
00180         if ((hostf = fopen(pbuf, "r")) == NULL) return (-1);
00181 
00182         r = __ivaliduser(hostf, raddr, luser, ruser);
00183         (void)fclose(hostf);
00184         if (r == 0) return (0);
00185     }
00186     return (-1);
00187 }

Generated on Fri Apr 14 22:57:26 2006 for minix by  doxygen 1.4.6