1/* 2 * Copyright (c) 1983, 1993, 1994 3 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 *
| 1/* 2 * Copyright (c) 1983, 1993, 1994 3 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 *
|
33 * $FreeBSD: head/lib/libc/net/rcmd.c 56636 2000-01-26 14:13:41Z shin $
| 33 * $FreeBSD: head/lib/libc/net/rcmd.c 56698 2000-01-27 23:07:25Z jasone $
|
34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; 38#endif /* LIBC_SCCS and not lint */ 39 40#include <sys/param.h> 41#include <sys/socket.h> 42#include <sys/stat.h> 43 44#include <netinet/in.h> 45#include <arpa/inet.h> 46 47#include <signal.h> 48#include <fcntl.h> 49#include <netdb.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#ifdef YP 57#include <rpc/rpc.h> 58#include <rpcsvc/yp_prot.h> 59#include <rpcsvc/ypclnt.h> 60#endif 61 62/* wrapper for KAME-special getnameinfo() */ 63#ifndef NI_WITHSCOPEID 64#define NI_WITHSCOPEID 0 65#endif 66 67extern int innetgr __P(( const char *, const char *, const char *, const char * )); 68 69#define max(a, b) ((a > b) ? a : b) 70 71int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *)); 72static int __icheckhost __P((void *, char *, int, int)); 73 74char paddr[INET6_ADDRSTRLEN]; 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 long oldmask; 98 pid_t pid; 99 int s, aport, lport, timo, error; 100 char c; 101 int refused; 102 char num[8]; 103 104 pid = getpid(); 105 106 memset(&hints, 0, sizeof(hints)); 107 hints.ai_flags = AI_CANONNAME; 108 hints.ai_family = af; 109 hints.ai_socktype = SOCK_STREAM; 110 hints.ai_protocol = 0; 111 (void)snprintf(num, sizeof(num), "%d", ntohs(rport)); 112 error = getaddrinfo(*ahost, num, &hints, &res); 113 if (error) { 114 fprintf(stderr, "rcmd: getaddrinfo: %s\n", 115 gai_strerror(error)); 116 if (error == EAI_SYSTEM) 117 fprintf(stderr, "rcmd: getaddrinfo: %s\n", 118 strerror(errno)); 119 return (-1); 120 } 121 if (res->ai_canonname) 122 *ahost = res->ai_canonname; 123 ai = res; 124 refused = 0; 125 oldmask = sigblock(sigmask(SIGURG)); 126 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 127 s = rresvport_af(&lport, ai->ai_family); 128 if (s < 0) { 129 if (errno == EAGAIN) 130 (void)fprintf(stderr, 131 "rcmd: socket: All ports in use\n"); 132 else 133 (void)fprintf(stderr, "rcmd: socket: %s\n", 134 strerror(errno)); 135 sigsetmask(oldmask); 136 freeaddrinfo(res); 137 return (-1); 138 }
| 34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; 38#endif /* LIBC_SCCS and not lint */ 39 40#include <sys/param.h> 41#include <sys/socket.h> 42#include <sys/stat.h> 43 44#include <netinet/in.h> 45#include <arpa/inet.h> 46 47#include <signal.h> 48#include <fcntl.h> 49#include <netdb.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#ifdef YP 57#include <rpc/rpc.h> 58#include <rpcsvc/yp_prot.h> 59#include <rpcsvc/ypclnt.h> 60#endif 61 62/* wrapper for KAME-special getnameinfo() */ 63#ifndef NI_WITHSCOPEID 64#define NI_WITHSCOPEID 0 65#endif 66 67extern int innetgr __P(( const char *, const char *, const char *, const char * )); 68 69#define max(a, b) ((a > b) ? a : b) 70 71int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *)); 72static int __icheckhost __P((void *, char *, int, int)); 73 74char paddr[INET6_ADDRSTRLEN]; 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 long oldmask; 98 pid_t pid; 99 int s, aport, lport, timo, error; 100 char c; 101 int refused; 102 char num[8]; 103 104 pid = getpid(); 105 106 memset(&hints, 0, sizeof(hints)); 107 hints.ai_flags = AI_CANONNAME; 108 hints.ai_family = af; 109 hints.ai_socktype = SOCK_STREAM; 110 hints.ai_protocol = 0; 111 (void)snprintf(num, sizeof(num), "%d", ntohs(rport)); 112 error = getaddrinfo(*ahost, num, &hints, &res); 113 if (error) { 114 fprintf(stderr, "rcmd: getaddrinfo: %s\n", 115 gai_strerror(error)); 116 if (error == EAI_SYSTEM) 117 fprintf(stderr, "rcmd: getaddrinfo: %s\n", 118 strerror(errno)); 119 return (-1); 120 } 121 if (res->ai_canonname) 122 *ahost = res->ai_canonname; 123 ai = res; 124 refused = 0; 125 oldmask = sigblock(sigmask(SIGURG)); 126 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 127 s = rresvport_af(&lport, ai->ai_family); 128 if (s < 0) { 129 if (errno == EAGAIN) 130 (void)fprintf(stderr, 131 "rcmd: socket: All ports in use\n"); 132 else 133 (void)fprintf(stderr, "rcmd: socket: %s\n", 134 strerror(errno)); 135 sigsetmask(oldmask); 136 freeaddrinfo(res); 137 return (-1); 138 }
|
139 _libc_fcntl(s, F_SETOWN, pid);
| 139 _fcntl(s, F_SETOWN, pid);
|
140 if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0) 141 break;
| 140 if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0) 141 break;
|
142 (void)_libc_close(s);
| 142 (void)_close(s);
|
143 if (errno == EADDRINUSE) { 144 lport--; 145 continue; 146 } 147 if (errno == ECONNREFUSED) 148 refused = 1; 149 if (ai->ai_next != NULL) { 150 int oerrno = errno; 151 152 getnameinfo(ai->ai_addr, ai->ai_addrlen, 153 paddr, sizeof(paddr), 154 NULL, 0, 155 NI_NUMERICHOST|NI_WITHSCOPEID); 156 (void)fprintf(stderr, "connect to address %s: ", 157 paddr); 158 errno = oerrno; 159 perror(0); 160 ai = ai->ai_next; 161 getnameinfo(ai->ai_addr, ai->ai_addrlen, 162 paddr, sizeof(paddr), 163 NULL, 0, 164 NI_NUMERICHOST|NI_WITHSCOPEID); 165 fprintf(stderr, "Trying %s...\n", paddr); 166 continue; 167 } 168 if (refused && timo <= 16) {
| 143 if (errno == EADDRINUSE) { 144 lport--; 145 continue; 146 } 147 if (errno == ECONNREFUSED) 148 refused = 1; 149 if (ai->ai_next != NULL) { 150 int oerrno = errno; 151 152 getnameinfo(ai->ai_addr, ai->ai_addrlen, 153 paddr, sizeof(paddr), 154 NULL, 0, 155 NI_NUMERICHOST|NI_WITHSCOPEID); 156 (void)fprintf(stderr, "connect to address %s: ", 157 paddr); 158 errno = oerrno; 159 perror(0); 160 ai = ai->ai_next; 161 getnameinfo(ai->ai_addr, ai->ai_addrlen, 162 paddr, sizeof(paddr), 163 NULL, 0, 164 NI_NUMERICHOST|NI_WITHSCOPEID); 165 fprintf(stderr, "Trying %s...\n", paddr); 166 continue; 167 } 168 if (refused && timo <= 16) {
|
169 (void)_libc_sleep(timo);
| 169 struct timespec time_to_sleep, time_remaining; 170 171 time_to_sleep.tv_sec = timo; 172 time_to_sleep.tv_nsec = 0; 173 (void)_nanosleep(&time_to_sleep, &time_remaining); 174
|
170 timo *= 2; 171 ai = res; 172 refused = 0; 173 continue; 174 } 175 freeaddrinfo(res); 176 (void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno)); 177 sigsetmask(oldmask); 178 return (-1); 179 } 180 lport--; 181 if (fd2p == 0) {
| 175 timo *= 2; 176 ai = res; 177 refused = 0; 178 continue; 179 } 180 freeaddrinfo(res); 181 (void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno)); 182 sigsetmask(oldmask); 183 return (-1); 184 } 185 lport--; 186 if (fd2p == 0) {
|
182 _libc_write(s, "", 1);
| 187 _write(s, "", 1);
|
183 lport = 0; 184 } else { 185 char num[8]; 186 int s2 = rresvport_af(&lport, ai->ai_family), s3; 187 int len = ai->ai_addrlen; 188 int nfds; 189 190 if (s2 < 0) 191 goto bad; 192 listen(s2, 1); 193 (void)snprintf(num, sizeof(num), "%d", lport);
| 188 lport = 0; 189 } else { 190 char num[8]; 191 int s2 = rresvport_af(&lport, ai->ai_family), s3; 192 int len = ai->ai_addrlen; 193 int nfds; 194 195 if (s2 < 0) 196 goto bad; 197 listen(s2, 1); 198 (void)snprintf(num, sizeof(num), "%d", lport);
|
194 if (_libc_write(s, num, strlen(num)+1) != strlen(num)+1) {
| 199 if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
|
195 (void)fprintf(stderr, 196 "rcmd: write (setting up stderr): %s\n", 197 strerror(errno));
| 200 (void)fprintf(stderr, 201 "rcmd: write (setting up stderr): %s\n", 202 strerror(errno));
|
198 (void)_libc_close(s2);
| 203 (void)_close(s2);
|
199 goto bad; 200 } 201 nfds = max(s, s2)+1; 202 if(nfds > FD_SETSIZE) { 203 fprintf(stderr, "rcmd: too many files\n");
| 204 goto bad; 205 } 206 nfds = max(s, s2)+1; 207 if(nfds > FD_SETSIZE) { 208 fprintf(stderr, "rcmd: too many files\n");
|
204 (void)_libc_close(s2);
| 209 (void)_close(s2);
|
205 goto bad; 206 } 207again: 208 FD_ZERO(&reads); 209 FD_SET(s, &reads); 210 FD_SET(s2, &reads); 211 errno = 0; 212 if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){ 213 if (errno != 0) 214 (void)fprintf(stderr, 215 "rcmd: select (setting up stderr): %s\n", 216 strerror(errno)); 217 else 218 (void)fprintf(stderr, 219 "select: protocol failure in circuit setup\n");
| 210 goto bad; 211 } 212again: 213 FD_ZERO(&reads); 214 FD_SET(s, &reads); 215 FD_SET(s2, &reads); 216 errno = 0; 217 if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){ 218 if (errno != 0) 219 (void)fprintf(stderr, 220 "rcmd: select (setting up stderr): %s\n", 221 strerror(errno)); 222 else 223 (void)fprintf(stderr, 224 "select: protocol failure in circuit setup\n");
|
220 (void)_libc_close(s2);
| 225 (void)_close(s2);
|
221 goto bad; 222 } 223 s3 = accept(s2, (struct sockaddr *)&from, &len); 224 switch (from.ss_family) { 225 case AF_INET: 226 aport = ntohs(((struct sockaddr_in *)&from)->sin_port); 227 break; 228#ifdef INET6 229 case AF_INET6: 230 aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port); 231 break; 232#endif 233 default: 234 aport = 0; /* error */ 235 break; 236 } 237 /* 238 * XXX careful for ftp bounce attacks. If discovered, shut them 239 * down and check for the real auxiliary channel to connect. 240 */ 241 if (aport == 20) {
| 226 goto bad; 227 } 228 s3 = accept(s2, (struct sockaddr *)&from, &len); 229 switch (from.ss_family) { 230 case AF_INET: 231 aport = ntohs(((struct sockaddr_in *)&from)->sin_port); 232 break; 233#ifdef INET6 234 case AF_INET6: 235 aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port); 236 break; 237#endif 238 default: 239 aport = 0; /* error */ 240 break; 241 } 242 /* 243 * XXX careful for ftp bounce attacks. If discovered, shut them 244 * down and check for the real auxiliary channel to connect. 245 */ 246 if (aport == 20) {
|
242 _libc_close(s3);
| 247 _close(s3);
|
243 goto again; 244 }
| 248 goto again; 249 }
|
245 (void)_libc_close(s2);
| 250 (void)_close(s2);
|
246 if (s3 < 0) { 247 (void)fprintf(stderr, 248 "rcmd: accept: %s\n", strerror(errno)); 249 lport = 0; 250 goto bad; 251 } 252 *fd2p = s3; 253 if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) { 254 (void)fprintf(stderr, 255 "socket: protocol failure in circuit setup.\n"); 256 goto bad2; 257 } 258 }
| 251 if (s3 < 0) { 252 (void)fprintf(stderr, 253 "rcmd: accept: %s\n", strerror(errno)); 254 lport = 0; 255 goto bad; 256 } 257 *fd2p = s3; 258 if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) { 259 (void)fprintf(stderr, 260 "socket: protocol failure in circuit setup.\n"); 261 goto bad2; 262 } 263 }
|
259 (void)_libc_write(s, locuser, strlen(locuser)+1); 260 (void)_libc_write(s, remuser, strlen(remuser)+1); 261 (void)_libc_write(s, cmd, strlen(cmd)+1); 262 if (_libc_read(s, &c, 1) != 1) {
| 264 (void)_write(s, locuser, strlen(locuser)+1); 265 (void)_write(s, remuser, strlen(remuser)+1); 266 (void)_write(s, cmd, strlen(cmd)+1); 267 if (_read(s, &c, 1) != 1) {
|
263 (void)fprintf(stderr, 264 "rcmd: %s: %s\n", *ahost, strerror(errno)); 265 goto bad2; 266 } 267 if (c != 0) {
| 268 (void)fprintf(stderr, 269 "rcmd: %s: %s\n", *ahost, strerror(errno)); 270 goto bad2; 271 } 272 if (c != 0) {
|
268 while (_libc_read(s, &c, 1) == 1) { 269 (void)_libc_write(STDERR_FILENO, &c, 1);
| 273 while (_read(s, &c, 1) == 1) { 274 (void)_write(STDERR_FILENO, &c, 1);
|
270 if (c == '\n') 271 break; 272 } 273 goto bad2; 274 } 275 sigsetmask(oldmask); 276 freeaddrinfo(res); 277 return (s); 278bad2: 279 if (lport)
| 275 if (c == '\n') 276 break; 277 } 278 goto bad2; 279 } 280 sigsetmask(oldmask); 281 freeaddrinfo(res); 282 return (s); 283bad2: 284 if (lport)
|
280 (void)_libc_close(*fd2p);
| 285 (void)_close(*fd2p);
|
281bad:
| 286bad:
|
282 (void)_libc_close(s);
| 287 (void)_close(s);
|
283 sigsetmask(oldmask); 284 freeaddrinfo(res); 285 return (-1); 286} 287 288int 289rresvport(port) 290 int *port; 291{ 292 return rresvport_af(port, AF_INET); 293} 294 295int 296rresvport_af(alport, family) 297 int *alport, family; 298{ 299 int i, s, len, err; 300 struct sockaddr_storage ss; 301 u_short *sport; 302 303 memset(&ss, 0, sizeof(ss)); 304 ss.ss_family = family; 305 switch (family) { 306 case AF_INET: 307 ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in); 308 sport = &((struct sockaddr_in *)&ss)->sin_port; 309 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY; 310 break; 311#ifdef INET6 312 case AF_INET6: 313 ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6); 314 sport = &((struct sockaddr_in6 *)&ss)->sin6_port; 315 ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any; 316 break; 317#endif 318 default: 319 errno = EAFNOSUPPORT; 320 return -1; 321 } 322 323 s = socket(ss.ss_family, SOCK_STREAM, 0); 324 if (s < 0) 325 return (-1); 326#if 0 /* compat_exact_traditional_rresvport_semantics */ 327 sin.sin_port = htons((u_short)*alport); 328 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 329 return (s); 330 if (errno != EADDRINUSE) {
| 288 sigsetmask(oldmask); 289 freeaddrinfo(res); 290 return (-1); 291} 292 293int 294rresvport(port) 295 int *port; 296{ 297 return rresvport_af(port, AF_INET); 298} 299 300int 301rresvport_af(alport, family) 302 int *alport, family; 303{ 304 int i, s, len, err; 305 struct sockaddr_storage ss; 306 u_short *sport; 307 308 memset(&ss, 0, sizeof(ss)); 309 ss.ss_family = family; 310 switch (family) { 311 case AF_INET: 312 ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in); 313 sport = &((struct sockaddr_in *)&ss)->sin_port; 314 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY; 315 break; 316#ifdef INET6 317 case AF_INET6: 318 ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6); 319 sport = &((struct sockaddr_in6 *)&ss)->sin6_port; 320 ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any; 321 break; 322#endif 323 default: 324 errno = EAFNOSUPPORT; 325 return -1; 326 } 327 328 s = socket(ss.ss_family, SOCK_STREAM, 0); 329 if (s < 0) 330 return (-1); 331#if 0 /* compat_exact_traditional_rresvport_semantics */ 332 sin.sin_port = htons((u_short)*alport); 333 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 334 return (s); 335 if (errno != EADDRINUSE) {
|
331 (void)_libc_close(s);
| 336 (void)_close(s);
|
332 return (-1); 333 } 334#endif 335 *sport = 0; 336 if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
| 337 return (-1); 338 } 339#endif 340 *sport = 0; 341 if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
|
337 (void)_libc_close(s);
| 342 (void)_close(s);
|
338 return (-1); 339 } 340 *alport = (int)ntohs(*sport); 341 return (s); 342} 343 344int __check_rhosts_file = 1; 345char *__rcmd_errstr; 346 347int 348ruserok(rhost, superuser, ruser, luser) 349 const char *rhost, *ruser, *luser; 350 int superuser; 351{ 352 return ruserok_af(rhost, superuser, ruser, luser, AF_INET); 353} 354 355int 356ruserok_af(rhost, superuser, ruser, luser, af) 357 const char *rhost, *ruser, *luser; 358 int superuser, af; 359{ 360 struct hostent *hp; 361 union { 362 struct in_addr addr_in; 363 struct in6_addr addr_in6; 364 } addr; 365 char **ap; 366 int ret, h_error; 367 368 if ((hp = getipnodebyname(rhost, af, AI_DEFAULT, &h_error)) == NULL) 369 return (-1); 370 ret = -1; 371 for (ap = hp->h_addr_list; *ap; ++ap) { 372 bcopy(*ap, &addr, hp->h_length); 373 if (iruserok_af(&addr, superuser, ruser, luser, af) == 0) { 374 ret = 0; 375 break; 376 } 377 } 378 freehostent(hp); 379 return (ret); 380} 381 382/* 383 * New .rhosts strategy: We are passed an ip address. We spin through 384 * hosts.equiv and .rhosts looking for a match. When the .rhosts only 385 * has ip addresses, we don't have to trust a nameserver. When it 386 * contains hostnames, we spin through the list of addresses the nameserver 387 * gives us and look for a match. 388 * 389 * Returns 0 if ok, -1 if not ok. 390 */ 391int 392iruserok(raddr, superuser, ruser, luser) 393 unsigned long raddr; 394 int superuser; 395 const char *ruser, *luser; 396{ 397 return iruserok_af(&raddr, superuser, ruser, luser, AF_INET); 398} 399 400int 401iruserok_af(raddr, superuser, ruser, luser, af) 402 void *raddr; 403 int superuser; 404 const char *ruser, *luser; 405 int af; 406{ 407 register char *cp; 408 struct stat sbuf; 409 struct passwd *pwd; 410 FILE *hostf; 411 uid_t uid; 412 int first; 413 char pbuf[MAXPATHLEN]; 414 int len = 0; 415 416 switch (af) { 417 case AF_INET: 418 len = sizeof(struct in_addr); 419 break; 420#ifdef INET6 421 case AF_INET6: 422 len = sizeof(struct in6_addr); 423 break; 424#endif 425 } 426 427 first = 1; 428 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 429again: 430 if (hostf) { 431 if (__ivaliduser_af(hostf, raddr, luser, ruser, af, len) 432 == 0) { 433 (void)fclose(hostf); 434 return (0); 435 } 436 (void)fclose(hostf); 437 } 438 if (first == 1 && (__check_rhosts_file || superuser)) { 439 first = 0; 440 if ((pwd = getpwnam(luser)) == NULL) 441 return (-1); 442 (void)strcpy(pbuf, pwd->pw_dir); 443 (void)strcat(pbuf, "/.rhosts"); 444 445 /* 446 * Change effective uid while opening .rhosts. If root and 447 * reading an NFS mounted file system, can't read files that 448 * are protected read/write owner only. 449 */ 450 uid = geteuid(); 451 (void)seteuid(pwd->pw_uid); 452 hostf = fopen(pbuf, "r"); 453 (void)seteuid(uid); 454 455 if (hostf == NULL) 456 return (-1); 457 /* 458 * If not a regular file, or is owned by someone other than 459 * user or root or if writeable by anyone but the owner, quit. 460 */ 461 cp = NULL; 462 if (lstat(pbuf, &sbuf) < 0) 463 cp = ".rhosts lstat failed"; 464 else if (!S_ISREG(sbuf.st_mode)) 465 cp = ".rhosts not regular file"; 466 else if (fstat(fileno(hostf), &sbuf) < 0) 467 cp = ".rhosts fstat failed"; 468 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) 469 cp = "bad .rhosts owner"; 470 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) 471 cp = ".rhosts writeable by other than owner"; 472 /* If there were any problems, quit. */ 473 if (cp) { 474 __rcmd_errstr = cp; 475 (void)fclose(hostf); 476 return (-1); 477 } 478 goto again; 479 } 480 return (-1); 481} 482 483/* 484 * XXX 485 * Don't make static, used by lpd(8). 486 * 487 * Returns 0 if ok, -1 if not ok. 488 */ 489int 490__ivaliduser(hostf, raddr, luser, ruser) 491 FILE *hostf; 492 u_int32_t raddr; 493 const char *luser, *ruser; 494{ 495 return __ivaliduser_af(hostf, &raddr, luser, ruser, AF_INET, 496 sizeof(raddr)); 497} 498 499int 500__ivaliduser_af(hostf, raddr, luser, ruser, af, len) 501 FILE *hostf; 502 void *raddr; 503 const char *luser, *ruser; 504 int af, len; 505{ 506 register char *user, *p; 507 int ch; 508 char buf[MAXHOSTNAMELEN + 128]; /* host + login */ 509 char hname[MAXHOSTNAMELEN]; 510 struct hostent *hp; 511 /* Presumed guilty until proven innocent. */ 512 int userok = 0, hostok = 0; 513 int h_error; 514#ifdef YP 515 char *ypdomain; 516 517 if (yp_get_default_domain(&ypdomain)) 518 ypdomain = NULL; 519#else 520#define ypdomain NULL 521#endif 522 /* We need to get the damn hostname back for netgroup matching. */ 523 if ((hp = getipnodebyaddr((char *)raddr, len, af, &h_error)) == NULL) 524 return (-1); 525 strncpy(hname, hp->h_name, sizeof(hname)); 526 hname[sizeof(hname) - 1] = '\0'; 527 freehostent(hp); 528 529 while (fgets(buf, sizeof(buf), hostf)) { 530 p = buf; 531 /* Skip lines that are too long. */ 532 if (strchr(p, '\n') == NULL) { 533 while ((ch = getc(hostf)) != '\n' && ch != EOF); 534 continue; 535 } 536 if (*p == '\n' || *p == '#') { 537 /* comment... */ 538 continue; 539 } 540 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 541 *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p; 542 p++; 543 } 544 if (*p == ' ' || *p == '\t') { 545 *p++ = '\0'; 546 while (*p == ' ' || *p == '\t') 547 p++; 548 user = p; 549 while (*p != '\n' && *p != ' ' && 550 *p != '\t' && *p != '\0') 551 p++; 552 } else 553 user = p; 554 *p = '\0'; 555 /* 556 * Do +/- and +@/-@ checking. This looks really nasty, 557 * but it matches SunOS's behavior so far as I can tell. 558 */ 559 switch(buf[0]) { 560 case '+': 561 if (!buf[1]) { /* '+' matches all hosts */ 562 hostok = 1; 563 break; 564 } 565 if (buf[1] == '@') /* match a host by netgroup */ 566 hostok = innetgr((char *)&buf[2], 567 (char *)&hname, NULL, ypdomain); 568 else /* match a host by addr */ 569 hostok = __icheckhost(raddr,(char *)&buf[1], 570 af, len); 571 break; 572 case '-': /* reject '-' hosts and all their users */ 573 if (buf[1] == '@') { 574 if (innetgr((char *)&buf[2], 575 (char *)&hname, NULL, ypdomain)) 576 return(-1); 577 } else { 578 if (__icheckhost(raddr,(char *)&buf[1],af,len)) 579 return(-1); 580 } 581 break; 582 default: /* if no '+' or '-', do a simple match */ 583 hostok = __icheckhost(raddr, buf, af, len); 584 break; 585 } 586 switch(*user) { 587 case '+': 588 if (!*(user+1)) { /* '+' matches all users */ 589 userok = 1; 590 break; 591 } 592 if (*(user+1) == '@') /* match a user by netgroup */ 593 userok = innetgr(user+2, NULL, ruser, ypdomain); 594 else /* match a user by direct specification */ 595 userok = !(strcmp(ruser, user+1)); 596 break; 597 case '-': /* if we matched a hostname, */ 598 if (hostok) { /* check for user field rejections */ 599 if (!*(user+1)) 600 return(-1); 601 if (*(user+1) == '@') { 602 if (innetgr(user+2, NULL, 603 ruser, ypdomain)) 604 return(-1); 605 } else { 606 if (!strcmp(ruser, user+1)) 607 return(-1); 608 } 609 } 610 break; 611 default: /* no rejections: try to match the user */ 612 if (hostok) 613 userok = !(strcmp(ruser,*user ? user : luser)); 614 break; 615 } 616 if (hostok && userok) 617 return(0); 618 } 619 return (-1); 620} 621 622/* 623 * Returns "true" if match, 0 if no match. 624 */ 625static int 626__icheckhost(raddr, lhost, af, len) 627 void *raddr; 628 register char *lhost; 629 int af, len; 630{ 631 register struct hostent *hp; 632 char laddr[BUFSIZ]; /* xxx */ 633 register char **pp; 634 int h_error; 635 int match; 636 637 /* Try for raw ip address first. */ 638 if (inet_pton(af, lhost, laddr) == 1) { 639 if (memcmp(raddr, laddr, len) == 0) 640 return (1); 641 else 642 return (0); 643 } 644 645 /* Better be a hostname. */ 646 if ((hp = getipnodebyname(lhost, af, AI_DEFAULT, &h_error)) == NULL) 647 return (0); 648 649 /* Spin through ip addresses. */ 650 match = 0; 651 for (pp = hp->h_addr_list; *pp; ++pp) 652 if (!bcmp(raddr, *pp, len)) { 653 match = 1; 654 break; 655 } 656 657 freehostent(hp); 658 return (match); 659}
| 343 return (-1); 344 } 345 *alport = (int)ntohs(*sport); 346 return (s); 347} 348 349int __check_rhosts_file = 1; 350char *__rcmd_errstr; 351 352int 353ruserok(rhost, superuser, ruser, luser) 354 const char *rhost, *ruser, *luser; 355 int superuser; 356{ 357 return ruserok_af(rhost, superuser, ruser, luser, AF_INET); 358} 359 360int 361ruserok_af(rhost, superuser, ruser, luser, af) 362 const char *rhost, *ruser, *luser; 363 int superuser, af; 364{ 365 struct hostent *hp; 366 union { 367 struct in_addr addr_in; 368 struct in6_addr addr_in6; 369 } addr; 370 char **ap; 371 int ret, h_error; 372 373 if ((hp = getipnodebyname(rhost, af, AI_DEFAULT, &h_error)) == NULL) 374 return (-1); 375 ret = -1; 376 for (ap = hp->h_addr_list; *ap; ++ap) { 377 bcopy(*ap, &addr, hp->h_length); 378 if (iruserok_af(&addr, superuser, ruser, luser, af) == 0) { 379 ret = 0; 380 break; 381 } 382 } 383 freehostent(hp); 384 return (ret); 385} 386 387/* 388 * New .rhosts strategy: We are passed an ip address. We spin through 389 * hosts.equiv and .rhosts looking for a match. When the .rhosts only 390 * has ip addresses, we don't have to trust a nameserver. When it 391 * contains hostnames, we spin through the list of addresses the nameserver 392 * gives us and look for a match. 393 * 394 * Returns 0 if ok, -1 if not ok. 395 */ 396int 397iruserok(raddr, superuser, ruser, luser) 398 unsigned long raddr; 399 int superuser; 400 const char *ruser, *luser; 401{ 402 return iruserok_af(&raddr, superuser, ruser, luser, AF_INET); 403} 404 405int 406iruserok_af(raddr, superuser, ruser, luser, af) 407 void *raddr; 408 int superuser; 409 const char *ruser, *luser; 410 int af; 411{ 412 register char *cp; 413 struct stat sbuf; 414 struct passwd *pwd; 415 FILE *hostf; 416 uid_t uid; 417 int first; 418 char pbuf[MAXPATHLEN]; 419 int len = 0; 420 421 switch (af) { 422 case AF_INET: 423 len = sizeof(struct in_addr); 424 break; 425#ifdef INET6 426 case AF_INET6: 427 len = sizeof(struct in6_addr); 428 break; 429#endif 430 } 431 432 first = 1; 433 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 434again: 435 if (hostf) { 436 if (__ivaliduser_af(hostf, raddr, luser, ruser, af, len) 437 == 0) { 438 (void)fclose(hostf); 439 return (0); 440 } 441 (void)fclose(hostf); 442 } 443 if (first == 1 && (__check_rhosts_file || superuser)) { 444 first = 0; 445 if ((pwd = getpwnam(luser)) == NULL) 446 return (-1); 447 (void)strcpy(pbuf, pwd->pw_dir); 448 (void)strcat(pbuf, "/.rhosts"); 449 450 /* 451 * Change effective uid while opening .rhosts. If root and 452 * reading an NFS mounted file system, can't read files that 453 * are protected read/write owner only. 454 */ 455 uid = geteuid(); 456 (void)seteuid(pwd->pw_uid); 457 hostf = fopen(pbuf, "r"); 458 (void)seteuid(uid); 459 460 if (hostf == NULL) 461 return (-1); 462 /* 463 * If not a regular file, or is owned by someone other than 464 * user or root or if writeable by anyone but the owner, quit. 465 */ 466 cp = NULL; 467 if (lstat(pbuf, &sbuf) < 0) 468 cp = ".rhosts lstat failed"; 469 else if (!S_ISREG(sbuf.st_mode)) 470 cp = ".rhosts not regular file"; 471 else if (fstat(fileno(hostf), &sbuf) < 0) 472 cp = ".rhosts fstat failed"; 473 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) 474 cp = "bad .rhosts owner"; 475 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) 476 cp = ".rhosts writeable by other than owner"; 477 /* If there were any problems, quit. */ 478 if (cp) { 479 __rcmd_errstr = cp; 480 (void)fclose(hostf); 481 return (-1); 482 } 483 goto again; 484 } 485 return (-1); 486} 487 488/* 489 * XXX 490 * Don't make static, used by lpd(8). 491 * 492 * Returns 0 if ok, -1 if not ok. 493 */ 494int 495__ivaliduser(hostf, raddr, luser, ruser) 496 FILE *hostf; 497 u_int32_t raddr; 498 const char *luser, *ruser; 499{ 500 return __ivaliduser_af(hostf, &raddr, luser, ruser, AF_INET, 501 sizeof(raddr)); 502} 503 504int 505__ivaliduser_af(hostf, raddr, luser, ruser, af, len) 506 FILE *hostf; 507 void *raddr; 508 const char *luser, *ruser; 509 int af, len; 510{ 511 register char *user, *p; 512 int ch; 513 char buf[MAXHOSTNAMELEN + 128]; /* host + login */ 514 char hname[MAXHOSTNAMELEN]; 515 struct hostent *hp; 516 /* Presumed guilty until proven innocent. */ 517 int userok = 0, hostok = 0; 518 int h_error; 519#ifdef YP 520 char *ypdomain; 521 522 if (yp_get_default_domain(&ypdomain)) 523 ypdomain = NULL; 524#else 525#define ypdomain NULL 526#endif 527 /* We need to get the damn hostname back for netgroup matching. */ 528 if ((hp = getipnodebyaddr((char *)raddr, len, af, &h_error)) == NULL) 529 return (-1); 530 strncpy(hname, hp->h_name, sizeof(hname)); 531 hname[sizeof(hname) - 1] = '\0'; 532 freehostent(hp); 533 534 while (fgets(buf, sizeof(buf), hostf)) { 535 p = buf; 536 /* Skip lines that are too long. */ 537 if (strchr(p, '\n') == NULL) { 538 while ((ch = getc(hostf)) != '\n' && ch != EOF); 539 continue; 540 } 541 if (*p == '\n' || *p == '#') { 542 /* comment... */ 543 continue; 544 } 545 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 546 *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p; 547 p++; 548 } 549 if (*p == ' ' || *p == '\t') { 550 *p++ = '\0'; 551 while (*p == ' ' || *p == '\t') 552 p++; 553 user = p; 554 while (*p != '\n' && *p != ' ' && 555 *p != '\t' && *p != '\0') 556 p++; 557 } else 558 user = p; 559 *p = '\0'; 560 /* 561 * Do +/- and +@/-@ checking. This looks really nasty, 562 * but it matches SunOS's behavior so far as I can tell. 563 */ 564 switch(buf[0]) { 565 case '+': 566 if (!buf[1]) { /* '+' matches all hosts */ 567 hostok = 1; 568 break; 569 } 570 if (buf[1] == '@') /* match a host by netgroup */ 571 hostok = innetgr((char *)&buf[2], 572 (char *)&hname, NULL, ypdomain); 573 else /* match a host by addr */ 574 hostok = __icheckhost(raddr,(char *)&buf[1], 575 af, len); 576 break; 577 case '-': /* reject '-' hosts and all their users */ 578 if (buf[1] == '@') { 579 if (innetgr((char *)&buf[2], 580 (char *)&hname, NULL, ypdomain)) 581 return(-1); 582 } else { 583 if (__icheckhost(raddr,(char *)&buf[1],af,len)) 584 return(-1); 585 } 586 break; 587 default: /* if no '+' or '-', do a simple match */ 588 hostok = __icheckhost(raddr, buf, af, len); 589 break; 590 } 591 switch(*user) { 592 case '+': 593 if (!*(user+1)) { /* '+' matches all users */ 594 userok = 1; 595 break; 596 } 597 if (*(user+1) == '@') /* match a user by netgroup */ 598 userok = innetgr(user+2, NULL, ruser, ypdomain); 599 else /* match a user by direct specification */ 600 userok = !(strcmp(ruser, user+1)); 601 break; 602 case '-': /* if we matched a hostname, */ 603 if (hostok) { /* check for user field rejections */ 604 if (!*(user+1)) 605 return(-1); 606 if (*(user+1) == '@') { 607 if (innetgr(user+2, NULL, 608 ruser, ypdomain)) 609 return(-1); 610 } else { 611 if (!strcmp(ruser, user+1)) 612 return(-1); 613 } 614 } 615 break; 616 default: /* no rejections: try to match the user */ 617 if (hostok) 618 userok = !(strcmp(ruser,*user ? user : luser)); 619 break; 620 } 621 if (hostok && userok) 622 return(0); 623 } 624 return (-1); 625} 626 627/* 628 * Returns "true" if match, 0 if no match. 629 */ 630static int 631__icheckhost(raddr, lhost, af, len) 632 void *raddr; 633 register char *lhost; 634 int af, len; 635{ 636 register struct hostent *hp; 637 char laddr[BUFSIZ]; /* xxx */ 638 register char **pp; 639 int h_error; 640 int match; 641 642 /* Try for raw ip address first. */ 643 if (inet_pton(af, lhost, laddr) == 1) { 644 if (memcmp(raddr, laddr, len) == 0) 645 return (1); 646 else 647 return (0); 648 } 649 650 /* Better be a hostname. */ 651 if ((hp = getipnodebyname(lhost, af, AI_DEFAULT, &h_error)) == NULL) 652 return (0); 653 654 /* Spin through ip addresses. */ 655 match = 0; 656 for (pp = hp->h_addr_list; *pp; ++pp) 657 if (!bcmp(raddr, *pp, len)) { 658 match = 1; 659 break; 660 } 661 662 freehostent(hp); 663 return (match); 664}
|