1 #include "FEATURE/uwin" 2 3 #if !_UWIN || _lib_rcmd 4 5 void _STUB_rcmd(){} 6 7 #else 8 9 /* 10 * Copyright (c) 1983 11 * The Regents of the University of California. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #if defined(LIBC_SCCS) && !defined(lint) 39 static char sccsid[] = "@(#)rcmd.c 5.17 (Berkeley) 6/27/88"; 40 #endif /* LIBC_SCCS and not lint */ 41 42 #include "rlib.h" 43 #include <pwd.h> 44 #include <sys/file.h> 45 #include <sys/signal.h> 46 #if 1 47 #define _PATH_HEQUIV "/etc/hosts.equiv" 48 #endif 49 #include <sys/stat.h> 50 51 #if NLS 52 #include "nl_types.h" 53 #endif 54 55 #ifdef YP 56 #include <rpcsvc/ypclnt.h> 57 extern void setnetgrent(const char *); 58 extern void endnetgrent(void); 59 extern int getnetgrent(char **, char **, char **); 60 static char *nisdomain = NULL; 61 static int _checknetgrouphost(const char *, const char *, int); 62 static int _checknetgroupuser(const char *, const char *); 63 #endif 64 65 #if defined(__EXPORT__) 66 #define extern __EXPORT__ 67 #endif 68 69 extern int rresvport(int *alport) 70 { 71 struct sockaddr_in sin; 72 int s; 73 74 sin.sin_family = AF_INET; 75 sin.sin_addr.s_addr = INADDR_ANY; 76 s = socket(AF_INET, SOCK_STREAM, 0); 77 if (s < 0) 78 return (-1); 79 for (;;) { 80 sin.sin_port = htons((u_short)*alport); 81 if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 82 return (s); 83 if (errno != EADDRINUSE) { 84 (void) close(s); 85 return (-1); 86 } 87 (*alport)--; 88 if (*alport == IPPORT_RESERVED/2) { 89 (void) close(s); 90 errno = EAGAIN; /* close */ 91 return (-1); 92 } 93 } 94 } 95 96 extern int rcmd(char **ahost, unsigned short rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p) 97 { 98 int s, timo = 1; 99 #ifdef F_SETOWN 100 pid_t pid; 101 #endif 102 #ifdef _POSIX_SOURCE 103 sigset_t set, oset; 104 #else 105 long oldmask; 106 #endif 107 struct sockaddr_in sin, from; 108 char c; 109 int lport = IPPORT_RESERVED - 1; 110 struct hostent *hp; 111 112 #if NLS 113 libc_nls_init(); 114 #endif 115 116 #ifdef F_SETOWN 117 pid = getpid(); 118 #endif 119 hp = gethostbyname(*ahost); 120 if (hp == 0) { 121 #if NLS 122 fprintf(stderr, "%s: %s\n", *ahost, 123 catgets(_libc_cat, HerrorListSet, 124 2, "unknown host")); 125 #else 126 fprintf(stderr, "%s: unknown host\n", *ahost); 127 #endif 128 return (-1); 129 } 130 *ahost = hp->h_name; 131 #ifdef SIGURG 132 #ifdef _POSIX_SOURCE 133 sigemptyset (&set); 134 sigaddset (&set, SIGURG); 135 sigprocmask (SIG_BLOCK, &set, &oset); 136 #else 137 oldmask = sigblock(sigmask(SIGURG)); 138 #endif 139 #endif 140 for (;;) { 141 s = rresvport(&lport); 142 if (s < 0) { 143 if (errno == EAGAIN) 144 #if NLS 145 fprintf(stderr, "socket: %s\n", 146 catgets(_libc_cat, NetMiscSet, 147 NetMiscAllPortsInUse, 148 "All ports in use")); 149 #else 150 fprintf(stderr, "socket: All ports in use\n"); 151 #endif 152 else 153 #if NLS 154 perror(catgets(_libc_cat, NetMiscSet, 155 NetMiscRcmdSocket, 156 "rcmd: socket")); 157 #else 158 perror("rcmd: socket"); 159 #endif 160 #ifdef SIGURG 161 #ifdef _POSIX_SOURCE 162 sigprocmask (SIG_SETMASK, &oset, 163 (sigset_t *)NULL); 164 #else 165 sigsetmask(oldmask); 166 #endif 167 #endif 168 return (-1); 169 } 170 #ifdef F_SETOWN 171 fcntl(s, F_SETOWN, pid); 172 #endif 173 sin.sin_family = hp->h_addrtype; 174 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); 175 sin.sin_port = rport; 176 if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 177 break; 178 (void) close(s); 179 if (errno == EADDRINUSE) { 180 lport--; 181 continue; 182 } 183 if (errno == ECONNREFUSED && timo <= 16) { 184 sleep(timo); 185 timo *= 2; 186 continue; 187 } 188 if (hp->h_addr_list[1] != NULL) { 189 int oerrno = errno; 190 191 fprintf(stderr, 192 #if NLS 193 "%s %s: ", catgets(_libc_cat, NetMiscSet, 194 NetMiscAllPortsInUse, 195 "connect to address"), 196 inet_ntoa(sin.sin_addr)); 197 198 #else 199 200 "connect to address %s: ", inet_ntoa(sin.sin_addr)); 201 #endif 202 errno = oerrno; 203 perror(0); 204 hp->h_addr_list++; 205 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, 206 hp->h_length); 207 208 #if NLS 209 fprintf(stderr, catgets(_libc_cat, NetMiscSet, 210 NetMiscTrying, 211 "Trying %s...\n"), 212 #else 213 fprintf(stderr, "Trying %s...\n", 214 #endif 215 inet_ntoa(sin.sin_addr)); 216 continue; 217 } 218 perror(hp->h_name); 219 #ifdef SIGURG 220 #ifdef _POSIX_SOURCE 221 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); 222 #else 223 sigsetmask(oldmask); 224 #endif 225 #endif 226 return (-1); 227 } 228 lport--; 229 if (fd2p == 0) { 230 write(s, "", 1); 231 lport = 0; 232 } else { 233 char num[8]; 234 int s2 = rresvport(&lport), s3; 235 int len = sizeof (from); 236 237 if (s2 < 0) 238 goto bad; 239 listen(s2, 1); 240 (void) snprintf(num, sizeof(num), "%d", lport); 241 if (write(s, num, strlen(num)+1) != strlen(num)+1) { 242 #if NLS 243 perror(catgets(_libc_cat, NetMiscSet, 244 NetMiscSettingUpStderr, 245 "write: setting up stderr")); 246 #else 247 perror("write: setting up stderr"); 248 #endif 249 (void) close(s2); 250 goto bad; 251 } 252 s3 = accept(s2, (struct sockaddr *)&from, &len); 253 (void) close(s2); 254 if (s3 < 0) { 255 #if NLS 256 perror(catgets(_libc_cat, NetMiscSet, 257 NetMiscAccept, 258 "accept")); 259 #else 260 perror("accept"); 261 #endif 262 lport = 0; 263 goto bad; 264 } 265 *fd2p = s3; 266 from.sin_port = ntohs((u_short)from.sin_port); 267 if (from.sin_family != AF_INET || 268 from.sin_port >= IPPORT_RESERVED) { 269 fprintf(stderr, 270 #if NLS 271 "%s\n", 272 catgets(_libc_cat, NetMiscSet, 273 NetMiscProtocolFailure, 274 "socket: protocol failure in circuit setup.")); 275 #else 276 "socket: protocol failure in circuit setup.\n"); 277 #endif 278 goto bad2; 279 } 280 } 281 (void) write(s, locuser, strlen(locuser)+1); 282 (void) write(s, remuser, strlen(remuser)+1); 283 (void) write(s, cmd, strlen(cmd)+1); 284 if (read(s, &c, 1) != 1) { 285 perror(*ahost); 286 goto bad2; 287 } 288 if (c != 0) { 289 while (read(s, &c, 1) == 1) { 290 (void) write(2, &c, 1); 291 if (c == '\n') 292 break; 293 } 294 goto bad2; 295 } 296 #ifdef SIGURG 297 #ifdef _POSIX_SOURCE 298 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); 299 #else 300 sigsetmask(oldmask); 301 #endif 302 #endif 303 return (s); 304 bad2: 305 if (lport) 306 (void) close(*fd2p); 307 bad: 308 (void) close(s); 309 #ifdef SIGURG 310 #ifdef _POSIX_SOURCE 311 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); 312 #else 313 sigsetmask(oldmask); 314 #endif 315 #endif 316 return (-1); 317 } 318 319 extern int ruserok(const char *rhost, int superuser, const char *ruser, const char *luser) 320 { 321 FILE *hostf; 322 char fhost[MAXHOSTNAMELEN]; 323 int first = 1; 324 register const char *sp; 325 register char *p; 326 int baselen = -1; 327 uid_t saveuid; 328 329 saveuid = geteuid(); 330 sp = rhost; 331 p = fhost; 332 while (*sp) { 333 if (*sp == '.') { 334 if (baselen == -1) 335 baselen = sp - rhost; 336 *p++ = *sp++; 337 } else { 338 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 339 } 340 } 341 *p = '\0'; 342 hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r"); 343 again: 344 if (hostf) { 345 if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 346 (void) fclose(hostf); 347 seteuid(saveuid); 348 return(0); 349 } 350 (void) fclose(hostf); 351 } 352 if (first == 1) { 353 struct stat sbuf; 354 struct passwd *pwd; 355 char pbuf[MAXPATHLEN]; 356 357 first = 0; 358 if ((pwd = getpwnam(luser)) == NULL) 359 return(-1); 360 (void)strcpy(pbuf, pwd->pw_dir); 361 (void)strcat(pbuf, "/.rhosts"); 362 (void)seteuid(pwd->pw_uid); 363 if ((hostf = fopen(pbuf, "r")) == NULL) { 364 seteuid(saveuid); 365 return(-1); 366 } 367 (void)fstat(fileno(hostf), &sbuf); 368 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 369 fclose(hostf); 370 seteuid(saveuid); 371 return(-1); 372 } 373 goto again; 374 } 375 seteuid(saveuid); 376 return (-1); 377 } 378 379 int 380 _validuser(FILE *hostf, const char *rhost, const char *luser, 381 const char *ruser, int baselen) 382 { 383 char *user; 384 char ahost[MAXHOSTNAMELEN]; 385 register char *p; 386 int hostvalid = 0; 387 int uservalid = 0; 388 389 while (fgets(ahost, sizeof (ahost), hostf)) { 390 /* We need to get rid of all comments. */ 391 p = strchr (ahost, '#'); 392 if (p) *p = '\0'; 393 p = ahost; 394 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 395 *p = isupper(*p) ? tolower(*p) : *p; 396 p++; 397 } 398 if (*p == ' ' || *p == '\t') { 399 *p++ = '\0'; 400 while (*p == ' ' || *p == '\t') 401 p++; 402 user = p; 403 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 404 p++; 405 } else 406 user = p; 407 *p = '\0'; 408 /* Adding new authentication -Nilendu */ 409 410 /* enable all host for + entry */ 411 if ('+' == ahost[0] && '\0' == ahost[1] ) 412 hostvalid = 1; 413 414 /* enable all user for + entry */ 415 if ('+' == user[0] && '\0' == user[1] ) 416 uservalid = 1; 417 418 /* disable all host for - entry */ 419 if ('-' == ahost[0] && '\0' == ahost[1] ) 420 hostvalid = 0; 421 422 /* disable all user for - entry */ 423 if ('-' == user[0] && '\0' == user[1] ) 424 uservalid = 0; 425 426 427 #ifdef YP 428 /* disable host from -hostname entry */ 429 if ('-' == ahost[0] && '@' != ahost[1] 430 && _checkhost(rhost, &ahost[1], baselen)) 431 return -1; 432 /* disable host from -@netgroup entry for host */ 433 if ('-' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2] 434 && _checknetgrouphost(rhost, &ahost[2], baselen)) 435 return -1; 436 /* disable user from -user entry */ 437 if ('\0' != *user && user[0] == '-' && user[1] != '@' 438 && !strcmp(&user[1], ruser)) 439 return -1; 440 /* disable user from -@netgroup entry for user */ 441 if ('\0' != *user && user[0] == '-' && user[1] == '@' 442 && user[2] != '\0' && _checknetgroupuser(ruser, &user[2])) 443 return -1; 444 /* enable host from +@netgroup entry for host */ 445 if ('+' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2]) 446 hostvalid = _checknetgrouphost(rhost, &ahost[2], baselen); 447 else 448 hostvalid = _checkhost(rhost, ahost, baselen); 449 /* enable user from +@netgroup entry for user */ 450 if ('\0' != *user && user[0] == '+' 451 && user[1] == '@' && user[2] != '\0') 452 uservalid = _checknetgroupuser(ruser, &user[2]); 453 else 454 uservalid = !strcmp(ruser, *user ? user : luser); 455 456 if (hostvalid && uservalid) 457 return 0; 458 #else 459 hostvalid = hostvalid ? 1 : _checkhost(rhost, ahost, baselen); 460 uservalid = uservalid ? 1 : !stricmp(ruser,*user ? user : luser); 461 if (hostvalid && uservalid) 462 return 0; 463 464 #endif /* YP */ 465 hostvalid = uservalid = 0; 466 } 467 return (-1); 468 } 469 470 int 471 _checkhost(const char *rhost, const char *lhost, int len) 472 { 473 static char ldomain[MAXHOSTNAMELEN + 1]; 474 static char *domainp = NULL; 475 static int nodomain = 0; 476 register char *cp; 477 478 if (len == -1) 479 return(!strcmp(rhost, lhost)); 480 if (strncmp(rhost, lhost, len)) 481 return(0); 482 if (!strcmp(rhost, lhost)) 483 return(1); 484 if (*(lhost + len) != '\0') 485 return(0); 486 if (nodomain) 487 return(0); 488 if (!domainp) { 489 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 490 nodomain = 1; 491 return(0); 492 } 493 ldomain[MAXHOSTNAMELEN] = (char) 0; 494 if ((domainp = index(ldomain, '.')) == (char *)NULL) { 495 nodomain = 1; 496 return(0); 497 } 498 for (cp = ++domainp; *cp; ++cp) 499 if (isupper(*cp)) 500 *cp = tolower(*cp); 501 } 502 return(!strcmp(domainp, rhost + len +1)); 503 } 504 505 #ifdef YP 506 static int 507 _checknetgrouphost(const char *rhost, const char *netgr, int baselen) 508 { 509 char *host, *user, *domain; 510 int status; 511 512 if (NULL == nisdomain) 513 yp_get_default_domain(&nisdomain); 514 515 setnetgrent(netgr); 516 while (1) 517 { 518 while (1 == (status = getnetgrent(&host, &user, &domain)) 519 && NULL == host 520 && NULL != domain 521 && 0 != strcmp(domain, nisdomain)) 522 ; /* find valid host entry */ 523 524 if (0 == status || NULL == host) 525 { 526 endnetgrent(); 527 return 0; 528 } 529 530 if(1 == _checkhost(rhost, host, baselen)) 531 { 532 endnetgrent(); 533 return 1; 534 } 535 } 536 } 537 538 static int 539 _checknetgroupuser(const char *ruser, const char *netgr) 540 { 541 char *host, *user, *domain; 542 int status; 543 544 if (NULL == nisdomain) 545 yp_get_default_domain(&nisdomain); 546 547 setnetgrent(netgr); 548 while (1) 549 { 550 while (1 == (status = getnetgrent(&host, &user, &domain)) 551 && NULL == user 552 && NULL != domain 553 && 0 != strcmp(domain, nisdomain)) 554 ; /* find valid user entry */ 555 556 if (0 == status || NULL == user) 557 { 558 endnetgrent(); 559 return 0; 560 } 561 562 if(0 == strcmp(ruser, user)) 563 { 564 endnetgrent(); 565 return 1; 566 } 567 } 568 } 569 #endif /* YP */ 570 571 #endif 572