psss / rpms / libguestfs

Forked from rpms/libguestfs 5 years ago
Clone
Blob Blame History Raw
From 289a05aa49ae751cf763b3030eda5e3e870d724e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 21 Nov 2013 17:34:44 +0000
Subject: [PATCH] builder/sysprep: Allow 'random' as a password selector.

This chooses a random password.

(cherry picked from commit 02b5f00b2bf563d87134ad5f90ec06dbb9535bea)
---
 builder/builder.ml                    | 34 +++++++++-------------------
 builder/virt-builder.pod              |  7 ++++++
 mllib/password.ml                     | 42 +++++++++++++++++++++--------------
 mllib/password.mli                    |  4 +++-
 sysprep/sysprep_operation_password.ml |  7 ++++++
 5 files changed, 53 insertions(+), 41 deletions(-)

diff --git a/builder/builder.ml b/builder/builder.ml
index e0b724b..541eb60 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -448,31 +448,19 @@ let main () =
    * Note 'None' means that we randomize the root password.
    *)
   let () =
-    let make_random_password () =
-      (* Get random characters from the set [A-Za-z0-9] with some
-       * homoglyphs removed.
-       *)
-      let chars =
-        "ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789" in
-      Urandom.urandom_uniform 16 chars
-    in
-
-    let root_password =
-      match root_password with
-      | Some pw ->
-        msg (f_"Setting root password");
-        pw
-      | None ->
-        let pw = make_random_password () in
-        msg (f_"Random root password: %s [did you mean to use --root-password?]")
-          pw;
-        Password.Set_password pw in
-
     match g#inspect_get_type root with
     | "linux" ->
-      let h = Hashtbl.create 1 in
-      Hashtbl.replace h "root" root_password;
-      set_linux_passwords ~prog ?password_crypto g root h
+      let password_map = Hashtbl.create 1 in
+      let pw =
+        match root_password with
+        | Some pw ->
+          msg (f_"Setting root password");
+          pw
+        | None ->
+          msg (f_"Setting random root password [did you mean to use --root-password?]");
+          Password.Set_random_password in
+      Hashtbl.replace password_map "root" pw;
+      set_linux_passwords ~prog ?password_crypto g root password_map
     | _ ->
       eprintf (f_"%s: warning: root password could not be set for this type of guest\n%!") prog in
 
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index 19dc3ea..7b74bdb 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -705,6 +705,13 @@ Set the root password to the literal string C<PASSWORD>.
 B<Note: this is not secure> since any user on the same machine can
 see the cleartext password using L<ps(1)>.
 
+=item B<--root-password> random
+
+Choose a random password, which is printed on stdout.  The password
+has approximately 120 bits of randomness.
+
+This is the default.
+
 =back
 
 =head3 Creating user accounts
diff --git a/mllib/password.ml b/mllib/password.ml
index 8cadc9d..99923d7 100644
--- a/mllib/password.ml
+++ b/mllib/password.ml
@@ -17,14 +17,24 @@
  *)
 
 open Common_gettext.Gettext
+open Common_utils
 open Printf
 
 type password_crypto = [`MD5 | `SHA256 | `SHA512 ]
 
-type password_selector = Set_password of string
+type password_selector =
+| Set_password of string
+| Set_random_password
 
 type password_map = (string, password_selector) Hashtbl.t
 
+let make_random_password =
+  (* Get random characters from the set [A-Za-z0-9] with some
+   * homoglyphs removed.
+   *)
+  let chars = "ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789" in
+  fun () -> Urandom.urandom_uniform 16 chars
+
 let password_crypto_of_string ~prog = function
   | "md5" -> `MD5
   | "sha256" -> `SHA256
@@ -35,20 +45,12 @@ let password_crypto_of_string ~prog = function
     exit 1
 
 let rec parse_selector ~prog arg =
-  let i =
-    try String.index arg ':'
-    with Not_found ->
-      eprintf (f_"%s: invalid password format; see the man page.\n") prog;
-      exit 1 in
-  let key, value =
-    let len = String.length arg in
-    String.sub arg 0 i, String.sub arg (i+1) (len-(i+1)) in
-
-  match key with
-  | "file" -> Set_password (read_password_from_file value)
-  | "password" -> Set_password value
+  match string_nsplit ":" arg with
+  | [ "file"; filename ] -> Set_password (read_password_from_file filename)
+  | "password" :: password -> Set_password (String.concat ":" password)
+  | [ "random" ] -> Set_random_password
   | _ ->
-    eprintf (f_"%s: password format, \"%s:...\" is not recognized; see the man page.\n") prog key;
+    eprintf (f_"%s: invalid password selector '%s'; see the man page.\n") prog arg;
     exit 1
 
 and read_password_from_file filename =
@@ -83,9 +85,15 @@ let rec set_linux_passwords ~prog ?password_crypto g root passwords =
           let selector = Hashtbl.find passwords user in
           let j = String.index_from line (i+1) ':' in
           let rest = String.sub line j (String.length line - j) in
-          match selector with
-          | Set_password password ->
-            user ^ ":" ^ encrypt password crypto ^ rest
+          let pwfield =
+            match selector with
+            | Set_password password -> encrypt password crypto
+            | Set_random_password ->
+              let password = make_random_password () in
+              printf (f_"Setting random password of %s to %s\n%!")
+                user password;
+              encrypt password crypto in
+          user ^ ":" ^ pwfield ^ rest
         with Not_found -> line
     ) shadow in
 
diff --git a/mllib/password.mli b/mllib/password.mli
index 4c72ed7..dce9486 100644
--- a/mllib/password.mli
+++ b/mllib/password.mli
@@ -21,7 +21,9 @@ type password_crypto = [ `MD5 | `SHA256 | `SHA512 ]
 val password_crypto_of_string : prog:string -> string -> password_crypto
 (** Parse --password-crypto parameter on command line. *)
 
-type password_selector = Set_password of string
+type password_selector =
+| Set_password of string
+| Set_random_password
 
 val parse_selector : prog:string -> string -> password_selector
 (** Parse the selector field in --password/--root-password.  Note this
diff --git a/sysprep/sysprep_operation_password.ml b/sysprep/sysprep_operation_password.ml
index a5c894f..0cd834a 100644
--- a/sysprep/sysprep_operation_password.ml
+++ b/sysprep/sysprep_operation_password.ml
@@ -136,6 +136,13 @@ Set the password to the literal string C<PASSWORD>.
 B<Note: this is not secure> since any user on the same machine
 can see the cleartext password using L<ps(1)>.
 
+=item B<--password USERNAME:random>
+
+=item B<--root-password random>
+
+Choose a random password, which is printed on stdout.  The password
+has approximately 120 bits of randomness.
+
 =back"
       };
 
-- 
1.8.4.2