/* * Execute the basic proxy protocol of CONNECT and response, until the * last line of the response has been read. The tunnel is then open. */ void proxy_protocol(PTSTREAM *pts) { /* Create the proxy CONNECT command into buf */ if (args_info.remproxy_given ) { if( args_info.verbose_flag ) message( "\nTunneling to %s (remote proxy)\n", args_info.remproxy_arg ); sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.remproxy_arg ); } else { if( args_info.verbose_flag ) message( "\nTunneling to %s (destination)\n", args_info.dest_arg ); sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.dest_arg ); } if ( args_info.user_given && args_info.pass_given ) { /* Create connect string including the authorization part */ if (args_info.ntlm_flag) { if (ntlm_challenge == 1) { build_type3_response(); strzcat( buf, "Proxy-Authorization: NTLM %s\r\n", ntlm_type3_buf ); } else if (ntlm_challenge == 0) { strzcat( buf, "Proxy-Authorization: NTLM %s\r\n", ntlm_type1_buf ); } } else { strzcat( buf, "Proxy-Authorization: Basic %s\r\n", basicauth(args_info.user_arg, args_info.pass_arg ) ); } } strzcat( buf, "Proxy-Connection: Keep-Alive\r\n"); /* Add extra header(s), headers are already \r\n terminated */ if ( args_info.header_given ) strzcat( buf, "%s", args_info.header_arg ); strzcat( buf, "\r\n" ); /* Print the CONNECT instruction before sending to proxy */ if( args_info.verbose_flag ) { message( "Communication with local proxy:\n"); print_line_prefix(buf, " -> "); } /* Send the CONNECT instruction to the proxy */ if( stream_write( pts, buf, strlen( buf )) < 0 ) { my_perror( "Socket write error" ); exit( 1 ); } // if( args_info.verbose_flag ) // message( "Data received from local proxy:\n"); /* Read the first line of the response and analyze it */ analyze_HTTP(pts); if (args_info.remproxy_given ) { /* Clean buffer for next analysis */ while ( strcmp( buf, "\r\n" ) != 0 ) readline(pts); /* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */ if ( args_info.encryptremproxy_flag ) stream_enable_ssl(stunnel); if( args_info.verbose_flag ) message( "\nTunneling to %s (destination)\n", args_info.dest_arg ); sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.dest_arg); if ( args_info.remuser_given && args_info.rempass_given ) strzcat( buf, "Proxy-Authorization: Basic %s\r\n", basicauth(args_info.remuser_arg, args_info.rempass_arg )); strzcat( buf, "Proxy-Connection: Keep-Alive\r\n"); /* Add extra header(s), headers are already \r\n terminated */ if ( args_info.header_given ) strzcat( buf, "%s", args_info.header_arg ); strzcat( buf, "\r\n" ); /* Print the CONNECT instruction before sending to proxy */ if( args_info.verbose_flag ) { message( "Communication with remote proxy:\n"); print_line_prefix(buf, " -> "); } /* Send the CONNECT instruction to the proxy */ if( stream_write( pts, buf, strlen( buf )) < 0 ) { my_perror( "Socket write error" ); exit( 1 ); } // if( args_info.verbose_flag ) // message( "Received from remote proxy:\n"); /* Read the first line of the response and analyze it */ analyze_HTTP(pts); } /* * Then, repeat reading lines of the responses until a blank line * (which signifies the end of the response) is encountered. */ if (ntlm_challenge == 1) { ntlm_challenge = 2; } else { do { readline(pts); } while ( strcmp( buf, "\r\n" ) != 0 ); } }
int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info ) { /* Character of the parsed option. */ int c; /* Tmd retval */ int r; int missing_required_options = 0; args_info->help_given = 0; args_info->version_given = 0; args_info->user_given = 0; args_info->pass_given = 0; args_info->remuser_given = 0; args_info->rempass_given = 0; args_info->proxy_given = 0; args_info->proxyauth_given = 0; args_info->proxyhost_given = 0; args_info->proxyport_given = 0; args_info->dest_given = 0; args_info->remproxy_given = 0; args_info->remproxyauth_given = 0; args_info->verbose_given = 0; args_info->ntlm_given = 0; args_info->inetd_given = 0; args_info->quiet_given = 0; args_info->header_given = 0; args_info->domain_given = 0; args_info->encrypt_given = 0; args_info->encryptproxy_given = 0; args_info->encryptremproxy_given = 0; args_info->proctitle_given = 0; args_info->host_given = 0; /* No... we can't make this a function... -- Maniac */ #define clear_args() \ { \ args_info->user_arg = NULL; \ args_info->pass_arg = NULL; \ args_info->remuser_arg = NULL; \ args_info->rempass_arg = NULL; \ args_info->domain_arg = NULL; \ args_info->proxy_arg = NULL; \ args_info->proxyauth_arg = NULL; \ args_info->proxyhost_arg = NULL; \ args_info->dest_arg = NULL; \ args_info->remproxy_arg = NULL; \ args_info->remproxyauth_arg = NULL; \ args_info->header_arg[0] = '\0'; \ args_info->verbose_flag = 0; \ args_info->ntlm_flag = 0; \ args_info->inetd_flag = 0; \ args_info->quiet_flag = 0; \ args_info->standalone_arg = 0; \ args_info->encrypt_flag = 0; \ args_info->encryptproxy_flag = 0; \ args_info->encryptremproxy_flag = 0; \ args_info->proctitle_arg = NULL; \ args_info->host_arg = NULL; \ } clear_args(); optarg = 0; #ifdef HAVE_GETOPT_LONG optind = 1; opterr = 1; optopt = '?'; #endif while (1) { #ifdef HAVE_GETOPT_LONG int option_index = 0; /* Struct option: Name, Has_arg, Flag, Value */ static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "user", 1, NULL, 'u' }, { "pass", 1, NULL, 's' }, { "domain", 1, NULL, 't' }, // { "uservar", 1, NULL, 'U' }, // { "passvar", 1, NULL, 'S' }, { "passfile", 1, NULL, 'F' }, { "proxy", 1, NULL, 'p' }, { "proxyauth", 1, NULL, 'P' }, { "dest", 1, NULL, 'd' }, { "remproxy", 1, NULL, 'r' }, { "remproxyauth", 1, NULL, 'R' }, { "proctitle", 1, NULL, 'x' }, { "host", 1, NULL, 'o' }, { "header", 1, NULL, 'H' }, { "verbose", 0, NULL, 'v' }, { "ntlm", 0, NULL, 'N' }, { "inetd", 0, NULL, 'i' }, { "standalone", 1, NULL, 'a' }, { "quiet", 0, NULL, 'q' }, { "encrypt", 0, NULL, 'e' }, { "encrypt-proxy", 0, NULL, 'E' }, { "encrypt-remproxy",0,NULL, 'X' }, { NULL, 0, NULL, 0 } }; c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqo:", long_options, &option_index); #else c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqo:" ); #endif if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ clear_args (); cmdline_parser_print_help (); exit(0); #ifdef USE_SSL case 'e': /* Turn on SSL encryption */ args_info->encrypt_flag = !(args_info->encrypt_flag); if( args_info->verbose_flag ) message("SSL enabled\n"); break; case 'E': /* Turn on client to proxy SSL encryption */ args_info->encryptproxy_flag = !(args_info->encryptproxy_flag); if( args_info->verbose_flag ) message("SSL client to proxy enabled\n"); break; #endif case 'i': /* Run from inetd. */ if ( args_info->standalone_arg > 0 ) { fprintf( stderr, "%s: '--inetd' ('-i') conflicts with '--standalone' ('-a')\n", PACKAGE ); clear_args(); exit( 1 ); } args_info->inetd_flag = !(args_info->inetd_flag); break; case 'a': /* Run as standalone daemon */ if ( args_info->inetd_flag ) { fprintf( stderr, "%s: `--standalone' (`-a') conflicts with `--inetd' (`-i')\n", PACKAGE ); clear_args(); exit(1); } if ( ( args_info->standalone_arg = atoi( optarg ) ) < 1 ) { fprintf( stderr, "%s: Illegal port value for `--standalone' (`-a')\n", PACKAGE); clear_args(); exit(1); } break; case 'V': /* Print version and exit. */ clear_args (); cmdline_parser_print_version (); exit(0); case 'x': args_info->proctitle_given = 1; message( "Proctitle override enabled\n" ); args_info->proctitle_arg = gengetopt_strdup (optarg); break; case 'o': args_info->host_given = 1; /* message( "Host-header override enabled\n" ); */ args_info->host_arg = gengetopt_strdup (optarg); break; case 'u': /* Username to send to HTTPS proxy for authentication. */ if (args_info->user_given) { fprintf (stderr, "%s: `--user' (`-u'), `--proxyauth' (`-P') or `--passfile' (`-F') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->user_given = 1; args_info->user_arg = gengetopt_strdup (optarg); message ("Option -u/--user is deprecated, please use -P/--proxyauth user:pass\n"); break; case 's': /* Password to send to HTTPS proxy for authentication. */ if (args_info->pass_given) { fprintf (stderr, "%s: `--pass' (`-s') or `--passfile' (`-F') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->pass_given = 1; args_info->pass_arg = gengetopt_strdup (optarg); message ("Option -s/--pass is deprecated, please use -P/--proxyauth user:pass\n"); break; case 't': /* Env Var with NTLM DOMAIN (when overriding). */ if (args_info->domain_given) { fprintf (stderr, "%s: `--domain' (`-t') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->domain_given = 1; args_info->domain_arg = gengetopt_strdup (optarg); break; case 'F': /* File containing Username & Password to send to HTTPS proxy for authentication. */ if (args_info->user_given) { fprintf (stderr, "%s: `--user' (`-u') or `--passfile' (`-F') option given more than once\n", PACKAGE); clear_args (); exit(1); } if (args_info->pass_given) { fprintf (stderr, "%s: `--pass' (`-s') or `--passfile' (`-F') option given more than once\n", PACKAGE); clear_args (); exit(1); } char *result = getCredentialsFromFile(optarg, &(args_info->user_arg), &(args_info->pass_arg), &(args_info->remuser_arg), &(args_info->rempass_arg) ); if ( args_info->user_arg != NULL ) args_info->user_given = 1; if ( args_info->pass_arg != NULL ) args_info->pass_given = 1; if ( args_info->remuser_arg != NULL ) args_info->remuser_given = 1; if ( args_info->rempass_arg != NULL ) args_info->rempass_given = 1; if( result != NULL ) { fprintf( stderr, "%s: Bad password file for `--passfile' (`-F')\n%s\n", PACKAGE, result); clear_args(); exit(1); } break; case 'p': /* HTTPS Proxy host:port to connect to. */ if (args_info->proxy_given) { fprintf (stderr, "%s: `--proxy' (`-p') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->proxy_given = 1; args_info->proxy_arg = gengetopt_strdup (optarg); break; case 'P': /* HTTPS Proxy auth user:pass for local proxy */ if (args_info->proxyauth_given) { fprintf (stderr, "%s: `--proxyauth' (`-P') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->proxyauth_given = 1; args_info->proxyauth_arg = gengetopt_strdup (optarg); break; case 'r': /* Use a remote proxy */ if (args_info->remproxy_given) { fprintf (stderr, "%s: `--remproxy' (`-r') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->remproxy_given = 1; args_info->remproxy_arg = gengetopt_strdup (optarg); break; case 'R': /* HTTPS Proxy auth user:pass for remote proxy */ if (args_info->remproxyauth_given) { fprintf (stderr, "%s: `--remproxyauth' (`-P') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->remproxyauth_given = 1; args_info->remproxyauth_arg = gengetopt_strdup (optarg); break; case 'X': /* Turn on local to remote proxy SSL encryption */ args_info->encryptremproxy_flag = !(args_info->encryptremproxy_flag); if( args_info->verbose_flag ) message("SSL local to remote proxy enabled\n"); break; case 'd': /* Destination host to built the tunnel to. */ if (args_info->dest_given) { fprintf (stderr, "%s: `--dest' (`-d') option given more than once\n", PACKAGE); clear_args (); exit(1); } args_info->dest_given = 1; args_info->dest_arg = gengetopt_strdup (optarg); break; case 'H': /* Extra headers to send to HTTPS proxy. */ args_info->header_given++; strzcat( args_info->header_arg, "%s\r\n", optarg); break; case 'v': /* Turn on verbosity. */ if (args_info->quiet_flag) { /* -q also on cmd line */ fprintf (stderr, "-v and -q are mutually exclusive\n"); clear_args(); exit(1); } args_info->verbose_flag = !(args_info->verbose_flag); break; case 'N': /* Turn on NTLM. */ args_info->ntlm_flag = !(args_info->ntlm_flag); break; case 'q': /* Suppress messages -- Quiet mode */ args_info->quiet_flag = !(args_info->quiet_flag); break; case 0: /* Long option with no short option */ case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ clear_args(); exit(1); default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c\n", PACKAGE, c); clear_args(); abort(); } /* switch */ } /* while */ /* For Windows quiet is the default output. -- Dag */ #ifdef CYGWIN if (! args_info->verbose_flag ) { args_info->quiet_flag = 1; } #endif /* Get credentials from environment. -- Dag */ char *tmp = NULL; if ( args_info->user_arg == NULL ) { if ( (tmp = getenv("PROXYUSER")) != NULL) { args_info->user_given = 1; args_info->user_arg = gengetopt_strdup (tmp); if( args_info->verbose_flag ) message( "Found user '%s' in env variable PROXYUSER.\n", args_info->user_arg); } } if ( args_info->pass_arg == NULL ) { if ( (tmp = getenv("PROXYPASS")) != NULL ) { args_info->pass_given = 1; args_info->pass_arg = gengetopt_strdup (tmp); if( args_info->verbose_flag ) message( "Found password in env variable PROXYPASS.\n", args_info->pass_arg); } } if ( args_info->remuser_arg == NULL ) { if ( (tmp = getenv("REMPROXYUSER")) != NULL ) { args_info->remuser_given = 1; args_info->user_arg = gengetopt_strdup (tmp); if( args_info->verbose_flag ) message( "Found remote user '%s' in env variable REMPROXYPASS.\n", args_info->remuser_arg); } } if ( args_info->rempass_arg == NULL ) { if ( (tmp = getenv("REMPROXYPASS")) != NULL ) { args_info->rempass_given = 1; args_info->user_arg = gengetopt_strdup (tmp); if( args_info->verbose_flag ) message( "Found remote password in env variable REMPROXYPASS.\n" ); } } if ( args_info->proxy_arg == NULL ) { if ( ((tmp = getenv("http_proxy")) != NULL) || ((tmp = getenv("HTTP_PROXY")) != NULL) ) { int r; char * temp; temp = malloc( 56+1 ); r = sscanf( tmp, "http://%56[^/]/", temp ); // message( "r = '%d'\ntemp = '%s'\n", r, temp); args_info->proxy_given = 1; args_info->proxy_arg = gengetopt_strdup (temp); if( args_info->verbose_flag ) message( "Proxy info found using env variable HTTP_PROXY (%s).\n", args_info->proxy_arg); } } if (! args_info->proxy_given && ! args_info->dest_given ) { clear_args (); // cmdline_parser_print_help (); message( "No proxy or destination given, exiting\nUse '--help' flag for usage info\n" ); exit(1); } if (args_info->proxy_given ) { char * phost; int pport; phost = malloc( 50+1 ); r = sscanf( args_info->proxy_arg, "%50[^:]:%5u", phost, &pport ); if ( r == 2 ) { args_info->proxyhost_arg = phost; args_info->proxyport_arg = pport; args_info->proxyhost_given = 1; args_info->proxyport_given = 1; } else { message( "parse_cmdline: could not find your proxy hostname/ip (%s)\n", args_info->proxy_arg ); missing_required_options++; } } /* Parse -P/--proxyauth information */ if (args_info->proxyauth_given ) { char *puser = NULL; char *ppass = NULL; puser = malloc( 24+1 ); ppass = malloc( 24+1 ); r = sscanf( args_info->proxyauth_arg, "%24[^:]:%24s", puser, ppass ); if ( r == 2 ) { args_info->user_arg = puser; args_info->pass_arg = ppass; args_info->user_given = 1; args_info->pass_given = 1; } else if ( r == 1 ) { args_info->user_arg = args_info->proxyauth_arg; args_info->user_given = 1; } else { message( "parse_cmdline: could not find your proxy auth user/pass\n" ); missing_required_options++; } } /* Parse -R/--remproxyauth information */ if (args_info->remproxyauth_given ) { char *ruser = NULL; char *rpass = NULL; ruser = malloc( 24+1 ); rpass = malloc( 24+1 ); r = sscanf( args_info->remproxyauth_arg, "%24[^:]:%24s", ruser, rpass ); if ( r == 2 ) { args_info->remuser_arg = ruser; args_info->rempass_arg = rpass; args_info->remuser_given = 1; args_info->rempass_given = 1; } else if ( r == 1 ) { args_info->remuser_arg = args_info->remproxyauth_arg; args_info->remuser_given = 1; } else { message( "parse_cmdline: could not find your proxy auth user/pass\n" ); missing_required_options++; } } if ( missing_required_options ) exit(1); return 0; }