build_image: generate /etc/shadow from /etc/passwd

When a password has been marked as shadowed, we need to make sure there
is an entry for it in /etc/shadow.  Otherwise, pam will prevent people
from logging in as those accounts even when other auth methods will work
(like ssh keys).

BUG=chromium:361864
TEST=built an image and checked content/perms of /etc/shadow and looked correct
TEST=built an image and could ssh into it

Change-Id: I5ddabdd9e959d7632733217090343028a14ebd6d
Reviewed-on: https://chromium-review.googlesource.com/196360
Reviewed-by: Chris Masone <cmasone@chromium.org>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/build_library/base_image_util.sh b/build_library/base_image_util.sh
index 36027fc..514bf08 100755
--- a/build_library/base_image_util.sh
+++ b/build_library/base_image_util.sh
@@ -179,6 +179,8 @@
   sudo find "${root_fs_dir}/usr/include" -depth -type d -exec rmdir {} + \
     2>/dev/null || :
 
+  setup_etc_shadow "${root_fs_dir}"
+
   # Zero rootfs free space to make it more compressible so auto-update
   # payloads become smaller
   zero_free_space "${root_fs_dir}"
diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh
index 0a0f4d2..5454332 100755
--- a/build_library/build_image_util.sh
+++ b/build_library/build_image_util.sh
@@ -173,3 +173,50 @@
   sudo -E ${EMERGE_BOARD_CMD} --root-deps=rdeps --usepkgonly -v \
     "$@" ${EMERGE_JOBS}
 }
+
+# Create the /etc/shadow file with all the right entries.
+SHARED_USER_NAME="chronos"
+setup_etc_shadow() {
+  local root=$1
+  local shadow="${root}/etc/shadow"
+  local passwd="${root}/etc/passwd"
+  local line
+  local cmds
+
+  # Remove the file completely so we know it is fully initialized
+  # with the correct permissions.  Note: we're just making it writable
+  # here to simplify scripting; permission fixing happens at the end.
+  cmds=(
+    "rm -f '${shadow}'"
+    "install -m 666 /dev/null '${shadow}'"
+  )
+  sudo_multi "${cmds[@]}"
+
+  # Create shadow entries for all accounts in /etc/passwd that says
+  # they expect it.  Otherwise, pam will not let people even log in
+  # via ssh keyauth.  http://crbug.com/361864
+  while read -r line; do
+    local acct=$(cut -d: -f1 <<<"${line}")
+    local pass=$(cut -d: -f2 <<<"${line}")
+
+    case ${pass} in
+    # Login is disabled -> do nothing.
+    '!') ;;
+    # Password will be set later by tools.
+    '*') ;;
+    # Password is shadowed.
+    'x')
+      echo "${acct}:*:::::::" >> "${shadow}"
+      ;;
+    # Password is set directly.
+    *) ;;
+    esac
+  done <"${passwd}"
+
+  # Now make the settings sane.
+  cmds=(
+    "chown 0:0 '${shadow}'"
+    "chmod 600 '${shadow}'"
+  )
+  sudo_multi "${cmds[@]}"
+}
diff --git a/build_library/dev_image_util.sh b/build_library/dev_image_util.sh
index 75d3474..f550c32 100755
--- a/build_library/dev_image_util.sh
+++ b/build_library/dev_image_util.sh
@@ -133,6 +133,8 @@
     sudo ln -sf /usr/local/bin/bash "${root_fs_dir}"/bin/bash
   fi
 
+  setup_etc_shadow "${root_fs_dir}"
+
   info "Developer image built and stored at ${image_name}"
 
   cleanup_mounts