| 1 | /* |
| 2 | * Copyright (c) 1983 Regents of the University of California. |
| 3 | * All rights reserved. The Berkeley software License Agreement |
| 4 | * specifies the terms and conditions for redistribution. |
| 5 | */ |
| 6 | |
| 7 | #ifndef lint |
| 8 | static char sccsid[] = "@(#)rcmd.c 5.1 (Berkeley) %G%"; |
| 9 | #endif not lint |
| 10 | |
| 11 | #include <stdio.h> |
| 12 | #include <sys/types.h> |
| 13 | #include <sys/socket.h> |
| 14 | |
| 15 | #include <netinet/in.h> |
| 16 | |
| 17 | #include <netdb.h> |
| 18 | #include <errno.h> |
| 19 | |
| 20 | extern errno; |
| 21 | char *index(), *sprintf(); |
| 22 | |
| 23 | rcmd(ahost, rport, locuser, remuser, cmd, fd2p) |
| 24 | char **ahost; |
| 25 | int rport; |
| 26 | char *locuser, *remuser, *cmd; |
| 27 | int *fd2p; |
| 28 | { |
| 29 | int s, timo = 1; |
| 30 | struct sockaddr_in sin, sin2, from; |
| 31 | char c; |
| 32 | int lport = IPPORT_RESERVED - 1; |
| 33 | struct hostent *hp; |
| 34 | |
| 35 | hp = gethostbyname(*ahost); |
| 36 | if (hp == 0) { |
| 37 | fprintf(stderr, "%s: unknown host\n", *ahost); |
| 38 | return (-1); |
| 39 | } |
| 40 | *ahost = hp->h_name; |
| 41 | retry: |
| 42 | s = rresvport(&lport); |
| 43 | if (s < 0) |
| 44 | return (-1); |
| 45 | sin.sin_family = hp->h_addrtype; |
| 46 | bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); |
| 47 | sin.sin_port = rport; |
| 48 | if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { |
| 49 | (void) close(s); |
| 50 | if (errno == EADDRINUSE) { |
| 51 | lport--; |
| 52 | goto retry; |
| 53 | } |
| 54 | if (errno == ECONNREFUSED && timo <= 16) { |
| 55 | sleep(timo); |
| 56 | timo *= 2; |
| 57 | goto retry; |
| 58 | } |
| 59 | perror(hp->h_name); |
| 60 | return (-1); |
| 61 | } |
| 62 | lport--; |
| 63 | if (fd2p == 0) { |
| 64 | write(s, "", 1); |
| 65 | lport = 0; |
| 66 | } else { |
| 67 | char num[8]; |
| 68 | int s2 = rresvport(&lport), s3; |
| 69 | int len = sizeof (from); |
| 70 | |
| 71 | if (s2 < 0) |
| 72 | goto bad; |
| 73 | listen(s2, 1); |
| 74 | (void) sprintf(num, "%d", lport); |
| 75 | if (write(s, num, strlen(num)+1) != strlen(num)+1) { |
| 76 | perror("write: setting up stderr"); |
| 77 | (void) close(s2); |
| 78 | goto bad; |
| 79 | } |
| 80 | s3 = accept(s2, &from, &len, 0); |
| 81 | (void) close(s2); |
| 82 | if (s3 < 0) { |
| 83 | perror("accept"); |
| 84 | lport = 0; |
| 85 | goto bad; |
| 86 | } |
| 87 | *fd2p = s3; |
| 88 | from.sin_port = ntohs((u_short)from.sin_port); |
| 89 | if (from.sin_family != AF_INET || |
| 90 | from.sin_port >= IPPORT_RESERVED) { |
| 91 | fprintf(stderr, |
| 92 | "socket: protocol failure in circuit setup.\n"); |
| 93 | goto bad2; |
| 94 | } |
| 95 | } |
| 96 | (void) write(s, locuser, strlen(locuser)+1); |
| 97 | (void) write(s, remuser, strlen(remuser)+1); |
| 98 | (void) write(s, cmd, strlen(cmd)+1); |
| 99 | if (read(s, &c, 1) != 1) { |
| 100 | perror(*ahost); |
| 101 | goto bad2; |
| 102 | } |
| 103 | if (c != 0) { |
| 104 | while (read(s, &c, 1) == 1) { |
| 105 | (void) write(2, &c, 1); |
| 106 | if (c == '\n') |
| 107 | break; |
| 108 | } |
| 109 | goto bad2; |
| 110 | } |
| 111 | return (s); |
| 112 | bad2: |
| 113 | if (lport) |
| 114 | (void) close(*fd2p); |
| 115 | bad: |
| 116 | (void) close(s); |
| 117 | return (-1); |
| 118 | } |
| 119 | |
| 120 | rresvport(alport) |
| 121 | int *alport; |
| 122 | { |
| 123 | struct sockaddr_in sin; |
| 124 | int s; |
| 125 | |
| 126 | sin.sin_family = AF_INET; |
| 127 | sin.sin_addr.s_addr = 0; |
| 128 | s = socket(AF_INET, SOCK_STREAM, 0, 0); |
| 129 | if (s < 0) |
| 130 | return (-1); |
| 131 | for (;;) { |
| 132 | sin.sin_port = htons((u_short)*alport); |
| 133 | if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) |
| 134 | return (s); |
| 135 | if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { |
| 136 | perror("socket"); |
| 137 | (void) close(s); |
| 138 | return (-1); |
| 139 | } |
| 140 | (*alport)--; |
| 141 | if (*alport == IPPORT_RESERVED/2) { |
| 142 | fprintf(stderr, "socket: All ports in use\n"); |
| 143 | (void) close(s); |
| 144 | return (-1); |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | ruserok(rhost, superuser, ruser, luser) |
| 150 | char *rhost; |
| 151 | int superuser; |
| 152 | char *ruser, *luser; |
| 153 | { |
| 154 | FILE *hostf; |
| 155 | char ahost[32]; |
| 156 | int first = 1; |
| 157 | |
| 158 | hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); |
| 159 | again: |
| 160 | if (hostf) { |
| 161 | while (fgets(ahost, sizeof (ahost), hostf)) { |
| 162 | register char *p; |
| 163 | char *user; |
| 164 | |
| 165 | p = ahost; |
| 166 | while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') |
| 167 | p++; |
| 168 | if (*p == ' ' || *p == '\t') { |
| 169 | *p++ = '\0'; |
| 170 | while (*p == ' ' || *p == '\t') |
| 171 | p++; |
| 172 | user = p; |
| 173 | while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') |
| 174 | p++; |
| 175 | } else |
| 176 | user = p; |
| 177 | *p = '\0'; |
| 178 | if (!strcmp(rhost, ahost) && |
| 179 | !strcmp(ruser, *user ? user : luser)) { |
| 180 | (void) fclose(hostf); |
| 181 | return (0); |
| 182 | } |
| 183 | } |
| 184 | (void) fclose(hostf); |
| 185 | } |
| 186 | if (first == 1) { |
| 187 | first = 0; |
| 188 | hostf = fopen(".rhosts", "r"); |
| 189 | goto again; |
| 190 | } |
| 191 | return (-1); |
| 192 | } |