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