This refactors the curl functions used to talk to vCenter into a library module. --- po/POTFILES-ml | 1 + v2v/Makefile.am | 2 ++ v2v/curl.ml | 71 ++++++++++++++++++++++++++++++++++++++ v2v/curl.mli | 38 ++++++++++++++++++++ v2v/input_libvirt_vcenter_https.ml | 54 +++-------------------------- 5 files changed, 116 insertions(+), 50 deletions(-) create mode 100644 v2v/curl.ml create mode 100644 v2v/curl.mli diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 437926f..239e586 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -100,6 +100,7 @@ v2v/OVF.ml v2v/cmdline.ml v2v/convert_linux.ml v2v/convert_windows.ml +v2v/curl.ml v2v/detect_antivirus.ml v2v/domainxml.ml v2v/input_disk.ml diff --git a/v2v/Makefile.am b/v2v/Makefile.am index 7f30240..6bfdb62 100644 --- a/v2v/Makefile.am +++ b/v2v/Makefile.am @@ -44,6 +44,7 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-v2v SOURCES_MLI = \ convert_linux.mli \ convert_windows.mli \ + curl.mli \ detect_antivirus.ml \ detect_antivirus.mli \ DOM.mli \ @@ -75,6 +76,7 @@ SOURCES_ML = \ types.ml \ xml.ml \ utils.ml \ + curl.ml \ domainxml.ml \ DOM.ml \ kvmuid.ml \ diff --git a/v2v/curl.ml b/v2v/curl.ml new file mode 100644 index 0000000..29315b4 --- /dev/null +++ b/v2v/curl.ml @@ -0,0 +1,71 @@ +(* virt-v2v + * Copyright (C) 2009-2015 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +open Printf + +open Common_utils + +type curl_args = (string * string option) list + +let run curl_args = + let config_file, chan = Filename.open_temp_file "v2vcurl" ".conf" in + List.iter ( + function + | name, None -> fprintf chan "%s\n" name + | name, Some value -> + fprintf chan "%s = \"" name; + (* Write the quoted value. See 'curl' man page for what is + * allowed here. + *) + let len = String.length value in + for i = 0 to len-1 do + match value.[i] with + | '\\' -> output_string chan "\\\\" + | '"' -> output_string chan "\\\"" + | '\t' -> output_string chan "\\t" + | '\n' -> output_string chan "\\n" + | '\r' -> output_string chan "\\r" + | '\x0b' -> output_string chan "\\v" + | c -> output_char chan c + done; + fprintf chan "\"\n" + ) curl_args; + close_out chan; + + let cmd = sprintf "curl -q --config %s" (Filename.quote config_file) in + let lines = external_command cmd in + Unix.unlink config_file; + lines + +let print_curl_command chan curl_args = + (* Don't print passwords in the debug output. *) + let curl_args = + List.map ( + function + | ("user", Some _) -> ("user", Some "<hidden>") + | x -> x + ) curl_args in + + (* Dump out the approximate curl command that was run. *) + fprintf chan "curl -q"; + List.iter ( + function + | name, None -> fprintf chan " --%s" name + | name, Some value -> fprintf chan " --%s %s" name (Filename.quote value) + ) curl_args; + fprintf chan "\n"; diff --git a/v2v/curl.mli b/v2v/curl.mli new file mode 100644 index 0000000..eb89e23 --- /dev/null +++ b/v2v/curl.mli @@ -0,0 +1,38 @@ +(* virt-v2v + * Copyright (C) 2009-2015 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +(** Functions for dealing with [curl]. *) + +type curl_args = (string * string option) list + +val run : curl_args -> string list +(** [run curl_args] runs the [curl] command. + + It actually uses the [curl --config] option to pass the arguments + securely to curl through an external file. Thus passwords etc are + not exposed to other users on the same machine. + + The curl arguments are a list of key, value pairs corresponding + to curl command line parameters, without leading dashes, + eg. [("user", Some "user:password")]. + + The result is the output of curl as a list of lines. *) + +val print_curl_command : out_channel -> curl_args -> unit +(** Print the curl command line. This elides any arguments that + might contain passwords, so is useful for debugging. *) diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml index 99f3ee1..13108c7 100644 --- a/v2v/input_libvirt_vcenter_https.ml +++ b/v2v/input_libvirt_vcenter_https.ml @@ -36,7 +36,7 @@ let readahead_for_copying = Some (64 * 1024 * 1024) (* Return the session cookie. It is memoized, so you can call this * as often as required. *) -let rec get_session_cookie = +let get_session_cookie = let session_cookie = ref "" in fun password scheme uri sslverify url -> if !session_cookie <> "" then @@ -60,24 +60,11 @@ let rec get_session_cookie = let curl_args = if not sslverify then ("insecure", None) :: curl_args else curl_args in - let lines = run_curl_get_lines curl_args in + let lines = Curl.run curl_args in let dump_response chan = - (* Don't print passwords in the debug output. *) - let curl_args = - List.map ( - function - | ("user", Some _) -> ("user", Some "<hidden>") - | x -> x - ) curl_args in - (* Dump out the approximate curl command that was run. *) - fprintf chan "curl -q"; - List.iter ( - function - | name, None -> fprintf chan " --%s" name - | name, Some value -> fprintf chan " --%s %s" name (quote value) - ) curl_args; - fprintf chan "\n"; + Curl.print_curl_command chan curl_args; + (* Dump out the output of the command. *) List.iter (fun x -> fprintf chan "%s\n" x) lines; flush chan @@ -137,39 +124,6 @@ let rec get_session_cookie = Some !session_cookie ) -(* Run 'curl' and pass the arguments securely through the --config - * option and an external file. - *) -and run_curl_get_lines curl_args = - let config_file, chan = Filename.open_temp_file "v2vcurl" ".conf" in - List.iter ( - function - | name, None -> fprintf chan "%s\n" name - | name, Some value -> - fprintf chan "%s = \"" name; - (* Write the quoted value. See 'curl' man page for what is - * allowed here. - *) - let len = String.length value in - for i = 0 to len-1 do - match value.[i] with - | '\\' -> output_string chan "\\\\" - | '"' -> output_string chan "\\\"" - | '\t' -> output_string chan "\\t" - | '\n' -> output_string chan "\\n" - | '\r' -> output_string chan "\\r" - | '\x0b' -> output_string chan "\\v" - | c -> output_char chan c - done; - fprintf chan "\"\n" - ) curl_args; - close_out chan; - - let cmd = sprintf "curl -q --config %s" (quote config_file) in - let lines = external_command cmd in - Unix.unlink config_file; - lines - let multiple_slash = Str.regexp "/+" (* Helper function to extract the dcPath from a URI. *) -- 2.5.0