- updated to 1.9.1
[packages/proxytunnel.git] / proxytunnel-git.patch
1 diff --git a/.gitignore b/.gitignore
2 new file mode 100644
3 index 0000000..c15583a
4 --- /dev/null
5 +++ b/.gitignore
6 @@ -0,0 +1,4 @@
7 +*.o
8 +*.exec
9 +proxytunnel.exe
10 +proxytunnel
11 diff --git a/.travis.yml b/.travis.yml
12 new file mode 100644
13 index 0000000..1348562
14 --- /dev/null
15 +++ b/.travis.yml
16 @@ -0,0 +1,14 @@
17 +language: c
18 +compiler:
19 +  - clang
20 +  - gcc
21 +addons:
22 +  apt:
23 +    packages:
24 +    - asciidoc
25 +    - xmlto
26 +install:
27 +  - make clean
28 +script:
29 +  - make
30 +  - make docs
31 \ No newline at end of file
32 diff --git a/Makefile b/Makefile
33 index 006b5b1..57328e8 100644
34 --- a/Makefile
35 +++ b/Makefile
36 @@ -5,17 +5,9 @@
37  name = proxytunnel
38  version = $(shell awk 'BEGIN { FS="\"" } /^\#define VERSION / { print $$2 }' config.h)
39  
40 -ifneq ($(wildcard .svn),)
41 -revision = $(shell svnversion | awk 'BEGIN { RS=":" } { next } END { print $$1 }')
42 -else
43 -revision = $(shell echo '$$Revision$$' | sed -e 's/\$$Revision: \([0-9]\+\) \$$$$/\1/')
44 -endif
45 -
46  CC ?= cc
47  CFLAGS ?= -Wall -O2 -ggdb
48  
49 -OPTFLAGS = -DREVISION=\"$(revision)\"
50 -
51  # Comment on non-gnu systems
52  OPTFLAGS += -DHAVE_GETOPT_LONG
53  
54 @@ -46,9 +38,9 @@ OPTFLAGS += -DSO_REUSEPORT
55  
56  # END system dependant block
57  
58 -SSL_LIBS := $(shell pkg-config --libs libssl 2>/dev/null)
59 -ifeq ($(SSL_LIBS),)
60  SSL_LIBS := $(shell pkg-config --libs openssl 2>/dev/null)
61 +ifeq ($(SSL_LIBS),)
62 +SSL_LIBS := $(shell pkg-config --libs libssl 2>/dev/null)
63  endif
64  ifeq ($(SSL_LIBS),)
65  SSL_LIBS := -lssl -lcrypto
66 @@ -63,8 +55,6 @@ mandir = $(datadir)/man
67  # Remove strlcpy/strlcat on (open)bsd/darwin systems
68  OBJ = proxytunnel.o    \
69         base64.o        \
70 -       strlcpy.o       \
71 -       strlcat.o       \
72         strzcat.o       \
73         setproctitle.o  \
74         io.o            \
75 @@ -76,9 +66,15 @@ OBJ = proxytunnel.o  \
76         ntlm.o          \
77         ptstream.o
78  
79 +UNAME = $(shell uname)
80 +ifneq ($(UNAME),Darwin)
81 +OBJ += strlcpy.o       \
82 +       strlcat.o
83 +endif
84 +
85  .PHONY: all clean docs install
86  
87 -all: proxytunnel docs
88 +all: proxytunnel
89  
90  docs:
91         $(MAKE) -C docs
92 @@ -91,7 +87,8 @@ clean:
93         $(MAKE) -C docs clean
94  
95  install:
96 -       install -Dp -m0755 $(name) $(DESTDIR)$(bindir)/$(name)
97 +       install -d $(DESTDIR)$(bindir)
98 +       install -p -m555 $(name) $(DESTDIR)$(bindir)
99         $(MAKE) -C docs install
100  
101  .c.o:
102 diff --git a/README b/README
103 index 1c30836..bdb7fe3 100644
104 --- a/README
105 +++ b/README
106 @@ -3,8 +3,6 @@ proxytunnel
107  -----------
108  
109  Author:                Jos Visser <josv@osp.nl>, Mark Janssen <maniac@maniac.nl>
110 -Date:          Mon Mar  3 22:49:43 CET 2008
111 -Version:       1.9.0
112  
113  Hi all,
114  
115 @@ -22,27 +20,32 @@ Proxytunnel is very easy to use, when running proxytunnel with the help
116  option it specifies it's command-line options.
117  
118  $ ./proxytunnel --help
119 -proxytunnel 1.9.0 (rev 224) Copyright 2001-2008 Proxytunnel Project
120 +proxytunnel 1.9.9 Copyright 2001-2018 Proxytunnel Project
121  Usage: proxytunnel [OPTIONS]...
122 -Build generic tunnels trough HTTPS proxy's, supports HTTP authorization
123 +Build generic tunnels through HTTPS proxies using HTTP authentication
124  
125  Standard options:
126 - -i, --inetd               Run from inetd (default=off)
127 + -i, --inetd               Run from inetd (default: off)
128   -a, --standalone=INT      Run as standalone daemon on specified port
129   -p, --proxy=STRING        Local proxy host:port combination
130   -r, --remproxy=STRING     Remote proxy host:port combination (using 2 proxies)
131   -d, --dest=STRING         Destination host:port combination
132   -e, --encrypt             SSL encrypt data between local proxy and destination
133   -E, --encrypt-proxy       SSL encrypt data between client and local proxy
134 - -X, --encrypt-remproxy    Encrypt between 1st and 2nd proxy using SSL
135 + -X, --encrypt-remproxy    SSL encrypt data between local and remote proxy
136 + -L                        (legacy) enforce TLSv1 connection
137 + -T, --no-ssl3             Do not connect using SSLv3
138  
139  Additional options for specific features:
140 + -z, --no-check-certficate Don't verify server SSL certificate
141 + -C, --cacert=STRING       Path to trusted CA certificate or directory
142   -F, --passfile=STRING     File with credentials for proxy authentication
143   -P, --proxyauth=STRING    Proxy auth credentials user:pass combination
144 - -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination
145 + -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination 
146   -N, --ntlm                Use NTLM based authentication
147   -t, --domain=STRING       NTLM domain (default: autodetect)
148   -H, --header=STRING       Add additional HTTP headers to send to proxy
149 + -o STRING                 send custom Host Header
150   -x, --proctitle=STRING    Use a different process title
151  
152  Miscellaneous options:
153 @@ -51,7 +54,6 @@ Miscellaneous options:
154   -h, --help                Print help and exit
155   -V, --version             Print version and exit
156  
157 -
158  To use this program with OpenSSH to connect to a host somewhere, create
159  a $HOME/.ssh/config file with the following content:
160  
161 diff --git a/TODO b/TODO
162 index 4339a0f..45c19e4 100644
163 --- a/TODO
164 +++ b/TODO
165 @@ -8,14 +8,11 @@
166  
167  
168  ### SSL proxy support
169 -- Lobby for the Apache project to allow CONNECT over SSL (much like GET,
170 -  PUT and HEAD is supported over SSL)
171 -  see: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744
172 +- Starting with Apache 2.4 using CONNECT over SSL is supported !!
173 +  See: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744
174  
175  
176  ### Code cleanup
177 -- Fix permissions in subversion tree (some files are wrongly executable)
178 -
179  - Find some hardcore C experts to help us improve the code quality
180  
181  - Improve the error output, make it consistent throughout the program
182 diff --git a/cmdline.c b/cmdline.c
183 index 15ebe98..e1ee9b0 100644
184 --- a/cmdline.c
185 +++ b/cmdline.c
186 @@ -38,14 +38,14 @@ extern char * optarg;
187  static char *getCredentialsFromFile( const char* filename, char **user, char **pass, char **rem_user, char **rem_pass);
188  
189  void cmdline_parser_print_version (void) {
190 -       printf ("%s %s (rev %s) Copyright 2001-2008 Proxytunnel Project\n", PACKAGE, VERSION, REVISION);
191 +       printf ("%s %s Copyright 2001-2018 Proxytunnel Project\n", PACKAGE, VERSION);
192  }
193  
194  void cmdline_parser_print_help (void) {
195         cmdline_parser_print_version ();
196         printf(
197  "Usage: %s [OPTIONS]...\n"
198 -"Build generic tunnels trough HTTPS proxies using HTTP authentication\n"
199 +"Build generic tunnels through HTTPS proxies using HTTP authentication\n"
200  "\n"
201  "Standard options:\n"
202  // FIXME: "   -c, --config=FILE       Read config options from file\n"
203 @@ -59,9 +59,15 @@ void cmdline_parser_print_help (void) {
204  " -e, --encrypt             SSL encrypt data between local proxy and destination\n"
205  " -E, --encrypt-proxy       SSL encrypt data between client and local proxy\n"
206  " -X, --encrypt-remproxy    SSL encrypt data between local and remote proxy\n"
207 +" -L                        (legacy) enforce TLSv1 connection\n"
208 +" -T, --no-ssl3             Do not connect using SSLv3\n"
209  #endif
210  "\n"
211  "Additional options for specific features:\n"
212 +#ifdef USE_SSL
213 +" -z, --no-check-certficate Don't verify server SSL certificate\n"
214 +" -C, --cacert=STRING       Path to trusted CA certificate or directory\n"
215 +#endif
216  " -F, --passfile=STRING     File with credentials for proxy authentication\n"
217  " -P, --proxyauth=STRING    Proxy auth credentials user:pass combination\n"
218  " -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination\n"
219 @@ -72,6 +78,7 @@ void cmdline_parser_print_help (void) {
220  " -N, --ntlm                Use NTLM based authentication\n"
221  " -t, --domain=STRING       NTLM domain (default: autodetect)\n"
222  " -H, --header=STRING       Add additional HTTP headers to send to proxy\n"
223 +" -o STRING                 send custom Host Header\n"
224  #ifdef SETPROCTITLE
225  " -x, --proctitle=STRING    Use a different process title\n"
226  #endif
227 @@ -132,6 +139,9 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
228         args_info->encryptproxy_given = 0;
229         args_info->encryptremproxy_given = 0;
230         args_info->proctitle_given = 0;
231 +       args_info->enforcetls1_given = 0;
232 +       args_info->host_given = 0;
233 +       args_info->cacert_given = 0;
234  
235  /* No... we can't make this a function... -- Maniac */
236  #define clear_args() \
237 @@ -156,8 +166,13 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
238         args_info->encrypt_flag = 0; \
239         args_info->encryptproxy_flag = 0; \
240         args_info->encryptremproxy_flag = 0; \
241 +       args_info->no_ssl3_flag = 0; \
242         args_info->proctitle_arg = NULL; \
243 -} 
244 +       args_info->enforcetls1_flag = 0; \
245 +       args_info->host_arg = NULL; \
246 +       args_info->no_check_cert_flag = 0; \
247 +       args_info->cacert_arg = NULL; \
248 +}
249  
250         clear_args();
251  
252 @@ -189,6 +204,8 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
253                         { "remproxy",           1, NULL, 'r' },
254                         { "remproxyauth",       1, NULL, 'R' },
255                         { "proctitle",          1, NULL, 'x' },
256 +                       { "host",           1, NULL, 'o' },
257 +                       { "tlsenforce",     1, NULL, 'L' },
258                         { "header",                     1, NULL, 'H' },
259                         { "verbose",            0, NULL, 'v' },
260                         { "ntlm",                       0, NULL, 'N' },
261 @@ -198,12 +215,15 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
262                         { "encrypt",            0, NULL, 'e' },
263                         { "encrypt-proxy",      0, NULL, 'E' },
264                         { "encrypt-remproxy",0,NULL, 'X' },
265 +                       { "no-ssl3",            0, NULL, 'T' },
266 +                       { "no-check-certificate",0,NULL,'z' },
267 +                       { "cacert",         1, NULL, 'C' },
268                         { NULL,                         0, NULL, 0 }
269                 };
270  
271 -               c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq", long_options, &option_index);
272 +               c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:", long_options, &option_index);
273  #else
274 -               c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq" );
275 +               c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:" );
276  #endif
277  
278                 if (c == -1)
279 @@ -262,6 +282,18 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
280                                 args_info->proctitle_arg = gengetopt_strdup (optarg);
281                                 break;
282  
283 +                       case 'L':
284 +                               args_info->enforcetls1_given = 1;
285 +                               message("Enforcing TLSv1");
286 +                               args_info->enforcetls1_flag = 1;
287 +                               break;
288 +
289 +                       case 'o':
290 +                               args_info->host_given = 1;
291 +                               message("Host-header override enabled\n");
292 +                               args_info->host_arg = gengetopt_strdup (optarg);
293 +                               break;
294 +
295                         case 'u':       /* Username to send to HTTPS proxy for authentication.  */
296                                 if (args_info->user_given) {
297                                         fprintf (stderr, "%s: `--user' (`-u'), `--proxyauth' (`-P') or `--passfile' (`-F') option given more than once\n", PACKAGE);
298 @@ -370,6 +402,11 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
299                                         message("SSL local to remote proxy enabled\n");
300                                 break;
301  
302 +                       case 'T':   /* Turn off SSLv3 */
303 +                               args_info->no_ssl3_flag = !(args_info->no_ssl3_flag);
304 +                               if( args_info->verbose_flag )
305 +                                       message("SSLv3 disabled\n");
306 +                               break;
307  
308                         case 'd':       /* Destination host to built the tunnel to.  */
309                                 if (args_info->dest_given) {
310 @@ -403,6 +440,22 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
311                                 args_info->quiet_flag = !(args_info->quiet_flag);
312                                 break;
313  
314 +                       case 'z':       /* Don't verify server SSL certificate */
315 +                               args_info->no_check_cert_flag = 1;
316 +                               if( args_info->verbose_flag )
317 +                                       message("Server SSL certificate verification disabled\n");
318 +                               break;
319 +
320 +                       case 'C':       /* Trusted CA certificate (or directory) for server SSL certificate verification */
321 +                               if (args_info->cacert_given) {
322 +                                       fprintf (stderr, "%s: `--cacert' (`-C') option given more than once\n", PACKAGE);
323 +                                       clear_args ();
324 +                                       exit(1);
325 +                               }
326 +                               args_info->cacert_given = 1;
327 +                               args_info->cacert_arg = gengetopt_strdup (optarg);
328 +                               break;
329 +
330                         case 0: /* Long option with no short option */
331  
332                         case '?':       /* Invalid option.  */
333 @@ -461,10 +514,11 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
334  
335         if ( args_info->proxy_arg == NULL ) {
336                 if ( ((tmp = getenv("http_proxy")) != NULL) || ((tmp = getenv("HTTP_PROXY")) != NULL) ) {
337 -                       int r;
338 +                       //int r;
339                         char * temp;
340                         temp = malloc( 56+1 );
341 -                       r = sscanf( tmp, "http://%56[^/]/", temp );
342 +                       sscanf( tmp, "http://%56[^/]/", temp );
343 +                       //r = sscanf( tmp, "http://%56[^/]/", temp );
344  //                     message( "r = '%d'\ntemp = '%s'\n", r, temp);
345  
346                         args_info->proxy_given = 1;
347 @@ -474,7 +528,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
348                 }
349         }
350  
351 -       if (! args_info->proxy_given || ! args_info->dest_given ) {
352 +       if (! args_info->proxy_given && ! args_info->dest_given ) {
353                 clear_args ();
354  //             cmdline_parser_print_help ();
355                 message( "No proxy or destination given, exiting\nUse '--help' flag for usage info\n" );
356 @@ -482,12 +536,23 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
357         }
358  
359         if (args_info->proxy_given ) {
360 +               char proxy_arg_fmt[32];
361 +               size_t proxy_arg_len;
362                 char * phost;
363                 int pport;
364  
365 -               phost = malloc( 50+1 );
366 -
367 -               r = sscanf( args_info->proxy_arg, "%50[^:]:%5u", phost, &pport );
368 +               proxy_arg_len = strlen( args_info->proxy_arg );
369 +               if ( (phost = malloc( proxy_arg_len + 1 )) == NULL ) {
370 +                       message( "Out of memory\n" );
371 +                       exit(1);
372 +               }
373 +               snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "%%%zu[^:]:%%5u", proxy_arg_len - 1 );
374 +               r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport );
375 +               if ( r != 2 ) {
376 +                       /* try bracket-enclosed IPv6 literal */
377 +                       snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "[%%%zu[^]]]:%%5u", proxy_arg_len - 1 );
378 +                       r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport );
379 +               }
380                 if ( r == 2 ) {
381                         args_info->proxyhost_arg = phost;
382                         args_info->proxyport_arg = pport;
383 diff --git a/cmdline.h b/cmdline.h
384 index 2eccab7..cd85191 100644
385 --- a/cmdline.h
386 +++ b/cmdline.h
387 @@ -47,7 +47,12 @@ struct gengetopt_args_info {
388         int encrypt_flag;               /* Turn on SSL encryption (default=off). */
389         int encryptproxy_flag;  /* Turn on client to proxy SSL encryption (def=off).*/
390         int encryptremproxy_flag;  /* Turn on local to remote proxy SSL encryption (def=off).*/
391 +       int no_ssl3_flag;               /* Turn off SSLv3 (default=on) */
392         char *proctitle_arg;    /* Override process title (default=off). */
393 +       int enforcetls1_flag;    /* Override default and enforce TLSv1 */
394 +       char *host_arg;         /* Optional Host Header */
395 +       int no_check_cert_flag; /* Turn off server SSL certificate verification (default=on) */
396 +       char *cacert_arg;               /* Trusted CA certificate (or directory) for server SSL certificate verification */
397         int help_given;                 /* Whether help was given. */
398         int version_given;              /* Whether version was given. */
399         int user_given;                 /* Whether user was given. */
400 @@ -71,6 +76,9 @@ struct gengetopt_args_info {
401         int encryptproxy_given; /* Whether encrypt was given */
402         int encryptremproxy_given;   /* Whether encrypt was given */
403         int proctitle_given;    /* Whether to override process title */
404 +       int enforcetls1_given;   /* Wheter to enforce TLSv1 */
405 +       int host_given;         /* Wheter we override the Host Header */
406 +       int cacert_given;               /* Whether cacert was given */
407  };
408  
409  int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info );
410 diff --git a/config.h b/config.h
411 index 4e73de1..204ded5 100644
412 --- a/config.h
413 +++ b/config.h
414 @@ -17,7 +17,7 @@
415   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
416   */
417  
418 -#define VERSION "1.9.0"
419 +#define VERSION "1.9.9"
420  #define PACKAGE "proxytunnel"
421  #define PURPOSE "Build generic tunnels through HTTPS proxies"
422  #define AUTHORS "Jos Visser (Muppet) <josv@osp.nl>, Mark Janssen (Maniac) <maniac@maniac.nl>"
423 diff --git a/contrib/proxytunnel.spec b/contrib/proxytunnel.spec
424 index 0c0493d..69cd62e 100644
425 --- a/contrib/proxytunnel.spec
426 +++ b/contrib/proxytunnel.spec
427 @@ -47,7 +47,7 @@ proxy authentication.
428  
429  %files
430  %defattr(-, root, root, 0755)
431 -%doc CHANGES CREDITS INSTALL KNOWN_ISSUES LICENSE.txt README RELNOTES TODO docs/*.txt docs/*.html
432 +%doc CHANGES CREDITS INSTALL KNOWN_ISSUES LICENSE.txt README RELNOTES TODO docs/*.adoc docs/*.html
433  %doc %{_mandir}/man1/proxytunnel.1*
434  %{_bindir}/proxytunnel
435  
436 diff --git a/docs/Makefile b/docs/Makefile
437 index 09babbb..f313c38 100644
438 --- a/docs/Makefile
439 +++ b/docs/Makefile
440 @@ -2,25 +2,26 @@ prefix = /usr/local
441  datadir = $(prefix)/share
442  mandir = $(datadir)/man
443  
444 -txttargets = $(shell echo *.txt)
445 -htmltargets = $(patsubst %.txt, %.html, $(txttargets))
446 +adoctargets = $(shell echo *.adoc)
447 +htmltargets = $(patsubst %.adoc, %.html, $(adoctargets))
448  
449  docs: proxytunnel.1 $(htmltargets)
450  
451  install: proxytunnel.1
452 -       install -Dp -m0644 proxytunnel.1 $(DESTDIR)$(mandir)/man1/proxytunnel.1
453 +       install -d $(DESTDIR)$(mandir)/man1
454 +       install -p proxytunnel.1 $(DESTDIR)$(mandir)/man1
455  
456  clean:
457         rm -f proxytunnel.1 *.html *.xml
458  
459 -%.1.html: %.1.txt
460 +%.1.html: %.1.adoc
461         asciidoc -d manpage $<
462  
463  %.1: %.1.xml
464         xmlto man $<
465  
466 -%.html: %.txt
467 +%.html: %.adoc
468         asciidoc $<
469  
470 -%.1.xml: %.1.txt
471 +%.1.xml: %.1.adoc
472         asciidoc -b docbook -d manpage $<
473 diff --git a/docs/proxytunnel-paper.txt b/docs/proxytunnel-paper.adoc
474 similarity index 100%
475 rename from docs/proxytunnel-paper.txt
476 rename to docs/proxytunnel-paper.adoc
477 diff --git a/docs/proxytunnel.1.txt b/docs/proxytunnel.1.adoc
478 similarity index 90%
479 rename from docs/proxytunnel.1.txt
480 rename to docs/proxytunnel.1.adoc
481 index 03fa427..a884207 100644
482 --- a/docs/proxytunnel.1.txt
483 +++ b/docs/proxytunnel.1.adoc
484 @@ -49,6 +49,20 @@ also be used for other proxy-traversing purposes like proxy bouncing.
485  
486  == ADDITIONAL OPTIONS
487  
488 +*-T*, *--no-ssl3*::
489 +    Prevent the use of SSLv3 in encrypted connections (default: enabled)
490 +
491 +*-z*, *--no-check-certificate*::
492 +    Do not verify server SSL certificate when establishing an SSL connection.
493 +    By default, the server SSL certficate is verified and the target host name
494 +    is checked against the server certificate's subject alternative names if
495 +    any are present, or common name if there are no subject alternative names.
496 +
497 +*-C*, *--cacert*=_filename/directory_::
498 +    Specify a CA certificate file (or directory containing CA certificate(s))
499 +    to trust when verifying a server SSL certificate. If a directory is provided,
500 +    it must be prepared with OpenSSL's c_rehash tool. (default: /etc/ssl/certs)
501 +
502  *-F*, *--passfile*=_filename_::
503      Use _filename_ for reading username and password for HTTPS proxy
504      authentication, the file uses the same format as .wgetrc and can be shared
505 diff --git a/http.c b/http.c
506 index 3b7f6b9..3b85418 100644
507 --- a/http.c
508 +++ b/http.c
509 @@ -105,11 +105,11 @@ void proxy_protocol(PTSTREAM *pts) {
510         if (args_info.remproxy_given ) {
511                 if( args_info.verbose_flag )
512                         message( "\nTunneling to %s (remote proxy)\n", args_info.remproxy_arg );
513 -               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.remproxy_arg, args_info.remproxy_arg );
514 +               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.remproxy_arg, args_info.host_arg ? args_info.host_arg : args_info.remproxy_arg );
515         } else {
516                 if( args_info.verbose_flag )
517                         message( "\nTunneling to %s (destination)\n", args_info.dest_arg );
518 -               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.dest_arg );
519 +               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.host_arg ? args_info.host_arg : args_info.proxyhost_arg );
520         }
521         
522         if ( args_info.user_given && args_info.pass_given ) {
523 @@ -157,13 +157,13 @@ void proxy_protocol(PTSTREAM *pts) {
524                 while ( strcmp( buf, "\r\n" ) != 0 )
525                         readline(pts);
526  
527 -/* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */
528 -       if ( args_info.encryptremproxy_flag )
529 -               stream_enable_ssl(stunnel);
530 +               /* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */
531 +               if ( args_info.encryptremproxy_flag )
532 +                       stream_enable_ssl(stunnel, args_info.remproxy_arg);
533  
534                 if( args_info.verbose_flag )
535                         message( "\nTunneling to %s (destination)\n", args_info.dest_arg );
536 -               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.dest_arg);
537 +               sprintf( buf, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n", args_info.dest_arg, args_info.host_arg ? args_info.host_arg : args_info.dest_arg);
538  
539                 if ( args_info.remuser_given && args_info.rempass_given )
540                         strzcat( buf, "Proxy-Authorization: Basic %s\r\n", basicauth(args_info.remuser_arg, args_info.rempass_arg ));
541 diff --git a/io.c b/io.c
542 index acbcde7..e8df31a 100644
543 --- a/io.c
544 +++ b/io.c
545 @@ -29,6 +29,8 @@
546  #include "proxytunnel.h"
547  #include "io.h"
548  
549 +#define ACTIVE 1
550 +#define CLOSED 0
551  
552  /*
553   * Read one line of data from the tunnel. Line is terminated by a
554 @@ -41,7 +43,7 @@ int readline(PTSTREAM *pts) {
555  
556         /* Read one character at a time into buf, until a newline is encountered. */
557         while ( c != 10 && ( i < SIZE - 1 ) ) {
558 -               if( stream_read( pts, &c ,1) < 0) {
559 +               if( stream_read( pts, &c ,1) <= 0) {
560                         my_perror( "Socket read error" );
561                         exit( 1 );
562                 }
563 @@ -55,8 +57,8 @@ int readline(PTSTREAM *pts) {
564  
565         if( args_info.verbose_flag ) {
566                 /* Copy line of data into dstr without trailing newline */
567 -               char *dstr = malloc(sizeof(buf) + 1);
568 -               strlcpy( dstr, buf, strlen(buf) - 1);
569 +               char *dstr = malloc(strlen(buf) + 1);
570 +               strncpy( dstr, buf, strlen(buf));
571                 if (strcmp(dstr, ""))
572                         message( " <- %s\n", dstr );
573         }
574 @@ -81,11 +83,17 @@ void cpio(PTSTREAM *stream1, PTSTREAM *stream2) {
575         /* We are never interested in sockets being available for write */
576         FD_ZERO( &writefds );
577  
578 +
579 +       /* experimental timeout */
580 +       struct timeval select_timeout;
581 +       select_timeout.tv_sec = 30; /* should be fine */
582 +       select_timeout.tv_usec = 0;
583 +
584         if( args_info.verbose_flag )
585                 message( "\nTunnel established.\n" );
586  
587 -       /* Only diamonds are forever :-) */
588 -       while( 1==1 ) {
589 +        int stream_status = ACTIVE;
590 +       while( stream_status == ACTIVE ) {
591                 /* Clear the interesting socket sets */
592                 FD_ZERO( &readfds );
593                 FD_ZERO( &exceptfds );
594 @@ -99,32 +107,37 @@ void cpio(PTSTREAM *stream1, PTSTREAM *stream2) {
595                 FD_SET( stream_get_outgoing_fd(stream1), &exceptfds );
596                 FD_SET( stream_get_incoming_fd(stream2), &exceptfds );
597                 FD_SET( stream_get_outgoing_fd(stream2), &exceptfds );
598 -
599 -               /* Wait until something happens on the registered sockets/files */
600 -               if ( select( max_fd + 1, &readfds, &writefds, &exceptfds, 0 ) < 0 ) {
601 +                
602 +                /* reset the timeout, since select() does modify this struct! */
603 +                select_timeout.tv_sec = 30;
604 +                select_timeout.tv_usec = 0;
605 +
606 +               /* Wait/timeout something happens on the registered sockets/files */
607 +               int number_of_fds_ready;
608 +               number_of_fds_ready = select( max_fd + 1, &readfds, &writefds, &exceptfds, &select_timeout );
609 +               if ( number_of_fds_ready < 0 ) {
610                         perror("select error");
611                         exit(1);
612                 }
613  
614 -               /*
615 -                * Is stream1 ready for read? If so, copy a block of data
616 -                * from stream1 to stream2. Or else if stream2
617 -                * is ready for read, copy a block of data from the
618 -                * stream2 to stream1. Otherwise an exceptional condition
619 -                * is flagged and the program is terminated.
620 -                */
621 -               if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) ) {
622 -                       if ( stream_copy(stream1, stream2 ) )
623 -                               break;
624 -               } else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) ) {
625 -                       if( stream_copy(stream2, stream1 ) )
626 -                               break;
627 -               } else {
628 -                       my_perror( "Exceptional condition" );
629 -                       break;
630 -               }
631 +               if (number_of_fds_ready > 0) {
632 +                       /* Is stream1 ready for read? If so, copy a block of data
633 +                        * from stream1 to stream2. Or else if stream2
634 +                        * is ready for read, copy a block of data from the
635 +                        * stream2 to stream1. Otherwise an exceptional condition
636 +                        * is flagged and the program is terminated.
637 +                        */
638 +                       if ( FD_ISSET( stream_get_incoming_fd(stream1), &readfds ) ) {
639 +                               if ( stream_copy(stream1, stream2 ) )
640 +                                       stream_status = CLOSED;
641 +                       } else if( FD_ISSET( stream_get_incoming_fd(stream2), &readfds ) ) {
642 +                               if( stream_copy(stream2, stream1 ) )
643 +                                       stream_status = CLOSED;
644 +                       } else {
645 +                               my_perror( "Exceptional condition" );
646 +                               stream_status = CLOSED;
647 +                       }
648 +               } 
649         }
650         closeall();
651  }
652 -
653 -// vim:noexpandtab:ts=4
654 diff --git a/proxytunnel.c b/proxytunnel.c
655 index 9844e3d..18aa414 100644
656 --- a/proxytunnel.c
657 +++ b/proxytunnel.c
658 @@ -66,45 +66,44 @@ void signal_handler( int signal ) {
659   * the socket that is connected to the proxy
660   */
661  int tunnel_connect() {
662 -       struct sockaddr_in sa;
663 -       struct hostent *he;
664 +       struct addrinfo hints = {
665 +               .ai_family = AF_UNSPEC,
666 +               .ai_socktype = SOCK_STREAM,
667 +               .ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV,
668 +               .ai_protocol = 0
669 +       };
670 +       struct addrinfo * result, * rp;
671 +       int rc;
672 +       char service[6];
673         int sd;
674  
675 -       /* Create the socket */
676 -       if( ( sd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
677 -               my_perror("Can not create socket");
678 +       rc = snprintf( service, sizeof(service), "%d", args_info.proxyport_arg );
679 +       if( ( rc < 0 ) || ( rc >= sizeof(service) ) ) {
680 +               /* this should never happen */
681 +               message( "snprintf() failed" );
682                 exit(1);
683         }
684 -
685 -       /* Lookup the IP address of the proxy */
686 -       if( ! ( he = gethostbyname( args_info.proxyhost_arg ) ) ) {
687 -// FIXME:      my_perror("Local proxy %s could not be resolved", args_info.proxyhost_arg);
688 -               my_perror("Local proxy could not be resolved." );
689 +       rc = getaddrinfo( args_info.proxyhost_arg, service, &hints, &result );
690 +       if( rc != 0 ) {
691 +               message( "getaddrinfo() failed to resolve local proxy: %s\n",
692 +                       gai_strerror( rc ) );
693                 exit(1);
694         }
695
696 -       char ip[16];
697 -       snprintf(ip, 16, "%d.%d.%d.%d", he->h_addr[0] & 255, he->h_addr[1] & 255, he->h_addr[2] & 255, he->h_addr[3] & 255);
698 -       if( args_info.verbose_flag && strcmp(args_info.proxyhost_arg, ip)) {
699 -               message( "Local proxy %s resolves to %d.%d.%d.%d\n",
700 -                       args_info.proxyhost_arg,
701 -                       he->h_addr[0] & 255,
702 -                       he->h_addr[1] & 255,
703 -                       he->h_addr[2] & 255,
704 -                       he->h_addr[3] & 255 );
705 +       for (rp = result; rp != NULL; rp = rp->ai_next) {
706 +               sd = socket( rp->ai_family, rp->ai_socktype, rp->ai_protocol );
707 +               if( sd < 0 ) {
708 +                       continue;
709 +               }
710 +               if( connect( sd, rp->ai_addr, rp->ai_addrlen ) == 0 ) {
711 +                       break;
712 +               }
713 +               close(sd);
714         }
715 -
716 -       /* Set up the structure to connect to the proxy port of the proxy host */
717 -       memset( &sa, '\0', sizeof( sa ) );
718 -       sa.sin_family = AF_INET;
719 -       memcpy( &sa.sin_addr.s_addr, he->h_addr, 4);
720 -       sa.sin_port = htons( args_info.proxyport_arg );
721 -
722 -       /* Connect the socket */
723 -       if( connect( sd, (struct sockaddr*) &sa, sizeof( sa ) ) < 0 ) {
724 -               my_perror("connect() failed");
725 +       if( rp == NULL ) {
726 +               my_perror( "failed to connect to local proxy" );
727                 exit(1);
728         }
729 +       freeaddrinfo(result);
730  
731         /* Increase interactivity of tunnel, patch by Ingo Molnar */
732         int flag = 1;
733 @@ -266,7 +265,7 @@ void do_daemon()
734  #ifdef USE_SSL
735                         /* If --encrypt-proxy is specified, connect to the proxy using SSL */
736                         if ( args_info.encryptproxy_flag )
737 -                               stream_enable_ssl(stunnel);
738 +                               stream_enable_ssl(stunnel, args_info.proxy_arg);
739  #endif /* USE_SSL */
740  
741                         /* Open the tunnel */
742 @@ -275,7 +274,7 @@ void do_daemon()
743  #ifdef USE_SSL
744                         /* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
745                         if( args_info.encrypt_flag )
746 -                               stream_enable_ssl(stunnel);
747 +                               stream_enable_ssl(stunnel, args_info.dest_arg);
748  #endif /* USE_SSL */
749  
750  #ifdef SETPROCTITLE
751 @@ -388,7 +387,7 @@ int main( int argc, char *argv[] ) {
752                 /* If --encrypt-proxy is specified, connect to the proxy using SSL */
753  #ifdef USE_SSL
754                 if ( args_info.encryptproxy_flag )
755 -                       stream_enable_ssl(stunnel);
756 +                       stream_enable_ssl(stunnel, args_info.proxy_arg);
757  #endif /* USE_SSL */
758  
759                 /* Open the tunnel */
760 @@ -397,7 +396,7 @@ int main( int argc, char *argv[] ) {
761                 /* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
762  #ifdef USE_SSL
763                 if( args_info.encrypt_flag )
764 -                       stream_enable_ssl(stunnel);
765 +                       stream_enable_ssl(stunnel, args_info.dest_arg);
766  #endif /* USE_SSL */
767  
768  #ifdef SETPROCTITLE
769 diff --git a/proxytunnel.h b/proxytunnel.h
770 index b948be0..593cd7e 100644
771 --- a/proxytunnel.h
772 +++ b/proxytunnel.h
773 @@ -26,14 +26,20 @@ void message( char *s, ... );
774  void my_perror( char *msg );
775  void signal_handler( int signal );
776  int tunnel_connect();
777 -void analyze_HTTP();
778 -void proxy_protocol();
779 +void analyze_HTTP(PTSTREAM *pts);
780 +void proxy_protocol(PTSTREAM *pts);
781  void closeall();
782  void do_daemon();
783  void initsetproctitle(int argc, char *argv[]);
784  void setproctitle(const char *fmt, ...);
785 +
786 +#if defined(__APPLE__) && defined(__MACH__)
787 +/* Don't include strlcat and strlcpy since they are provided as macros on OSX */
788 +#else
789  size_t strlcat(char *dst, const char *src, size_t siz);
790  size_t strlcpy(char *dst, const char *src, size_t siz);
791 +#endif
792 +
793  size_t strzcat(char *dst, char *format, ...);
794  int main( int argc, char *argv[] );
795  char * readpassphrase(const char *, char *, size_t, int);
796 diff --git a/ptstream.c b/ptstream.c
797 index 4c87c80..d1c5f44 100644
798 --- a/ptstream.c
799 +++ b/ptstream.c
800 @@ -19,12 +19,15 @@
801  
802  /* ptstream.c */
803  
804 +#include <arpa/inet.h>
805 +#include <openssl/x509v3.h>
806  #include <stdio.h>
807  #include <stdlib.h>
808  #include <string.h>
809  #include <unistd.h>
810  #include <sys/types.h>
811  #include <sys/socket.h>
812 +#include <sys/stat.h>
813  
814  #include "proxytunnel.h"
815  
816 @@ -142,24 +145,199 @@ int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to) {
817  }
818  
819  
820 +/* Check the certificate host name against the expected host name */
821 +/* Return 1 if peer hostname is valid, any other value indicates failure */
822 +int check_cert_valid_host(const char *cert_host, const char *peer_host) {
823 +       if (cert_host == NULL || peer_host == NULL) {
824 +               return 0;
825 +       }
826 +       if (cert_host[0] == '*') {
827 +               if (strncmp(cert_host, "*.", 2) != 0) {
828 +                       /* Invalid wildcard hostname */
829 +                       return 0;
830 +               }
831 +               /* Skip "*." */
832 +               cert_host += 2;
833 +               /* Wildcards can only match the first subdomain component */
834 +               while (*peer_host++ != '.' && *peer_host != '\0')
835 +                       ;;
836 +       }
837 +       if (strlen(cert_host) == 0 || strlen(peer_host) == 0) {
838 +               return 0;
839 +       }
840 +       return strcmp(cert_host, peer_host) == 0;
841 +}
842 +
843 +
844 +int check_cert_valid_ip6(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in6_addr *addr6) {
845 +       int i;
846 +       for (i = 0; i < cert_ip_len; i++) {
847 +               if (cert_ip_data[i] != addr6->s6_addr[i]) {
848 +                       return 0;
849 +               }
850 +       }
851 +       return 1;
852 +}
853 +
854 +
855 +int check_cert_valid_ip(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in_addr *addr) {
856 +       int i;
857 +       for (i = 0; i < cert_ip_len; i++) {
858 +               if (cert_ip_data[i] != ((addr->s_addr >> (i * 8)) & 0xFF)) {
859 +                       return 0;
860 +               }
861 +       }
862 +       return 1;
863 +}
864 +
865 +
866 +int check_cert_names(X509 *cert, char *peer_host) {
867 +       char peer_cn[256];
868 +       const GENERAL_NAME *gn;
869 +       STACK_OF(GENERAL_NAME) *gen_names;
870 +       struct in_addr addr;
871 +       struct in6_addr addr6;
872 +       int peer_host_is_ipv4 = 0, peer_host_is_ipv6 = 0;
873 +       int i, san_count;
874 +
875 +       gen_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
876 +       san_count = sk_GENERAL_NAME_num(gen_names);
877 +       if (san_count > 0) {
878 +               peer_host_is_ipv4 = (inet_pton(AF_INET, peer_host, &addr) == 1);
879 +               peer_host_is_ipv6 = (peer_host_is_ipv4 ? 0 : inet_pton(AF_INET6, peer_host, &addr6) == 1);
880 +               for (i = 0; i < san_count; i++) {
881 +                       gn = sk_GENERAL_NAME_value(gen_names, i);
882 +                       if (gn->type == GEN_DNS && !(peer_host_is_ipv4 || peer_host_is_ipv6)) {
883 +                               if (check_cert_valid_host((char*)ASN1_STRING_data(gn->d.ia5), peer_host)) {
884 +                                       return 1;
885 +                               }
886 +                       } else if (gn->type == GEN_IPADD) {
887 +                               if (gn->d.ip->length == 4 && peer_host_is_ipv4) {
888 +                                       if (check_cert_valid_ip(gn->d.ip->data, gn->d.ip->length, &addr)) {
889 +                                               return 1;
890 +                                       }
891 +                               } else if (gn->d.ip->length == 16 && peer_host_is_ipv6) {
892 +                                       if (check_cert_valid_ip6(gn->d.ip->data, gn->d.ip->length, &addr6)) {
893 +                                               return 1;
894 +                                       }
895 +                               }
896 +                       }
897 +               }
898 +               message("Host name %s does not match certificate subject alternative names\n", peer_host);
899 +       } else {
900 +               X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_cn, sizeof(peer_cn));
901 +               message("Host name %s does not match certificate common name %s or any subject alternative names\n", peer_host, peer_cn);
902 +               return check_cert_valid_host(peer_cn, peer_host);
903 +       }
904 +       return 0;
905 +}
906 +
907  /* Initiate an SSL handshake on this stream and encrypt all subsequent data */
908 -int stream_enable_ssl(PTSTREAM *pts) {
909 +int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) {
910  #ifdef USE_SSL
911 -       SSL_METHOD *meth;
912 +       const SSL_METHOD *meth;
913         SSL *ssl;
914         SSL_CTX *ctx;
915 -       
916 +       long res = 1;
917 +       long ssl_options = 0;
918 +
919 +       X509* cert = NULL;
920 +       int status;
921 +       struct stat st_buf;
922 +       const char *ca_file = NULL;
923 +       const char *ca_dir = "/etc/ssl/certs/"; /* Default cert directory if none given */
924 +       long vresult;
925 +       char *peer_host = NULL;
926 +       char proxy_arg_fmt[32];
927 +       size_t proxy_arg_len;
928 +
929         /* Initialise the connection */
930         SSLeay_add_ssl_algorithms();
931 -       meth = SSLv3_client_method();
932 +       if (args_info.enforcetls1_flag) {
933 +               meth = TLSv1_client_method();
934 +       } else {
935 +               meth = SSLv23_client_method();
936 +       }
937         SSL_load_error_strings();
938  
939         ctx = SSL_CTX_new (meth);
940 +       if (args_info.no_ssl3_flag) {
941 +               ssl_options |= SSL_OP_NO_SSLv3;
942 +       }
943 +       SSL_CTX_set_options (ctx, ssl_options);
944 +
945 +       if ( !args_info.no_check_cert_flag ) {
946 +               if ( args_info.cacert_given ) {
947 +                       if ((status = stat(args_info.cacert_arg, &st_buf)) != 0) {
948 +                               message("Error reading certificate path %s\n", args_info.cacert_arg);
949 +                               goto fail;
950 +                       }
951 +                       if (S_ISDIR(st_buf.st_mode)) {
952 +                               ca_dir = args_info.cacert_arg;
953 +                       } else {
954 +                               ca_dir = NULL;
955 +                               ca_file = args_info.cacert_arg;
956 +                       }
957 +               }
958 +               if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) {
959 +                       message("Error loading certificate(s) from %s\n", args_info.cacert_arg);
960 +                       goto fail;
961 +               }
962 +       }
963 +
964         ssl = SSL_new (ctx);
965 +       
966         SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
967         SSL_set_wfd (ssl, stream_get_outgoing_fd(pts)); 
968 +
969 +       /* Determine the host name we are connecting to */
970 +       proxy_arg_len = strlen(proxy_arg);
971 +       if ((peer_host = malloc(proxy_arg_len + 1)) == NULL) {
972 +               message("Out of memory\n");
973 +               goto fail;
974 +       }
975 +       snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), proxy_arg[0] == '[' ? "[%%%zu[^]]]" : "%%%zu[^:]", proxy_arg_len - 1 );
976 +       if ( sscanf( proxy_arg, proxy_arg_fmt, peer_host ) != 1 ) {
977 +               goto fail;
978 +       }
979 +
980 +       /* SNI support */
981 +       if ( args_info.verbose_flag ) {
982 +               message( "Set SNI hostname to %s\n", peer_host);
983 +       }
984 +       res = SSL_set_tlsext_host_name(ssl, peer_host);
985 +       if (res < 0) {
986 +               message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n  %u\n", res );
987 +               exit( 1 );
988 +       }
989 +       
990         SSL_connect (ssl);
991  
992 +       if ( !args_info.no_check_cert_flag ) {
993 +               /* Make sure peer presented a certificate */
994 +               cert = SSL_get_peer_certificate(ssl);
995 +               if (cert == NULL) {
996 +                       message("No certificate presented\n");
997 +                       goto fail;
998 +               }
999 +
1000 +               /* Check that the certificate is valid */
1001 +               vresult = SSL_get_verify_result(ssl);
1002 +               if (vresult != X509_V_OK) {
1003 +                       message("Certificate verification failed (%s)\n",
1004 +                                       X509_verify_cert_error_string(vresult));
1005 +                       goto fail;
1006 +               }
1007 +
1008 +               /* Verify the certificate name matches the host we are connecting to */
1009 +               if (!check_cert_names(cert, peer_host)) {
1010 +                       goto fail;
1011 +               }
1012 +
1013 +               free(peer_host);
1014 +               X509_free(cert);
1015 +       }
1016 +
1017         /* Store ssl and ctx parameters */
1018         pts->ssl = ssl;
1019         pts->ctx = ctx;
1020 @@ -168,6 +346,17 @@ int stream_enable_ssl(PTSTREAM *pts) {
1021  #endif /* USE_SSL */
1022  
1023         return 1;
1024 +
1025 +fail:
1026 +#ifdef USE_SSL
1027 +       if (cert != NULL) {
1028 +               X509_free(cert);
1029 +       }
1030 +       if (peer_host != NULL) {
1031 +               free(peer_host);
1032 +       }
1033 +#endif /* USE_SSL */
1034 +       exit(1);
1035  }
1036  
1037  
1038 diff --git a/ptstream.h b/ptstream.h
1039 index e7efd43..ee36af2 100644
1040 --- a/ptstream.h
1041 +++ b/ptstream.h
1042 @@ -44,7 +44,7 @@ int stream_close(PTSTREAM *pts);
1043  int stream_read(PTSTREAM *pts, void *buf, size_t len);
1044  int stream_write(PTSTREAM *pts, void *buf, size_t len);
1045  int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to);
1046 -int stream_enable_ssl(PTSTREAM *pts);
1047 +int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg);
1048  int stream_get_incoming_fd(PTSTREAM *pts);
1049  int stream_get_outgoing_fd(PTSTREAM *pts);
1050  
1051 diff --git a/readpassphrase.c b/readpassphrase.c
1052 index 1870700..b107624 100644
1053 --- a/readpassphrase.c
1054 +++ b/readpassphrase.c
1055 @@ -135,8 +135,13 @@ restart:
1056                 oterm.c_lflag |= ECHO;
1057         }
1058  
1059 -       if (!(flags & RPP_STDIN))
1060 -               (void)write(output, prompt, strlen(prompt));
1061 +       if (!(flags & RPP_STDIN)) {
1062 +               ssize_t bytes_written = write(output, prompt, strlen(prompt));
1063 +               if (bytes_written != strlen(prompt)) {
1064 +                       message("Error on writing bytes to prompt\n");
1065 +               }
1066 +       }
1067 +
1068         end = buf + bufsiz - 1;
1069         for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) {
1070                 if (p < end) {
1071 @@ -153,8 +158,12 @@ restart:
1072         }
1073         *p = '\0';
1074         save_errno = errno;
1075 -       if (!(term.c_lflag & ECHO))
1076 -               (void)write(output, "\n", 1);
1077 +       if (!(term.c_lflag & ECHO)) {
1078 +               ssize_t bytes_written = write(output, "\n", 1);
1079 +               if (bytes_written != 1) {
1080 +                       message("Error writing one byte to prompt\n");
1081 +               }
1082 +       }
1083  
1084         /* Restore old terminal settings and signals. */
1085         if (memcmp(&term, &oterm, sizeof(term)) != 0) {
This page took 0.172377 seconds and 4 git commands to generate.