diff mbox series

[v3] downloader: add option to send Basic Auth info

Message ID 20171215104514.23885-1-charles-antoine.couret@essensium.com
State Changes Requested
Headers show
Series [v3] downloader: add option to send Basic Auth info | expand

Commit Message

Couret Charles-Antoine Dec. 15, 2017, 10:45 a.m. UTC
This option is needed if an update is protected by username / password to
avoid that anybody can download this update file.

This method is used by Cumulocity infrastructure for example to deploy
updates.

Signed-off-by: Charles-Antoine Couret <charles-antoine.couret@essensium.com>
---
 corelib/downloader.c                | 34 +++++++++++++++++++++++++++-------
 doc/source/swupdate.rst             |  2 ++
 examples/configuration/swupdate.cfg |  4 ++++
 3 files changed, 33 insertions(+), 7 deletions(-)

Comments

Stefano Babic Dec. 15, 2017, 6:13 p.m. UTC | #1
Hi Charles-Antoine,

On 15/12/2017 11:45, Charles-Antoine Couret wrote:
> This option is needed if an update is protected by username / password to
> avoid that anybody can download this update file.
> 
> This method is used by Cumulocity infrastructure for example to deploy
> updates.
> 
> Signed-off-by: Charles-Antoine Couret <charles-antoine.couret@essensium.com>
> ---

Mmmhhh...do you test it ?

>  corelib/downloader.c                | 34 +++++++++++++++++++++++++++-------
>  doc/source/swupdate.rst             |  2 ++
>  examples/configuration/swupdate.cfg |  4 ++++
>  3 files changed, 33 insertions(+), 7 deletions(-)
> 
> diff --git a/corelib/downloader.c b/corelib/downloader.c
> index 27bb4e8..0f33e4c 100644
> --- a/corelib/downloader.c
> +++ b/corelib/downloader.c
> @@ -62,6 +62,7 @@ struct dwl_options {
>  	char *url;
>  	unsigned int retries;
>  	unsigned int timeout;
> +	char *auth;

This is auth in struct dwl_options

>  };
>  
>  /* notify download progress each second */
> @@ -76,6 +77,7 @@ static struct option long_options[] = {
>      {"url", required_argument, NULL, 'u'},
>      {"retries", required_argument, NULL, 'r'},
>      {"timeout", required_argument, NULL, 't'},
> +    {"authentification", required_argument, NULL, 'a'},
>      {NULL, 0, NULL, 0}};
>  
>  
> @@ -200,7 +202,7 @@ static void set_option_common(CURL *curl_handle,
>   * for that, the -i option is used.
>   */
>  static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries,
> -					unsigned long lowspeed_time)
> +					unsigned long lowspeed_time, char *auth)
>  {
>  	CURL *curl_handle;
>  	CURLcode res = CURLE_GOT_NOTHING;
> @@ -253,6 +255,12 @@ static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries,
>  		return FAILURE;
>  	}
>  
> +	/* Set Authentification */
> +	if (auth && curl_easy_setopt(curl_handle, CURLOPT_USERPWD, auth) != CURLE_OK) {
> +		TRACE("Runs out of memory: serious internal error");
> +		return FAILURE;
> +	}
> +
>  	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
>  	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd);
>  	set_option_common(curl_handle, lowspeed_time, &progress);
> @@ -314,6 +322,13 @@ static int download_settings(void *elem, void  __attribute__ ((__unused__)) *dat
>  		SETSTRING(opt->url, tmp);
>  	}
>  
> +	GET_FIELD_STRING(LIBCFG_PARSER, elem, "authentication", tmp);
> +	if (strlen(tmp)) {
> +		SETSTRING(opt->authentication, tmp);

...and here you set "authentication" (not existing) in dwl_options.
Build fails, please fix it.

> +	} else {
> +		opt->authentication = NULL;
> +	}
> +
>  	get_field(LIBCFG_PARSER, elem, "retries",
>  		&opt->retries);
>  	get_field(LIBCFG_PARSER, elem, "timeout",
> @@ -327,10 +342,11 @@ void download_print_help(void)
>  	fprintf(
>  	    stdout,
>  	    "\tdownload arguments (mandatory arguments are marked with '*'):\n"
> -	    "\t  -u, --url <url>   * <url> is a link to the .swu update image\n"
> -	    "\t  -r, --retries       number of retries (resumed download) if connection\n"
> -	    "\t                      is broken (0 means indefinitely retries) (default: %d)\n"
> -	    "\t  -t, --timeout       timeout to check if a connection is lost (default: %d)\n",
> +	    "\t  -u, --url <url>      * <url> is a link to the .swu update image\n"
> +	    "\t  -r, --retries          number of retries (resumed download) if connection\n"
> +	    "\t                         is broken (0 means indefinitely retries) (default: %d)\n"
> +	    "\t  -t, --timeout          timeout to check if a connection is lost (default: %d)\n"
> +	    "\t  -a, --authentication   authentification information as username:password\n",
>  	    DL_DEFAULT_RETRIES, DL_LOWSPEED_TIME);
>  }
>  
> @@ -345,6 +361,7 @@ int start_download(const char *fname, int argc, char *argv[])
>  
>  	options.retries = DL_DEFAULT_RETRIES;
>  	options.timeout = DL_LOWSPEED_TIME;
> +	options.auth = NULL;
>  
>  	if (fname) {
>  		read_module_settings(fname, "download", download_settings,
> @@ -353,7 +370,7 @@ int start_download(const char *fname, int argc, char *argv[])
>  
>  	/* reset to optind=1 to parse download's argument vector */
>  	optind = 1;
> -	while ((choice = getopt_long(argc, argv, "t:u:r:",
> +	while ((choice = getopt_long(argc, argv, "t:u:r:a:",
>  				     long_options, NULL)) != -1) {
>  		switch (choice) {
>  		case 't':
> @@ -362,6 +379,9 @@ int start_download(const char *fname, int argc, char *argv[])
>  		case 'u':
>  			SETSTRING(options.url, optarg);
>  			break;
> +		case 'a':
> +			SETSTRING(options.auth, optarg);
> +			break;
>  		case 'r':
>  			options.retries = strtoul(optarg, NULL, 10);
>  			break;
> @@ -379,7 +399,7 @@ int start_download(const char *fname, int argc, char *argv[])
>  	 */
>  	for (attempt = 0;; attempt++) {
>  		result = download_from_url(options.url, options.retries,
> -						options.timeout);
> +						options.timeout, options.auth);
>  		if (result != FAILURE) {
>  			ipc_message msg;
>  			if (ipc_postupdate(&msg) != 0) {
> diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst
> index 138e0c4..8e5ca40 100644
> --- a/doc/source/swupdate.rst
> +++ b/doc/source/swupdate.rst
> @@ -534,6 +534,8 @@ Command line parameters
>  | -t <timeout>| integer  | Timeout for connection lost when           |
>  |             |          | downloading                                |
>  +-------------+----------+--------------------------------------------+
> +| -a <usr:pwd>| string   | Send user and password for Basic Auth      |
> ++-------------+----------+--------------------------------------------+
>  
>  
>  systemd Integration
> diff --git a/examples/configuration/swupdate.cfg b/examples/configuration/swupdate.cfg
> index f9366fd..5c9e122 100644
> --- a/examples/configuration/swupdate.cfg
> +++ b/examples/configuration/swupdate.cfg
> @@ -48,8 +48,12 @@ globals :
>  #			  it is the number of seconds that can be accepted without
>  #			  receiving any packets. If it elapses, the connection is
>  #			  considered broken.
> +# authentication	: string
> +#			  credentials needed to get software if server
> +#			  enables Basic Auth to allow this downloading
>  download :
>  {
> +	authentication = "user:password";
>  	retries = 3;
>  	timeout = 1800;
>  	url = "http://example.com/software.swu";
> 

Best regards,
Stefano Babic
diff mbox series

Patch

diff --git a/corelib/downloader.c b/corelib/downloader.c
index 27bb4e8..0f33e4c 100644
--- a/corelib/downloader.c
+++ b/corelib/downloader.c
@@ -62,6 +62,7 @@  struct dwl_options {
 	char *url;
 	unsigned int retries;
 	unsigned int timeout;
+	char *auth;
 };
 
 /* notify download progress each second */
@@ -76,6 +77,7 @@  static struct option long_options[] = {
     {"url", required_argument, NULL, 'u'},
     {"retries", required_argument, NULL, 'r'},
     {"timeout", required_argument, NULL, 't'},
+    {"authentification", required_argument, NULL, 'a'},
     {NULL, 0, NULL, 0}};
 
 
@@ -200,7 +202,7 @@  static void set_option_common(CURL *curl_handle,
  * for that, the -i option is used.
  */
 static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries,
-					unsigned long lowspeed_time)
+					unsigned long lowspeed_time, char *auth)
 {
 	CURL *curl_handle;
 	CURLcode res = CURLE_GOT_NOTHING;
@@ -253,6 +255,12 @@  static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries,
 		return FAILURE;
 	}
 
+	/* Set Authentification */
+	if (auth && curl_easy_setopt(curl_handle, CURLOPT_USERPWD, auth) != CURLE_OK) {
+		TRACE("Runs out of memory: serious internal error");
+		return FAILURE;
+	}
+
 	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
 	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd);
 	set_option_common(curl_handle, lowspeed_time, &progress);
@@ -314,6 +322,13 @@  static int download_settings(void *elem, void  __attribute__ ((__unused__)) *dat
 		SETSTRING(opt->url, tmp);
 	}
 
+	GET_FIELD_STRING(LIBCFG_PARSER, elem, "authentication", tmp);
+	if (strlen(tmp)) {
+		SETSTRING(opt->authentication, tmp);
+	} else {
+		opt->authentication = NULL;
+	}
+
 	get_field(LIBCFG_PARSER, elem, "retries",
 		&opt->retries);
 	get_field(LIBCFG_PARSER, elem, "timeout",
@@ -327,10 +342,11 @@  void download_print_help(void)
 	fprintf(
 	    stdout,
 	    "\tdownload arguments (mandatory arguments are marked with '*'):\n"
-	    "\t  -u, --url <url>   * <url> is a link to the .swu update image\n"
-	    "\t  -r, --retries       number of retries (resumed download) if connection\n"
-	    "\t                      is broken (0 means indefinitely retries) (default: %d)\n"
-	    "\t  -t, --timeout       timeout to check if a connection is lost (default: %d)\n",
+	    "\t  -u, --url <url>      * <url> is a link to the .swu update image\n"
+	    "\t  -r, --retries          number of retries (resumed download) if connection\n"
+	    "\t                         is broken (0 means indefinitely retries) (default: %d)\n"
+	    "\t  -t, --timeout          timeout to check if a connection is lost (default: %d)\n"
+	    "\t  -a, --authentication   authentification information as username:password\n",
 	    DL_DEFAULT_RETRIES, DL_LOWSPEED_TIME);
 }
 
@@ -345,6 +361,7 @@  int start_download(const char *fname, int argc, char *argv[])
 
 	options.retries = DL_DEFAULT_RETRIES;
 	options.timeout = DL_LOWSPEED_TIME;
+	options.auth = NULL;
 
 	if (fname) {
 		read_module_settings(fname, "download", download_settings,
@@ -353,7 +370,7 @@  int start_download(const char *fname, int argc, char *argv[])
 
 	/* reset to optind=1 to parse download's argument vector */
 	optind = 1;
-	while ((choice = getopt_long(argc, argv, "t:u:r:",
+	while ((choice = getopt_long(argc, argv, "t:u:r:a:",
 				     long_options, NULL)) != -1) {
 		switch (choice) {
 		case 't':
@@ -362,6 +379,9 @@  int start_download(const char *fname, int argc, char *argv[])
 		case 'u':
 			SETSTRING(options.url, optarg);
 			break;
+		case 'a':
+			SETSTRING(options.auth, optarg);
+			break;
 		case 'r':
 			options.retries = strtoul(optarg, NULL, 10);
 			break;
@@ -379,7 +399,7 @@  int start_download(const char *fname, int argc, char *argv[])
 	 */
 	for (attempt = 0;; attempt++) {
 		result = download_from_url(options.url, options.retries,
-						options.timeout);
+						options.timeout, options.auth);
 		if (result != FAILURE) {
 			ipc_message msg;
 			if (ipc_postupdate(&msg) != 0) {
diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst
index 138e0c4..8e5ca40 100644
--- a/doc/source/swupdate.rst
+++ b/doc/source/swupdate.rst
@@ -534,6 +534,8 @@  Command line parameters
 | -t <timeout>| integer  | Timeout for connection lost when           |
 |             |          | downloading                                |
 +-------------+----------+--------------------------------------------+
+| -a <usr:pwd>| string   | Send user and password for Basic Auth      |
++-------------+----------+--------------------------------------------+
 
 
 systemd Integration
diff --git a/examples/configuration/swupdate.cfg b/examples/configuration/swupdate.cfg
index f9366fd..5c9e122 100644
--- a/examples/configuration/swupdate.cfg
+++ b/examples/configuration/swupdate.cfg
@@ -48,8 +48,12 @@  globals :
 #			  it is the number of seconds that can be accepted without
 #			  receiving any packets. If it elapses, the connection is
 #			  considered broken.
+# authentication	: string
+#			  credentials needed to get software if server
+#			  enables Basic Auth to allow this downloading
 download :
 {
+	authentication = "user:password";
 	retries = 3;
 	timeout = 1800;
 	url = "http://example.com/software.swu";