Advertisement
Guest User

rshd.c fixed for OpenBSD 7.1

a guest
Jul 13th, 2022
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.78 KB | None | 0 0
  1. --- rshd.c.ori 2014-04-16 21:14:57.000000000 +0200
  2. +++ rshd.c 2022-07-10 23:14:08.444649863 +0200
  3. @@ -40,13 +40,14 @@
  4. #include <sys/ioctl.h>
  5. #include <sys/time.h>
  6. #include <sys/socket.h>
  7. -
  8. +#include <sys/param.h>
  9. +#include <sys/stat.h>
  10. #include <netinet/in_systm.h>
  11. #include <netinet/in.h>
  12. #include <netinet/ip.h>
  13. #include <netinet/ip_var.h>
  14. #include <arpa/inet.h>
  15. -
  16. +#include <ctype.h>
  17. #include <err.h>
  18. #include <errno.h>
  19. #include <fcntl.h>
  20. @@ -63,7 +64,7 @@
  21. #include <stdarg.h>
  22. #include <login_cap.h>
  23. #include <bsd_auth.h>
  24. -
  25. +#include <netgroup.h>
  26. int keepalive = 1;
  27. int check_all;
  28. int log_success; /* If TRUE, log all successful accesses */
  29. @@ -83,7 +84,7 @@
  30. int
  31. main(int argc, char *argv[])
  32. {
  33. - extern int __check_rhosts_file;
  34. + //extern int __check_rhosts_file;
  35. struct linger linger;
  36. int ch, on = 1;
  37. socklen_t fromlen;
  38. @@ -101,7 +102,7 @@
  39. log_success = 1;
  40. break;
  41. case 'l':
  42. - __check_rhosts_file = 0;
  43. + //__check_rhosts_file = 0;
  44. break;
  45. case 'n':
  46. keepalive = 0;
  47. @@ -134,13 +135,332 @@
  48. exit(0);
  49. }
  50.  
  51. +static int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
  52. + const char *, const char *);
  53. +static int __icheckhost(struct sockaddr *, socklen_t, const char *);
  54. +static char *__gethostloop(struct sockaddr *, socklen_t);
  55. +static int iruserok_sa(const void *, int, int, const char *, const char *);
  56. +
  57. +int
  58. +iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
  59. + const char *luser)
  60. +{
  61. + struct sockaddr *sa;
  62. + char *cp;
  63. + struct stat sbuf;
  64. + struct passwd pwstore, *pwd;
  65. + FILE *hostf;
  66. + uid_t uid;
  67. + int first;
  68. + char pbuf[PATH_MAX], pwbuf[_PW_BUF_LEN];
  69. +
  70. + sa = (struct sockaddr *)raddr;
  71. + first = 1;
  72. + hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "re");
  73. +again:
  74. + if (hostf) {
  75. + if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
  76. + (void)fclose(hostf);
  77. + return (0);
  78. + }
  79. + (void)fclose(hostf);
  80. + }
  81. + if (first == 1) {
  82. + int len;
  83. +
  84. + first = 0;
  85. + pwd = NULL;
  86. + getpwnam_r(luser, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
  87. + if (pwd == NULL)
  88. + return (-1);
  89. + len = snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
  90. + if (len < 0 || len >= sizeof pbuf)
  91. + return (-1);
  92. +
  93. + /*
  94. + * Change effective uid while opening .rhosts. If root and
  95. + * reading an NFS mounted file system, can't read files that
  96. + * are protected read/write owner only.
  97. + */
  98. + uid = geteuid();
  99. + (void)seteuid(pwd->pw_uid);
  100. + hostf = fopen(pbuf, "re");
  101. + (void)seteuid(uid);
  102. +
  103. + if (hostf == NULL)
  104. + return (-1);
  105. + /*
  106. + * If not a regular file, or is owned by someone other than
  107. + * user or root or if writeable by anyone but the owner, quit.
  108. + */
  109. + cp = NULL;
  110. + if (lstat(pbuf, &sbuf) == -1)
  111. + cp = ".rhosts lstat failed";
  112. + else if (!S_ISREG(sbuf.st_mode))
  113. + cp = ".rhosts not regular file";
  114. + else if (fstat(fileno(hostf), &sbuf) == -1)
  115. + cp = ".rhosts fstat failed";
  116. + else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
  117. + cp = "bad .rhosts owner";
  118. + else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
  119. + cp = ".rhosts writable by other than owner";
  120. + /* If there were any problems, quit. */
  121. + if (cp) {
  122. + (void)fclose(hostf);
  123. + return (-1);
  124. + }
  125. + goto again;
  126. + }
  127. + return (-1);
  128. +}
  129. +
  130. +int
  131. +__ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen,
  132. + const char *luser, const char *ruser)
  133. +{
  134. + char *user, *p;
  135. + char *buf;
  136. + const char *auser, *ahost;
  137. + int hostok, userok;
  138. + char *rhost = (char *)-1;
  139. + char domain[HOST_NAME_MAX+1];
  140. + size_t buflen;
  141. +
  142. + getdomainname(domain, sizeof(domain));
  143. +
  144. + while ((buf = fgetln(hostf, &buflen))) {
  145. + p = buf;
  146. + if (*p == '#')
  147. + continue;
  148. + while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') {
  149. + if (!isprint((unsigned char)*p))
  150. + goto bail;
  151. + *p = isupper((unsigned char)*p) ?
  152. + tolower((unsigned char)*p) : *p;
  153. + p++;
  154. + }
  155. + if (p >= buf + buflen)
  156. + continue;
  157. + if (*p == ' ' || *p == '\t') {
  158. + *p++ = '\0';
  159. + while (p < buf + buflen && (*p == ' ' || *p == '\t'))
  160. + p++;
  161. + if (p >= buf + buflen)
  162. + continue;
  163. + user = p;
  164. + while (p < buf + buflen && *p != '\n' && *p != ' ' &&
  165. + *p != '\t') {
  166. + if (!isprint((unsigned char)*p))
  167. + goto bail;
  168. + p++;
  169. + }
  170. + } else
  171. + user = p;
  172. + *p = '\0';
  173. +
  174. + if (p == buf)
  175. + continue;
  176. +
  177. + auser = *user ? user : luser;
  178. + ahost = buf;
  179. +
  180. + if (strlen(ahost) > HOST_NAME_MAX)
  181. + continue;
  182. +
  183. + /*
  184. + * innetgr() must lookup a hostname (we do not attempt
  185. + * to change the semantics so that netgroups may have
  186. + * #.#.#.# addresses in the list.)
  187. + */
  188. + if (ahost[0] == '+')
  189. + switch (ahost[1]) {
  190. + case '\0':
  191. + hostok = 1;
  192. + break;
  193. + case '@':
  194. + if (rhost == (char *)-1)
  195. + rhost = __gethostloop(raddr, salen);
  196. + hostok = 0;
  197. + if (rhost)
  198. + hostok = innetgr(&ahost[2], rhost,
  199. + NULL, domain);
  200. + break;
  201. + default:
  202. + hostok = __icheckhost(raddr, salen, &ahost[1]);
  203. + break;
  204. + }
  205. + else if (ahost[0] == '-')
  206. + switch (ahost[1]) {
  207. + case '\0':
  208. + hostok = -1;
  209. + break;
  210. + case '@':
  211. + if (rhost == (char *)-1)
  212. + rhost = __gethostloop(raddr, salen);
  213. + hostok = 0;
  214. + if (rhost)
  215. + hostok = -innetgr(&ahost[2], rhost,
  216. + NULL, domain);
  217. + break;
  218. + default:
  219. + hostok = -__icheckhost(raddr, salen, &ahost[1]);
  220. + break;
  221. + }
  222. + else
  223. + hostok = __icheckhost(raddr, salen, ahost);
  224. +
  225. +
  226. + if (auser[0] == '+')
  227. + switch (auser[1]) {
  228. + case '\0':
  229. + userok = 1;
  230. + break;
  231. + case '@':
  232. + userok = innetgr(&auser[2], NULL, ruser,
  233. + domain);
  234. + break;
  235. + default:
  236. + userok = strcmp(ruser, &auser[1]) ? 0 : 1;
  237. + break;
  238. + }
  239. + else if (auser[0] == '-')
  240. + switch (auser[1]) {
  241. + case '\0':
  242. + userok = -1;
  243. + break;
  244. + case '@':
  245. + userok = -innetgr(&auser[2], NULL, ruser,
  246. + domain);
  247. + break;
  248. + default:
  249. + userok = strcmp(ruser, &auser[1]) ? 0 : -1;
  250. + break;
  251. + }
  252. + else
  253. + userok = strcmp(ruser, auser) ? 0 : 1;
  254. +
  255. + /* Check if one component did not match */
  256. + if (hostok == 0 || userok == 0)
  257. + continue;
  258. +
  259. + /* Check if we got a forbidden pair */
  260. + if (userok <= -1 || hostok <= -1)
  261. + return (-1);
  262. +
  263. + /* Check if we got a valid pair */
  264. + if (hostok >= 1 && userok >= 1)
  265. + return (0);
  266. + }
  267. +bail:
  268. + return (-1);
  269. +}
  270. +
  271. +/*
  272. + * Returns "true" if match, 0 if no match. If we do not find any
  273. + * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
  274. + */
  275. +static int
  276. +__icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost)
  277. +{
  278. + struct addrinfo hints, *res, *r;
  279. + char h1[NI_MAXHOST], h2[NI_MAXHOST];
  280. + int error;
  281. + const int niflags = NI_NUMERICHOST;
  282. +
  283. + h1[0] = '\0';
  284. + if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
  285. + niflags) != 0)
  286. + return (0);
  287. +
  288. + /* Resolve laddr into sockaddr */
  289. + memset(&hints, 0, sizeof(hints));
  290. + hints.ai_family = raddr->sa_family;
  291. + hints.ai_socktype = SOCK_DGRAM; /*dummy*/
  292. + res = NULL;
  293. + error = getaddrinfo(lhost, "0", &hints, &res);
  294. + if (error)
  295. + return (0);
  296. +
  297. + /*
  298. + * Try string comparisons between raddr and laddr.
  299. + */
  300. + for (r = res; r; r = r->ai_next) {
  301. + h2[0] = '\0';
  302. + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
  303. + NULL, 0, niflags) != 0)
  304. + continue;
  305. + if (strcmp(h1, h2) == 0) {
  306. + freeaddrinfo(res);
  307. + return (1);
  308. + }
  309. + }
  310. +
  311. + /* No match. */
  312. + freeaddrinfo(res);
  313. + return (0);
  314. +}
  315. +
  316. +/*
  317. + * Return the hostname associated with the supplied address.
  318. + * Do a reverse lookup as well for security. If a loop cannot
  319. + * be found, pack the result of inet_ntoa() into the string.
  320. + */
  321. +static char *
  322. +__gethostloop(struct sockaddr *raddr, socklen_t salen)
  323. +{
  324. + static char remotehost[NI_MAXHOST];
  325. + char h1[NI_MAXHOST], h2[NI_MAXHOST];
  326. + struct addrinfo hints, *res, *r;
  327. + int error;
  328. + const int niflags = NI_NUMERICHOST;
  329. +
  330. + h1[0] = remotehost[0] = '\0';
  331. + if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
  332. + NULL, 0, NI_NAMEREQD) != 0)
  333. + return (NULL);
  334. + if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
  335. + niflags) != 0)
  336. + return (NULL);
  337. +
  338. + /*
  339. + * Look up the name and check that the supplied
  340. + * address is in the list
  341. + */
  342. + memset(&hints, 0, sizeof(hints));
  343. + hints.ai_family = raddr->sa_family;
  344. + hints.ai_socktype = SOCK_DGRAM; /*dummy*/
  345. + hints.ai_flags = AI_CANONNAME;
  346. + res = NULL;
  347. + error = getaddrinfo(remotehost, "0", &hints, &res);
  348. + if (error)
  349. + return (NULL);
  350. +
  351. + for (r = res; r; r = r->ai_next) {
  352. + h2[0] = '\0';
  353. + if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
  354. + NULL, 0, niflags) != 0)
  355. + continue;
  356. + if (strcmp(h1, h2) == 0) {
  357. + freeaddrinfo(res);
  358. + return (remotehost);
  359. + }
  360. + }
  361. +
  362. + /*
  363. + * either the DNS adminstrator has made a configuration
  364. + * mistake, or someone has attempted to spoof us
  365. + */
  366. + freeaddrinfo(res);
  367. + return (NULL);
  368. +}
  369. +
  370. char *envinit[1] = { 0 };
  371. extern char **environ;
  372.  
  373. void
  374. doit(struct sockaddr *fromp)
  375. {
  376. - extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
  377. + //extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
  378. struct addrinfo hints, *res, *res0;
  379. int gaierror;
  380. struct passwd *pwd;
  381. @@ -382,12 +702,12 @@
  382. (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
  383. iruserok_sa(fromp, fromp->sa_len, pwd->pw_uid == 0,
  384. remuser, locuser) < 0)) {
  385. - if (__rcmd_errstr)
  386. + /*if (__rcmd_errstr)
  387. syslog(LOG_INFO|LOG_AUTH,
  388. "%s@%s as %s: permission denied (%s). cmd='%.80s'",
  389. remuser, hostname, locuser, __rcmd_errstr,
  390. cmdbuf);
  391. - else
  392. + else*/
  393. syslog(LOG_INFO|LOG_AUTH,
  394. "%s@%s as %s: permission denied. cmd='%.80s'",
  395. remuser, hostname, locuser, cmdbuf);
  396.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement