Commit d0c0689e3ce9f57db360d5d1206090211ddd92c5
v1.1
Yves Rutschle committed on 7/10/2013, 9:06:51 PMParent: d7e9cbb655626718177c36988d3b63a579dbfb66
Files changed
sslh.c | changed |
sslh.c | ||
---|---|---|
@@ -27,11 +27,24 @@ | ||
27 | 27 | |
28 | 28 | LynxOS: |
29 | 29 | gcc -o tcproxy tcproxy.c -lnetinet |
30 | 30 | |
31 | +HISTORY | |
32 | + | |
33 | +v1.1: 21MAY2007 | |
34 | + Making sslhc more like a real daemon: | |
35 | + * If $PIDFILE is defined, write first PID to it upon startup | |
36 | + * Fork at startup (detach from terminal) | |
37 | + (thanks to http://www.enderunix.org/docs/eng/daemon.php -- good checklist) | |
38 | + * Less memory usage (?) | |
39 | + | |
40 | +v1.0: | |
41 | + * Basic functionality: privilege dropping, target hostnames and ports | |
42 | + configurable. | |
43 | + | |
31 | 44 | */ |
32 | 45 | |
33 | - | |
46 | + | |
34 | 47 | |
35 | 48 | |
36 | 49 | |
37 | 50 | |
@@ -39,8 +52,9 @@ | ||
39 | 52 | |
40 | 53 | |
41 | 54 | |
42 | 55 | |
56 | + | |
43 | 57 | |
44 | 58 | |
45 | 59 | |
46 | 60 | |
@@ -50,10 +64,13 @@ | ||
50 | 64 | perror(str); \ |
51 | 65 | exit(1); \ |
52 | 66 | } |
53 | 67 | |
54 | - | |
68 | + | |
69 | +"\texport PIDFILE=/var/run/sslhc.pid" \ | |
70 | +"\tsslh [-t <timeout>] -u <username> -p <listenport> -s [sshhost:]port -l [sslhost:]port [-v]\n" | |
55 | 71 | |
72 | +int verbose = 0; /* That's really quite global */ | |
56 | 73 | |
57 | 74 | /* Starts a listening socket on specified port. |
58 | 75 | Returns file descriptor |
59 | 76 | */ |
@@ -127,41 +144,40 @@ | ||
127 | 144 | |
128 | 145 | if (FD_ISSET(fd1, &fds)) { |
129 | 146 | res = fd2fd(fd2, fd1); |
130 | 147 | if (!res) { |
131 | - printf("client socket closed\n"); | |
148 | + if (verbose) fprintf(stderr, "client socket closed\n"); | |
132 | 149 | return res; |
133 | 150 | } |
134 | 151 | } |
135 | 152 | |
136 | 153 | if (FD_ISSET(fd2, &fds)) { |
137 | 154 | res = fd2fd(fd1, fd2); |
138 | 155 | if (!res) { |
139 | - printf("server socket closed\n"); | |
156 | + if (verbose) fprintf(stderr, "server socket closed\n"); | |
140 | 157 | return res; |
141 | 158 | } |
142 | 159 | } |
143 | 160 | } |
144 | 161 | } |
145 | 162 | |
146 | -/* returns a static string that prints the IP and port of the sockaddr */ | |
147 | -char* get_addr(struct sockaddr* s) | |
163 | +/* returns a string that prints the IP and port of the sockaddr */ | |
164 | +char* sprintaddr(char* buf, size_t size, struct sockaddr* s) | |
148 | 165 | { |
149 | 166 | char addr_str[1024]; |
150 | - static char addr_name[1024]; | |
151 | 167 | |
152 | 168 | inet_ntop(AF_INET, &((struct sockaddr_in*)s)->sin_addr, addr_str, sizeof(addr_str)); |
153 | - snprintf(addr_name, sizeof(addr_name), "%s:%d", addr_str,ntohs(((struct sockaddr_in*)s)->sin_port)); | |
154 | - return addr_name; | |
169 | + snprintf(buf, size, "%s:%d", addr_str, ntohs(((struct sockaddr_in*)s)->sin_port)); | |
170 | + return buf; | |
155 | 171 | } |
156 | 172 | |
157 | 173 | /* turns a "hostname:port" string into a struct sockaddr; |
158 | 174 | sock: socket address to which to copy the addr |
159 | 175 | fullname: input string -- it gets clobbered |
160 | 176 | serv: default service/port |
161 | 177 | (defaults don't work yet) |
162 | 178 | */ |
163 | -int resolve_name(struct sockaddr *sock, char* fullname, int port) { | |
179 | +void resolve_name(struct sockaddr *sock, char* fullname, int port) { | |
164 | 180 | struct addrinfo *addr, hint; |
165 | 181 | char *serv, *host; |
166 | 182 | int res; |
167 | 183 | |
@@ -194,13 +210,12 @@ | ||
194 | 210 | memcpy(sock, addr->ai_addr, sizeof(*sock)); |
195 | 211 | } |
196 | 212 | |
197 | 213 | /* |
198 | - * Settings that depend on the command line. | |
214 | + * Settings that depend on the command line. That's less global than verbose * :-) | |
199 | 215 | * They're set in main(), but also used in start_shoveler(), and it'd be heavy-handed |
200 | 216 | * to pass it all as parameters |
201 | 217 | */ |
202 | -int verbose = 0; | |
203 | 218 | int timeout = 2; |
204 | 219 | int listen_port = 443; |
205 | 220 | struct sockaddr addr_ssl, addr_ssh; |
206 | 221 | |
@@ -288,21 +303,55 @@ | ||
288 | 303 | setuid(pw->pw_uid); |
289 | 304 | CHECK_RES_DIE(res, "setuid"); |
290 | 305 | } |
291 | 306 | |
307 | +/* Writes my PID if $PIDFILE is defined */ | |
308 | +void write_pid_file(void) | |
309 | +{ | |
310 | + char *pidfile = getenv("PIDFILE"); | |
311 | + FILE *f; | |
312 | + | |
313 | + if (!pidfile) | |
314 | + return; | |
315 | + | |
316 | + f = fopen(pidfile, "w"); | |
317 | + if (!f) { | |
318 | + perror(pidfile); | |
319 | + exit(1); | |
320 | + } | |
321 | + | |
322 | + fprintf(f, "%d\n", getpid()); | |
323 | + fclose(f); | |
324 | +} | |
325 | + | |
326 | +void printsettings(void) | |
327 | +{ | |
328 | + char buf[64]; | |
329 | + | |
330 | + fprintf( | |
331 | + stderr, | |
332 | + "SSL addr: %s (after timeout %ds)\n", | |
333 | + sprintaddr(buf, sizeof(buf), &addr_ssl), | |
334 | + timeout | |
335 | + ); | |
336 | + fprintf(stderr, "SSH addr: %s\n", sprintaddr(buf, sizeof(buf), &addr_ssh)); | |
337 | + fprintf(stderr, "listening on port %d\n", listen_port); | |
338 | +} | |
339 | + | |
292 | 340 | int main(int argc, char *argv[]) |
293 | 341 | { |
294 | 342 | |
295 | 343 | extern char *optarg; |
296 | 344 | extern int optind; |
297 | 345 | int c, res; |
298 | 346 | |
299 | - int in_socket, out_socket, listen_socket; | |
347 | + int in_socket, listen_socket; | |
300 | 348 | |
301 | 349 | /* Init defaults */ |
302 | 350 | char *user_name = "nobody"; |
303 | - char ssl_str[] = "localhost:443"; /* need to copy -- Linux doesn't let write to BSS? */ | |
351 | + char ssl_str[] = "localhost:443"; | |
304 | 352 | char ssh_str[] = "localhost:22"; |
353 | + | |
305 | 354 | resolve_name(&addr_ssl, ssl_str, 443); |
306 | 355 | resolve_name(&addr_ssh, ssh_str, 22); |
307 | 356 | |
308 | 357 | while ((c = getopt(argc, argv, "t:l:s:p:vu:")) != EOF) { |
@@ -337,26 +386,30 @@ | ||
337 | 386 | exit(2); |
338 | 387 | } |
339 | 388 | } |
340 | 389 | |
341 | - if (verbose) { | |
342 | - fprintf(stderr, "SSL addr: %s (after timeout %ds)\n", get_addr(&addr_ssl), timeout); | |
343 | - fprintf(stderr, "SSH addr: %s\n", get_addr(&addr_ssh)); | |
344 | - fprintf(stderr, "listening on port %d\n", listen_port); | |
345 | - } | |
390 | + if (verbose) | |
391 | + printsettings(); | |
346 | 392 | |
347 | - | |
348 | 393 | setup_signals(); |
349 | 394 | |
350 | 395 | listen_socket = start_listen_socket(listen_port); |
351 | 396 | |
397 | + if (fork() > 0) exit(0); /* Detach */ | |
398 | + | |
399 | + write_pid_file(); | |
400 | + | |
352 | 401 | drop_privileges(user_name); |
353 | 402 | |
403 | + /* New session -- become group leader */ | |
404 | + res = setsid(); | |
405 | + CHECK_RES_DIE(res, "setsid: already process leader"); | |
406 | + | |
354 | 407 | /* Main server loop: accept connections, find what they are, fork shovelers */ |
355 | 408 | while (1) |
356 | 409 | { |
357 | 410 | in_socket = accept(listen_socket, 0, 0); |
358 | - fprintf(stderr, "accepted fd %d\n", in_socket); | |
411 | + if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket); | |
359 | 412 | |
360 | 413 | if (!fork()) |
361 | 414 | { |
362 | 415 | start_shoveler(in_socket); |
Built with git-ssb-web