root/trunk/TunnelRunner.c

Revision 99, 3.4 kB (checked in by bart, 1 year ago)

0.8.1

Line 
1 /* $Id: TunnelRunner.c,v 1.1 2004/06/23 08:12:20 bart Exp $ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <sys/select.h>
15
16 #define BUFSIZE 4096
17
18 int child;
19
20 static void sighandler(int s)
21 {
22         if(s != SIGCHLD)
23         {
24                 if(child > 0) {
25                         kill(child, s);
26                 }
27
28                 signal(s, SIG_DFL);
29                 kill(getpid(), s);
30         }
31 }
32
33 int main(int argc, char **argv)
34 {
35         int i, r, devnull, status, p[2];
36         char *em;
37         char buf[BUFSIZE];
38
39         buf[0] = '\0';
40        
41         if(argc == 3 && strstr(argv[1], "-k") != NULL) {
42                 setuid(geteuid());
43                
44                 kill(atoi(argv[2]), SIGTERM);
45                 exit(0);
46         }
47
48         if(argc < 2)
49         {
50                 exit(1);
51         }
52
53         if(strstr(argv[1], "ssh") == NULL)
54         {
55                 exit(1);
56         }
57
58         for(i=1; i < argc; i++) {
59                 argv[i-1] = argv[i];
60                 argv[i] = '\0';
61         }
62
63         /* Handle some signals. */
64         signal(SIGCHLD, sighandler);
65
66         signal(SIGKILL, sighandler);
67         signal(SIGTERM, sighandler);
68         signal(SIGALRM, sighandler);
69         signal(SIGHUP, sighandler);
70         signal(SIGINT, sighandler);
71         signal(SIGQUIT, sighandler);
72         signal(SIGPIPE, sighandler);
73         signal(SIGTERM, sighandler);
74
75         if(pipe(p) == -1)
76         {
77                 em = strerror(errno);
78                 printf("pipe() failed (%s)\n", (em) ? em : "");
79                 return(-1);
80         }
81        
82         setuid(geteuid());
83        
84         child = fork();
85
86         /* If the fork failed. */
87         if(child == -1)
88         {
89                 em = strerror(errno);
90                 printf("fork() failed (%s)\n", (em) ? em : "");
91                 return(-1);
92         }
93
94         /* If we're the child. */
95         if(child == 0)
96         {
97                 /* Close the read end of the pipe. */
98                 close(p[0]);
99
100                 /* Tie the write end of the pipe to stderr. */
101                 if(dup2(p[1], STDERR_FILENO) == -1)
102                 {
103                         em = strerror(errno);
104                         printf("dup2() failed (%s)\n", (em) ? em : "");
105                         exit(1);
106                 }
107
108                 /* We aren't interested in the stuff spewed to stdout. */
109                 if((devnull = open("/dev/null", O_WRONLY)) == -1)
110                 {
111                         em = strerror(errno);
112                         fprintf(stderr, "open failed : %s\n", (em)? em : "");
113                         exit(1);
114                 }
115
116                 /* Now direct stdout to our /dev/null filehandle. */
117                 if(dup2(devnull, STDOUT_FILENO) == -1)
118                 {
119                         em = strerror(errno);
120                         fprintf(stderr, "dup2() failed (%s)\n", (em) ? em : "");
121                         exit(1);
122                 }
123
124                 /* STDIN should block forever, so we tie it to the writ end of the pipe. */
125                 while(dup2(p[1], STDIN_FILENO) == -1)
126                 {
127                         em = strerror(errno);
128                         fprintf(stderr, "dup2() failed (%s)\n", (em) ? em : "");
129                         exit(1);
130                 }
131
132                 /* Execute ssh. */
133                 if(execv(argv[0], argv) == -1)
134                 {
135                         fprintf(stderr, "execv() failed (%s)\n", strerror(errno));
136                         exit(1);
137                 }
138
139                 /* We shouldn't reach this. */
140                 exit(1);
141         }
142
143         /* If we're the father (uh-oh). */
144         if(child > 0)
145         {
146                 /* Close the write end of the pipe. */
147                 close(p[1]);
148
149                 for(;;)
150                 {
151                         /* Read until we get EOF. */
152                         for(;;)
153                         {
154                                 r = read(p[0], buf, BUFSIZE-1);
155
156                                 if((r == -1) && (errno != EINTR))
157                                 {
158                                         em = strerror(errno);
159                                         printf("read() failed : %s\n", (em) ? em : "");
160                                         exit(1);
161                                 }
162
163                                 else if(r == 0)
164                                 {
165                                         /* We got EOF. Wait for ssh to exit. */
166                                         while(waitpid(child, &status, 0) == -1)
167                                         {
168                                                 if(errno == EINTR)
169                                                 {
170                                                         continue;
171                                                 }
172
173                                                 em = strerror(errno);
174                                                 printf("waitpid() failed (%s)\n", (em) ? em : "");
175                                                 exit(1);
176                                         }
177
178                                         exit(0);
179                                 }
180
181                                 else
182                                 {
183                                         buf[r] = '\0';
184
185                                         if((strstr(buf, "Could not request")) && (strstr(buf, "forwarding")))
186                                         {
187                                                 printf("tunnel failed\n");
188                                                 kill(child, SIGTERM);
189                                         }
190                                 }
191                         }
192                 }
193         }
194
195         return(0);
196 }
Note: See TracBrowser for help on using the browser.