From 7c478bd95313f5f23a4c958a745db2134aa03244 Mon Sep 17 00:00:00 2001 From: "stevel@tonic-gate" Date: Tue, 14 Jun 2005 00:00:00 -0700 Subject: OpenSolaris Launch --- .../ssh-http-proxy-connect.c | 284 +++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c (limited to 'usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c') diff --git a/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c b/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c new file mode 100644 index 0000000000..33182730ae --- /dev/null +++ b/usr/src/cmd/ssh/ssh-http-proxy-connect/ssh-http-proxy-connect.c @@ -0,0 +1,284 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * An http client that let's users 'ssh' to the + * outside of the firewall by opening up a connection + * through the http proxy. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proxy-io.h" + +#define DEFAULT_HTTPPROXYPORT "80" +#define CONNECT_STRLEN 256 + +static int debug_flag = 0; + +static void +usage(void) +{ + (void) fprintf(stderr, gettext("Usage: ssh-http-proxy-connect " + "[-h http_proxy_host] [-p http_proxy_port]\n" + "remote_host remote_port\n")); + exit(1); +} + +/* PRINTFLIKE1 */ +static void +debug(const char *format, ...) +{ + char fmtbuf[BUFFER_SIZ]; + va_list args; + + if (debug_flag == 0) { + return; + } + va_start(args, format); + (void) snprintf(fmtbuf, sizeof (fmtbuf), + "ssh-http-proxy: %s\n", format); + (void) vfprintf(stderr, fmtbuf, args); + va_end(args); +} + +static void +signal_handler(int sig) +{ + exit(0); +} + +int +main(int argc, char **argv) +{ + extern char *optarg; + extern int optind; + int retval, err_code, sock, ssh_port; + int version, ret_code; + char *httpproxy = NULL; + char *temp, *httpproxyport = NULL; + char *ssh_host; + char connect_str[CONNECT_STRLEN], connect_reply[BUFFER_SIZ]; + char *ret_string; + struct addrinfo hints, *ai; + struct pollfd fds[2]; + + /* Initialization for variables, set locale and textdomain */ + + (void) setlocale(LC_ALL, ""); + +#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ +#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ +#endif + (void) textdomain(TEXT_DOMAIN); + + /* Set up the signal handler */ + (void) signal(SIGINT, signal_handler); + (void) signal(SIGPIPE, signal_handler); + (void) signal(SIGPOLL, signal_handler); + + while ((retval = getopt(argc, argv, "dp:h:")) != -1) { + switch (retval) { + case 'h': + httpproxy = optarg; + break; + case 'p': + httpproxyport = optarg; + break; + case 'd': + debug_flag = 1; + break; + default: + break; + } + } + + if (optind != argc - 2) { + usage(); + } + + ssh_host = argv[optind++]; + ssh_port = atoi(argv[optind]); + + /* + * If the name of the http proxy were not + * passed on the command line, try the + * user's environment. First try HTTPPROXY. + * If it's not set, try http_proxy. + * Check the url specified for http_proxy + * for errors. + */ + if (httpproxy == NULL) { + if ((httpproxy = getenv("HTTPPROXY")) == NULL) { + /* Try the other environment variable http_proxy */ + if ((temp = getenv("http_proxy")) != NULL) { + temp += strlen("http://"); + if (strpbrk(temp, ":") == NULL) { + /* Malformed url */ + (void) fprintf(stderr, gettext("ssh-http-proxy: " + "Incorrect url specified for http_proxy " + "environment variable\n")); + exit(1); + } + httpproxy = strtok(temp, ":"); + httpproxyport = strtok(NULL, "/"); + } else { + (void) fprintf(stderr, + gettext("ssh-http-proxy: http proxy not specified\n")); + exit(1); + } + } + } + + /* + * Extract the proxy port number from the user's environment. + * Ignored if HTTPPROXY is not set. + */ + if ((httpproxy != NULL) && (httpproxyport == NULL)) { + if ((httpproxyport = getenv("HTTPPROXYPORT")) == NULL) { + httpproxyport = DEFAULT_HTTPPROXYPORT; + } + } + + debug("HTTPPROXY = %s", httpproxy); + debug("HTTPPROXYPORT = %s", httpproxyport); + + bzero(&hints, sizeof (struct addrinfo)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ((err_code = getaddrinfo(httpproxy, httpproxyport, &hints, &ai)) + != 0) { + (void) fprintf(stderr, "ssh-http-proxy: Unable to " + "perform name lookup\n"); + (void) fprintf(stderr, "%s: %s\n", httpproxy, + gai_strerror(err_code)); + exit(1); + } + + if ((sock = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) { + perror("socket"); + exit(1); + } + + /* Connect to the http proxy */ + if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { + (void) fprintf(stderr, gettext("ssh-http-proxy: Unable to connect" + " to %s: %s\n"), httpproxy, strerror(errno)); + (void) close(sock); + exit(1); + } else { + /* Successful connection. */ + (void) snprintf(connect_str, sizeof (connect_str), + "CONNECT %s:%d HTTP/1.1\r\n\r\n", ssh_host, ssh_port); + if (write(sock, &connect_str, strlen(connect_str)) < 0) { + perror("write"); + (void) close(sock); + exit(1); + } + + if (read(sock, connect_reply, sizeof (connect_reply)) == -1) { + perror("read"); + (void) close(sock); + exit(1); + } + + if (sscanf(connect_reply, "HTTP/1.%d %d", + &version, &ret_code) != 2) { + (void) fprintf(stderr, + gettext("ssh-http-proxy: HTTP reply not understood\n")); + (void) close(sock); + exit(1); + } + + ret_string = strtok(connect_reply, "\n"); + + /* If the return error code is not 200, print an error and quit. */ + if (ret_code != 200) { + (void) fprintf(stderr, "%s\n", ret_string); + (void) close(sock); + exit(1); + } else { + debug("%s", ret_string); + } + } + + fds[0].fd = STDIN_FILENO; /* Poll stdin for data. */ + fds[1].fd = sock; /* Poll the socket for data. */ + fds[0].events = fds[1].events = POLLIN; + + for (;;) { + if (poll(fds, 2, INFTIM) == -1) { + perror("poll"); + (void) close(sock); + exit(1); + } + + /* Data arrived on stdin, write it to the socket */ + if (fds[0].revents & POLLIN) { + if (proxy_read_write_loop(STDIN_FILENO, sock) == 0) { + (void) close(sock); + exit(1); + } + } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + (void) close(sock); + exit(1); + } + + /* Data arrived on the socket, write it to stdout */ + if (fds[1].revents & POLLIN) { + if (proxy_read_write_loop(sock, STDOUT_FILENO) == 0) { + (void) close(sock); + exit(1); + } + } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { + (void) close(sock); + exit(1); + } + } + + /* NOTREACHED */ + return (0); +} -- cgit v1.2.3