]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lslogins: fix password verification
authorKarel Zak <kzak@redhat.com>
Wed, 23 May 2018 10:43:26 +0000 (12:43 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Jul 2018 13:47:30 +0000 (15:47 +0200)
Let's follow the standard $id$salt$encrypted password format in
verification code.

The current code is useless and for example PWD-LOCK column is always
FALSE.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1581611
Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/lslogins.c

index 51033b01bba4e8a105279a31bc7885fc14019191..169962b72c55213f6c79ac0672a274b9d15b794a 100644 (file)
@@ -561,14 +561,84 @@ static int get_nprocs(const uid_t uid)
        return nprocs;
 }
 
+static const char *get_pwd_method(const char *str, const char **next, unsigned int *sz)
+{
+       const char *p = str;
+       const char *res = NULL;
+
+       if (!p || *p++ != '$')
+               return NULL;
+
+       if (sz)
+               *sz = 0;
+
+       switch (*p) {
+       case '1':
+               res = "MD5";
+               if (sz)
+                       *sz = 22;
+               break;
+       case '2':
+               p++;
+               if (*p == 'a' || *p == 'y')
+                       res = "Blowfish";
+               break;
+       case '5':
+               res = "SHA-256";
+               if (sz)
+                       *sz = 43;
+               break;
+       case '6':
+               res = "SHA-512";
+               if (sz)
+                       *sz = 86;
+               break;
+       default:
+               return NULL;
+       }
+       p++;
+
+       if (!*p || *p != '$')
+               return NULL;
+       if (next)
+               *next = ++p;
+       return res;
+}
+
+#define is_valid_pwd_char(x)   (isalnum((unsigned char) (x)) || (x) ==  '.' || (x) == '/')
+
 static int valid_pwd(const char *str)
 {
-       const char *p;
+       const char *p = str;
+       unsigned int sz = 0, n;
+
+       /* $id$ */
+       if (get_pwd_method(str, &p, &sz) == NULL)
+               return 0;
+       if (!*p)
+               return 0;
 
-       for (p = str; p && *p; p++)
-               if (!isalnum((unsigned char) *p))
+       /* salt$ */
+       for (; p && *p; p++) {
+               if (*p == '$') {
+                       p++;
+                       break;
+               }
+               if (!is_valid_pwd_char(*p))
                        return 0;
-       return p > str ? 1 : 0;
+       }
+       if (!*p)
+               return 0;
+
+       /* encrypted */
+       for (n = 0; p && *p; p++, n++) {
+               if (!is_valid_pwd_char(*p))
+                       return 0;
+       }
+
+       if (sz && n != sz)
+               return 0;
+       return 1;
 }
 
 static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const char *username)