Support HTTP(S) proxies when downloading resources
diff mbox

Message ID 20161027050701.13448-1-sam@mendozajonas.com
State Accepted
Headers show

Commit Message

Samuel Mendoza-Jonas Oct. 27, 2016, 5:07 a.m. UTC
Allow the user to specify a HTTP and HTTPS proxy server. The discover
server will set the http_proxy and https_proxy environment variables,
enabling the proxy servers for any further HTTP(S) requests.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
---
 discover/platform-powerpc.c   | 29 +++++++++++++++++++++++++++++
 discover/platform.c           |  7 +++++++
 lib/pb-config/pb-config.c     |  3 +++
 lib/pb-protocol/pb-protocol.c | 13 +++++++++++++
 lib/types/types.h             |  3 +++
 ui/ncurses/nc-config-help.c   |  4 ++++
 ui/ncurses/nc-config.c        | 29 ++++++++++++++++++++++++++++-
 7 files changed, 87 insertions(+), 1 deletion(-)

Patch
diff mbox

diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c
index a4b13e4..77e8824 100644
--- a/discover/platform-powerpc.c
+++ b/discover/platform-powerpc.c
@@ -60,6 +60,8 @@  static const char *known_params[] = {
 	"petitboot,write?",
 	"petitboot,snapshots?",
 	"petitboot,console",
+	"petitboot,http_proxy",
+	"petitboot,https_proxy",
 	NULL,
 };
 
@@ -525,6 +527,19 @@  static void populate_bootdev_config(struct platform_powerpc *platform,
 	config->n_autoboot_opts = 1;
 }
 
+static void set_proxy_variables(struct config *config)
+{
+	if (config->http_proxy)
+		setenv("http_proxy", config->http_proxy, 1);
+	else
+		unsetenv("http_proxy");
+
+	if (config->https_proxy)
+		setenv("https_proxy", config->https_proxy, 1);
+	else
+		unsetenv("https_proxy");
+}
+
 static void populate_config(struct platform_powerpc *platform,
 		struct config *config)
 {
@@ -573,6 +588,14 @@  static void populate_config(struct platform_powerpc *platform,
 	/* If a full path is already set we don't want to override it */
 	config->manual_console = config->boot_console &&
 					!strchr(config->boot_console, '[');
+
+	val = get_param(platform, "petitboot,http_proxy");
+	if (val)
+		config->http_proxy = talloc_strdup(config, val);
+	val = get_param(platform, "petitboot,https_proxy");
+	if (val)
+		config->https_proxy = talloc_strdup(config, val);
+	set_proxy_variables(config);
 }
 
 static char *iface_config_str(void *ctx, struct interface_config *config)
@@ -754,6 +777,12 @@  static int update_config(struct platform_powerpc *platform,
 		update_string_config(platform, "petitboot,console", val);
 	}
 
+	val = config->http_proxy ?: "";
+	update_string_config(platform, "petitboot,http_proxy", val);
+	val = config->https_proxy ?: "";
+	update_string_config(platform, "petitboot,https_proxy", val);
+	set_proxy_variables(config);
+
 	update_network_config(platform, config);
 
 	update_bootdev_config(platform, config);
diff --git a/discover/platform.c b/discover/platform.c
index 93cd057..cc6306f 100644
--- a/discover/platform.c
+++ b/discover/platform.c
@@ -87,6 +87,11 @@  static void dump_config(struct config *config)
 	if (config->manual_console)
 		pb_log("    (Manually set)\n");
 
+	if (config->http_proxy)
+		pb_log("  HTTP Proxy: %s\n", config->http_proxy);
+	if (config->https_proxy)
+		pb_log("  HTTPS Proxy: %s\n", config->https_proxy);
+
 
 	pb_log(" language: %s\n", config->lang ?: "");
 }
@@ -121,6 +126,8 @@  void config_set_defaults(struct config *config)
 	config->network.n_interfaces = 0;
 	config->network.dns_servers = NULL;
 	config->network.n_dns_servers = 0;
+	config->http_proxy = NULL;
+	config->https_proxy = NULL;
 	config->safe_mode = false;
 	config->allow_writes = true;
 	config->disable_snapshots = false;
diff --git a/lib/pb-config/pb-config.c b/lib/pb-config/pb-config.c
index 2f9af28..7fa925c 100644
--- a/lib/pb-config/pb-config.c
+++ b/lib/pb-config/pb-config.c
@@ -63,6 +63,9 @@  struct config *config_copy(void *ctx, const struct config *src)
 		dest->network.dns_servers[i] = talloc_strdup(dest,
 				src->network.dns_servers[i]);
 
+	dest->http_proxy = talloc_strdup(dest, src->http_proxy);
+	dest->https_proxy = talloc_strdup(dest, src->https_proxy);
+
 	dest->n_autoboot_opts = src->n_autoboot_opts;
 	dest->autoboot_opts = talloc_array(dest, struct autoboot_option,
 					dest->n_autoboot_opts);
diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c
index 47d04a3..64bd161 100644
--- a/lib/pb-protocol/pb-protocol.c
+++ b/lib/pb-protocol/pb-protocol.c
@@ -305,6 +305,9 @@  int pb_protocol_config_len(const struct config *config)
 	for (i = 0; i < config->network.n_dns_servers; i++)
 		len += 4 + optional_strlen(config->network.dns_servers[i]);
 
+	len += 4 + optional_strlen(config->http_proxy);
+	len += 4 + optional_strlen(config->https_proxy);
+
 	len += 4;
 	for (i = 0; i < config->n_autoboot_opts; i++) {
 		if (config->autoboot_opts[i].boot_type == BOOT_DEVICE_TYPE)
@@ -550,6 +553,9 @@  int pb_protocol_serialise_config(const struct config *config,
 				config->network.dns_servers[i]);
 	}
 
+	pos += pb_protocol_serialise_string(pos, config->http_proxy);
+	pos += pb_protocol_serialise_string(pos, config->https_proxy);
+
 	*(uint32_t *)pos = __cpu_to_be32(config->n_autoboot_opts);
 	pos += 4;
 	for (i = 0; i < config->n_autoboot_opts; i++) {
@@ -1082,6 +1088,13 @@  int pb_protocol_deserialise_config(struct config *config,
 		config->network.dns_servers[i] = str;
 	}
 
+	if (read_string(config, &pos, &len, &str))
+		goto out;
+	config->http_proxy = str;
+	if (read_string(config, &pos, &len, &str))
+		goto out;
+	config->https_proxy = str;
+
 	if (read_u32(&pos, &len, &config->n_autoboot_opts))
 		goto out;
 	config->autoboot_opts = talloc_array(config, struct autoboot_option,
diff --git a/lib/types/types.h b/lib/types/types.h
index 31922d0..d660d6b 100644
--- a/lib/types/types.h
+++ b/lib/types/types.h
@@ -161,6 +161,9 @@  struct config {
 	unsigned int		ipmi_bootdev;
 	bool			ipmi_bootdev_persistent;
 
+	char			*http_proxy;
+	char			*https_proxy;
+
 	bool			allow_writes;
 
 	char			*boot_console;
diff --git a/ui/ncurses/nc-config-help.c b/ui/ncurses/nc-config-help.c
index a0cbb20..6b0d59f 100644
--- a/ui/ncurses/nc-config-help.c
+++ b/ui/ncurses/nc-config-help.c
@@ -44,6 +44,10 @@  mask, gateway, and a DNS server or servers for a network interface. Select \
 this option if you do not have a DHCP server, or want explicit control of \
 network settings.\n"
 "\n"
+"HTTP(S) Proxy: Allows you to specify an optional HTTP or HTTPS proxy server \
+if required, for example: \"http://proxy:3128\". Any HTTP(S) requests made by \
+the pb-discover server will use these details.\n"
+"\n"
 "Disk R/W: Certain bootloader configurations may request write access to \
 disks to save information or update parameters (eg. GRUB2). "
 "Use this option to control access to disks.\n");
diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c
index 1bc77e8..487f460 100644
--- a/ui/ncurses/nc-config.c
+++ b/ui/ncurses/nc-config.c
@@ -33,7 +33,7 @@ 
 #include "nc-config.h"
 #include "nc-widgets.h"
 
-#define N_FIELDS	44
+#define N_FIELDS	48
 
 extern struct help_text config_help_text;
 
@@ -106,6 +106,10 @@  struct config_screen {
 		struct nc_widget_textbox	*dns_f;
 		struct nc_widget_label		*dns_dhcp_help_l;
 		struct nc_widget_label		*dns_help_l;
+		struct nc_widget_label		*http_proxy_l;
+		struct nc_widget_textbox	*http_proxy_f;
+		struct nc_widget_label		*https_proxy_l;
+		struct nc_widget_textbox	*https_proxy_f;
 
 		struct nc_widget_label		*allow_write_l;
 		struct nc_widget_select		*allow_write_f;
@@ -335,6 +339,13 @@  static int screen_process_form(struct config_screen *screen)
 		}
 	}
 
+	talloc_free(config->http_proxy);
+	talloc_free(config->https_proxy);
+	str = widget_textbox_get_value(screen->widgets.http_proxy_f);
+	config->http_proxy = talloc_strdup(config, str);
+	str = widget_textbox_get_value(screen->widgets.https_proxy_f);
+	config->https_proxy = talloc_strdup(config, str);
+
 	allow_write = widget_select_get_value(screen->widgets.allow_write_f);
 	if (allow_write != config->allow_writes)
 		config->allow_writes = allow_write;
@@ -585,6 +596,13 @@  static void config_screen_layout_widgets(struct config_screen *screen)
 		y += 1;
 	}
 
+	wf = widget_textbox_base(screen->widgets.http_proxy_f);
+	layout_pair(screen, y, screen->widgets.http_proxy_l, wf);
+	y++;
+	wf = widget_textbox_base(screen->widgets.https_proxy_f);
+	layout_pair(screen, y, screen->widgets.https_proxy_l, wf);
+	y++;
+
 	y += 1;
 
 	layout_pair(screen, y, screen->widgets.allow_write_l,
@@ -1028,6 +1046,15 @@  static void config_screen_setup_widgets(struct config_screen *screen,
 	screen->widgets.dns_dhcp_help_l = widget_new_label(set, 0, 0,
 			_("(if not provided by DHCP server)"));
 
+	screen->widgets.http_proxy_l = widget_new_label(set, 0, 0,
+					_("HTTP Proxy:"));
+	screen->widgets.http_proxy_f = widget_new_textbox(set, 0, 0, 32,
+						config->http_proxy);
+	screen->widgets.https_proxy_l = widget_new_label(set, 0, 0,
+					_("HTTPS Proxy:"));
+	screen->widgets.https_proxy_f = widget_new_textbox(set, 0, 0, 32,
+						config->http_proxy);
+
 	if (config->safe_mode)
 		screen->widgets.safe_mode = widget_new_label(set, 0, 0,
 			 _("Selecting 'OK' will exit safe mode"));