1 /* $NetBSD: rexec.c,v 1.15 2002/11/11 23:43:03 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #if defined(LIBC_SCCS) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93"; 40 #else 41 __RCSID("$NetBSD: rexec.c,v 1.15 2002/11/11 23:43:03 thorpej Exp $"); 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include <sys/types.h> 46 #include <sys/socket.h> 47 48 #include <netinet/in.h> 49 50 #include <assert.h> 51 #include <err.h> 52 #include <errno.h> 53 #include <netdb.h> 54 #include <stdio.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 int rexecoptions; 59 60 int ruserpass __P((const char *, char **, char **)); 61 int rexec __P((char **, int, char *, char *, char *, int *)); 62 63 int 64 rexec(ahost, rport, name, pass, cmd, fd2p) 65 char **ahost; 66 int rport; 67 char *name, *pass, *cmd; 68 int *fd2p; 69 { 70 struct sockaddr_in rsin, from; 71 socklen_t fromlen; 72 struct hostent *hp; 73 u_short port; 74 size_t len; 75 unsigned int timo = 1; 76 int s, s3; 77 char c; 78 79 _DIAGASSERT(ahost != NULL); 80 _DIAGASSERT(name != NULL); 81 _DIAGASSERT(pass != NULL); 82 _DIAGASSERT(cmd != NULL); 83 /* fd2p may be NULL */ 84 85 hp = gethostbyname(*ahost); 86 if (hp == 0) { 87 warnx("Error resolving %s (%s)", *ahost, hstrerror(h_errno)); 88 return -1; 89 } 90 *ahost = hp->h_name; 91 (void)ruserpass(hp->h_name, &name, &pass); 92 retry: 93 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 94 warn("Cannot create socket"); 95 return (-1); 96 } 97 rsin.sin_family = hp->h_addrtype; 98 rsin.sin_len = sizeof(rsin); 99 rsin.sin_port = rport; 100 /* Avoid data corruption from bogus DNS results */ 101 if (hp->h_length > (int) sizeof(rsin.sin_addr)) 102 len = sizeof(rsin.sin_addr); 103 else 104 len = hp->h_length; 105 memcpy(&rsin.sin_addr, hp->h_addr, len); 106 if (connect(s, (struct sockaddr *)(void *)&rsin, sizeof(rsin)) == -1) { 107 if (errno == ECONNREFUSED && timo <= 16) { 108 (void)close(s); 109 sleep(timo); 110 timo *= 2; 111 goto retry; 112 } 113 warn("Cannot connect to %s", hp->h_name); 114 return -1; 115 } 116 port = 0; 117 if (fd2p == 0) { 118 (void)write(s, "", 1); 119 } else { 120 char num[8]; 121 int s2; 122 struct sockaddr_in sin2; 123 socklen_t sin2len; 124 125 s2 = socket(AF_INET, SOCK_STREAM, 0); 126 if (s2 == -1) { 127 warn("Error creating socket"); 128 (void)close(s); 129 return -1; 130 } 131 listen(s2, 1); 132 sin2len = sizeof(sin2); 133 if (getsockname(s2, (struct sockaddr *)(void *)&sin2, 134 &sin2len) == -1 || sin2len != sizeof(sin2)) { 135 warn("Failed to get socket name"); 136 (void)close(s2); 137 goto bad; 138 } 139 port = ntohs((u_short)sin2.sin_port); 140 (void)snprintf(num, sizeof(num), "%u", port); 141 (void)write(s, num, strlen(num)+1); 142 143 fromlen = sizeof(from); 144 s3 = accept(s2, (struct sockaddr *)(void *)&from, &fromlen); 145 (void)close(s2); 146 if (s3 == -1) { 147 warn("Error accepting connection"); 148 port = 0; 149 goto bad; 150 } 151 *fd2p = s3; 152 } 153 (void)write(s, name, strlen(name) + 1); 154 /* should public key encypt the password here */ 155 (void)write(s, pass, strlen(pass) + 1); 156 (void)write(s, cmd, strlen(cmd) + 1); 157 if (read(s, &c, 1) != 1) { 158 warn("Error reading from %s", *ahost); 159 goto bad; 160 } 161 if (c != 0) { 162 while (read(s, &c, 1) == 1) { 163 (void) write(2, &c, 1); 164 if (c == '\n') 165 break; 166 } 167 goto bad; 168 } 169 return s; 170 bad: 171 if (port) 172 (void)close(*fd2p); 173 (void)close(s); 174 return -1; 175 } 176