xref: /netbsd-src/external/gpl2/xcvs/dist/src/rsh-client.c (revision 74e8c71cd1136230728133034816cf03b1f4af1f)
1a7c91847Schristos /* CVS rsh client stuff.
2a7c91847Schristos 
3a7c91847Schristos    This program is free software; you can redistribute it and/or modify
4a7c91847Schristos    it under the terms of the GNU General Public License as published by
5a7c91847Schristos    the Free Software Foundation; either version 2, or (at your option)
6a7c91847Schristos    any later version.
7a7c91847Schristos 
8a7c91847Schristos    This program is distributed in the hope that it will be useful,
9a7c91847Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
10a7c91847Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11a7c91847Schristos    GNU General Public License for more details.  */
125a6c14c8Schristos #include <sys/cdefs.h>
13*74e8c71cSchristos __RCSID("$NetBSD: rsh-client.c,v 1.3 2017/08/22 10:06:57 christos Exp $");
14a7c91847Schristos 
15a7c91847Schristos #include <config.h>
16a7c91847Schristos 
17a7c91847Schristos #include "cvs.h"
18a7c91847Schristos #include "buffer.h"
19a7c91847Schristos 
20a7c91847Schristos #ifdef CLIENT_SUPPORT
21a7c91847Schristos 
22a7c91847Schristos #include "rsh-client.h"
23a7c91847Schristos 
24a7c91847Schristos #ifndef NO_EXT_METHOD
25a7c91847Schristos 
26a7c91847Schristos /* Contact the server by starting it with rsh.  */
27a7c91847Schristos 
28a7c91847Schristos /* Right now, we have two different definitions for this function,
29a7c91847Schristos    depending on whether we start the rsh server using popenRW or not.
30a7c91847Schristos    This isn't ideal, and the best thing would probably be to change
31a7c91847Schristos    the OS/2 port to be more like the regular Unix client (i.e., by
32a7c91847Schristos    implementing piped_child)... but I'm doing something else at the
33a7c91847Schristos    moment, and wish to make only one change at a time.  -Karl */
34a7c91847Schristos 
35a7c91847Schristos # ifdef START_RSH_WITH_POPEN_RW
36a7c91847Schristos 
37a7c91847Schristos 
38a7c91847Schristos 
39a7c91847Schristos /* This is actually a crock -- it's OS/2-specific, for no one else
40a7c91847Schristos    uses it.  If I get time, I want to make piped_child and all the
41a7c91847Schristos    other stuff in os2/run.c work right.  In the meantime, this gets us
42a7c91847Schristos    up and running, and that's most important. */
43a7c91847Schristos void
start_rsh_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)44a7c91847Schristos start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
45a7c91847Schristos                   struct buffer **from_server_p)
46a7c91847Schristos {
47a7c91847Schristos     int pipes[2];
48a7c91847Schristos     int child_pid;
49a7c91847Schristos 
50a7c91847Schristos     /* If you're working through firewalls, you can set the
51a7c91847Schristos        CVS_RSH environment variable to a script which uses rsh to
52a7c91847Schristos        invoke another rsh on a proxy machine.  */
53a7c91847Schristos     char *cvs_rsh = (root->cvs_rsh != NULL
54a7c91847Schristos 		     ? root->cvs_rsh : getenv ("CVS_RSH"));
55a7c91847Schristos     char *cvs_server = (root->cvs_server != NULL
56a7c91847Schristos 			? root->cvs_server : getenv ("CVS_SERVER"));
57a7c91847Schristos     int i = 0;
58*74e8c71cSchristos     /* This needs to fit "rsh", "-b", "-l", "USER", "--", "host",
59a7c91847Schristos        "cmd (w/ args)", and NULL.  We leave some room to grow. */
60*74e8c71cSchristos     char *rsh_argv[16];
61a7c91847Schristos 
62*74e8c71cSchristos     if (!cvs_rsh || !*cvs_rsh)
63a7c91847Schristos 	/* People sometimes suggest or assume that this should default
64a7c91847Schristos 	   to "remsh" on systems like HPUX in which that is the
65a7c91847Schristos 	   system-supplied name for the rsh program.  However, that
66a7c91847Schristos 	   causes various problems (keep in mind that systems such as
67a7c91847Schristos 	   HPUX might have non-system-supplied versions of "rsh", like
68a7c91847Schristos 	   a Kerberized one, which one might want to use).  If we
69a7c91847Schristos 	   based the name on what is found in the PATH of the person
70a7c91847Schristos 	   who runs configure, that would make it harder to
71a7c91847Schristos 	   consistently produce the same result in the face of
72a7c91847Schristos 	   different people producing binary distributions.  If we
73a7c91847Schristos 	   based it on "remsh" always being the default for HPUX
74a7c91847Schristos 	   (e.g. based on uname), that might be slightly better but
75a7c91847Schristos 	   would require us to keep track of what the defaults are for
76a7c91847Schristos 	   each system type, and probably would cope poorly if the
77a7c91847Schristos 	   existence of remsh or rsh varies from OS version to OS
78a7c91847Schristos 	   version.  Therefore, it seems best to have the default
79a7c91847Schristos 	   remain "rsh", and tell HPUX users to specify remsh, for
80a7c91847Schristos 	   example in CVS_RSH or other such mechanisms to be devised,
81a7c91847Schristos 	   if that is what they want (the manual already tells them
82a7c91847Schristos 	   that).  */
83a7c91847Schristos 	cvs_rsh = RSH_DFLT;
84a7c91847Schristos     if (!cvs_server)
85a7c91847Schristos 	cvs_server = "cvs";
86a7c91847Schristos 
87a7c91847Schristos     /* The command line starts out with rsh. */
88a7c91847Schristos     rsh_argv[i++] = cvs_rsh;
89a7c91847Schristos 
90a7c91847Schristos #   ifdef RSH_NEEDS_BINARY_FLAG
91a7c91847Schristos     /* "-b" for binary, under OS/2. */
92a7c91847Schristos     rsh_argv[i++] = "-b";
93a7c91847Schristos #   endif /* RSH_NEEDS_BINARY_FLAG */
94a7c91847Schristos 
95a7c91847Schristos     /* Then we strcat more things on the end one by one. */
96a7c91847Schristos     if (root->username != NULL)
97a7c91847Schristos     {
98a7c91847Schristos 	rsh_argv[i++] = "-l";
99a7c91847Schristos 	rsh_argv[i++] = root->username;
100a7c91847Schristos     }
101a7c91847Schristos 
102*74e8c71cSchristos     /* Only non-option arguments from here. (CVE-2017-12836) */
103*74e8c71cSchristos     rsh_argv[i++] = "--";
104*74e8c71cSchristos 
105a7c91847Schristos     rsh_argv[i++] = root->hostname;
106a7c91847Schristos     rsh_argv[i++] = cvs_server;
107a7c91847Schristos     rsh_argv[i++] = "server";
108a7c91847Schristos 
109a7c91847Schristos     /* Mark the end of the arg list. */
110a7c91847Schristos     rsh_argv[i]   = NULL;
111a7c91847Schristos 
112a7c91847Schristos     if (trace)
113a7c91847Schristos     {
114a7c91847Schristos 	fprintf (stderr, " -> Starting server: ");
115a7c91847Schristos 	for (i = 0; rsh_argv[i]; i++)
116a7c91847Schristos 	    fprintf (stderr, "%s ", rsh_argv[i]);
117a7c91847Schristos 	putc ('\n', stderr);
118a7c91847Schristos     }
119a7c91847Schristos 
120a7c91847Schristos     /* Do the deed. */
121a7c91847Schristos     child_pid = popenRW (rsh_argv, pipes);
122a7c91847Schristos     if (child_pid < 0)
123a7c91847Schristos 	error (1, errno, "cannot start server via rsh");
124a7c91847Schristos 
125a7c91847Schristos     /* Give caller the file descriptors in a form it can deal with. */
126a7c91847Schristos     make_bufs_from_fds (pipes[0], pipes[1], child_pid, to_server_p,
127a7c91847Schristos                         from_server_p, 0);
128a7c91847Schristos }
129a7c91847Schristos 
130a7c91847Schristos # else /* ! START_RSH_WITH_POPEN_RW */
131a7c91847Schristos 
132a7c91847Schristos void
start_rsh_server(cvsroot_t * root,struct buffer ** to_server_p,struct buffer ** from_server_p)133a7c91847Schristos start_rsh_server (cvsroot_t *root, struct buffer **to_server_p,
134a7c91847Schristos                   struct buffer **from_server_p)
135a7c91847Schristos {
136a7c91847Schristos     /* If you're working through firewalls, you can set the
137a7c91847Schristos        CVS_RSH environment variable to a script which uses rsh to
138a7c91847Schristos        invoke another rsh on a proxy machine.  */
139a7c91847Schristos     char *cvs_rsh = (root->cvs_rsh != NULL
140a7c91847Schristos 		     ? root->cvs_rsh : getenv ("CVS_RSH"));
141a7c91847Schristos     char *cvs_server = (root->cvs_server != NULL
142a7c91847Schristos 			? root->cvs_server : getenv ("CVS_SERVER"));
143a7c91847Schristos     char *command;
144a7c91847Schristos     int tofd, fromfd;
145a7c91847Schristos     int child_pid;
146a7c91847Schristos 
147a7c91847Schristos     if (!cvs_rsh)
148a7c91847Schristos 	cvs_rsh = RSH_DFLT;
149a7c91847Schristos     if (!cvs_server)
150a7c91847Schristos 	cvs_server = "cvs";
151a7c91847Schristos 
152a7c91847Schristos     /* Pass the command to rsh as a single string.  This shouldn't
153a7c91847Schristos      * affect most rsh servers at all, and will pacify some buggy
154a7c91847Schristos      * versions of rsh that grab switches out of the middle of the
155a7c91847Schristos      * command (they're calling the GNU getopt routines incorrectly).
156a7c91847Schristos      *
157a7c91847Schristos      * If you are running a very old (Nov 3, 1994, before 1.5)
158a7c91847Schristos      * version of the server, you need to make sure that your .bashrc
159a7c91847Schristos      * on the server machine does not set CVSROOT to something
160a7c91847Schristos      * containing a colon (or better yet, upgrade the server).
161a7c91847Schristos      */
162a7c91847Schristos     command = Xasprintf ("%s server", cvs_server);
163a7c91847Schristos 
164a7c91847Schristos     {
165*74e8c71cSchristos         char *argv[16];
166a7c91847Schristos 	char **p = argv;
167a7c91847Schristos 
168a7c91847Schristos 	*p++ = cvs_rsh;
169a7c91847Schristos 
170a7c91847Schristos 	/* If the login names differ between client and server
171a7c91847Schristos 	 * pass it on to rsh.
172a7c91847Schristos 	 */
173a7c91847Schristos 	if (root->username != NULL)
174a7c91847Schristos 	{
175a7c91847Schristos 	    *p++ = "-l";
176a7c91847Schristos 	    *p++ = root->username;
177a7c91847Schristos 	}
178a7c91847Schristos 
179*74e8c71cSchristos 	*p++ = "--";
180*74e8c71cSchristos 
181a7c91847Schristos 	*p++ = root->hostname;
182a7c91847Schristos 	*p++ = command;
183a7c91847Schristos 	*p++ = NULL;
184a7c91847Schristos 
185a7c91847Schristos 	if (trace)
186a7c91847Schristos         {
187a7c91847Schristos 	    int i;
188a7c91847Schristos 
189a7c91847Schristos             fprintf (stderr, " -> Starting server: ");
190a7c91847Schristos 	    for (i = 0; argv[i]; i++)
191a7c91847Schristos 	        fprintf (stderr, "%s ", argv[i]);
192a7c91847Schristos 	    putc ('\n', stderr);
193a7c91847Schristos 	}
194a7c91847Schristos 	child_pid = piped_child (argv, &tofd, &fromfd, true);
195a7c91847Schristos 
196a7c91847Schristos 	if (child_pid < 0)
197a7c91847Schristos 	    error (1, errno, "cannot start server via rsh");
198a7c91847Schristos     }
199a7c91847Schristos     free (command);
200a7c91847Schristos 
201a7c91847Schristos     make_bufs_from_fds (tofd, fromfd, child_pid, root, to_server_p,
202a7c91847Schristos                         from_server_p, 0);
203a7c91847Schristos }
204a7c91847Schristos 
205a7c91847Schristos # endif /* START_RSH_WITH_POPEN_RW */
206a7c91847Schristos 
207a7c91847Schristos #endif /* NO_EXT_METHOD */
208a7c91847Schristos 
209a7c91847Schristos #endif /* CLIENT_SUPPORT */
210