[lxc-devel] [PATCH 3/3] Improve setting the default password in a new container

TAMUKI Shoichi tamuki at linet.gr.jp
Mon Oct 6 10:31:49 UTC 2014


The default password in a new container is now auto-generated using
phoneme rules and (good) random numbers.

Even if the default random password is set in a distribution-specific
template and you use the download template to pull a pre-built rootfs
image, you will get the same password every time unless the pre-built
rootfs image is updated.

So, the default random password in a new container is to be set after
container creation.  The user names whose passwords to be changed are
stored in *.chpasswd file which is located at /usr/share/lxc/config.
Each line of the file specifies a user name whose password is to be
changed.  If the target *.chpasswd file does not exist, no password is
changed in a new container.

Signed-off-by: TAMUKI Shoichi <tamuki at linet.gr.jp>
---
 config/templates/Makefile.am           |  27 +++-
 config/templates/altlinux.chpasswd     |   1 +
 config/templates/archlinux.chpasswd    |   1 +
 config/templates/busybox.chpasswd      |   1 +
 config/templates/centos.chpasswd       |   1 +
 config/templates/debian.chpasswd       |   1 +
 config/templates/fedora.chpasswd       |   1 +
 config/templates/gentoo.chpasswd       |   1 +
 config/templates/openmandriva.chpasswd |   1 +
 config/templates/opensuse.chpasswd     |   1 +
 config/templates/oracle.chpasswd       |   2 +
 config/templates/plamo.chpasswd        |   1 +
 config/templates/ubuntu.chpasswd       |   1 +
 src/lxc/Makefile.am                    |   2 +
 src/lxc/lxccontainer.c                 | 218 ++++++++++++++++++++++++++++++++-
 src/lxc/pwgen.c                        | 201 ++++++++++++++++++++++++++++++
 src/lxc/pwgen.h                        |  26 ++++
 17 files changed, 483 insertions(+), 4 deletions(-)
 create mode 100644 config/templates/altlinux.chpasswd
 create mode 100644 config/templates/archlinux.chpasswd
 create mode 100644 config/templates/busybox.chpasswd
 create mode 100644 config/templates/centos.chpasswd
 create mode 100644 config/templates/debian.chpasswd
 create mode 100644 config/templates/fedora.chpasswd
 create mode 100644 config/templates/gentoo.chpasswd
 create mode 100644 config/templates/openmandriva.chpasswd
 create mode 100644 config/templates/opensuse.chpasswd
 create mode 100644 config/templates/oracle.chpasswd
 create mode 100644 config/templates/plamo.chpasswd
 create mode 100644 config/templates/ubuntu.chpasswd
 create mode 100644 src/lxc/pwgen.c
 create mode 100644 src/lxc/pwgen.h

diff --git a/config/templates/Makefile.am b/config/templates/Makefile.am
index 82ca8be..22b231f 100644
--- a/config/templates/Makefile.am
+++ b/config/templates/Makefile.am
@@ -1,30 +1,55 @@
 templatesconfigdir=@LXCTEMPLATECONFIG@
 
-EXTRA_DIST = common.seccomp
+EXTRA_DIST = \
+	altlinux.chpasswd \
+	archlinux.chpasswd \
+	busybox.chpasswd \
+	centos.chpasswd \
+	common.seccomp \
+	debian.chpasswd \
+	fedora.chpasswd \
+	gentoo.chpasswd \
+	openmandriva.chpasswd \
+	opensuse.chpasswd \
+	oracle.chpasswd \
+	plamo.chpasswd \
+	ubuntu.chpasswd
 
 templatesconfig_DATA = \
+	altlinux.chpasswd \
+	archlinux.chpasswd \
 	archlinux.common.conf \
 	archlinux.userns.conf \
+	busybox.chpasswd \
+	centos.chpasswd \
 	centos.common.conf \
 	centos.userns.conf \
 	common.conf \
 	common.seccomp \
+	debian.chpasswd \
 	debian.common.conf \
 	debian.userns.conf \
+	fedora.chpasswd \
 	fedora.common.conf \
 	fedora.userns.conf \
+	gentoo.chpasswd \
 	gentoo.common.conf \
 	gentoo.moresecure.conf \
 	gentoo.userns.conf \
+	openmandriva.chpasswd \
+	opensuse.chpasswd \
 	opensuse.common.conf \
 	opensuse.userns.conf \
+	oracle.chpasswd \
 	oracle.common.conf \
 	oracle.userns.conf \
+	plamo.chpasswd \
 	plamo.common.conf \
 	plamo.userns.conf \
 	ubuntu-cloud.common.conf \
 	ubuntu-cloud.lucid.conf \
 	ubuntu-cloud.userns.conf \
+	ubuntu.chpasswd
 	ubuntu.common.conf \
 	ubuntu.lucid.conf \
 	ubuntu.userns.conf \
diff --git a/config/templates/altlinux.chpasswd b/config/templates/altlinux.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/altlinux.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/archlinux.chpasswd b/config/templates/archlinux.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/archlinux.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/busybox.chpasswd b/config/templates/busybox.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/busybox.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/centos.chpasswd b/config/templates/centos.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/centos.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/debian.chpasswd b/config/templates/debian.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/debian.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/fedora.chpasswd b/config/templates/fedora.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/fedora.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/gentoo.chpasswd b/config/templates/gentoo.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/gentoo.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/openmandriva.chpasswd b/config/templates/openmandriva.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/openmandriva.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/opensuse.chpasswd b/config/templates/opensuse.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/opensuse.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/oracle.chpasswd b/config/templates/oracle.chpasswd
new file mode 100644
index 0000000..e4b3edb
--- /dev/null
+++ b/config/templates/oracle.chpasswd
@@ -0,0 +1,2 @@
+root
+oracle
diff --git a/config/templates/plamo.chpasswd b/config/templates/plamo.chpasswd
new file mode 100644
index 0000000..d8649da
--- /dev/null
+++ b/config/templates/plamo.chpasswd
@@ -0,0 +1 @@
+root
diff --git a/config/templates/ubuntu.chpasswd b/config/templates/ubuntu.chpasswd
new file mode 100644
index 0000000..e9e5f7c
--- /dev/null
+++ b/config/templates/ubuntu.chpasswd
@@ -0,0 +1 @@
+ubuntu
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index da3f78e..fe6793f 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -89,6 +89,7 @@ liblxc_so_SOURCES = \
 	lxcutmp.c lxcutmp.h \
 	lxclock.h lxclock.c \
 	lxccontainer.c lxccontainer.h \
+	pwgen.c pwgen.h \
 	version.h \
 	\
 	$(LSM_SOURCES)
@@ -117,6 +118,7 @@ AM_CFLAGS=-I$(top_srcdir)/src \
 	-DLXCINITDIR=\"$(LXCINITDIR)\" \
 	-DLIBEXECDIR=\"$(LIBEXECDIR)\" \
 	-DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\" \
+	-DLXCTEMPLATECONFIG=\"$(LXCTEMPLATECONFIG)\" \
 	-DLOGPATH=\"$(LOGPATH)\" \
 	-DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \
 	-DLXC_USERNIC_DB=\"$(LXC_USERNIC_DB)\" \
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index dbbd24a..2301355 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -56,6 +56,7 @@
 #include "namespace.h"
 #include "lxclock.h"
 #include "sync.h"
+#include "pwgen.h"
 
 #if HAVE_IFADDRS_H
 #include <ifaddrs.h>
@@ -868,6 +869,50 @@ static char *get_template_path(const char *t)
 	return tpath;
 }
 
+/*
+ * Given the '-t' template option to lxc-create, figure out what to
+ * do.  If the template is a full executable path, just return NULL.
+ * If the template is 'download', use the effective template instead.
+ * If it is something like 'ubuntu', then return LXCTEMPLATECONFIG/
+ * ubuntu.chpasswd.  Return the chpasswd file, or return NULL if not
+ * exist.
+ */
+static char *get_chpasswd_path(const char *t, char *const argv[])
+{
+	int i, ret, len;
+	const char *et = t;
+	char *p, *chpwpath;
+
+	if (t[0] == '/')
+		return NULL;
+	if (!strcmp(t, "download")) {
+		for (i = 0, et = NULL; argv[i] && !et; i++)
+			if (!strcmp(argv[i], "-d"))
+				et = argv[i + 1];
+			else if (!strncmp(argv[i], "--d", 3))
+				et = ((p = strchr(argv[i], '=')) != NULL)
+						? p + 1 : argv[i + 1];
+	} else
+		et = t;
+
+	len = strlen(LXCTEMPLATECONFIG) + strlen(et) + strlen(".chpasswd") + 2;
+	chpwpath = malloc(len);
+	if (!chpwpath)
+		return NULL;
+	ret = snprintf(chpwpath, len, "%s/%s.chpasswd", LXCTEMPLATECONFIG, et);
+	if (ret < 0 || ret >= len) {
+		free(chpwpath);
+		return NULL;
+	}
+	if (access(chpwpath, R_OK) < 0) {
+		NOTICE("nothing to do chpasswd: %s", et);
+		free(chpwpath);
+		return NULL;
+	}
+
+	return chpwpath;
+}
+
 static char *lxcbasename(char *path)
 {
 	char *p = path + strlen(path) - 1;
@@ -880,8 +925,9 @@ static char *figureout_rootfs(struct lxc_conf *conf);
 static char **prepend_lxc_usernsexec(char **tpath, struct lxc_conf *conf,
 		int nargs, char **newargv);
 
-static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet,
-				char *const argv[])
+static bool create_run_template(struct lxc_container *c, char *tpath,
+		char **const uname, char **const passwd, bool quiet,
+		char *const argv[])
 {
 	pid_t pid;
 
@@ -979,6 +1025,99 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
 		return false;
 	}
 
+	if (!uname)
+		return true;
+
+	pid = fork();
+	if (pid < 0) {
+		SYSERROR("failed to fork task for chpasswd");
+		return false;
+	}
+
+	if (pid == 0) { // child
+		char *sharg, *rootfs;
+		char *chpasswd = NULL;
+		int i, j;
+		int ret, len, nargs = 0;
+		char *p;
+		char **newargv;
+		struct lxc_conf *conf = c->lxc_conf;
+
+		if (quiet) {
+			close(0);
+			close(1);
+			close(2);
+			open("/dev/zero", O_RDONLY);
+			open("/dev/null", O_RDWR);
+			open("/dev/null", O_RDWR);
+		}
+
+		rootfs=figureout_rootfs(conf);
+
+		/*
+		 * create our new array, pre-pend the template name and
+		 * base args
+		 */
+		nargs += 3; // "sh", "-c" and
+		// "echo \"$chpasswd\" | chroot $rootfs /usr/sbin/chpasswd"
+		// args
+
+		newargv = malloc(nargs * sizeof(*newargv));
+		if (!newargv)
+			exit(1);
+		newargv[0] = "sh";
+		newargv[1] = "-c";
+
+		for (i = j = 0; uname[i]; i++, j += len - 1) {
+			len = strlen(uname[i]) + strlen(passwd[i]) + 3;
+			chpasswd = realloc(chpasswd, j + len);
+			if (!chpasswd)
+				exit(1);
+			ret = snprintf(chpasswd + j, len, "%s:%s\n",
+					uname[i], passwd[i]);
+			if (ret < 0 || ret >= len)
+				exit(1);
+		}
+		if ((p = strrchr(chpasswd, '\n')) != NULL)
+			*p = '\0';
+
+		len = strlen("echo") + strlen(chpasswd)
+				+ strlen("chroot") + strlen(rootfs)
+				+ strlen("/usr/sbin/chpasswd") + 9;
+		sharg = malloc(len);
+		if (!sharg)
+			exit(1);
+		ret = snprintf(sharg, len,
+				"echo \"%s\" | chroot %s /usr/sbin/chpasswd",
+				chpasswd, rootfs);
+		if (ret < 0 || ret >= len)
+			exit(1);
+		newargv[2] = sharg;
+
+		/* add trailing NULL */
+		nargs++;
+		newargv = realloc(newargv, nargs * sizeof(*newargv));
+		if (!newargv)
+			exit(1);
+		newargv[nargs - 1] = NULL;
+
+		tpath = "sh";
+		/* prepend the template command with lxc-usernsexec */
+		if (!lxc_list_empty(&conf->id_map))
+			newargv = prepend_lxc_usernsexec(&tpath, conf,
+					nargs, newargv);
+
+		/* execute */
+		execvp(tpath, newargv);
+		SYSERROR("failed to execute chpasswd");
+		exit(1);
+	}
+
+	if (wait_for_pid(pid) != 0) {
+		ERROR("chpasswd for %s failed", c->name);
+		return false;
+	}
+
 	return true;
 }
 
@@ -1275,6 +1414,12 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 	bool ret = false;
 	pid_t pid;
 	char *tpath = NULL;
+	char *chpwpath = NULL;
+	char **uname = NULL, **passwd = NULL;
+	int i;
+	FILE *fp;
+	char *p, *line = NULL;
+	size_t len = 0;
 	int partial_fd;
 
 	if (!c)
@@ -1286,6 +1431,49 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 			ERROR("bad template: %s", t);
 			goto out;
 		}
+		chpwpath = get_chpasswd_path(t, argv);
+		if (chpwpath) {
+			fp = fopen(chpwpath, "r");
+			for (i = 0; getline(&line, &len, fp) != -1; i++) {
+				if ((p = strchr(line, '\n')) != NULL)
+					*p = '\0';
+				if (!(uname = realloc(uname,
+						(i + 1) * sizeof(*uname)))) {
+					SYSERROR("out of memory");
+					exit(1);
+				}
+				if (!(uname[i] = malloc(strlen(line) + 1))) {
+					SYSERROR("out of memory");
+					exit(1);
+				}
+				strcpy(uname[i], line);
+				if (!(passwd = realloc(passwd,
+						(i + 1) * sizeof(*passwd)))) {
+					SYSERROR("out of memory");
+					exit(1);
+				}
+				if (!(passwd[i] = malloc(11))) {
+					SYSERROR("out of memory");
+					exit(1);
+				}
+				pw_phonemes(passwd[i], 10);
+			}
+			if (line)
+				free(line);
+			fclose(fp);
+			if (!(uname = realloc(uname,
+					(i + 1) * sizeof(*uname)))) {
+				SYSERROR("out of memory");
+				exit(1);
+			}
+			uname[i] = NULL;
+			if (!(passwd = realloc(passwd,
+					(i + 1) * sizeof(*passwd)))) {
+				SYSERROR("out of memory");
+				exit(1);
+			}
+			passwd[i] = NULL;
+		}
 	}
 
 	/*
@@ -1375,9 +1563,17 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 	if (!load_config_locked(c, c->configfile))
 		goto out_unlock;
 
-	if (!create_run_template(c, tpath, !!(flags & LXC_CREATE_QUIET), argv))
+	if (!create_run_template(c, tpath, uname, passwd,
+			!!(flags & LXC_CREATE_QUIET), argv))
 		goto out_unlock;
 
+	if (uname)
+		for (i = 0; uname[i]; i++)
+			printf("The default %s password is: %s\n",
+					uname[i], passwd[i]);
+	else
+		printf("No password is changed.\n");
+
 	// now clear out the lxc_conf we have, reload from the created
 	// container
 	lxcapi_clear_config(c);
@@ -1399,6 +1595,22 @@ out:
 free_tpath:
 	if (tpath)
 		free(tpath);
+	if (chpwpath)
+		free(chpwpath);
+	if (uname) {
+		char **pp;
+
+		for (pp = uname; *pp; pp++)
+			free(*pp);
+		free(uname);
+	}
+	if (passwd) {
+		char **pp;
+
+		for (pp = passwd; *pp; pp++)
+			free(*pp);
+		free(passwd);
+	}
 	return ret;
 }
 
diff --git a/src/lxc/pwgen.c b/src/lxc/pwgen.c
new file mode 100644
index 0000000..c5a83d0
--- /dev/null
+++ b/src/lxc/pwgen.c
@@ -0,0 +1,201 @@
+/*
+ * pwgen.c --- generate secure password using phoneme rules and
+ *             (good) random numbers.
+ *
+ * Copyright (C) 2001,2002 by Theodore Ts'o
+ * Copyright (C) 2014 by TAMUKI Shoichi
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "pwgen.h"
+
+struct pw_element {
+	const char *str;
+	int flags;
+};
+
+/* Flags for the pw_element */
+#define CONSONANT	0x0001
+#define VOWEL		0x0002
+#define DIPTHONG	0x0004
+#define NOT_FIRST	0x0008
+
+struct pw_element elements[] = {
+	{ "a",	VOWEL },
+	{ "ae", VOWEL | DIPTHONG },
+	{ "ah",	VOWEL | DIPTHONG },
+	{ "ai", VOWEL | DIPTHONG },
+	{ "b",  CONSONANT },
+	{ "c",	CONSONANT },
+	{ "ch", CONSONANT | DIPTHONG },
+	{ "d",	CONSONANT },
+	{ "e",	VOWEL },
+	{ "ee", VOWEL | DIPTHONG },
+	{ "ei",	VOWEL | DIPTHONG },
+	{ "f",	CONSONANT },
+	{ "g",	CONSONANT },
+	{ "gh", CONSONANT | DIPTHONG | NOT_FIRST },
+	{ "h",	CONSONANT },
+	{ "i",	VOWEL },
+	{ "ie", VOWEL | DIPTHONG },
+	{ "j",	CONSONANT },
+	{ "k",	CONSONANT },
+	{ "l",	CONSONANT },
+	{ "m",	CONSONANT },
+	{ "n",	CONSONANT },
+	{ "ng",	CONSONANT | DIPTHONG | NOT_FIRST },
+	{ "o",	VOWEL },
+	{ "oh",	VOWEL | DIPTHONG },
+	{ "oo",	VOWEL | DIPTHONG },
+	{ "p",	CONSONANT },
+	{ "ph",	CONSONANT | DIPTHONG },
+	{ "qu",	CONSONANT | DIPTHONG },
+	{ "r",	CONSONANT },
+	{ "s",	CONSONANT },
+	{ "sh",	CONSONANT | DIPTHONG },
+	{ "t",	CONSONANT },
+	{ "th",	CONSONANT | DIPTHONG },
+	{ "u",	VOWEL },
+	{ "v",	CONSONANT },
+	{ "w",	CONSONANT },
+	{ "x",	CONSONANT },
+	{ "y",	CONSONANT },
+	{ "z",	CONSONANT }
+};
+
+#define NUM_ELEMENTS (sizeof(elements) / sizeof(struct pw_element))
+
+/* Flags for the pwgen function */
+#define PW_DIGITS	0x0001	/* At least one digit */
+#define PW_UPPERS	0x0002	/* At least one upper letter */
+
+static int pw_number(int max_num);
+static int get_random_fd(void);
+
+void pw_phonemes(char *buf, int size)
+{
+	int feature_flags, should_be, prev, first;
+	int c, i, len, flags;
+	const char *str;
+
+try_again:
+	feature_flags = PW_DIGITS | PW_UPPERS;
+	should_be = (pw_number(2)) ? VOWEL : CONSONANT;
+	prev = 0, first = 1;
+	c = 0;
+	while (c < size) {
+		str = elements[i = pw_number(NUM_ELEMENTS)].str;
+		len = strlen(str);
+		flags = elements[i].flags;
+		/* Don't allow us to overflow the buffer */
+		if (c + len > size)
+			continue;
+		/* Filter on the basic type of the next element */
+		if (!(flags & should_be))
+			continue;
+		/* Handle the NOT_FIRST flag */
+		if (first && flags & NOT_FIRST)
+			continue;
+		/* Don't allow VOWEL followed a Vowel/Dipthong pair */
+		if (prev & VOWEL && flags & VOWEL && flags & DIPTHONG)
+			continue;
+		/*
+		 * OK, we found an element which matches our criteria,
+		 * let's do it!
+		 */
+		strcpy(buf + c, str);
+		if ((first || flags & CONSONANT) && !pw_number(5)) {
+			buf[c] = toupper(buf[c]);
+			feature_flags &= ~PW_UPPERS;
+		}
+		/* Time to stop? */
+		if ((c += len) == size)
+			break;
+		if (!first && pw_number(10) < 3) {
+			buf[c++] = '0' + pw_number(10), buf[c] = 0;
+			feature_flags &= ~PW_DIGITS;
+			should_be = (pw_number(2)) ? VOWEL : CONSONANT;
+			prev = 0, first = 1;
+			continue;
+		}
+		/* OK, figure out what the next element should be */
+		should_be = (should_be == CONSONANT) ? VOWEL
+				: ((prev & VOWEL || flags & DIPTHONG
+				|| pw_number(5) < 2) ? VOWEL : CONSONANT);
+		prev = flags, first = 0;
+	}
+	if (feature_flags & (PW_DIGITS | PW_UPPERS))
+		goto try_again;
+}
+
+/*
+ * Generate a random number n, where 0 <= n < max_num, using
+ * /dev/urandom if possible.
+ */
+static int pw_number(int max_num)
+{
+	int fd, i;
+	unsigned int rand_num;
+	char *cp = (char *) &rand_num;
+	int nbytes = 4, lose_counter = 0;
+
+	if ((fd = get_random_fd()) >= 0)
+		while (nbytes > 0)
+			if ((i = read(fd, cp, nbytes)) < 0
+					&& (errno == EINTR || errno == EAGAIN))
+				continue;
+			else if (i <= 0) {
+				if (lose_counter++ == 8)
+					break;
+			} else
+				cp += i, nbytes -= i, lose_counter = 0;
+	close(fd);
+	if (nbytes == 0)
+		return rand_num % max_num;
+	/* OK, we weren't able to use /dev/random, fall back to rand/rand48 */
+	return (int) (drand48() * max_num);
+}
+
+/* Borrowed/adapted from e2fsprogs's UUID generation code */
+static int get_random_fd(void)
+{
+	static int fd = -2;
+	struct timeval tv;
+	int i;
+
+	if (fd == -2) {
+		gettimeofday(&tv, 0);
+		if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
+			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+		srand48(tv.tv_sec << 9 ^ tv.tv_usec >> 11 ^ getpid()
+				^ getpgrp() << 15);
+	}
+	/* Crank the random number generator a few times */
+	gettimeofday(&tv, 0);
+	for (i = 0; i < ((tv.tv_sec ^ tv.tv_usec) & 0x1f); i++)
+		drand48();
+	return fd;
+}
+
diff --git a/src/lxc/pwgen.h b/src/lxc/pwgen.h
new file mode 100644
index 0000000..9d0adc5
--- /dev/null
+++ b/src/lxc/pwgen.h
@@ -0,0 +1,26 @@
+/*
+ * pwgen.h --- header file for password generator
+ *
+ * Copyright (C) 2001,2002 by Theodore Ts'o
+ * Copyright (C) 2014 by TAMUKI Shoichi
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __PWGEN_H
+#define __PWGEN_H
+extern void pw_phonemes(char *buf, int size);
+#endif
+
-- 
1.9.0


More information about the lxc-devel mailing list