diff --git a/builder/Makefile.am b/builder/Makefile.am index a828ffd5a..30ada877d 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -65,6 +65,7 @@ OBJECTS = \ $(top_builddir)/mllib/libdir.cmx \ $(top_builddir)/mllib/common_gettext.cmx \ $(top_builddir)/mllib/common_utils.cmx \ + $(top_builddir)/mllib/urandom.cmx \ $(top_builddir)/mllib/random_seed.cmx \ $(top_builddir)/mllib/hostname.cmx \ $(top_builddir)/mllib/firstboot.cmx \ diff --git a/mllib/Makefile.am b/mllib/Makefile.am index 32e0ddf7a..bacd2bc2b 100644 --- a/mllib/Makefile.am +++ b/mllib/Makefile.am @@ -48,6 +48,8 @@ SOURCES = \ tty-c.c \ tTY.mli \ tTY.ml \ + urandom.mli \ + urandom.ml \ uri-c.c \ uRI.mli \ uRI.ml @@ -70,6 +72,7 @@ OBJECTS = \ libdir.cmx \ common_gettext.cmx \ common_utils.cmx \ + urandom.cmx \ random_seed.cmx \ hostname.cmx \ firstboot.cmx \ diff --git a/mllib/random_seed.ml b/mllib/random_seed.ml index f90c83328..9ac20ebbf 100644 --- a/mllib/random_seed.ml +++ b/mllib/random_seed.ml @@ -78,13 +78,8 @@ and make_random_seed_file g file = (* Default to 512 bytes of randomness. *) 512 in - let entropy = - (* Get n bytes of randomness from the host. *) - let chan = open_in "/dev/urandom" in - let buf = String.create n in - really_input chan buf 0 n; - close_in chan; - buf in + (* Get n bytes of randomness from the host. *) + let entropy = Urandom.urandom_bytes n in if file_exists then ( (* Truncate the original file and append, in order to diff --git a/mllib/urandom.ml b/mllib/urandom.ml new file mode 100644 index 000000000..3df9b7abb --- /dev/null +++ b/mllib/urandom.ml @@ -0,0 +1,48 @@ +(* Read /dev/urandom. + * Copyright (C) 2013 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. + *) + +(* Read and return N bytes (only) from /dev/urandom. + * + * As pointed out by Edwin Török, previous versions of this had a big + * problem. They used the OCaml buffered I/O library which would read + * a lot more data than requested. This version uses unbuffered I/O + * from the Unix module. + *) + +open Unix + +let open_urandom_fd () = openfile "/dev/urandom" [O_RDONLY] 0 + +let read_byte fd = + let s = String.make 1 ' ' in + fun () -> + if read fd s 0 1 = 0 then ( + close fd; + raise End_of_file + ); + Char.code s.[0] + +let urandom_bytes n = + assert (n > 0); + let ret = String.make n ' ' in + let fd = open_urandom_fd () in + for i = 0 to n-1 do + ret.[i] <- Char.chr (read_byte fd ()) + done; + close fd; + ret diff --git a/mllib/urandom.mli b/mllib/urandom.mli new file mode 100644 index 000000000..a7d78088a --- /dev/null +++ b/mllib/urandom.mli @@ -0,0 +1,22 @@ +(* Read /dev/urandom. + * Copyright (C) 2013 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. + *) + +(** Read and return N bytes (only) from /dev/urandom. *) + +val urandom_bytes : int -> string +(** Read N bytes from /dev/urandom and return it as a binary string. *) diff --git a/po/POTFILES-ml b/po/POTFILES-ml index ebdcf2c25..33362c909 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -21,6 +21,7 @@ mllib/progress.ml mllib/random_seed.ml mllib/tTY.ml mllib/uRI.ml +mllib/urandom.ml resize/resize.ml sparsify/sparsify.ml sysprep/main.ml diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 124cadf2d..aa5ad5039 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -89,6 +89,7 @@ OBJECTS = \ $(top_builddir)/mllib/uRI.cmx \ $(top_builddir)/mllib/crypt-c.o \ $(top_builddir)/mllib/crypt.cmx \ + $(top_builddir)/mllib/urandom.cmx \ $(top_builddir)/mllib/password.cmx \ $(top_builddir)/mllib/random_seed.cmx \ $(top_builddir)/mllib/hostname.cmx \