1 /* Rsh.c */
2 /**********************************************************************************************************
3 Copyright (c) 2002-2013 Abdul-Rahman Allouche. All rights reserved
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 documentation files (the Gabedit), to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
8 and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9
10 The above copyright notice and this permission notice shall be included in all copies or substantial portions
11 of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
14 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
16 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17 DEALINGS IN THE SOFTWARE.
18 ************************************************************************************************************/
19
20 /****************************************************************
21 * *
22 * Execute a shell command in remote host *
23 * rsh - Remote Shell Client for Windows 95/98 system *
24 * rsh - Remote Shell Client using rsh system *
25 * command for a unix/Linux system *
26 * *
27 ****************************************************************/
28 #include "../../Config.h"
29 #include <glib.h> /* definition of G_OS_WIN32 if windows */
30 #include "../Common/Global.h"
31 #include "../Utils/UtilsInterface.h"
32 #include "../Utils/Utils.h"
33
34 #ifdef G_OS_WIN32
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <winsock.h>
40 #include <fcntl.h>
41 #include <io.h>
42
43 /* local socket address structure */
44 struct sockaddr_in anaddr;
45
46 /* server socket address structure */
47 struct sockaddr_in saddr;
48
49 /* the local rsh port; determined dynamically */
50 u_short rshPort;
51
52 /* the local rsh port for client FileErr output */
53 u_short rshErrPort;
54
55 /* the remote rsh port; basically, the 'shell' port from services */
56 u_short rshSPort;
57
58 /* the rsh protocol ("tcp") */
59 u_short rshProto;
60
61 /* the rsh client socket for outgoing connections */
62 SOCKET rshClient=INVALID_SOCKET;
63
64 /* the rsh client socket for FileErr input */
65 SOCKET rshClientErr=INVALID_SOCKET;
66
67 char userName[64];
68 char cmd[4096];
69
70 /* set when a connection has been detected on the FileErr channel */
71 int FileErrFlag=0;
72
73 /* socket options variables */
74 int on=1;
75 struct linger linger;
76 static FILE* FileErr = NULL;
77 static FILE* FileOut = NULL;
78
79 /********************************************************************
80 * winsockError :displays the current Winsock error in text format *
81 ********************************************************************/
winsockError()82 void winsockError()
83 {
84 int errCode;
85
86 fprintf(FileErr, "Winsock error: ");
87
88 errCode=WSAGetLastError();
89 switch(errCode)
90 {
91 case WSAENETDOWN:
92 fprintf(FileErr, "The network subsystem has failed.\n");
93 break;
94 case WSAEINTR:
95 fprintf(FileErr, "A blocking call was cancelled. This can be caused by\n1) a short response time, or\n2) User interrupts the process.\n");
96 break;
97 case WSAEINPROGRESS:
98 fprintf(FileErr, "A blocking call is in progress.\n");
99 break;
100 case WSAENOBUFS:
101 fprintf(FileErr, "No buffer space is available.\n");
102 break;
103 case WSAENOTSOCK:
104 fprintf(FileErr, "Invalid socket descriptor.\n");
105 break;
106 case WSAEADDRINUSE:
107 fprintf(FileErr, "The specified address is already in use.\n");
108 break;
109 case WSAEADDRNOTAVAIL:
110 fprintf(FileErr, "The specified address is not available\nfrom the local machine.\n");
111 break;
112 case WSAECONNREFUSED:
113 fprintf(FileErr, "The connection attempt was refused.\n");
114 break;
115 case WSAEINVAL:
116 fprintf(FileErr, "The socket is not bound to an address.\n");
117 break;
118 case WSAEISCONN:
119 fprintf(FileErr, "The socket is already connected.\n");
120 break;
121 case WSAEMFILE:
122 fprintf(FileErr, "The maximum number of sockets has exceeded.\n");
123 break;
124 case WSAENETUNREACH:
125 fprintf(FileErr, "Network cannot be reached from this host at this time.\n");
126 break;
127 case WSAETIMEDOUT:
128 fprintf(FileErr, "Attempt to connect timed out without establishing a connection.\n");
129 break;
130 case WSAENOTCONN:
131 fprintf(FileErr, "The socket is not connected.\n");
132 break;
133 case WSAESHUTDOWN:
134 fprintf(FileErr, "The socket has been shut down.\n");
135 break;
136 case WSAECONNABORTED:
137 fprintf(FileErr, "The virtual circuit was aborted due to timeout or other failure.\n");
138 break;
139 case WSAECONNRESET:
140 fprintf(FileErr, "The virtual circuit was reset by the remote side.\n");
141 break;
142 case WSAEACCES:
143 fprintf(FileErr, "The requested address is a broadcast address.\n");
144 break;
145 case WSAENETRESET:
146 fprintf(FileErr, "The connection must be reset.\n");
147 break;
148 case WSAHOST_NOT_FOUND:
149 fprintf(FileErr, "Authoritative Answer Host is not found.\n");
150 break;
151 default:
152 fprintf(FileErr, "%d.\n", errCode);
153 break;
154 }
155 }
156
157 /************************************************************************
158 * error : display an error message and possibly the last Winsock error *
159 *************************************************************************/
error(char * message,int ex)160 void error (char* message, int ex)
161 {
162 fprintf(FileErr,"%s\n",message);
163 /* Message(message,"Error",TRUE);*/
164 winsockError();
165 if(ex)
166 {
167 WSACleanup();
168 return;
169 }
170 }
171
172 /************************************************************************
173 * rresvport : the windows hack of rresvport; *
174 * bind a socket to a reserved port using the given protocol, if any *
175 ************************************************************************/
rresvport(u_short * alport,int sProto)176 int rresvport (u_short* alport, int sProto)
177 {
178 struct sockaddr_in sin;
179 int s;
180
181 sin.sin_family=AF_INET;
182 sin.sin_addr.s_addr=INADDR_ANY;
183 s=socket(AF_INET, SOCK_STREAM, sProto);
184 if(s<0)
185 return -1;
186
187 for((*alport)=IPPORT_RESERVED-1; (*alport)>IPPORT_RESERVED/2; (*alport)--)
188 {
189 sin.sin_port=htons((u_short)(*alport));
190 if(bind(s, (struct sockaddr*)&sin, sizeof(sin))==0)
191 return s;
192
193 if(WSAGetLastError()!=WSAEADDRINUSE)
194 break;
195 }
196 /* ran out of available ports or weird error; shouldn't happen too often...*/
197 closesocket(s);
198 return -1;
199 }
200 /****************************************************
201 * send to the server the assembled command buffer *
202 *****************************************************/
sendcommand(const char * buff,int bufflen,SOCKET rshClient,int flag)203 void sendcommand (const char* buff, int bufflen, SOCKET rshClient,int flag)
204 {
205 if(send(rshClient, buff, bufflen, flag) < bufflen)
206 error("Error sending command.", 0);
207 }
208
209
210 /****************************************************
211 * receive : receive a string from the given socket *
212 *****************************************************/
receive(SOCKET rshClient,char * buff,int blen)213 int receive (SOCKET rshClient, char* buff, int blen)
214 {
215 int bufflen;
216 int totallen=0;
217 do
218 {
219 bufflen=recv(rshClient, buff+totallen, blen-totallen, 0);
220 if(bufflen==SOCKET_ERROR)
221 return bufflen;
222 totallen+=bufflen;
223 } while(bufflen && totallen<blen && buff[bufflen-1]);
224 if(!totallen)
225 buff[0]=0;
226 buff[totallen]=0;
227 return totallen;
228 }
229
230 /************************************************
231 * hostCheck : check the remote host name and *
232 * fill the server address structure *
233 *************************************************/
hostCheck(const char * hostname)234 gboolean hostCheck (const char* hostname)
235 {
236 memset(&saddr, 0, sizeof(saddr));
237 saddr.sin_addr.s_addr=inet_addr(hostname);
238 if(saddr.sin_addr.s_addr==(u_long)INADDR_NONE)
239 {
240 /*
241 we must have gotten a host name instead
242 of an IP address; resolve!
243 */
244 struct hostent* hostInfo=gethostbyname(hostname);
245 if(!hostInfo)
246 {
247 error("Invalid hostname!",1);
248 return FALSE;
249 }
250 memcpy((void*)&saddr.sin_addr.s_addr, hostInfo->h_addr, hostInfo->h_length);
251 }
252 return TRUE;
253 }
254
255 /********************************************************
256 * initSocket : standard socket initialization procedure *
257 *********************************************************/
initSocket()258 gboolean initSocket ()
259 {
260 /* get port number for rsh */
261 struct servent FAR* sp=getservbyname("shell", "tcp");
262 LPPROTOENT lpProto;
263 if(sp==NULL)
264 {
265 error("Cannot determine port number for the rsh client.",1);
266 return FALSE;
267 }
268 rshSPort=htons(sp->s_port);
269
270 /* get protocol number for tcp */
271 lpProto=getprotobyname("tcp");
272 if(!lpProto)
273 rshProto=IPPROTO_TCP;
274 else
275 rshProto=lpProto->p_proto;
276
277 /* create socket */
278 rshClient=rresvport(&rshPort, rshProto);
279 if(rshClient==INVALID_SOCKET)
280 {
281 error("Cannot allocate socket for the rsh client.",1);
282 return FALSE;
283 }
284 if(setsockopt(rshClient, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on))<0)
285 {
286 error("Cannot set SO_KEEPALIVE!\n", 0);
287 return FALSE;
288 }
289 linger.l_onoff=1;
290 linger.l_linger=60;
291 if(setsockopt(rshClient, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger))<0)
292 {
293 error("Cannot set SO_LINGER!\n", 0);
294 return FALSE;
295 }
296 return TRUE;
297 }
298
299 /********************************************************************
300 * openErrSocket : an additional socket is created for FileErr output *
301 *********************************************************************/
initErrSocket()302 gboolean initErrSocket ()
303 {
304 /* create the new socket and bind it to the client FileErr port */
305 rshErrPort=IPPORT_RESERVED-1;
306 rshClientErr=rresvport(&rshErrPort,0);
307 if(rshClientErr==INVALID_SOCKET)
308 {
309 error("Cannot create FileErr socket!", 0);
310 return FALSE;
311 }
312
313 if(setsockopt(rshClientErr, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on))<0)
314 error("Cannot set SO_KEEPALIVE!", 0);
315 linger.l_onoff=0;
316 linger.l_linger=60;
317 if(setsockopt(rshClientErr, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger))<0)
318 error("Cannot set SO_LINGER!", 0);
319 /* now listen... */
320 if(listen(rshClientErr, 5))
321 error("Cannot listen!",1);
322 return TRUE;
323 }
324
325 /********************************************************
326 * rsh_command : pass the command string to the rsh server *
327 * and retrieve the results *
328 *********************************************************/
rsh_command(const char * cmd,const char * userName)329 void rsh_command (const char* cmd, const char* userName)
330 {
331 char cmdbuff[2048];
332 int cmdbufflen=0;
333 char buff[2048];
334 int respbufflen;
335 int firstbuf;
336 int i = 0;
337
338 /*memset(cmdbuff, 0, 2048*sizeof(char));*/
339 for(i=0;i<2047;i++)
340 {
341 cmdbuff[i] = ' ';
342 }
343 /* local FileErr port */
344 sprintf(cmdbuff+cmdbufflen, "%d", rshErrPort);
345 cmdbufflen=strlen(cmdbuff)+1;
346 /* remot user */
347 strcpy(cmdbuff+cmdbufflen, userName);
348 cmdbufflen+=strlen(userName)+1;
349 /* local user */
350 strcpy(cmdbuff+cmdbufflen, userName);
351 cmdbufflen+=strlen(userName)+1;
352 /* command */
353 strcpy(cmdbuff+cmdbufflen, cmd);
354 cmdbufflen+=strlen(cmd)+1;
355
356 sendcommand(cmdbuff, cmdbufflen, rshClient,0);
357
358 /* for some reason first buffer has nul char at begining */
359 /* Debug("End Send command\n");*/
360 firstbuf = 1;
361 if(!strstr(cmd,"&"))
362 while((respbufflen=receive(rshClient, buff, 2047))>0)
363 {
364 fprintf(FileOut, "%s", buff);
365 /* fwrite(buff, respbufflen, 1, FileOut);*/
366 }
367 }
368
369 /********************************************************
370 * clientThread : this is the FileErr client thread; *
371 * it is started before sending the command string *
372 * to the server; its purpose is to accept connections *
373 * from the server and receive the FileErr output *
374 *********************************************************/
clientThread()375 long clientThread ()
376 {
377 struct sockaddr anaddr;
378 int len=sizeof(anaddr);
379 char buff[2048];
380
381 SOCKET rshServer=accept(rshClientErr, (struct sockaddr FAR*)&anaddr, &len);
382 if(rshServer==INVALID_SOCKET)
383 {
384 error("Error connecting to the FileErr server port!", 0);
385 return 0;
386 }
387
388 FileErrFlag=1; /* mark connection made*/
389
390 while(receive(rshServer, buff, 2047)>0)
391 fprintf(FileErr, "%s", buff);
392 FileErrFlag=0;
393 closesocket(rshClientErr);
394 shutdown(rshClientErr, 2);
395 closesocket(rshServer);
396 shutdown(rshServer, 2);
397
398
399 return 0;
400 }
401
402 /********************************************************
403 * rsh : main processing routine; connect to server, *
404 * pass command line and wait for results *
405 *********************************************************/
rsh(char * fout,char * ferr,const char * cmd,const char * hostname,const char * userName,char * passwod)406 void rsh (char *fout,char *ferr,const char* cmd,
407 const char *hostname,const char* userName,char *passwod)
408 {
409 HANDLE threadHnd = NULL;
410
411 FileOut = FOpen(fout,"w");
412 FileErr = FOpen(ferr,"w");
413
414 /*
415 Debug("fout=%s\n",fout);
416 Debug("fout=%s\n",ferr);
417
418 Debug("Begin winsockCheck\n");
419 */
420 if( !winsockCheck(FileErr) )
421 goto closeall;
422
423 /*
424 Debug("End winsockCheck\n");
425
426 Debug("Begin hostCeck\n");
427 */
428 if( !hostCheck(hostname) )
429 goto closeall;
430
431 /*
432 Debug("End hostCeck\n");
433
434 Debug("Begin initSocket\n");
435 */
436 if( !initSocket() )
437 goto closeall;
438
439 /* Debug("End initSocket\n");*/
440
441 if(!initErrSocket())
442 {
443 error("Cannot create error socket!", 0);
444 goto closeall;
445 }
446
447 saddr.sin_family=AF_INET;
448 saddr.sin_port=rshSPort;
449 if(connect(rshClient, (struct sockaddr FAR*)&saddr, sizeof(saddr)))
450 {
451 error("Cannot connect to RSH port!\n",1);
452 goto closeall;
453 }
454
455
456 if(rshClientErr!=INVALID_SOCKET)
457 {
458 DWORD threadID;
459 threadHnd=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)clientThread,
460 (LPVOID)0, 0, (LPDWORD)&threadID);
461 if(!threadHnd)
462 {
463 error("Cannot start client thread...",1);
464 goto closeall;
465 }
466 }
467 /* Debug("cmd = %sg\n",cmd);*/
468 rsh_command(cmd, userName);
469 /* Debug("End rsh_command\n");*/
470 closesocket(rshClient);
471 shutdown(rshClient, 2);
472
473 if(!strstr(cmd,"&"))
474 if(threadHnd)
475 {
476 DWORD exitCode=0;
477 GetExitCodeThread(threadHnd, &exitCode);
478 while(exitCode==STILL_ACTIVE && FileErrFlag)
479 {
480 Sleep(50);
481 GetExitCodeThread(threadHnd, &exitCode);
482 }
483 CloseHandle(threadHnd);
484 }
485 if(strstr(cmd,"&") && threadHnd)
486 {
487 Sleep(500);
488 shutdown(rshClientErr, 2);
489 }
490
491 /* Debug("End rThread\n");*/
492 WSACleanup();
493
494 closeall :
495 if(FileOut)
496 fclose(FileOut);
497 if(FileErr)
498 fclose(FileErr);
499
500 }
501 #else /* G_SO_WIN32 */
502 /********************************************************
503 * rsh : main processing routine; connect to server, *
504 * pass command line and wait for results *
505 *********************************************************/
506 #include <stdlib.h>
507
rsh(char * fout,char * ferr,const char * cmd,const char * hostname,const char * userName,char * passwod)508 void rsh (char *fout,char *ferr,const char* cmd,
509 const char *hostname,const char* userName,char *passwod)
510 {
511 gchar *commandrcp;
512 commandrcp = g_strdup_printf(
513 "sh -c \"sh -c 'rsh -l%s %s %s' >%s 2>%s\"",
514 userName,hostname,cmd,
515 fout,ferr);
516 /* Debug("%s\n",commandrcp);*/
517 {int ierr = system(commandrcp);}
518 g_free(commandrcp);
519 }
520 #endif /* G_SO_WIN32 */
521 /*********************************************************/
522
523