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 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 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