source: rtems-libbsd/freebsd-userspace/lib/libc/net/rcmd.c @ 028aaaf

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 028aaaf was 028aaaf, checked in by Joel Sherrill <joel.sherrill@…>, on 07/11/12 at 21:01:37

freebsd-userspace: All files in old libnetworking/libc now present

But they don't all compile. Multiple issues left to address.

  • Property mode set to 100644
File size: 18.7 KB
Line 
1#include "port_before.h"
2
3/*
4 * Copyright (c) 1983, 1993, 1994
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char sccsid[] = "@(#)rcmd.c      8.3 (Berkeley) 3/26/94";
34#endif /* LIBC_SCCS and not lint */
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include "namespace.h"
39#include <sys/param.h>
40#include <sys/socket.h>
41#include <sys/stat.h>
42
43#include <netinet/in.h>
44#include <arpa/inet.h>
45
46#include <signal.h>
47#include <fcntl.h>
48#include <netdb.h>
49#include <stdlib.h>
50#include <unistd.h>
51#include <pwd.h>
52#include <errno.h>
53#include <stdio.h>
54#include <ctype.h>
55#include <string.h>
56#include <rpc/rpc.h>
57#ifdef YP
58#include <rpcsvc/yp_prot.h>
59#include <rpcsvc/ypclnt.h>
60#endif
61#include <arpa/nameser.h>
62#include "un-namespace.h"
63
64extern int innetgr( const char *, const char *, const char *, const char * );
65
66#define max(a, b)       ((a > b) ? a : b)
67
68int __ivaliduser(FILE *, u_int32_t, const char *, const char *);
69int __ivaliduser_af(FILE *,const void *, const char *, const char *, int, int);
70int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, const char *,
71    const char *);
72static int __icheckhost(const struct sockaddr *, socklen_t, const char *);
73
74char paddr[NI_MAXHOST];
75
76int
77rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
78        char **ahost;
79        u_short rport;
80        const char *locuser, *remuser, *cmd;
81        int *fd2p;
82{
83        return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
84}
85
86int
87rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
88        char **ahost;
89        u_short rport;
90        const char *locuser, *remuser, *cmd;
91        int *fd2p;
92        int af;
93{
94        struct addrinfo hints, *res, *ai;
95        struct sockaddr_storage from;
96        fd_set reads;
97        sigset_t oldmask, newmask;
98        pid_t pid;
99        int s, aport, lport, timo, error;
100        char c, *p;
101        int refused, nres;
102        char num[8];
103        static char canonnamebuf[MAXDNAME];     /* is it proper here? */
104
105        /* call rcmdsh() with specified remote shell if appropriate. */
106        if (!issetugid() && (p = getenv("RSH"))) {
107                struct servent *sp = getservbyname("shell", "tcp");
108
109                if (sp && sp->s_port == rport)
110                        return (rcmdsh(ahost, rport, locuser, remuser,
111                            cmd, p));
112        }
113
114        /* use rsh(1) if non-root and remote port is shell. */
115        if (geteuid()) {
116                struct servent *sp = getservbyname("shell", "tcp");
117
118                if (sp && sp->s_port == rport)
119                        return (rcmdsh(ahost, rport, locuser, remuser,
120                            cmd, NULL));
121        }
122
123        pid = getpid();
124
125        memset(&hints, 0, sizeof(hints));
126        hints.ai_flags = AI_CANONNAME;
127        hints.ai_family = af;
128        hints.ai_socktype = SOCK_STREAM;
129        hints.ai_protocol = 0;
130        (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
131        error = getaddrinfo(*ahost, num, &hints, &res);
132        if (error) {
133                fprintf(stderr, "rcmd: getaddrinfo: %s\n",
134                        gai_strerror(error));
135                if (error == EAI_SYSTEM)
136                        fprintf(stderr, "rcmd: getaddrinfo: %s\n",
137                                strerror(errno));
138                return (-1);
139        }
140
141        if (res->ai_canonname
142         && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {
143                strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
144                *ahost = canonnamebuf;
145        }
146        nres = 0;
147        for (ai = res; ai; ai = ai->ai_next)
148                nres++;
149        ai = res;
150        refused = 0;
151        sigemptyset(&newmask);
152        sigaddset(&newmask, SIGURG);
153        _sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask);
154        for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
155                s = rresvport_af(&lport, ai->ai_family);
156                if (s < 0) {
157                        if (errno != EAGAIN && ai->ai_next) {
158                                ai = ai->ai_next;
159                                continue;
160                        }
161                        if (errno == EAGAIN)
162                                (void)fprintf(stderr,
163                                    "rcmd: socket: All ports in use\n");
164                        else
165                                (void)fprintf(stderr, "rcmd: socket: %s\n",
166                                    strerror(errno));
167                        freeaddrinfo(res);
168                        _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
169                            NULL);
170                        return (-1);
171                }
172                _fcntl(s, F_SETOWN, pid);
173                if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
174                        break;
175                (void)_close(s);
176                if (errno == EADDRINUSE) {
177                        lport--;
178                        continue;
179                }
180                if (errno == ECONNREFUSED)
181                        refused = 1;
182                if (ai->ai_next == NULL && (!refused || timo > 16)) {
183                        (void)fprintf(stderr, "%s: %s\n",
184                                      *ahost, strerror(errno));
185                        freeaddrinfo(res);
186                        _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
187                            NULL);
188                        return (-1);
189                }
190                if (nres > 1) {
191                        int oerrno = errno;
192
193                        getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
194                            sizeof(paddr), NULL, 0, NI_NUMERICHOST);
195                        (void)fprintf(stderr, "connect to address %s: ",
196                                      paddr);
197                        errno = oerrno;
198                        perror(0);
199                }
200                if ((ai = ai->ai_next) == NULL) {
201                        /* refused && timo <= 16 */
202                        struct timespec time_to_sleep, time_remaining;
203
204                        time_to_sleep.tv_sec = timo;
205                        time_to_sleep.tv_nsec = 0;
206                        (void)_nanosleep(&time_to_sleep, &time_remaining);
207                        timo *= 2;
208                        ai = res;
209                        refused = 0;
210                }
211                if (nres > 1) {
212                        getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
213                            sizeof(paddr), NULL, 0, NI_NUMERICHOST);
214                        fprintf(stderr, "Trying %s...\n", paddr);
215                }
216        }
217        lport--;
218        if (fd2p == 0) {
219                _write(s, "", 1);
220                lport = 0;
221        } else {
222                int s2 = rresvport_af(&lport, ai->ai_family), s3;
223                socklen_t len = ai->ai_addrlen;
224                int nfds;
225
226                if (s2 < 0)
227                        goto bad;
228                _listen(s2, 1);
229                (void)snprintf(num, sizeof(num), "%d", lport);
230                if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
231                        (void)fprintf(stderr,
232                            "rcmd: write (setting up stderr): %s\n",
233                            strerror(errno));
234                        (void)_close(s2);
235                        goto bad;
236                }
237                nfds = max(s, s2)+1;
238                if(nfds > FD_SETSIZE) {
239                        fprintf(stderr, "rcmd: too many files\n");
240                        (void)_close(s2);
241                        goto bad;
242                }
243again:
244                FD_ZERO(&reads);
245                FD_SET(s, &reads);
246                FD_SET(s2, &reads);
247                errno = 0;
248                if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
249                        if (errno != 0)
250                                (void)fprintf(stderr,
251                                    "rcmd: select (setting up stderr): %s\n",
252                                    strerror(errno));
253                        else
254                                (void)fprintf(stderr,
255                                "select: protocol failure in circuit setup\n");
256                        (void)_close(s2);
257                        goto bad;
258                }
259                s3 = _accept(s2, (struct sockaddr *)&from, &len);
260                switch (from.ss_family) {
261                case AF_INET:
262                        aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
263                        break;
264#ifdef INET6
265                case AF_INET6:
266                        aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
267                        break;
268#endif
269                default:
270                        aport = 0;      /* error */
271                        break;
272                }
273                /*
274                 * XXX careful for ftp bounce attacks. If discovered, shut them
275                 * down and check for the real auxiliary channel to connect.
276                 */
277                if (aport == 20) {
278                        _close(s3);
279                        goto again;
280                }
281                (void)_close(s2);
282                if (s3 < 0) {
283                        (void)fprintf(stderr,
284                            "rcmd: accept: %s\n", strerror(errno));
285                        lport = 0;
286                        goto bad;
287                }
288                *fd2p = s3;
289                if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
290                        (void)fprintf(stderr,
291                            "socket: protocol failure in circuit setup.\n");
292                        goto bad2;
293                }
294        }
295        (void)_write(s, locuser, strlen(locuser)+1);
296        (void)_write(s, remuser, strlen(remuser)+1);
297        (void)_write(s, cmd, strlen(cmd)+1);
298        if (_read(s, &c, 1) != 1) {
299                (void)fprintf(stderr,
300                    "rcmd: %s: %s\n", *ahost, strerror(errno));
301                goto bad2;
302        }
303        if (c != 0) {
304                while (_read(s, &c, 1) == 1) {
305                        (void)_write(STDERR_FILENO, &c, 1);
306                        if (c == '\n')
307                                break;
308                }
309                goto bad2;
310        }
311        _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
312        freeaddrinfo(res);
313        return (s);
314bad2:
315        if (lport)
316                (void)_close(*fd2p);
317bad:
318        (void)_close(s);
319        _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
320        freeaddrinfo(res);
321        return (-1);
322}
323
324int
325rresvport(port)
326        int *port;
327{
328        return rresvport_af(port, AF_INET);
329}
330
331int
332rresvport_af(alport, family)
333        int *alport, family;
334{
335        int s;
336        struct sockaddr_storage ss;
337        u_short *sport;
338
339        memset(&ss, 0, sizeof(ss));
340        ss.ss_family = family;
341        switch (family) {
342        case AF_INET:
343                ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in);
344                sport = &((struct sockaddr_in *)&ss)->sin_port;
345                ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
346                break;
347#ifdef INET6
348        case AF_INET6:
349                ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6);
350                sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
351                ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
352                break;
353#endif
354        default:
355                errno = EAFNOSUPPORT;
356                return -1;
357        }
358
359        s = _socket(ss.ss_family, SOCK_STREAM, 0);
360        if (s < 0)
361                return (-1);
362#if 0 /* compat_exact_traditional_rresvport_semantics */
363        sin.sin_port = htons((u_short)*alport);
364        if (_bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
365                return (s);
366        if (errno != EADDRINUSE) {
367                (void)_close(s);
368                return (-1);
369        }
370#endif
371        *sport = 0;
372        if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
373                (void)_close(s);
374                return (-1);
375        }
376        *alport = (int)ntohs(*sport);
377        return (s);
378}
379
380int     __check_rhosts_file = 1;
381char    *__rcmd_errstr;
382
383int
384ruserok(rhost, superuser, ruser, luser)
385        const char *rhost, *ruser, *luser;
386        int superuser;
387{
388        struct addrinfo hints, *res, *r;
389        int error;
390
391        memset(&hints, 0, sizeof(hints));
392        hints.ai_family = PF_UNSPEC;
393        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
394        error = getaddrinfo(rhost, "0", &hints, &res);
395        if (error)
396                return (-1);
397
398        for (r = res; r; r = r->ai_next) {
399                if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
400                    luser) == 0) {
401                        freeaddrinfo(res);
402                        return (0);
403                }
404        }
405        freeaddrinfo(res);
406        return (-1);
407}
408
409/*
410 * New .rhosts strategy: We are passed an ip address. We spin through
411 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
412 * has ip addresses, we don't have to trust a nameserver.  When it
413 * contains hostnames, we spin through the list of addresses the nameserver
414 * gives us and look for a match.
415 *
416 * Returns 0 if ok, -1 if not ok.
417 */
418int
419iruserok(raddr, superuser, ruser, luser)
420        unsigned long raddr;
421        int superuser;
422        const char *ruser, *luser;
423{
424        struct sockaddr_in sin;
425
426        memset(&sin, 0, sizeof(sin));
427        sin.sin_family = AF_INET;
428        sin.sin_len = sizeof(struct sockaddr_in);
429        memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
430        return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser,
431                ruser, luser);
432}
433
434/*
435 * AF independent extension of iruserok.
436 *
437 * Returns 0 if ok, -1 if not ok.
438 */
439int
440iruserok_sa(ra, rlen, superuser, ruser, luser)
441        const void *ra;
442        int rlen;
443        int superuser;
444        const char *ruser, *luser;
445{
446        char *cp;
447        struct stat sbuf;
448        struct passwd *pwd;
449        FILE *hostf;
450        uid_t uid;
451        int first;
452        char pbuf[MAXPATHLEN];
453        const struct sockaddr *raddr;
454        struct sockaddr_storage ss;
455
456        /* avoid alignment issue */
457        if (rlen > sizeof(ss))
458                return(-1);
459        memcpy(&ss, ra, rlen);
460        raddr = (struct sockaddr *)&ss;
461
462        first = 1;
463        hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
464again:
465        if (hostf) {
466                if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
467                        (void)fclose(hostf);
468                        return (0);
469                }
470                (void)fclose(hostf);
471        }
472        if (first == 1 && (__check_rhosts_file || superuser)) {
473                first = 0;
474                if ((pwd = getpwnam(luser)) == NULL)
475                        return (-1);
476                (void)strcpy(pbuf, pwd->pw_dir);
477                (void)strcat(pbuf, "/.rhosts");
478
479                /*
480                 * Change effective uid while opening .rhosts.  If root and
481                 * reading an NFS mounted file system, can't read files that
482                 * are protected read/write owner only.
483                 */
484                uid = geteuid();
485                (void)seteuid(pwd->pw_uid);
486                hostf = fopen(pbuf, "r");
487                (void)seteuid(uid);
488
489                if (hostf == NULL)
490                        return (-1);
491                /*
492                 * If not a regular file, or is owned by someone other than
493                 * user or root or if writeable by anyone but the owner, quit.
494                 */
495                cp = NULL;
496                if (lstat(pbuf, &sbuf) < 0)
497                        cp = ".rhosts lstat failed";
498                else if (!S_ISREG(sbuf.st_mode))
499                        cp = ".rhosts not regular file";
500                else if (_fstat(fileno(hostf), &sbuf) < 0)
501                        cp = ".rhosts fstat failed";
502                else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
503                        cp = "bad .rhosts owner";
504                else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
505                        cp = ".rhosts writeable by other than owner";
506                /* If there were any problems, quit. */
507                if (cp) {
508                        __rcmd_errstr = cp;
509                        (void)fclose(hostf);
510                        return (-1);
511                }
512                goto again;
513        }
514        return (-1);
515}
516
517/*
518 * XXX
519 * Don't make static, used by lpd(8).
520 *
521 * Returns 0 if ok, -1 if not ok.
522 */
523int
524__ivaliduser(hostf, raddr, luser, ruser)
525        FILE *hostf;
526        u_int32_t raddr;
527        const char *luser, *ruser;
528{
529        struct sockaddr_in sin;
530
531        memset(&sin, 0, sizeof(sin));
532        sin.sin_family = AF_INET;
533        sin.sin_len = sizeof(struct sockaddr_in);
534        memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
535        return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
536                luser, ruser);
537}
538
539/*
540 * Returns 0 if ok, -1 if not ok.
541 *
542 * XXX obsolete API.
543 */
544int
545__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
546        FILE *hostf;
547        const void *raddr;
548        const char *luser, *ruser;
549        int af, len;
550{
551        struct sockaddr *sa = NULL;
552        struct sockaddr_in *sin = NULL;
553#ifdef INET6
554        struct sockaddr_in6 *sin6 = NULL;
555#endif
556        struct sockaddr_storage ss;
557
558        memset(&ss, 0, sizeof(ss));
559        switch (af) {
560        case AF_INET:
561                if (len != sizeof(sin->sin_addr))
562                        return -1;
563                sin = (struct sockaddr_in *)&ss;
564                sin->sin_family = AF_INET;
565                sin->sin_len = sizeof(struct sockaddr_in);
566                memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
567                break;
568#ifdef INET6
569        case AF_INET6:
570                if (len != sizeof(sin6->sin6_addr))
571                        return -1;
572                /* you will lose scope info */
573                sin6 = (struct sockaddr_in6 *)&ss;
574                sin6->sin6_family = AF_INET6;
575                sin6->sin6_len = sizeof(struct sockaddr_in6);
576                memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
577                break;
578#endif
579        default:
580                return -1;
581        }
582
583        sa = (struct sockaddr *)&ss;
584        return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
585}
586
587int
588__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
589        FILE *hostf;
590        const struct sockaddr *raddr;
591        socklen_t salen;
592        const char *luser, *ruser;
593{
594        char *user, *p;
595        int ch;
596        char buf[MAXHOSTNAMELEN + 128];         /* host + login */
597        char hname[MAXHOSTNAMELEN];
598        /* Presumed guilty until proven innocent. */
599        int userok = 0, hostok = 0;
600#ifdef YP
601        char *ypdomain;
602
603        if (yp_get_default_domain(&ypdomain))
604                ypdomain = NULL;
605#else
606#define ypdomain NULL
607#endif
608        /* We need to get the damn hostname back for netgroup matching. */
609        if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0,
610                        NI_NAMEREQD) != 0)
611                hname[0] = '\0';
612
613        while (fgets(buf, sizeof(buf), hostf)) {
614                p = buf;
615                /* Skip lines that are too long. */
616                if (strchr(p, '\n') == NULL) {
617                        while ((ch = getc(hostf)) != '\n' && ch != EOF);
618                        continue;
619                }
620                if (*p == '\n' || *p == '#') {
621                        /* comment... */
622                        continue;
623                }
624                while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
625                        *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p;
626                        p++;
627                }
628                if (*p == ' ' || *p == '\t') {
629                        *p++ = '\0';
630                        while (*p == ' ' || *p == '\t')
631                                p++;
632                        user = p;
633                        while (*p != '\n' && *p != ' ' &&
634                            *p != '\t' && *p != '\0')
635                                p++;
636                } else
637                        user = p;
638                *p = '\0';
639                /*
640                 * Do +/- and +@/-@ checking. This looks really nasty,
641                 * but it matches SunOS's behavior so far as I can tell.
642                 */
643                switch(buf[0]) {
644                case '+':
645                        if (!buf[1]) {     /* '+' matches all hosts */
646                                hostok = 1;
647                                break;
648                        }
649                        if (buf[1] == '@')  /* match a host by netgroup */
650                                hostok = hname[0] != '\0' &&
651                                    innetgr(&buf[2], hname, NULL, ypdomain);
652                        else            /* match a host by addr */
653                                hostok = __icheckhost(raddr, salen,
654                                                      (char *)&buf[1]);
655                        break;
656                case '-':     /* reject '-' hosts and all their users */
657                        if (buf[1] == '@') {
658                                if (hname[0] == '\0' ||
659                                    innetgr(&buf[2], hname, NULL, ypdomain))
660                                        return(-1);
661                        } else {
662                                if (__icheckhost(raddr, salen,
663                                                 (char *)&buf[1]))
664                                        return(-1);
665                        }
666                        break;
667                default:  /* if no '+' or '-', do a simple match */
668                        hostok = __icheckhost(raddr, salen, buf);
669                        break;
670                }
671                switch(*user) {
672                case '+':
673                        if (!*(user+1)) {      /* '+' matches all users */
674                                userok = 1;
675                                break;
676                        }
677                        if (*(user+1) == '@')  /* match a user by netgroup */
678                                userok = innetgr(user+2, NULL, ruser, ypdomain);
679                        else       /* match a user by direct specification */
680                                userok = !(strcmp(ruser, user+1));
681                        break;
682                case '-':               /* if we matched a hostname, */
683                        if (hostok) {   /* check for user field rejections */
684                                if (!*(user+1))
685                                        return(-1);
686                                if (*(user+1) == '@') {
687                                        if (innetgr(user+2, NULL,
688                                                        ruser, ypdomain))
689                                                return(-1);
690                                } else {
691                                        if (!strcmp(ruser, user+1))
692                                                return(-1);
693                                }
694                        }
695                        break;
696                default:        /* no rejections: try to match the user */
697                        if (hostok)
698                                userok = !(strcmp(ruser,*user ? user : luser));
699                        break;
700                }
701                if (hostok && userok)
702                        return(0);
703        }
704        return (-1);
705}
706
707/*
708 * Returns "true" if match, 0 if no match.
709 */
710static int
711__icheckhost(raddr, salen, lhost)
712        const struct sockaddr *raddr;
713        socklen_t salen;
714        const char *lhost;
715{
716        struct sockaddr_in sin;
717        struct sockaddr_in6 *sin6;
718        struct addrinfo hints, *res, *r;
719        int error;
720        char h1[NI_MAXHOST], h2[NI_MAXHOST];
721
722        if (raddr->sa_family == AF_INET6) {
723                sin6 = (struct sockaddr_in6 *)raddr;
724                if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
725                        memset(&sin, 0, sizeof(sin));
726                        sin.sin_family = AF_INET;
727                        sin.sin_len = sizeof(struct sockaddr_in);
728                        memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
729                               sizeof(sin.sin_addr));
730                        raddr = (struct sockaddr *)&sin;
731                        salen = sin.sin_len;
732                }
733        }
734
735        h1[0] = '\0';
736        if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
737                        NI_NUMERICHOST) != 0)
738                return (0);
739
740        /* Resolve laddr into sockaddr */
741        memset(&hints, 0, sizeof(hints));
742        hints.ai_family = raddr->sa_family;
743        hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/
744        res = NULL;
745        error = getaddrinfo(lhost, "0", &hints, &res);
746        if (error)
747                return (0);
748
749        for (r = res; r ; r = r->ai_next) {
750                h2[0] = '\0';
751                if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
752                                NULL, 0, NI_NUMERICHOST) != 0)
753                        continue;
754                if (strcmp(h1, h2) == 0) {
755                        freeaddrinfo(res);
756                        return (1);
757                }
758        }
759
760        /* No match. */
761        freeaddrinfo(res);
762        return (0);
763}
Note: See TracBrowser for help on using the repository browser.