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