1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <sys/types.h> 43 #include <sys/socket.h> 44 45 #include <netinet/in.h> 46 47 #include <stdio.h> 48 #include <netdb.h> 49 #include <errno.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <libintl.h> 54 55 #ifdef SYSV 56 #define bcopy(a, b, c) (void) memcpy((b), (a), (c)) 57 #endif 58 59 #define MAX_SHORTSTRLEN 6 60 61 extern char *_dgettext(); 62 63 void _ruserpass(const char *host, char **aname, char **apass); 64 65 int rexec(char **ahost, unsigned short rport, const char *name, 66 const char *pass, const char *cmd, int *fd2p) 67 { 68 return (rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET)); 69 } 70 71 int rexec_af(char **ahost, unsigned short rport, const char *name, 72 const char *pass, const char *cmd, int *fd2p, int af) 73 { 74 int s, timo = 1, s3; 75 char c; 76 ushort_t port; 77 static char hostname[MAXHOSTNAMELEN]; 78 int rc; 79 struct addrinfo *res; 80 struct addrinfo hints; 81 char aport[MAX_SHORTSTRLEN]; 82 83 if (!(af == AF_INET || af == AF_INET6 || af == AF_UNSPEC)) { 84 (void) fprintf(stderr, 85 _dgettext(TEXT_DOMAIN, "%d: Address family not " 86 "supported\n"), af); 87 errno = EAFNOSUPPORT; 88 return (-1); 89 } 90 memset(&hints, 0, sizeof (hints)); 91 (void) snprintf(aport, MAX_SHORTSTRLEN, "%u", ntohs(rport)); 92 hints.ai_flags = AI_CANONNAME|AI_ADDRCONFIG|AI_V4MAPPED; 93 hints.ai_socktype = SOCK_STREAM; 94 hints.ai_family = af; 95 rc = getaddrinfo(*ahost, aport, &hints, &res); 96 97 if (rc != 0) { 98 (void) fprintf(stderr, 99 _dgettext(TEXT_DOMAIN, "%s: unknown host\n"), 100 *ahost); 101 return (-1); 102 } 103 (void) strlcpy(hostname, res->ai_canonname, MAXHOSTNAMELEN); 104 *ahost = hostname; 105 _ruserpass(res->ai_canonname, (char **)&name, (char **)&pass); 106 retry: 107 s = socket(res->ai_addr->sa_family, res->ai_socktype, res->ai_protocol); 108 if (s < 0) { 109 perror("rexec: socket"); 110 freeaddrinfo(res); 111 return (-1); 112 } 113 if (connect(s, res->ai_addr, res->ai_addrlen) != 0) { 114 if (errno == ECONNREFUSED && timo <= 16) { 115 (void) close(s); 116 (void) sleep(timo); 117 timo *= 2; 118 goto retry; 119 } 120 perror(*ahost); 121 (void) close(s); 122 freeaddrinfo(res); 123 return (-1); 124 } 125 if (fd2p == 0) { 126 (void) write(s, "", 1); 127 port = 0; 128 } else { 129 int s2; 130 socklen_t sin2len; 131 struct sockaddr_storage sin2, from; 132 133 s2 = socket(res->ai_family, SOCK_STREAM, 0); 134 if (s2 < 0) { 135 (void) close(s); 136 freeaddrinfo(res); 137 return (-1); 138 } 139 (void) listen(s2, 1); 140 sin2len = (socklen_t)sizeof (sin2); 141 if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0) { 142 perror("getsockname"); 143 (void) close(s2); 144 goto bad; 145 } 146 if (res->ai_family == AF_INET6) { 147 port = ((struct sockaddr_in6 *)&sin2)->sin6_port; 148 } else { 149 port = ((struct sockaddr_in *)&sin2)->sin_port; 150 } 151 (void) snprintf(aport, MAX_SHORTSTRLEN, "%u", port); 152 (void) write(s, aport, strlen(aport)+1); 153 { 154 socklen_t len = (socklen_t)sizeof (from); 155 s3 = accept(s2, (struct sockaddr *)&from, &len); 156 (void) close(s2); 157 if (s3 < 0) { 158 perror("accept"); 159 port = 0; 160 goto bad; 161 } 162 } 163 *fd2p = s3; 164 } 165 (void) write(s, name, strlen(name) + 1); 166 /* should public key encypt the password here */ 167 (void) write(s, pass, strlen(pass) + 1); 168 (void) write(s, cmd, strlen(cmd) + 1); 169 if (read(s, &c, 1) != 1) { 170 perror(*ahost); 171 goto bad; 172 } 173 if (c != 0) { 174 while (read(s, &c, 1) == 1) { 175 (void) write(2, &c, 1); 176 if (c == '\n') 177 break; 178 } 179 goto bad; 180 } 181 freeaddrinfo(res); 182 return (s); 183 bad: 184 if (port) 185 (void) close(*fd2p); 186 (void) close(s); 187 freeaddrinfo(res); 188 return (-1); 189 } 190