Blame SOURCES/0030-v2v-vmware-Use-curl-config-to-pass-arguments-securel.patch

0d20ef
From 322a146ddc69384255f0567a85e7db56a9e36454 Mon Sep 17 00:00:00 2001
0d20ef
From: "Richard W.M. Jones" <rjones@redhat.com>
0d20ef
Date: Thu, 30 Oct 2014 09:02:00 +0000
0d20ef
Subject: [PATCH] v2v: vmware: Use 'curl --config' to pass arguments securely
0d20ef
 to curl.
0d20ef
0d20ef
Instead of making up an ordinary curl command line, write a temporary
0d20ef
config file and use 'curl --config tmpfile' to pass the arguments.
0d20ef
0d20ef
The advantage is that it's more secure if we want to supply passwords
0d20ef
to curl, since a '--user username:password' parameter on the command
0d20ef
line could be read (eg. by 'ps ax'), but the temporary file has mode
0d20ef
0600 and cannot be read by other users.
0d20ef
0d20ef
This is mostly code motion, but it also passes the '-q' option to curl
0d20ef
to stop it from reading default configuration files.
0d20ef
0d20ef
(cherry picked from commit b35b84684c845ceefd3c0ec519caf80366a798ea)
0d20ef
---
0d20ef
 v2v/input_libvirt_vcenter_https.ml | 75 +++++++++++++++++++++++++++++++++-----
0d20ef
 1 file changed, 65 insertions(+), 10 deletions(-)
0d20ef
0d20ef
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
0d20ef
index 56097e0..e514362 100644
0d20ef
--- a/v2v/input_libvirt_vcenter_https.ml
0d20ef
+++ b/v2v/input_libvirt_vcenter_https.ml
0d20ef
@@ -36,23 +36,45 @@ let readahead_for_copying = Some (64 * 1024 * 1024)
0d20ef
 (* Return the session cookie.  It is memoized, so you can call this
0d20ef
  * as often as required.
0d20ef
  *)
0d20ef
-let get_session_cookie =
0d20ef
+let rec get_session_cookie =
0d20ef
   let session_cookie = ref "" in
0d20ef
   fun verbose scheme uri sslverify url ->
0d20ef
     if !session_cookie <> "" then
0d20ef
       Some !session_cookie
0d20ef
     else (
0d20ef
-      let cmd =
0d20ef
-        sprintf "curl -s%s%s%s -I %s ||:"
0d20ef
-          (if not sslverify then " --insecure" else "")
0d20ef
-          (match uri.uri_user with Some _ -> " -u" | None -> "")
0d20ef
-          (match uri.uri_user with Some user -> " " ^ quote user | None -> "")
0d20ef
-          (quote url) in
0d20ef
-      let lines = external_command ~prog cmd in
0d20ef
+      let curl_args = [
0d20ef
+        "head", None;
0d20ef
+        "silent", None;
0d20ef
+        "url", Some url;
0d20ef
+      ] in
0d20ef
+      let curl_args =
0d20ef
+        match uri.uri_user with
0d20ef
+        | Some user -> ("user", Some user) :: curl_args
0d20ef
+        | None -> curl_args in
0d20ef
+      let curl_args =
0d20ef
+        if not sslverify then ("insecure", None) :: curl_args else curl_args in
0d20ef
+
0d20ef
+      let lines = run_curl_get_lines curl_args in
0d20ef
 
0d20ef
       let dump_response chan =
0d20ef
-        fprintf chan "%s\n" cmd;
0d20ef
-        List.iter (fun x -> fprintf chan "%s\n" x) lines
0d20ef
+        (* Don't print passwords in the debug output. *)
0d20ef
+        let curl_args =
0d20ef
+          List.map (
0d20ef
+            function
0d20ef
+            | ("user", Some _) -> ("user", Some "<hidden>")
0d20ef
+            | x -> x
0d20ef
+          ) curl_args in
0d20ef
+        (* Dump out the approximate curl command that was run. *)
0d20ef
+        fprintf chan "curl -q";
0d20ef
+        List.iter (
0d20ef
+          function
0d20ef
+          | name, None -> fprintf chan " --%s" name
0d20ef
+          | name, Some value -> fprintf chan " --%s %s" name (quote value)
0d20ef
+        ) curl_args;
0d20ef
+        fprintf chan "\n";
0d20ef
+        (* Dump out the output of the command. *)
0d20ef
+        List.iter (fun x -> fprintf chan "%s\n" x) lines;
0d20ef
+        flush chan
0d20ef
       in
0d20ef
 
0d20ef
       if verbose then dump_response stdout;
0d20ef
@@ -109,6 +131,39 @@ let get_session_cookie =
0d20ef
         Some !session_cookie
0d20ef
     )
0d20ef
 
0d20ef
+(* Run 'curl' and pass the arguments securely through the --config
0d20ef
+ * option and an external file.
0d20ef
+ *)
0d20ef
+and run_curl_get_lines curl_args =
0d20ef
+  let config_file, chan = Filename.open_temp_file "v2vcurl" ".conf" in
0d20ef
+  List.iter (
0d20ef
+    function
0d20ef
+    | name, None -> fprintf chan "%s\n" name
0d20ef
+    | name, Some value ->
0d20ef
+      fprintf chan "%s = \"" name;
0d20ef
+      (* Write the quoted value.  See 'curl' man page for what is
0d20ef
+       * allowed here.
0d20ef
+       *)
0d20ef
+      let len = String.length value in
0d20ef
+      for i = 0 to len-1 do
0d20ef
+        match value.[i] with
0d20ef
+        | '\\' -> output_string chan "\\\\"
0d20ef
+        | '"' -> output_string chan "\\\""
0d20ef
+        | '\t' -> output_string chan "\\t"
0d20ef
+        | '\n' -> output_string chan "\\n"
0d20ef
+        | '\r' -> output_string chan "\\r"
0d20ef
+        | '\x0b' -> output_string chan "\\v"
0d20ef
+        | c -> output_char chan c
0d20ef
+      done;
0d20ef
+      fprintf chan "\"\n"
0d20ef
+  ) curl_args;
0d20ef
+  close_out chan;
0d20ef
+
0d20ef
+  let cmd = sprintf "curl -q --config %s" (quote config_file) in
0d20ef
+  let lines = external_command ~prog cmd in
0d20ef
+  Unix.unlink config_file;
0d20ef
+  lines
0d20ef
+
0d20ef
 (* Helper function to extract the datacenter from a URI. *)
0d20ef
 let get_datacenter uri scheme =
0d20ef
   let default_dc = "ha-datacenter" in
0d20ef
-- 
0d20ef
1.8.3.1
0d20ef