1 /* 2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. 3 * Copyright (c) 1983, 1993, 1994 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/socket.h> 32 #include <sys/stat.h> 33 34 #include <netinet/in.h> 35 #include <arpa/inet.h> 36 37 #include <signal.h> 38 #include <fcntl.h> 39 #include <netdb.h> 40 #include <unistd.h> 41 #include <limits.h> 42 #include <pwd.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <ctype.h> 46 #include <string.h> 47 #include <syslog.h> 48 #include <stdlib.h> 49 #include <poll.h> 50 51 int 52 rcmd(char **ahost, int rport, const char *locuser, const char *remuser, 53 const char *cmd, int *fd2p) 54 { 55 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET); 56 } 57 58 int 59 rcmd_af(char **ahost, int porta, const char *locuser, const char *remuser, 60 const char *cmd, int *fd2p, int af) 61 { 62 static char hbuf[HOST_NAME_MAX+1]; 63 char pbuf[NI_MAXSERV]; 64 struct addrinfo hints, *res, *r; 65 int error; 66 struct sockaddr_storage from; 67 sigset_t oldmask, mask; 68 pid_t pid; 69 int s, lport, timo; 70 char c, *p; 71 int refused; 72 in_port_t rport = porta; 73 74 /* call rcmdsh() with specified remote shell if appropriate. */ 75 if (!issetugid() && (p = getenv("RSH")) && *p) { 76 struct servent *sp = getservbyname("shell", "tcp"); 77 78 if (sp && sp->s_port == rport) 79 return (rcmdsh(ahost, rport, locuser, remuser, 80 cmd, p)); 81 } 82 83 /* use rsh(1) if non-root and remote port is shell. */ 84 if (geteuid()) { 85 struct servent *sp = getservbyname("shell", "tcp"); 86 87 if (sp && sp->s_port == rport) 88 return (rcmdsh(ahost, rport, locuser, remuser, 89 cmd, NULL)); 90 } 91 92 pid = getpid(); 93 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport)); 94 memset(&hints, 0, sizeof(hints)); 95 hints.ai_family = af; 96 hints.ai_socktype = SOCK_STREAM; 97 hints.ai_flags = AI_CANONNAME; 98 error = getaddrinfo(*ahost, pbuf, &hints, &res); 99 if (error) { 100 #if 0 101 warnx("%s: %s", *ahost, gai_strerror(error)); 102 #endif 103 return (-1); 104 } 105 if (res->ai_canonname) { 106 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf)); 107 *ahost = hbuf; 108 } else 109 ; /*XXX*/ 110 111 r = res; 112 refused = 0; 113 sigemptyset(&mask); 114 sigaddset(&mask, SIGURG); 115 sigprocmask(SIG_BLOCK, &mask, &oldmask); 116 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 117 s = rresvport_af(&lport, r->ai_family); 118 if (s < 0) { 119 if (errno == EAGAIN) 120 (void)fprintf(stderr, 121 "rcmd: socket: All ports in use\n"); 122 else 123 (void)fprintf(stderr, "rcmd: socket: %s\n", 124 strerror(errno)); 125 if (r->ai_next) { 126 r = r->ai_next; 127 continue; 128 } else { 129 sigprocmask(SIG_SETMASK, &oldmask, NULL); 130 freeaddrinfo(res); 131 return (-1); 132 } 133 } 134 fcntl(s, F_SETOWN, pid); 135 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0) 136 break; 137 (void)close(s); 138 if (errno == EADDRINUSE) { 139 lport--; 140 continue; 141 } 142 if (errno == ECONNREFUSED) 143 refused++; 144 if (r->ai_next) { 145 int oerrno = errno; 146 char hbuf[NI_MAXHOST]; 147 const int niflags = NI_NUMERICHOST; 148 149 hbuf[0] = '\0'; 150 if (getnameinfo(r->ai_addr, r->ai_addrlen, 151 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0) 152 strlcpy(hbuf, "(invalid)", sizeof hbuf); 153 (void)fprintf(stderr, "connect to address %s: ", hbuf); 154 errno = oerrno; 155 perror(0); 156 r = r->ai_next; 157 hbuf[0] = '\0'; 158 if (getnameinfo(r->ai_addr, r->ai_addrlen, 159 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0) 160 strlcpy(hbuf, "(invalid)", sizeof hbuf); 161 (void)fprintf(stderr, "Trying %s...\n", hbuf); 162 continue; 163 } 164 if (refused && timo <= 16) { 165 (void)sleep(timo); 166 timo *= 2; 167 r = res; 168 refused = 0; 169 continue; 170 } 171 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname, 172 strerror(errno)); 173 sigprocmask(SIG_SETMASK, &oldmask, NULL); 174 freeaddrinfo(res); 175 return (-1); 176 } 177 /* given "af" can be PF_UNSPEC, we need the real af for "s" */ 178 af = r->ai_family; 179 freeaddrinfo(res); 180 #if 0 181 /* 182 * try to rresvport() to the same port. This will make rresvport() 183 * fail it's first bind, resulting in it choosing a random port. 184 */ 185 lport--; 186 #endif 187 if (fd2p == 0) { 188 write(s, "", 1); 189 lport = 0; 190 } else { 191 struct pollfd pfd[2]; 192 char num[8]; 193 int s2 = rresvport_af(&lport, af), s3; 194 socklen_t len = sizeof(from); 195 196 if (s2 < 0) 197 goto bad; 198 199 listen(s2, 1); 200 (void)snprintf(num, sizeof(num), "%d", lport); 201 if (write(s, num, strlen(num)+1) != strlen(num)+1) { 202 (void)fprintf(stderr, 203 "rcmd: write (setting up stderr): %s\n", 204 strerror(errno)); 205 (void)close(s2); 206 goto bad; 207 } 208 again: 209 pfd[0].fd = s; 210 pfd[0].events = POLLIN; 211 pfd[1].fd = s2; 212 pfd[1].events = POLLIN; 213 214 errno = 0; 215 if (poll(pfd, 2, INFTIM) < 1 || 216 (pfd[1].revents & (POLLIN|POLLHUP)) == 0) { 217 if (errno != 0) 218 (void)fprintf(stderr, 219 "rcmd: poll (setting up stderr): %s\n", 220 strerror(errno)); 221 else 222 (void)fprintf(stderr, 223 "poll: protocol failure in circuit setup\n"); 224 (void)close(s2); 225 goto bad; 226 } 227 s3 = accept(s2, (struct sockaddr *)&from, &len); 228 if (s3 < 0) { 229 (void)fprintf(stderr, 230 "rcmd: accept: %s\n", strerror(errno)); 231 lport = 0; 232 close(s2); 233 goto bad; 234 } 235 236 /* 237 * XXX careful for ftp bounce attacks. If discovered, shut them 238 * down and check for the real auxiliary channel to connect. 239 */ 240 switch (from.ss_family) { 241 case AF_INET: 242 case AF_INET6: 243 if (getnameinfo((struct sockaddr *)&from, len, 244 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 && 245 atoi(num) != 20) { 246 break; 247 } 248 close(s3); 249 goto again; 250 default: 251 break; 252 } 253 (void)close(s2); 254 255 *fd2p = s3; 256 switch (from.ss_family) { 257 case AF_INET: 258 case AF_INET6: 259 if (getnameinfo((struct sockaddr *)&from, len, 260 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 || 261 (atoi(num) >= IPPORT_RESERVED || 262 atoi(num) < IPPORT_RESERVED / 2)) { 263 (void)fprintf(stderr, 264 "socket: protocol failure in circuit setup.\n"); 265 goto bad2; 266 } 267 break; 268 default: 269 break; 270 } 271 } 272 (void)write(s, locuser, strlen(locuser)+1); 273 (void)write(s, remuser, strlen(remuser)+1); 274 (void)write(s, cmd, strlen(cmd)+1); 275 if (read(s, &c, 1) != 1) { 276 (void)fprintf(stderr, 277 "rcmd: %s: %s\n", *ahost, strerror(errno)); 278 goto bad2; 279 } 280 if (c != 0) { 281 while (read(s, &c, 1) == 1) { 282 (void)write(STDERR_FILENO, &c, 1); 283 if (c == '\n') 284 break; 285 } 286 goto bad2; 287 } 288 sigprocmask(SIG_SETMASK, &oldmask, NULL); 289 return (s); 290 bad2: 291 if (lport) 292 (void)close(*fd2p); 293 bad: 294 (void)close(s); 295 sigprocmask(SIG_SETMASK, &oldmask, NULL); 296 return (-1); 297 } 298 299