1 /* ruserok() - hosts.equiv and .rhosts check Author: Kees J. Bot
4 * Under Minix one can use IP addresses, CIDR network blocks, and hostnames
5 * with wildcards in .rhosts files. Only the iruserok() interface can be
6 * used, and the IP address is reverse/forward crosschecked if a hostname
7 * match is done. Ruserok() is dead and buried. The superuser parameter is
8 * ignored, because it makes root too special. Most users on Minix can be
9 * root, so hosts.equiv would become useless if root can't use it. Likewise
10 * .rhosts isn't checked to be root or user owned and stuff, users have to
11 * be careful themselves.
14 #include <sys/types.h>
22 #include <net/gen/in.h>
23 #include <net/gen/netdb.h>
24 #include <net/gen/inet.h>
25 #include <net/gen/socket.h>
26 #include <net/gen/nameser.h>
28 /* Odd global variable. Seems to be used by lpd(8). */
29 int __check_rhosts_file
= 1;
31 static int cidr_aton(char *word
, ipaddr_t
*addr
, ipaddr_t
*mask
)
32 /* Try to interpret 'word' as an CIDR spec, e.g. 172.16.102.64/27. */
36 static char S32
[]= "/32";
38 if (*word
== 0) return 0;
40 if ((slash
= strchr(word
, '/')) == NULL
) slash
= S32
;
43 r
= inet_aton(word
, addr
);
48 while ((*slash
- '0') < 10u) {
49 r
= 10*r
+ (*slash
++ - '0');
52 if (*slash
!= 0 || slash
[-1] == '/') return 0;
53 *mask
= htonl(r
== 0 ? 0L : (0xFFFFFFFFUL
>> (32 - r
)) << (32 - r
));
57 static int match(const char *word
, const char *pattern
)
58 /* Match word onto a pattern. Pattern may contain the * wildcard. */
61 #define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
68 do pattern
++; while (*pattern
== '*');
70 if (cp
== 0) return 1;
73 if (cw
== cp
&& match(word
+1, pattern
+1)) return 1;
79 if (cw
== 0 || cp
== 0) {
92 static int get_name(ipaddr_t addr
, char *name
)
93 /* Do a reverse lookup on the remote IP address followed by a forward lookup
94 * to check if the host has that address. Return true if this is so, return
95 * either the true name or the ascii IP address in name[].
102 he
= gethostbyaddr((char *) &addr
, sizeof(addr
), AF_INET
);
104 strcpy(name
, he
->h_name
);
105 he
= gethostbyname(name
);
107 if (he
!= NULL
&& he
->h_addrtype
== AF_INET
) {
108 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++) {
109 if (memcmp(he
->h_addr_list
[i
], &addr
, sizeof(addr
)) == 0) {
116 strcpy(name
, ok
? he
->h_name
: inet_ntoa(addr
));
120 int __ivaliduser(FILE *hostf
, unsigned long raddr
,
121 const char *luser
, const char *ruser
)
124 char buf
[MAXDNAME
+ 128]; /* host + login */
125 char rhost
[MAXDNAME
]; /* remote host */
132 while (fgets(buf
, sizeof(buf
), hostf
)) {
133 /* Skip lines that are too long. */
134 if (strchr(buf
, '\n') == NULL
) {
135 while ((ch
= fgetc(hostf
)) != '\n' && ch
!= EOF
);
141 while (isspace(*p
)) *p
++ = '\0';
142 if (*p
== '\0') break;
143 if (i
< 2) word
[i
] = p
;
145 while (*p
!= '\0' && !isspace(*p
)) p
++;
147 if (i
!= 1 && i
!= 2) continue;
148 if (word
[0][0] == '#') continue;
149 if (strcmp(ruser
, i
== 2 ? word
[1] : luser
) != 0) continue;
151 if (cidr_aton(word
[0], &addr
, &mask
)) {
152 if (((raddr
^ addr
) & mask
) == 0) return (0);
156 if (got_name
== -1) got_name
= get_name(raddr
, rhost
);
157 if (match(rhost
, word
[0])) return (0);
162 int iruserok(unsigned long raddr
, int superuser
,
163 const char *ruser
, const char *luser
)
165 /* Returns 0 if ok, -1 if not ok. */
171 for (i
= 0; i
< 2; i
++) {
173 strcpy(pbuf
, _PATH_HEQUIV
);
175 if (!__check_rhosts_file
) return (-1);
176 if ((pwd
= getpwnam(luser
)) == NULL
) return (-1);
177 (void)strcpy(pbuf
, pwd
->pw_dir
);
178 (void)strcat(pbuf
, "/.rhosts");
181 if ((hostf
= fopen(pbuf
, "r")) == NULL
)
188 r
= __ivaliduser(hostf
, raddr
, luser
, ruser
);
190 if (r
== 0) return (0);