busybox: handle crypt() errors in loginutils
authorJo-Philipp Wich <jo@mein.io>
Tue, 22 Jan 2019 11:01:09 +0000 (12:01 +0100)
committerJo-Philipp Wich <jo@mein.io>
Tue, 22 Jan 2019 11:08:00 +0000 (12:08 +0100)
The crypt(3) function is allowed to fail with either EINVAL or ENOSYS when
the given salt is either invalid or when the requested algorithm is not
implemented.

In such a case, libbb's pw_encrypt() function will silently convert the
crypt() NULL return value into an empty string which is then processed
without further errors by utilities such as chpasswd or passwd, causing
them to set an empty password when an unsupported cipher is requested.

Patch the relevant users of pw_encrypt() to abort in case an empty hash
is returned by pw_encrypt() in order to mitigate the problem.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
package/utils/busybox/Makefile
package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch [new file with mode: 0644]

index 74dbf84d3bd3c5918f07b35527795ca5a4cd72af..3969bbeb18c639622837b3d3cbaf28e67754ad3a 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=busybox
 PKG_VERSION:=1.30.0
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 PKG_FLAGS:=essential
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
diff --git a/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch b/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch
new file mode 100644 (file)
index 0000000..d443754
--- /dev/null
@@ -0,0 +1,53 @@
+--- a/loginutils/chpasswd.c
++++ b/loginutils/chpasswd.c
+@@ -97,6 +97,11 @@ int chpasswd_main(int argc UNUSED_PARAM,
+                       crypt_make_pw_salt(salt, algo);
+                       free_me = pass = pw_encrypt(pass, salt, 0);
++
++                      if (pass[0] == 0) {
++                              free(free_me);
++                              bb_perror_msg_and_die("password encryption failed");
++                      }
+               }
+               /* This is rather complex: if user is not found in /etc/shadow,
+--- a/loginutils/cryptpw.c
++++ b/loginutils/cryptpw.c
+@@ -95,7 +95,7 @@ int cryptpw_main(int argc UNUSED_PARAM,
+       /* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */
+       char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")];
+       char *salt_ptr;
+-      char *password;
++      char *password, *hash;
+       const char *opt_m, *opt_S;
+       int fd;
+@@ -140,8 +140,12 @@ int cryptpw_main(int argc UNUSED_PARAM,
+               /* may still be NULL on EOF/error */
+       }
+-      if (password)
+-              puts(pw_encrypt(password, salt, 1));
++      if (password) {
++              hash = pw_encrypt(password, salt, 1);
++              if (hash[0] == 0)
++                      bb_perror_msg_and_die("password encryption failed");
++              puts(hash);
++      }
+       return EXIT_SUCCESS;
+ }
+--- a/loginutils/passwd.c
++++ b/loginutils/passwd.c
+@@ -187,6 +187,10 @@ int passwd_main(int argc UNUSED_PARAM, c
+               if (!newp) {
+                       logmode = LOGMODE_STDIO;
+                       bb_error_msg_and_die("password for %s is unchanged", name);
++              } else if (newp[0] == 0) {
++                      logmode = LOGMODE_STDIO;
++                      free(newp);
++                      bb_perror_msg_and_die("password encryption failed");
+               }
+       } else if (opt & OPT_lock) {
+               if (!c)