xref: /openbsd/gnu/usr.bin/cvs/vms/rcmd.c (revision 50bf276c)
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