1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unixio.h>
5
6 #include <errno.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <netdb.h>
10
rcmd(char ** remote_hostname,int remote_port,char * local_user,char * remote_user,char * command,int zero)11 int rcmd(char **remote_hostname, int remote_port,
12 char *local_user, char *remote_user,
13 char *command, int zero)
14 {
15 struct hostent *remote_hp;
16 struct hostent *local_hp;
17 struct sockaddr_in remote_isa;
18 struct sockaddr_in local_isa;
19 char local_hostname[80];
20 char ch;
21 int s;
22 int local_port;
23 int rs;
24
25 remote_hp = gethostbyname(*remote_hostname);
26 if(!remote_hp)
27 {
28 perror("couldn't get remote host address");
29 exit(-1);
30 }
31
32 /* Copy remote IP address into socket address structure */
33 remote_isa.sin_family = AF_INET;
34 remote_isa.sin_port = htons(remote_port);
35 memcpy(&remote_isa.sin_addr, remote_hp->h_addr, sizeof(remote_isa.sin_addr));
36
37 gethostname(local_hostname, 80);
38 local_hp = gethostbyname(local_hostname);
39 if(!local_hp)
40 {
41 perror("couldn't get local host address");
42 exit(-1);
43 }
44
45 /* Copy local IP address into socket address structure */
46 local_isa.sin_family = AF_INET;
47 memcpy(&local_isa.sin_addr, local_hp->h_addr, sizeof(local_isa.sin_addr));
48
49 /* Create the local socket */
50 s = socket(AF_INET, SOCK_STREAM, 0);
51 if(s < 0)
52 {
53 perror("socket failed\n");
54 exit(-1);
55 }
56
57 /* Bind local socket with a port from IPPORT_RESERVED/2 to IPPORT_RESERVED - 1
58 this requires the OPER privilege under VMS -- to allow communication with
59 a stock rshd under UNIX */
60
61 for(local_port = IPPORT_RESERVED - 1; local_port >= IPPORT_RESERVED/2; local_port--)
62 {
63 local_isa.sin_port = htons(local_port);
64 rs = bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
65 if(rs == 0)
66 break;
67 }
68
69 /* Bind local socket to an unprivileged port. A normal rshd will drop the
70 connection; you must be running a patched rshd invoked through inetd for
71 this connection method to work */
72
73 if (rs != 0)
74 for(local_port = IPPORT_USERRESERVED - 1;
75 local_port > IPPORT_RESERVED;
76 local_port--)
77 {
78 local_isa.sin_port = htons(local_port);
79 rs = bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
80 if(rs == 0)
81 break;
82 }
83
84 rs = connect(s, (struct sockaddr *) &remote_isa, sizeof(remote_isa));
85 if(rs == -1)
86 {
87 fprintf(stderr, "connect: errno = %d\n", errno);
88 close(s);
89 exit(-2);
90 }
91
92 /* Now supply authentication information */
93
94 /* Auxiliary port number for error messages, we don't use it */
95 write(s, "0\0", 2);
96
97 /* Who are we */
98 write(s, local_user, strlen(local_user) + 1);
99
100 /* Who do we want to be */
101 write(s, remote_user, strlen(remote_user) + 1);
102
103 /* What do we want to run */
104 write(s, command, strlen(command) + 1);
105
106 /* NUL is sent back to us if information is acceptable */
107 read(s, &ch, 1);
108 if(ch != '\0')
109 {
110 errno = EPERM;
111 return -1;
112 }
113
114 return s;
115 }
116