]> git.saurik.com Git - apple/network_cmds.git/blob - rlogind.tproj/rlogind.c
a75acdb3182e06dd21b9246f6fc3fc8aa1997a33
[apple/network_cmds.git] / rlogind.tproj / rlogind.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*-
24 * Copyright (c) 1983, 1988, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
56 #ifndef lint
57 static char copyright[] =
58 "@(#) Copyright (c) 1983, 1988, 1989, 1993\n\
59 The Regents of the University of California. All rights reserved.\n";
60 #endif /* not lint */
61
62 #ifndef lint
63 static char sccsid[] = "@(#)rlogind.c 8.2 (Berkeley) 4/28/95";
64 #endif /* not lint */
65
66 /*
67 * remote login server:
68 * \0
69 * remuser\0
70 * locuser\0
71 * terminal_type/speed\0
72 * data
73 */
74
75 #define FD_SETSIZE 16 /* don't need many bits for select */
76 #include <sys/param.h>
77 #include <sys/stat.h>
78 #include <sys/ioctl.h>
79 #include <signal.h>
80 #ifdef __APPLE__
81 #include <sys/termios.h>
82 #else
83 #include <termios.h>
84 #endif
85
86 #include <sys/socket.h>
87 #include <netinet/in.h>
88 #include <netinet/in_systm.h>
89 #include <netinet/ip.h>
90 #include <arpa/inet.h>
91 #include <netdb.h>
92
93 #include <pwd.h>
94 #include <syslog.h>
95 #include <errno.h>
96 #include <stdio.h>
97 #include <unistd.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include "pathnames.h"
101
102 #ifndef TIOCPKT_WINDOW
103 #define TIOCPKT_WINDOW 0x80
104 #endif
105
106 #ifdef KERBEROS
107 #include <kerberosIV/des.h>
108 #include <kerberosIV/krb.h>
109 #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
110
111 AUTH_DAT *kdata;
112 KTEXT ticket;
113 u_char auth_buf[sizeof(AUTH_DAT)];
114 u_char tick_buf[sizeof(KTEXT_ST)];
115 Key_schedule schedule;
116 int doencrypt, retval, use_kerberos, vacuous;
117
118 #define ARGSTR "alnkvx"
119 #else
120 #define ARGSTR "aln"
121 #endif /* KERBEROS */
122
123 char *env[2];
124 #define NMAX 30
125 char lusername[NMAX+1], rusername[NMAX+1];
126 static char term[64] = "TERM=";
127 #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
128 int keepalive = 1;
129 int check_all = 0;
130
131 struct passwd *pwd;
132
133 void doit __P((int, struct sockaddr_in *));
134 int control __P((int, char *, int));
135 void protocol __P((int, int));
136 void cleanup __P((int));
137 void fatal __P((int, char *, int));
138 int do_rlogin __P((struct sockaddr_in *));
139 void getstr __P((char *, int, char *));
140 void setup_term __P((int));
141 int do_krb_login __P((struct sockaddr_in *));
142 void usage __P((void));
143 int local_domain __P((char *));
144 char *topdomain __P((char *));
145
146 int
147 main(argc, argv)
148 int argc;
149 char *argv[];
150 {
151 extern int __check_rhosts_file;
152 struct sockaddr_in from;
153 int ch, fromlen, on;
154
155 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
156
157 opterr = 0;
158 while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
159 switch (ch) {
160 case 'a':
161 check_all = 1;
162 break;
163 case 'l':
164 __check_rhosts_file = 0;
165 break;
166 case 'n':
167 keepalive = 0;
168 break;
169 #ifdef KERBEROS
170 case 'k':
171 use_kerberos = 1;
172 break;
173 case 'v':
174 vacuous = 1;
175 break;
176 #ifdef CRYPT
177 case 'x':
178 doencrypt = 1;
179 break;
180 #endif
181 #endif
182 case '?':
183 default:
184 usage();
185 break;
186 }
187 argc -= optind;
188 argv += optind;
189
190 #ifdef KERBEROS
191 if (use_kerberos && vacuous) {
192 usage();
193 fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
194 }
195 #endif
196 fromlen = sizeof (from);
197 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
198 syslog(LOG_ERR,"Can't get peer name of remote host: %m");
199 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
200 }
201 on = 1;
202 if (keepalive &&
203 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
204 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
205 on = IPTOS_LOWDELAY;
206 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
207 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
208 doit(0, &from);
209 }
210
211 int child;
212 int netf;
213 char line[MAXPATHLEN];
214 int confirmed;
215
216 struct winsize win = { 0, 0, 0, 0 };
217
218
219 void
220 doit(f, fromp)
221 int f;
222 struct sockaddr_in *fromp;
223 {
224 int master, pid, on = 1;
225 int authenticated = 0;
226 register struct hostent *hp;
227 char hostname[2 * MAXHOSTNAMELEN + 1];
228 char c;
229
230 alarm(60);
231 read(f, &c, 1);
232
233 if (c != 0)
234 exit(1);
235 #ifdef KERBEROS
236 if (vacuous)
237 fatal(f, "Remote host requires Kerberos authentication", 0);
238 #endif
239
240 alarm(0);
241 fromp->sin_port = ntohs((u_short)fromp->sin_port);
242 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr),
243 fromp->sin_family);
244 if (hp)
245 (void)strcpy(hostname, hp->h_name);
246 else
247 (void)strcpy(hostname, inet_ntoa(fromp->sin_addr));
248
249 #ifdef KERBEROS
250 if (use_kerberos) {
251 retval = do_krb_login(fromp);
252 if (retval == 0)
253 authenticated++;
254 else if (retval > 0)
255 fatal(f, krb_err_txt[retval], 0);
256 write(f, &c, 1);
257 confirmed = 1; /* we sent the null! */
258 } else
259 #endif
260 {
261 if (fromp->sin_family != AF_INET ||
262 fromp->sin_port >= IPPORT_RESERVED ||
263 fromp->sin_port < IPPORT_RESERVED/2) {
264 syslog(LOG_NOTICE, "Connection from %s on illegal port",
265 inet_ntoa(fromp->sin_addr));
266 fatal(f, "Permission denied", 0);
267 }
268 #ifdef IP_OPTIONS
269 {
270 u_char optbuf[BUFSIZ/3], *cp;
271 char lbuf[BUFSIZ], *lp;
272 int optsize = sizeof(optbuf), ipproto;
273 struct protoent *ip;
274
275 if ((ip = getprotobyname("ip")) != NULL)
276 ipproto = ip->p_proto;
277 else
278 ipproto = IPPROTO_IP;
279 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf,
280 &optsize) == 0 && optsize != 0) {
281 lp = lbuf;
282 for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
283 sprintf(lp, " %2.2x", *cp);
284 syslog(LOG_NOTICE,
285 "Connection received using IP options (ignored):%s",
286 lbuf);
287 if (setsockopt(0, ipproto, IP_OPTIONS,
288 (char *)NULL, optsize) != 0) {
289 syslog(LOG_ERR,
290 "setsockopt IP_OPTIONS NULL: %m");
291 exit(1);
292 }
293 }
294 }
295 #endif
296 if (do_rlogin(fromp) == 0)
297 authenticated++;
298 }
299 if (confirmed == 0) {
300 write(f, "", 1);
301 confirmed = 1; /* we sent the null! */
302 }
303 #ifdef KERBEROS
304 #ifdef CRYPT
305 if (doencrypt)
306 (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1);
307 #endif
308 #endif
309 netf = f;
310
311 pid = forkpty(&master, line, NULL, &win);
312 if (pid < 0) {
313 if (errno == ENOENT)
314 fatal(f, "Out of ptys", 0);
315 else
316 fatal(f, "Forkpty", 1);
317 }
318 if (pid == 0) {
319 if (f > 2) /* f should always be 0, but... */
320 (void) close(f);
321 setup_term(0);
322 if (authenticated) {
323 #ifdef KERBEROS
324 if (use_kerberos && (pwd->pw_uid == 0))
325 syslog(LOG_INFO|LOG_AUTH,
326 "ROOT Kerberos login from %s.%s@%s on %s\n",
327 kdata->pname, kdata->pinst, kdata->prealm,
328 hostname);
329 #endif
330
331 execle(_PATH_LOGIN, "login", "-p",
332 "-h", hostname, "-f", "--", lusername, NULL, env);
333 } else
334 execle(_PATH_LOGIN, "login", "-p",
335 "-h", hostname, "--", lusername, NULL, env);
336 fatal(STDERR_FILENO, _PATH_LOGIN, 1);
337 /*NOTREACHED*/
338 }
339 #ifdef CRYPT
340 #ifdef KERBEROS
341 /*
342 * If encrypted, don't turn on NBIO or the des read/write
343 * routines will croak.
344 */
345
346 if (!doencrypt)
347 #endif
348 #endif
349 ioctl(f, FIONBIO, &on);
350 ioctl(master, FIONBIO, &on);
351 ioctl(master, TIOCPKT, &on);
352 signal(SIGCHLD, cleanup);
353 protocol(f, master);
354 signal(SIGCHLD, SIG_IGN);
355 cleanup(0);
356 }
357
358 char magic[2] = { 0377, 0377 };
359 char oobdata[] = {TIOCPKT_WINDOW};
360
361 /*
362 * Handle a "control" request (signaled by magic being present)
363 * in the data stream. For now, we are only willing to handle
364 * window size changes.
365 */
366 int
367 control(pty, cp, n)
368 int pty;
369 char *cp;
370 int n;
371 {
372 struct winsize w;
373
374 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
375 return (0);
376 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
377 memmove(&w, cp+4, sizeof(w));
378 w.ws_row = ntohs(w.ws_row);
379 w.ws_col = ntohs(w.ws_col);
380 w.ws_xpixel = ntohs(w.ws_xpixel);
381 w.ws_ypixel = ntohs(w.ws_ypixel);
382 (void)ioctl(pty, TIOCSWINSZ, &w);
383 return (4+sizeof (w));
384 }
385
386 /*
387 * rlogin "protocol" machine.
388 */
389 void
390 protocol(f, p)
391 register int f, p;
392 {
393 char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
394 register pcc = 0, fcc = 0;
395 int cc, nfd, n;
396 char cntl;
397
398 /*
399 * Must ignore SIGTTOU, otherwise we'll stop
400 * when we try and set slave pty's window shape
401 * (our controlling tty is the master pty).
402 */
403 (void) signal(SIGTTOU, SIG_IGN);
404 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
405 if (f > p)
406 nfd = f + 1;
407 else
408 nfd = p + 1;
409 if (nfd > FD_SETSIZE) {
410 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
411 fatal(f, "internal error (select mask too small)", 0);
412 }
413 for (;;) {
414 fd_set ibits, obits, ebits, *omask;
415
416 FD_ZERO(&ebits);
417 FD_ZERO(&ibits);
418 FD_ZERO(&obits);
419 omask = (fd_set *)NULL;
420 if (fcc) {
421 FD_SET(p, &obits);
422 omask = &obits;
423 } else
424 FD_SET(f, &ibits);
425 if (pcc >= 0)
426 if (pcc) {
427 FD_SET(f, &obits);
428 omask = &obits;
429 } else
430 FD_SET(p, &ibits);
431 FD_SET(p, &ebits);
432 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
433 if (errno == EINTR)
434 continue;
435 fatal(f, "select", 1);
436 }
437 if (n == 0) {
438 /* shouldn't happen... */
439 sleep(5);
440 continue;
441 }
442 #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
443 if (FD_ISSET(p, &ebits)) {
444 cc = read(p, &cntl, 1);
445 if (cc == 1 && pkcontrol(cntl)) {
446 cntl |= oobdata[0];
447 send(f, &cntl, 1, MSG_OOB);
448 if (cntl & TIOCPKT_FLUSHWRITE) {
449 pcc = 0;
450 FD_CLR(p, &ibits);
451 }
452 }
453 }
454 if (FD_ISSET(f, &ibits)) {
455 #ifdef CRYPT
456 #ifdef KERBEROS
457 if (doencrypt)
458 fcc = des_read(f, fibuf, sizeof(fibuf));
459 else
460 #endif
461 #endif
462 fcc = read(f, fibuf, sizeof(fibuf));
463 if (fcc < 0 && errno == EWOULDBLOCK)
464 fcc = 0;
465 else {
466 register char *cp;
467 int left, n;
468
469 if (fcc <= 0)
470 break;
471 fbp = fibuf;
472
473 top:
474 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
475 if (cp[0] == magic[0] &&
476 cp[1] == magic[1]) {
477 left = fcc - (cp-fibuf);
478 n = control(p, cp, left);
479 if (n) {
480 left -= n;
481 if (left > 0)
482 bcopy(cp+n, cp, left);
483 fcc -= n;
484 goto top; /* n^2 */
485 }
486 }
487 FD_SET(p, &obits); /* try write */
488 }
489 }
490
491 if (FD_ISSET(p, &obits) && fcc > 0) {
492 cc = write(p, fbp, fcc);
493 if (cc > 0) {
494 fcc -= cc;
495 fbp += cc;
496 }
497 }
498
499 if (FD_ISSET(p, &ibits)) {
500 pcc = read(p, pibuf, sizeof (pibuf));
501 pbp = pibuf;
502 if (pcc < 0 && errno == EWOULDBLOCK)
503 pcc = 0;
504 else if (pcc <= 0)
505 break;
506 else if (pibuf[0] == 0) {
507 pbp++, pcc--;
508 #ifdef CRYPT
509 #ifdef KERBEROS
510 if (!doencrypt)
511 #endif
512 #endif
513 FD_SET(f, &obits); /* try write */
514 } else {
515 if (pkcontrol(pibuf[0])) {
516 pibuf[0] |= oobdata[0];
517 send(f, &pibuf[0], 1, MSG_OOB);
518 }
519 pcc = 0;
520 }
521 }
522 if ((FD_ISSET(f, &obits)) && pcc > 0) {
523 #ifdef CRYPT
524 #ifdef KERBEROS
525 if (doencrypt)
526 cc = des_write(f, pbp, pcc);
527 else
528 #endif
529 #endif
530 cc = write(f, pbp, pcc);
531 if (cc < 0 && errno == EWOULDBLOCK) {
532 /*
533 * This happens when we try write after read
534 * from p, but some old kernels balk at large
535 * writes even when select returns true.
536 */
537 if (!FD_ISSET(p, &ibits))
538 sleep(5);
539 continue;
540 }
541 if (cc > 0) {
542 pcc -= cc;
543 pbp += cc;
544 }
545 }
546 }
547 }
548
549 void
550 cleanup(signo)
551 int signo;
552 {
553 char *p;
554
555 p = line + sizeof(_PATH_DEV) - 1;
556 if (logout(p))
557 logwtmp(p, "", "");
558 (void)chmod(line, 0666);
559 (void)chown(line, 0, 0);
560 *p = 'p';
561 (void)chmod(line, 0666);
562 (void)chown(line, 0, 0);
563 shutdown(netf, 2);
564 exit(1);
565 }
566
567 void
568 fatal(f, msg, syserr)
569 int f;
570 char *msg;
571 int syserr;
572 {
573 int len;
574 char buf[BUFSIZ], *bp = buf;
575
576 /*
577 * Prepend binary one to message if we haven't sent
578 * the magic null as confirmation.
579 */
580 if (!confirmed)
581 *bp++ = '\01'; /* error indicator */
582 if (syserr)
583 len = sprintf(bp, "rlogind: %s: %s.\r\n",
584 msg, strerror(errno));
585 else
586 len = sprintf(bp, "rlogind: %s.\r\n", msg);
587 (void) write(f, buf, bp + len - buf);
588 exit(1);
589 }
590
591 int
592 do_rlogin(dest)
593 struct sockaddr_in *dest;
594 {
595 getstr(rusername, sizeof(rusername), "remuser too long");
596 getstr(lusername, sizeof(lusername), "locuser too long");
597 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
598
599 pwd = getpwnam(lusername);
600 if (pwd == NULL) {
601 syslog(LOG_ERR,
602 "rlogin denied for user %s: getpwnam() failed\n",
603 lusername);
604 return (-1);
605 }
606 if (pwd->pw_uid == 0 && strcmp("root", lusername))
607 {
608 syslog(LOG_ALERT,
609 "rlogin denied for non-root user %s with uid 0\n",
610 lusername);
611 return (-1);
612 }
613 return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername));
614 }
615
616 void
617 getstr(buf, cnt, errmsg)
618 char *buf;
619 int cnt;
620 char *errmsg;
621 {
622 char c;
623
624 do {
625 if (read(0, &c, 1) != 1)
626 exit(1);
627 if (--cnt < 0)
628 fatal(STDOUT_FILENO, errmsg, 0);
629 *buf++ = c;
630 } while (c != 0);
631 }
632
633 void
634 setup_term(fd)
635 int fd;
636 {
637 register char *cp = index(term+ENVSIZE, '/');
638 char *speed;
639 struct termios tt;
640
641 #ifndef notyet
642 tcgetattr(fd, &tt);
643 if (cp) {
644 *cp++ = '\0';
645 speed = cp;
646 cp = index(speed, '/');
647 if (cp)
648 *cp++ = '\0';
649 cfsetspeed(&tt, atoi(speed));
650 }
651
652 tt.c_iflag = TTYDEF_IFLAG;
653 tt.c_oflag = TTYDEF_OFLAG;
654 tt.c_lflag = TTYDEF_LFLAG;
655 tcsetattr(fd, TCSAFLUSH, &tt);
656 #else
657 if (cp) {
658 *cp++ = '\0';
659 speed = cp;
660 cp = index(speed, '/');
661 if (cp)
662 *cp++ = '\0';
663 tcgetattr(fd, &tt);
664 cfsetspeed(&tt, atoi(speed));
665 tcsetattr(fd, TCSAFLUSH, &tt);
666 }
667 #endif
668
669 env[0] = term;
670 env[1] = 0;
671 }
672
673 #ifdef KERBEROS
674 #define VERSION_SIZE 9
675
676 /*
677 * Do the remote kerberos login to the named host with the
678 * given inet address
679 *
680 * Return 0 on valid authorization
681 * Return -1 on valid authentication, no authorization
682 * Return >0 for error conditions
683 */
684 int
685 do_krb_login(dest)
686 struct sockaddr_in *dest;
687 {
688 int rc;
689 char instance[INST_SZ], version[VERSION_SIZE];
690 long authopts = 0L; /* !mutual */
691 struct sockaddr_in faddr;
692
693 kdata = (AUTH_DAT *) auth_buf;
694 ticket = (KTEXT) tick_buf;
695
696 instance[0] = '*';
697 instance[1] = '\0';
698
699 #ifdef CRYPT
700 if (doencrypt) {
701 rc = sizeof(faddr);
702 if (getsockname(0, (struct sockaddr *)&faddr, &rc))
703 return (-1);
704 authopts = KOPT_DO_MUTUAL;
705 rc = krb_recvauth(
706 authopts, 0,
707 ticket, "rcmd",
708 instance, dest, &faddr,
709 kdata, "", schedule, version);
710 des_set_key(kdata->session, schedule);
711
712 } else
713 #endif
714 rc = krb_recvauth(
715 authopts, 0,
716 ticket, "rcmd",
717 instance, dest, (struct sockaddr_in *) 0,
718 kdata, "", (bit_64 *) 0, version);
719
720 if (rc != KSUCCESS)
721 return (rc);
722
723 getstr(lusername, sizeof(lusername), "locuser");
724 /* get the "cmd" in the rcmd protocol */
725 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
726
727 pwd = getpwnam(lusername);
728 if (pwd == NULL)
729 return (-1);
730
731 /* returns nonzero for no access */
732 if (kuserok(kdata, lusername) != 0)
733 return (-1);
734
735 return (0);
736
737 }
738 #endif /* KERBEROS */
739
740 void
741 usage()
742 {
743 #ifdef KERBEROS
744 syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]");
745 #else
746 syslog(LOG_ERR, "usage: rlogind [-aln]");
747 #endif
748 }
749
750 /*
751 * Check whether host h is in our local domain,
752 * defined as sharing the last two components of the domain part,
753 * or the entire domain part if the local domain has only one component.
754 * If either name is unqualified (contains no '.'),
755 * assume that the host is local, as it will be
756 * interpreted as such.
757 */
758 int
759 local_domain(h)
760 char *h;
761 {
762 char localhost[MAXHOSTNAMELEN];
763 char *p1, *p2;
764
765 localhost[0] = 0;
766 (void) gethostname(localhost, sizeof(localhost));
767 p1 = topdomain(localhost);
768 p2 = topdomain(h);
769 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
770 return (1);
771 return (0);
772 }
773
774 char *
775 topdomain(h)
776 char *h;
777 {
778 register char *p;
779 char *maybe = NULL;
780 int dots = 0;
781
782 for (p = h + strlen(h); p >= h; p--) {
783 if (*p == '.') {
784 if (++dots == 2)
785 return (p);
786 maybe = p;
787 }
788 }
789 return (maybe);
790 }