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