OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [net/] [rcmd.c] - Blame information for rev 158

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*
2
 * Copyright (C) 1998 WIDE Project.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
/*
30
 * Copyright (c) 1983, 1993, 1994
31
 *      The Regents of the University of California.  All rights reserved.
32
 *
33
 * Redistribution and use in source and binary forms, with or without
34
 * modification, are permitted provided that the following conditions
35
 * are met:
36
 * 1. Redistributions of source code must retain the above copyright
37
 *    notice, this list of conditions and the following disclaimer.
38
 * 2. Redistributions in binary form must reproduce the above copyright
39
 *    notice, this list of conditions and the following disclaimer in the
40
 *    documentation and/or other materials provided with the distribution.
41
 * 4. Neither the name of the University nor the names of its contributors
42
 *    may be used to endorse or promote products derived from this software
43
 *    without specific prior written permission.
44
 *
45
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55
 * SUCH DAMAGE.
56
 */
57
 
58
#if defined(LIBC_SCCS) && !defined(lint)
59
static char sccsid[] = "@(#)rcmd.c      8.3 (Berkeley) 3/26/94";
60
#endif /* LIBC_SCCS and not lint */
61
 
62
#include <sys/param.h>
63
#include <sys/poll.h>
64
#include <sys/socket.h>
65
#include <sys/stat.h>
66
 
67
#include <netinet/in.h>
68
#include <arpa/inet.h>
69
 
70
#include <alloca.h>
71
#include <signal.h>
72
#include <fcntl.h>
73
#include <netdb.h>
74
#include <unistd.h>
75
#include <pwd.h>
76
#include <errno.h>
77
#include <stdio.h>
78
#include <stdio_ext.h>
79
#include <ctype.h>
80
#include <string.h>
81
#include <libintl.h>
82
#include <stdlib.h>
83
#include <wchar.h>
84
#include <sys/uio.h>
85
 
86
#include "local.h"
87
 
88
 
89
int __ivaliduser (FILE *, u_int32_t, const char *, const char *);
90
static int __validuser2_sa (FILE *, struct sockaddr *, size_t,
91
                            const char *, const char *, const char *);
92
static int ruserok2_sa (struct sockaddr *ra, size_t ralen,
93
                        int superuser, const char *ruser,
94
                        const char *luser, const char *rhost);
95
static int ruserok_sa (struct sockaddr *ra, size_t ralen,
96
                        int superuser, const char *ruser,
97
                        const char *luser);
98
int iruserok_af (const void *raddr, int superuser, const char *ruser,
99
                 const char *luser, sa_family_t af);
100
int iruserok (u_int32_t raddr, int superuser, const char *ruser,
101
              const char *luser);
102
 
103
libc_hidden_proto (iruserok_af)
104
 
105
libc_freeres_ptr(static char *ahostbuf);
106
 
107
int
108
rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
109
        char **ahost;
110
        u_short rport;
111
        const char *locuser, *remuser, *cmd;
112
        int *fd2p;
113
        sa_family_t af;
114
{
115
        char paddr[INET6_ADDRSTRLEN];
116
        struct addrinfo hints, *res, *ai;
117
        struct sockaddr_storage from;
118
        struct pollfd pfd[2];
119
        int32_t oldmask;
120
        pid_t pid;
121
        int s, lport, timo, error;
122
        char c;
123
        int refused;
124
        char num[8];
125
        ssize_t n;
126
 
127
        if (af != AF_INET && af != AF_INET6 && af != AF_UNSPEC)
128
          {
129
            __set_errno (EAFNOSUPPORT);
130
            return -1;
131
          }
132
 
133
        pid = __getpid();
134
 
135
        memset(&hints, '\0', sizeof(hints));
136
        hints.ai_flags = AI_CANONNAME;
137
        hints.ai_family = af;
138
        hints.ai_socktype = SOCK_STREAM;
139
        (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
140
        error = getaddrinfo(*ahost, num, &hints, &res);
141
        if (error) {
142
                if (error == EAI_NONAME && *ahost != NULL) {
143
                        if (_IO_fwide (stderr, 0) > 0)
144
                                __fwprintf(stderr, L"%s: Unknown host\n",
145
                                           *ahost);
146
                        else
147
                                fprintf(stderr, "%s: Unknown host\n", *ahost);
148
                } else {
149
                        if (_IO_fwide (stderr, 0) > 0)
150
                                __fwprintf(stderr, L"rcmd: getaddrinfo: %s\n",
151
                                           gai_strerror(error));
152
                        else
153
                                fprintf(stderr, "rcmd: getaddrinfo: %s\n",
154
                                        gai_strerror(error));
155
                }
156
                return (-1);
157
        }
158
 
159
        pfd[0].events = POLLIN;
160
        pfd[1].events = POLLIN;
161
 
162
        if (res->ai_canonname){
163
                free (ahostbuf);
164
                ahostbuf = strdup (res->ai_canonname);
165
                if (ahostbuf == NULL) {
166
                        if (_IO_fwide (stderr, 0) > 0)
167
                                __fwprintf(stderr, L"%s",
168
                                           _("rcmd: Cannot allocate memory\n"));
169
                        else
170
                                fputs(_("rcmd: Cannot allocate memory\n"),
171
                                      stderr);
172
                        return (-1);
173
                }
174
                *ahost = ahostbuf;
175
        } else
176
                *ahost = NULL;
177
        ai = res;
178
        refused = 0;
179
        oldmask = __sigblock(sigmask(SIGURG));
180
        for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
181
                char errbuf[200];
182
 
183
                s = rresvport_af(&lport, ai->ai_family);
184
                if (s < 0) {
185
                        if (errno == EAGAIN) {
186
                                if (_IO_fwide (stderr, 0) > 0)
187
                                        __fwprintf(stderr, L"%s",
188
                                                   _("rcmd: socket: All ports in use\n"));
189
                                else
190
                                        fputs(_("rcmd: socket: All ports in use\n"),
191
                                              stderr);
192
                        } else {
193
                                if (_IO_fwide (stderr, 0) > 0)
194
                                        __fwprintf(stderr,
195
                                                   L"rcmd: socket: %m\n");
196
                                else
197
                                        fprintf(stderr, "rcmd: socket: %m\n");
198
                        }
199
                        __sigsetmask(oldmask);
200
                        freeaddrinfo(res);
201
                        return -1;
202
                }
203
                __fcntl(s, F_SETOWN, pid);
204
                if (__connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
205
                        break;
206
                (void)__close(s);
207
                if (errno == EADDRINUSE) {
208
                        lport--;
209
                        continue;
210
                }
211
                if (errno == ECONNREFUSED)
212
                        refused = 1;
213
                if (ai->ai_next != NULL) {
214
                        int oerrno = errno;
215
                        char *buf = NULL;
216
 
217
                        getnameinfo(ai->ai_addr, ai->ai_addrlen,
218
                                    paddr, sizeof(paddr),
219
                                    NULL, 0,
220
                                    NI_NUMERICHOST);
221
 
222
                        if (__asprintf (&buf, _("connect to address %s: "),
223
                                        paddr) >= 0)
224
                          {
225
                            if (_IO_fwide (stderr, 0) > 0)
226
                              __fwprintf(stderr, L"%s", buf);
227
                            else
228
                              fputs (buf, stderr);
229
                            free (buf);
230
                          }
231
                        __set_errno (oerrno);
232
                        perror(0);
233
                        ai = ai->ai_next;
234
                        getnameinfo(ai->ai_addr, ai->ai_addrlen,
235
                                    paddr, sizeof(paddr),
236
                                    NULL, 0,
237
                                    NI_NUMERICHOST);
238
                        if (__asprintf (&buf, _("Trying %s...\n"), paddr) >= 0)
239
                          {
240
                            if (_IO_fwide (stderr, 0) > 0)
241
                              __fwprintf (stderr, L"%s", buf);
242
                            else
243
                              fputs (buf, stderr);
244
                            free (buf);
245
                          }
246
                        continue;
247
                }
248
                if (refused && timo <= 16) {
249
                        (void)sleep(timo);
250
                        timo *= 2;
251
                        ai = res;
252
                        refused = 0;
253
                        continue;
254
                }
255
                freeaddrinfo(res);
256
                if (_IO_fwide (stderr, 0) > 0)
257
                        (void)__fwprintf(stderr, L"%s: %s\n", *ahost,
258
                                         strerror_r(errno,
259
                                                      errbuf, sizeof (errbuf)));
260
                else
261
                        (void)fprintf(stderr, "%s: %s\n", *ahost,
262
                                      strerror_r(errno,
263
                                                   errbuf, sizeof (errbuf)));
264
                __sigsetmask(oldmask);
265
                return -1;
266
        }
267
        lport--;
268
        if (fd2p == 0) {
269
                __write(s, "", 1);
270
                lport = 0;
271
        } else {
272
                char num[8];
273
                int s2 = rresvport_af(&lport, ai->ai_family), s3;
274
                socklen_t len = ai->ai_addrlen;
275
 
276
                if (s2 < 0)
277
                        goto bad;
278
                listen(s2, 1);
279
                (void)snprintf(num, sizeof(num), "%d", lport);
280
                if (__write(s, num, strlen(num)+1) != (ssize_t)strlen(num)+1) {
281
                        char *buf = NULL;
282
 
283
                        if (__asprintf (&buf, _("\
284
rcmd: write (setting up stderr): %m\n")) >= 0)
285
                          {
286
                            if (_IO_fwide (stderr, 0) > 0)
287
                              __fwprintf(stderr, L"%s", buf);
288
                            else
289
                              fputs (buf, stderr);
290
                            free (buf);
291
                          }
292
                        (void)__close(s2);
293
                        goto bad;
294
                }
295
                pfd[0].fd = s;
296
                pfd[1].fd = s2;
297
                __set_errno (0);
298
                if (__poll (pfd, 2, -1) < 1 || (pfd[1].revents & POLLIN) == 0){
299
                        char *buf = NULL;
300
 
301
                        if ((errno != 0
302
                             && __asprintf(&buf, _("\
303
rcmd: poll (setting up stderr): %m\n")) >= 0)
304
                            || (errno == 0
305
                                && __asprintf(&buf, _("\
306
poll: protocol failure in circuit setup\n")) >= 0))
307
                          {
308
                            if (_IO_fwide (stderr, 0) > 0)
309
                              __fwprintf (stderr, L"%s", buf);
310
                            else
311
                              fputs (buf, stderr);
312
                            free  (buf);
313
                          }
314
                        (void)__close(s2);
315
                        goto bad;
316
                }
317
                s3 = TEMP_FAILURE_RETRY (accept(s2, (struct sockaddr *)&from,
318
                                                &len));
319
                switch (from.ss_family) {
320
                case AF_INET:
321
                        rport = ntohs(((struct sockaddr_in *)&from)->sin_port);
322
                        break;
323
                case AF_INET6:
324
                        rport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
325
                        break;
326
                default:
327
                        rport = 0;
328
                        break;
329
                }
330
                (void)__close(s2);
331
                if (s3 < 0) {
332
                        if (_IO_fwide (stderr, 0) > 0)
333
                                (void)__fwprintf(stderr,
334
                                                 L"rcmd: accept: %m\n");
335
                        else
336
                                (void)fprintf(stderr,
337
                                              "rcmd: accept: %m\n");
338
                        lport = 0;
339
                        goto bad;
340
                }
341
                *fd2p = s3;
342
 
343
                if (rport >= IPPORT_RESERVED || rport < IPPORT_RESERVED / 2){
344
                        char *buf = NULL;
345
 
346
                        if (__asprintf(&buf, _("\
347
socket: protocol failure in circuit setup\n")) >= 0)
348
                          {
349
                            if (_IO_fwide (stderr, 0) > 0)
350
                              __fwprintf (stderr, L"%s", buf);
351
                            else
352
                              fputs (buf, stderr);
353
                            free (buf);
354
                          }
355
                        goto bad2;
356
                }
357
        }
358
        struct iovec iov[3] =
359
          {
360
            [0] = { .iov_base = (void *) locuser,
361
                    .iov_len = strlen (locuser) + 1 },
362
            [1] = { .iov_base = (void *) remuser,
363
                    .iov_len = strlen (remuser) + 1 },
364
            [2] = { .iov_base = (void *) cmd,
365
                    .iov_len = strlen (cmd) + 1 }
366
          };
367
        (void) TEMP_FAILURE_RETRY (writev (s, iov, 3));
368
        n = TEMP_FAILURE_RETRY (read(s, &c, 1));
369
        if (n != 1) {
370
                char *buf = NULL;
371
 
372
                if ((n == 0
373
                     && asprintf(&buf, _("rcmd: %s: short read"),
374
                                   *ahost) >= 0)
375
                    || (n != 0
376
                        && asprintf(&buf, "rcmd: %s: %m\n", *ahost) >= 0))
377
                  {
378
                    if (_IO_fwide (stderr, 0) > 0)
379
                      __fwprintf (stderr, L"%s", buf);
380
                    else
381
                      fputs (buf, stderr);
382
                    free (buf);
383
                  }
384
                goto bad2;
385
        }
386
        if (c != 0) {
387
                while (__read(s, &c, 1) == 1) {
388
                        (void)__write(STDERR_FILENO, &c, 1);
389
                        if (c == '\n')
390
                                break;
391
                }
392
                goto bad2;
393
        }
394
        __sigsetmask(oldmask);
395
        freeaddrinfo(res);
396
        return s;
397
bad2:
398
        if (lport)
399
                (void)__close(*fd2p);
400
bad:
401
        (void)__close(s);
402
        __sigsetmask(oldmask);
403
        freeaddrinfo(res);
404
        return -1;
405
}
406
libc_hidden_def (rcmd_af)
407
 
408
int
409
rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
410
        char **ahost;
411
        u_short rport;
412
        const char *locuser, *remuser, *cmd;
413
        int *fd2p;
414
{
415
  return rcmd_af (ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
416
}
417
 
418
int
419
rresvport_af(alport, family)
420
        int *alport;
421
        sa_family_t family;
422
{
423
        struct sockaddr_storage ss;
424
        int s;
425
        size_t len;
426
        uint16_t *sport;
427
 
428
        switch(family){
429
        case AF_INET:
430
                len = sizeof(struct sockaddr_in);
431
                sport = &((struct sockaddr_in *)&ss)->sin_port;
432
                break;
433
        case AF_INET6:
434
                len = sizeof(struct sockaddr_in6);
435
                sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
436
                break;
437
        default:
438
                __set_errno (EAFNOSUPPORT);
439
                return -1;
440
        }
441
        s = __socket(family, SOCK_STREAM, 0);
442
        if (s < 0)
443
                return -1;
444
 
445
        memset (&ss, '\0', sizeof(ss));
446
#ifdef SALEN
447
        ss.__ss_len = len;
448
#endif
449
        ss.ss_family = family;
450
 
451
        /* Ignore invalid values.  */
452
        if (*alport < IPPORT_RESERVED / 2)
453
                *alport = IPPORT_RESERVED / 2;
454
        else if (*alport >= IPPORT_RESERVED)
455
                *alport = IPPORT_RESERVED - 1;
456
 
457
        int start = *alport;
458
        do {
459
                *sport = htons((uint16_t) *alport);
460
                if (__bind(s, (struct sockaddr *)&ss, len) >= 0)
461
                        return s;
462
                if (errno != EADDRINUSE) {
463
                        (void)__close(s);
464
                        return -1;
465
                }
466
                if ((*alport)-- == IPPORT_RESERVED/2)
467
                        *alport = IPPORT_RESERVED - 1;
468
        } while (*alport != start);
469
        (void)__close(s);
470
        __set_errno (EAGAIN);
471
        return -1;
472
}
473
libc_hidden_def (rresvport_af)
474
 
475
int
476
rresvport(alport)
477
        int *alport;
478
{
479
        return rresvport_af(alport, AF_INET);
480
}
481
 
482
int     __check_rhosts_file = 1;
483
char    *__rcmd_errstr;
484
 
485
int
486
ruserok_af(rhost, superuser, ruser, luser, af)
487
        const char *rhost, *ruser, *luser;
488
        int superuser;
489
        sa_family_t af;
490
{
491
        struct addrinfo hints, *res, *res0;
492
        int gai;
493
        int ret;
494
 
495
        memset (&hints, '\0', sizeof(hints));
496
        hints.ai_family = af;
497
        gai = getaddrinfo(rhost, NULL, &hints, &res0);
498
        if (gai)
499
                return -1;
500
        ret = -1;
501
        for (res=res0; res; res=res->ai_next)
502
                if (ruserok2_sa(res->ai_addr, res->ai_addrlen,
503
                                superuser, ruser, luser, rhost) == 0){
504
                        ret = 0;
505
                        break;
506
                }
507
        freeaddrinfo(res0);
508
        return (ret);
509
}
510
libc_hidden_def (ruserok_af)
511
 
512
int
513
ruserok(rhost, superuser, ruser, luser)
514
        const char *rhost, *ruser, *luser;
515
        int superuser;
516
{
517
        return ruserok_af(rhost, superuser, ruser, luser, AF_INET);
518
}
519
 
520
/* Extremely paranoid file open function. */
521
static FILE *
522
iruserfopen (const char *file, uid_t okuser)
523
{
524
  struct stat64 st;
525
  char *cp = NULL;
526
  FILE *res = NULL;
527
 
528
  /* If not a regular file, if owned by someone other than user or
529
     root, if writeable by anyone but the owner, or if hardlinked
530
     anywhere, quit.  */
531
  cp = NULL;
532
  if (__lxstat64 (_STAT_VER, file, &st))
533
    cp = _("lstat failed");
534
  else if (!S_ISREG (st.st_mode))
535
    cp = _("not regular file");
536
  else
537
    {
538
      res = fopen (file, "rc");
539
      if (!res)
540
        cp = _("cannot open");
541
      else if (__fxstat64 (_STAT_VER, fileno (res), &st) < 0)
542
        cp = _("fstat failed");
543
      else if (st.st_uid && st.st_uid != okuser)
544
        cp = _("bad owner");
545
      else if (st.st_mode & (S_IWGRP|S_IWOTH))
546
        cp = _("writeable by other than owner");
547
      else if (st.st_nlink > 1)
548
        cp = _("hard linked somewhere");
549
    }
550
 
551
  /* If there were any problems, quit.  */
552
  if (cp != NULL)
553
    {
554
      __rcmd_errstr = cp;
555
      if (res)
556
        fclose (res);
557
      return NULL;
558
    }
559
 
560
  /* No threads use this stream.  */
561
  __fsetlocking (res, FSETLOCKING_BYCALLER);
562
 
563
  return res;
564
}
565
 
566
/*
567
 * New .rhosts strategy: We are passed an ip address. We spin through
568
 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
569
 * has ip addresses, we don't have to trust a nameserver.  When it
570
 * contains hostnames, we spin through the list of addresses the nameserver
571
 * gives us and look for a match.
572
 *
573
 * Returns 0 if ok, -1 if not ok.
574
 */
575
static int
576
ruserok2_sa (ra, ralen, superuser, ruser, luser, rhost)
577
     struct sockaddr *ra;
578
     size_t ralen;
579
     int superuser;
580
     const char *ruser, *luser, *rhost;
581
{
582
  FILE *hostf = NULL;
583
  int isbad = -1;
584
 
585
  if (!superuser)
586
    hostf = iruserfopen (_PATH_HEQUIV, 0);
587
 
588
  if (hostf)
589
    {
590
      isbad = __validuser2_sa (hostf, ra, ralen, luser, ruser, rhost);
591
      fclose (hostf);
592
 
593
      if (!isbad)
594
        return 0;
595
    }
596
 
597
  if (__check_rhosts_file || superuser)
598
    {
599
      char *pbuf;
600
      struct passwd pwdbuf, *pwd;
601
      size_t dirlen;
602
      size_t buflen = __sysconf (_SC_GETPW_R_SIZE_MAX);
603
      char *buffer = __alloca (buflen);
604
      uid_t uid;
605
 
606
      if (__getpwnam_r (luser, &pwdbuf, buffer, buflen, &pwd) != 0
607
          || pwd == NULL)
608
        return -1;
609
 
610
      dirlen = strlen (pwd->pw_dir);
611
      pbuf = alloca (dirlen + sizeof "/.rhosts");
612
      __mempcpy (__mempcpy (pbuf, pwd->pw_dir, dirlen),
613
                 "/.rhosts", sizeof "/.rhosts");
614
 
615
       /* Change effective uid while reading .rhosts.  If root and
616
          reading an NFS mounted file system, can't read files that
617
          are protected read/write owner only.  */
618
       uid = __geteuid ();
619
       seteuid (pwd->pw_uid);
620
       hostf = iruserfopen (pbuf, pwd->pw_uid);
621
 
622
       if (hostf != NULL)
623
         {
624
           isbad = __validuser2_sa (hostf, ra, ralen, luser, ruser, rhost);
625
           fclose (hostf);
626
         }
627
 
628
       seteuid (uid);
629
       return isbad;
630
    }
631
  return -1;
632
}
633
/*
634
 * ruserok_sa() is now discussed on ipng, so
635
 * currently disabled for external use
636
 */
637
static int ruserok_sa(ra, ralen, superuser, ruser, luser)
638
     struct sockaddr *ra;
639
     size_t ralen;
640
     int superuser;
641
     const char *ruser, *luser;
642
{
643
  return ruserok2_sa(ra, ralen, superuser, ruser, luser, "-");
644
}
645
 
646
/* This is the exported version.  */
647
int
648
iruserok_af (raddr, superuser, ruser, luser, af)
649
     const void *raddr;
650
     int superuser;
651
     const char *ruser, *luser;
652
     sa_family_t af;
653
{
654
  struct sockaddr_storage ra;
655
  size_t ralen;
656
 
657
  memset (&ra, '\0', sizeof(ra));
658
  switch (af){
659
  case AF_INET:
660
    ((struct sockaddr_in *)&ra)->sin_family = AF_INET;
661
    memcpy (&(((struct sockaddr_in *)&ra)->sin_addr), raddr,
662
            sizeof(struct in_addr));
663
    ralen = sizeof(struct sockaddr_in);
664
    break;
665
  case AF_INET6:
666
    ((struct sockaddr_in6 *)&ra)->sin6_family = AF_INET6;
667
    memcpy (&(((struct sockaddr_in6 *)&ra)->sin6_addr), raddr,
668
            sizeof(struct in6_addr));
669
    ralen = sizeof(struct sockaddr_in6);
670
    break;
671
  default:
672
    return 0;
673
  }
674
  return ruserok_sa ((struct sockaddr *)&ra, ralen, superuser, ruser, luser);
675
}
676
libc_hidden_def (iruserok_af)
677
 
678
int
679
iruserok (raddr, superuser, ruser, luser)
680
     u_int32_t raddr;
681
     int superuser;
682
     const char *ruser, *luser;
683
{
684
  return iruserok_af (&raddr, superuser, ruser, luser, AF_INET);
685
}
686
 
687
/*
688
 * XXX
689
 * Don't make static, used by lpd(8).
690
 *
691
 * This function is not used anymore. It is only present because lpd(8)
692
 * calls it (!?!). We simply call __invaliduser2() with an illegal rhost
693
 * argument. This means that netgroups won't work in .rhost/hosts.equiv
694
 * files. If you want lpd to work with netgroups, fix lpd to use ruserok()
695
 * or PAM.
696
 * Returns 0 if ok, -1 if not ok.
697
 */
698
int
699
__ivaliduser(hostf, raddr, luser, ruser)
700
        FILE *hostf;
701
        u_int32_t raddr;
702
        const char *luser, *ruser;
703
{
704
        struct sockaddr_in ra;
705
        memset(&ra, '\0', sizeof(ra));
706
        ra.sin_family = AF_INET;
707
        ra.sin_addr.s_addr = raddr;
708
        return __validuser2_sa(hostf, (struct sockaddr *)&ra, sizeof(ra),
709
                               luser, ruser, "-");
710
}
711
 
712
 
713
/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */
714
static int
715
internal_function
716
__checkhost_sa (struct sockaddr *ra, size_t ralen, char *lhost,
717
                const char *rhost)
718
{
719
        struct addrinfo hints, *res0, *res;
720
        char raddr[INET6_ADDRSTRLEN];
721
        int match;
722
        int negate=1;    /* Multiply return with this to get -1 instead of 1 */
723
 
724
        /* Check nis netgroup.  */
725
        if (strncmp ("+@", lhost, 2) == 0)
726
                return innetgr (&lhost[2], rhost, NULL, NULL);
727
 
728
        if (strncmp ("-@", lhost, 2) == 0)
729
                return -innetgr (&lhost[2], rhost, NULL, NULL);
730
 
731
        /* -host */
732
        if (strncmp ("-", lhost,1) == 0) {
733
                negate = -1;
734
                lhost++;
735
        } else if (strcmp ("+",lhost) == 0) {
736
                return 1;                    /* asking for trouble, but ok.. */
737
        }
738
 
739
        /* Try for raw ip address first. */
740
        /* XXX */
741
        if (getnameinfo(ra, ralen,
742
                        raddr, sizeof(raddr), NULL, 0,
743
                        NI_NUMERICHOST) == 0
744
            && strcmp(raddr, lhost) == 0)
745
                return negate;
746
 
747
        /* Better be a hostname. */
748
        match = 0;
749
        memset(&hints, '\0', sizeof(hints));
750
        hints.ai_family = ra->sa_family;
751
        if (getaddrinfo(lhost, NULL, &hints, &res0) == 0){
752
                /* Spin through ip addresses. */
753
                for (res = res0; res; res = res->ai_next)
754
                  {
755
                    if (res->ai_family == ra->sa_family
756
                        && !memcmp(res->ai_addr, ra, res->ai_addrlen))
757
                      {
758
                        match = 1;
759
                        break;
760
                      }
761
                  }
762
                freeaddrinfo (res0);
763
        }
764
        return negate * match;
765
}
766
 
767
/* Returns 1 on positive match, 0 on no match, -1 on negative match.  */
768
static int
769
internal_function
770
__icheckuser (const char *luser, const char *ruser)
771
{
772
    /*
773
      luser is user entry from .rhosts/hosts.equiv file
774
      ruser is user id on remote host
775
      */
776
 
777
    /* [-+]@netgroup */
778
    if (strncmp ("+@", luser, 2) == 0)
779
        return innetgr (&luser[2], NULL, ruser, NULL);
780
 
781
    if (strncmp ("-@", luser,2) == 0)
782
        return -innetgr (&luser[2], NULL, ruser, NULL);
783
 
784
    /* -user */
785
    if (strncmp ("-", luser, 1) == 0)
786
        return -(strcmp (&luser[1], ruser) == 0);
787
 
788
    /* + */
789
    if (strcmp ("+", luser) == 0)
790
        return 1;
791
 
792
    /* simple string match */
793
    return strcmp (ruser, luser) == 0;
794
}
795
 
796
/*
797
 * Returns 1 for blank lines (or only comment lines) and 0 otherwise
798
 */
799
static int
800
__isempty (char *p)
801
{
802
    while (*p && isspace (*p)) {
803
        ++p;
804
    }
805
 
806
    return (*p == '\0' || *p == '#') ? 1 : 0 ;
807
}
808
 
809
/*
810
 * Returns 0 if positive match, -1 if _not_ ok.
811
 */
812
static int
813
__validuser2_sa(hostf, ra, ralen, luser, ruser, rhost)
814
        FILE *hostf;
815
        struct sockaddr *ra;
816
        size_t ralen;
817
        const char *luser, *ruser, *rhost;
818
{
819
    register const char *user;
820
    register char *p;
821
    int hcheck, ucheck;
822
    char *buf = NULL;
823
    size_t bufsize = 0;
824
    int retval = -1;
825
 
826
    while (__getline (&buf, &bufsize, hostf) > 0) {
827
        buf[bufsize - 1] = '\0'; /* Make sure it's terminated.  */
828
        p = buf;
829
 
830
        /* Skip empty or comment lines */
831
        if (__isempty (p)) {
832
            continue;
833
        }
834
 
835
        for (;*p && !isspace(*p); ++p) {
836
            *p = _tolower (*p);
837
        }
838
 
839
        /* Next we want to find the permitted name for the remote user.  */
840
        if (*p == ' ' || *p == '\t') {
841
            /* <nul> terminate hostname and skip spaces */
842
            for (*p++='\0'; *p && isspace (*p); ++p);
843
 
844
            user = p;                   /* this is the user's name */
845
            while (*p && !isspace (*p))
846
                ++p;                    /* find end of user's name */
847
        } else
848
            user = p;
849
 
850
        *p = '\0';              /* <nul> terminate username (+host?) */
851
 
852
        /* buf -> host(?) ; user -> username(?) */
853
 
854
        /* First check host part */
855
        hcheck = __checkhost_sa (ra, ralen, buf, rhost);
856
 
857
        if (hcheck < 0)
858
            break;
859
 
860
        if (hcheck) {
861
            /* Then check user part */
862
            if (! (*user))
863
                user = luser;
864
 
865
            ucheck = __icheckuser (user, ruser);
866
 
867
            /* Positive 'host user' match? */
868
            if (ucheck > 0) {
869
                retval = 0;
870
                break;
871
            }
872
 
873
            /* Negative 'host -user' match? */
874
            if (ucheck < 0)
875
                break;
876
 
877
            /* Neither, go on looking for match */
878
        }
879
    }
880
 
881
    if (buf != NULL)
882
      free (buf);
883
 
884
    return retval;
885
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.