Ejemplo n.º 1
0
/*
 * 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 );
	}
}
Ejemplo n.º 2
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;
}