summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libc/net/rcmd.c149
1 files changed, 94 insertions, 55 deletions
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
index e0310031b0..3db3d86400 100644
--- a/src/lib/libc/net/rcmd.c
+++ b/src/lib/libc/net/rcmd.c
@@ -57,9 +57,11 @@ static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
57#include <stdio.h> 57#include <stdio.h>
58#include <ctype.h> 58#include <ctype.h>
59#include <string.h> 59#include <string.h>
60#include <syslog.h>
60 61
61int __ivaliduser __P((FILE *, u_long, const char *, const char *)); 62int __ivaliduser __P((FILE *, u_long, const char *, const char *));
62static int __icheckhost __P((u_long, const char *)); 63static int __icheckhost __P((u_int32_t, const char *));
64static char *__gethostloop __P((u_int32_t));
63 65
64int 66int
65rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 67rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
@@ -253,7 +255,7 @@ ruserok(rhost, superuser, ruser, luser)
253 char **ap; 255 char **ap;
254 int i; 256 int i;
255#define MAXADDRS 35 257#define MAXADDRS 35
256 u_long addrs[MAXADDRS + 1]; 258 u_int32_t addrs[MAXADDRS + 1];
257 259
258 if ((hp = gethostbyname(rhost)) == NULL) 260 if ((hp = gethostbyname(rhost)) == NULL)
259 return (-1); 261 return (-1);
@@ -262,7 +264,7 @@ ruserok(rhost, superuser, ruser, luser)
262 addrs[i] = 0; 264 addrs[i] = 0;
263 265
264 for (i = 0; i < MAXADDRS && addrs[i]; i++) 266 for (i = 0; i < MAXADDRS && addrs[i]; i++)
265 if (iruserok(addrs[i], superuser, ruser, luser) == 0) 267 if (iruserok((u_long)addrs[i], superuser, ruser, luser) == 0)
266 return (0); 268 return (0);
267 return (-1); 269 return (-1);
268} 270}
@@ -352,9 +354,9 @@ again:
352 * Returns 0 if ok, -1 if not ok. 354 * Returns 0 if ok, -1 if not ok.
353 */ 355 */
354int 356int
355__ivaliduser(hostf, raddr, luser, ruser) 357__ivaliduser(hostf, raddrl, luser, ruser)
356 FILE *hostf; 358 FILE *hostf;
357 u_long raddr; 359 u_long raddrl;
358 const char *luser, *ruser; 360 const char *luser, *ruser;
359{ 361{
360 register char *user, *p; 362 register char *user, *p;
@@ -362,9 +364,9 @@ __ivaliduser(hostf, raddr, luser, ruser)
362 char buf[MAXHOSTNAMELEN + 128]; /* host + login */ 364 char buf[MAXHOSTNAMELEN + 128]; /* host + login */
363 const char *auser, *ahost; 365 const char *auser, *ahost;
364 int hostok, userok; 366 int hostok, userok;
365 char rhost[MAXHOSTNAMELEN]; 367 char *rhost = (char *)-1;
366 struct hostent *hp;
367 char domain[MAXHOSTNAMELEN]; 368 char domain[MAXHOSTNAMELEN];
369 u_int32_t raddr = (u_int32_t)raddrl;
368 370
369 getdomainname(domain, sizeof(domain)); 371 getdomainname(domain, sizeof(domain));
370 372
@@ -372,7 +374,8 @@ __ivaliduser(hostf, raddr, luser, ruser)
372 p = buf; 374 p = buf;
373 /* Skip lines that are too long. */ 375 /* Skip lines that are too long. */
374 if (strchr(p, '\n') == NULL) { 376 if (strchr(p, '\n') == NULL) {
375 while ((ch = getc(hostf)) != '\n' && ch != EOF); 377 while ((ch = getc(hostf)) != '\n' && ch != EOF)
378 ;
376 continue; 379 continue;
377 } 380 }
378 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 381 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
@@ -397,25 +400,24 @@ __ivaliduser(hostf, raddr, luser, ruser)
397 auser = *user ? user : luser; 400 auser = *user ? user : luser;
398 ahost = buf; 401 ahost = buf;
399 402
400 if ((hp = gethostbyaddr((char *) &raddr, 403 /*
401 sizeof(raddr), AF_INET)) == NULL) { 404 * innetgr() must lookup a hostname (we do not attempt
402 abort(); 405 * to change the semantics so that netgroups may have
403 return -1; 406 * #.#.#.# addresses in the list.)
404 } 407 */
405 (void) strncpy(rhost, hp->h_name, sizeof(rhost));
406 rhost[sizeof(rhost) - 1] = '\0';
407
408 if (ahost[0] == '+') 408 if (ahost[0] == '+')
409 switch (ahost[1]) { 409 switch (ahost[1]) {
410 case '\0': 410 case '\0':
411 hostok = 1; 411 hostok = 1;
412 break; 412 break;
413
414 case '@': 413 case '@':
415 hostok = innetgr(&ahost[2], rhost, NULL, 414 if (rhost == (char *)-1)
416 domain); 415 rhost = __gethostloop(raddr);
416 hostok = 0;
417 if (rhost)
418 hostok = innetgr(&ahost[2], rhost,
419 NULL, domain);
417 break; 420 break;
418
419 default: 421 default:
420 hostok = __icheckhost(raddr, &ahost[1]); 422 hostok = __icheckhost(raddr, &ahost[1]);
421 break; 423 break;
@@ -425,12 +427,14 @@ __ivaliduser(hostf, raddr, luser, ruser)
425 case '\0': 427 case '\0':
426 hostok = -1; 428 hostok = -1;
427 break; 429 break;
428
429 case '@': 430 case '@':
430 hostok = -innetgr(&ahost[2], rhost, NULL, 431 if (rhost == (char *)-1)
431 domain); 432 rhost = __gethostloop(raddr);
433 hostok = 0;
434 if (rhost)
435 hostok = -innetgr(&ahost[2], rhost,
436 NULL, domain);
432 break; 437 break;
433
434 default: 438 default:
435 hostok = -__icheckhost(raddr, &ahost[1]); 439 hostok = -__icheckhost(raddr, &ahost[1]);
436 break; 440 break;
@@ -444,14 +448,12 @@ __ivaliduser(hostf, raddr, luser, ruser)
444 case '\0': 448 case '\0':
445 userok = 1; 449 userok = 1;
446 break; 450 break;
447
448 case '@': 451 case '@':
449 userok = innetgr(&auser[2], NULL, ruser, 452 userok = innetgr(&auser[2], NULL, ruser,
450 domain); 453 domain);
451 break; 454 break;
452
453 default: 455 default:
454 userok = strcmp(ruser, &auser[1]) == 0; 456 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
455 break; 457 break;
456 } 458 }
457 else if (auser[0] == '-') 459 else if (auser[0] == '-')
@@ -459,59 +461,96 @@ __ivaliduser(hostf, raddr, luser, ruser)
459 case '\0': 461 case '\0':
460 userok = -1; 462 userok = -1;
461 break; 463 break;
462
463 case '@': 464 case '@':
464 userok = -innetgr(&auser[2], NULL, ruser, 465 userok = -innetgr(&auser[2], NULL, ruser,
465 domain); 466 domain);
466 break; 467 break;
467
468 default: 468 default:
469 userok = -(strcmp(ruser, &auser[1]) == 0); 469 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
470 break; 470 break;
471 } 471 }
472 else 472 else
473 userok = strcmp(ruser, auser) == 0; 473 userok = strcmp(ruser, auser) ? 0 : 1;
474 474
475 /* Check if one component did not match */ 475 /* Check if one component did not match */
476 if (hostok == 0 || userok == 0) 476 if (hostok == 0 || userok == 0)
477 continue; 477 continue;
478 478
479 /* Check if we got a forbidden pair */ 479 /* Check if we got a forbidden pair */
480 if (userok == -1 || hostok == -1) 480 if (userok <= -1 || hostok <= -1)
481 return -1; 481 return (-1);
482 482
483 /* Check if we got a valid pair */ 483 /* Check if we got a valid pair */
484 if (hostok == 1 && userok == 1) 484 if (hostok >= 1 && userok >= 1)
485 return 0; 485 return (0);
486 } 486 }
487 return -1; 487 return (-1);
488} 488}
489 489
490/* 490/*
491 * Returns "true" if match, 0 if no match. 491 * Returns "true" if match, 0 if no match. If we do not find any
492 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
492 */ 493 */
493static int 494static int
494__icheckhost(raddr, lhost) 495__icheckhost(raddr, lhost)
495 u_long raddr; 496 u_int32_t raddr;
496 const char *lhost; 497 const char *lhost;
497{ 498{
498 register struct hostent *hp; 499 register struct hostent *hp;
499 register u_long laddr;
500 register char **pp; 500 register char **pp;
501 struct in_addr in;
502
503 hp = gethostbyname(lhost);
504 if (hp != NULL) {
505 /* Spin through ip addresses. */
506 for (pp = hp->h_addr_list; *pp; ++pp)
507 if (!bcmp(&raddr, *pp, sizeof(raddr)))
508 return (1);
509 }
501 510
502 /* Try for raw ip address first. */ 511 in.s_addr = raddr;
503 if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1) 512 if (strcmp(lhost, inet_ntoa(in)) == 0)
504 return (raddr == laddr); 513 return (1);
505
506 /* Better be a hostname. */
507 if ((hp = gethostbyname(lhost)) == NULL)
508 return (0);
509
510 /* Spin through ip addresses. */
511 for (pp = hp->h_addr_list; *pp; ++pp)
512 if (!bcmp(&raddr, *pp, sizeof(u_long)))
513 return (1);
514
515 /* No match. */
516 return (0); 514 return (0);
517} 515}
516
517/*
518 * Return the hostname associated with the supplied address.
519 * Do a reverse lookup as well for security. If a loop cannot
520 * be found, pack the result of inet_ntoa() into the string.
521 */
522static char *
523__gethostloop(raddr)
524 u_int32_t raddr;
525{
526 static char remotehost[MAXHOSTNAMELEN];
527 struct hostent *hp;
528 struct in_addr in;
529
530 hp = gethostbyaddr((char *) &raddr, sizeof(raddr), AF_INET);
531 if (hp == NULL)
532 return (NULL);
533
534 /*
535 * Look up the name and check that the supplied
536 * address is in the list
537 */
538 strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
539 remotehost[sizeof(remotehost) - 1] = '\0';
540 hp = gethostbyname(remotehost);
541 if (hp == NULL)
542 return (NULL);
543
544 for (; hp->h_addr_list[0] != NULL; hp->h_addr_list++)
545 if (!bcmp(hp->h_addr_list[0], (caddr_t)&raddr, sizeof(raddr)))
546 return (remotehost);
547
548 /*
549 * either the DNS adminstrator has made a configuration
550 * mistake, or someone has attempted to spoof us
551 */
552 in.s_addr = raddr;
553 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
554 inet_ntoa(in), hp->h_name);
555 return (NULL);
556}