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