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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 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 void _ruserpass(const char *host, char **aname, char **apass);
62
rexec(char ** ahost,unsigned short rport,const char * name,const char * pass,const char * cmd,int * fd2p)63 int rexec(char **ahost, unsigned short rport, const char *name,
64 const char *pass, const char *cmd, int *fd2p)
65 {
66 return (rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET));
67 }
68
rexec_af(char ** ahost,unsigned short rport,const char * name,const char * pass,const char * cmd,int * fd2p,int af)69 int rexec_af(char **ahost, unsigned short rport, const char *name,
70 const char *pass, const char *cmd, int *fd2p, int af)
71 {
72 int s, timo = 1, s3;
73 char c;
74 ushort_t port;
75 static char hostname[MAXHOSTNAMELEN];
76 int rc;
77 struct addrinfo *res;
78 struct addrinfo hints;
79 char aport[MAX_SHORTSTRLEN];
80
81 if (!(af == AF_INET || af == AF_INET6 || af == AF_UNSPEC)) {
82 (void) fprintf(stderr,
83 dgettext(TEXT_DOMAIN, "%d: Address family not "
84 "supported\n"), af);
85 errno = EAFNOSUPPORT;
86 return (-1);
87 }
88 memset(&hints, 0, sizeof (hints));
89 (void) snprintf(aport, MAX_SHORTSTRLEN, "%u", ntohs(rport));
90 hints.ai_flags = AI_CANONNAME|AI_ADDRCONFIG|AI_V4MAPPED;
91 hints.ai_socktype = SOCK_STREAM;
92 hints.ai_family = af;
93 rc = getaddrinfo(*ahost, aport, &hints, &res);
94
95 if (rc != 0) {
96 (void) fprintf(stderr,
97 dgettext(TEXT_DOMAIN, "%s: unknown host\n"),
98 *ahost);
99 return (-1);
100 }
101 (void) strlcpy(hostname, res->ai_canonname, MAXHOSTNAMELEN);
102 *ahost = hostname;
103 _ruserpass(res->ai_canonname, (char **)&name, (char **)&pass);
104 retry:
105 s = socket(res->ai_addr->sa_family, res->ai_socktype, res->ai_protocol);
106 if (s < 0) {
107 perror("rexec: socket");
108 freeaddrinfo(res);
109 return (-1);
110 }
111 if (connect(s, res->ai_addr, res->ai_addrlen) != 0) {
112 if (errno == ECONNREFUSED && timo <= 16) {
113 (void) close(s);
114 (void) sleep(timo);
115 timo *= 2;
116 goto retry;
117 }
118 perror(*ahost);
119 (void) close(s);
120 freeaddrinfo(res);
121 return (-1);
122 }
123 if (fd2p == 0) {
124 (void) write(s, "", 1);
125 port = 0;
126 } else {
127 int s2;
128 socklen_t sin2len;
129 struct sockaddr_storage sin2, from;
130
131 s2 = socket(res->ai_family, SOCK_STREAM, 0);
132 if (s2 < 0) {
133 (void) close(s);
134 freeaddrinfo(res);
135 return (-1);
136 }
137 (void) listen(s2, 1);
138 sin2len = (socklen_t)sizeof (sin2);
139 if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0) {
140 perror("getsockname");
141 (void) close(s2);
142 goto bad;
143 }
144 if (res->ai_family == AF_INET6) {
145 port = ntohs(((struct sockaddr_in6 *)&sin2)->sin6_port);
146 } else {
147 port = ntohs(((struct sockaddr_in *)&sin2)->sin_port);
148 }
149 (void) snprintf(aport, MAX_SHORTSTRLEN, "%u", port);
150 (void) write(s, aport, strlen(aport)+1);
151 {
152 socklen_t len = (socklen_t)sizeof (from);
153 s3 = accept(s2, (struct sockaddr *)&from, &len);
154 (void) close(s2);
155 if (s3 < 0) {
156 perror("accept");
157 port = 0;
158 goto bad;
159 }
160 }
161 *fd2p = s3;
162 }
163 (void) write(s, name, strlen(name) + 1);
164 /* should public key encypt the password here */
165 (void) write(s, pass, strlen(pass) + 1);
166 (void) write(s, cmd, strlen(cmd) + 1);
167 if (read(s, &c, 1) != 1) {
168 perror(*ahost);
169 goto bad;
170 }
171 if (c != 0) {
172 while (read(s, &c, 1) == 1) {
173 (void) write(2, &c, 1);
174 if (c == '\n')
175 break;
176 }
177 goto bad;
178 }
179 freeaddrinfo(res);
180 return (s);
181 bad:
182 if (port)
183 (void) close(*fd2p);
184 (void) close(s);
185 freeaddrinfo(res);
186 return (-1);
187 }
188