[CVE-2013-4122]: Handle NULL returns from glibc 2.17+ crypt()
Ondřej Surý
8 years ago
0 | From dedad73e5e7a75d01a5f3d5a6702ab8ccd2ff40d Mon Sep 17 00:00:00 2001 | |
1 | From: mancha <mancha1@hush.com> | |
2 | Date: Thu, 11 Jul 2013 10:08:07 +0100 | |
3 | Subject: Handle NULL returns from glibc 2.17+ crypt() | |
4 | ||
5 | Starting with glibc 2.17 (eglibc 2.17), crypt() fails with EINVAL | |
6 | (w/ NULL return) if the salt violates specifications. Additionally, | |
7 | on FIPS-140 enabled Linux systems, DES/MD5-encrypted passwords | |
8 | passed to crypt() fail with EPERM (w/ NULL return). | |
9 | ||
10 | When using glibc's crypt(), check return value to avoid a possible | |
11 | NULL pointer dereference. | |
12 | ||
13 | Patch by mancha1@hush.com. | |
14 | ||
15 | --- cyrus-sasl2.orig/pwcheck/pwcheck_getpwnam.c | |
16 | +++ cyrus-sasl2/pwcheck/pwcheck_getpwnam.c | |
17 | @@ -32,6 +32,7 @@ char *userid; | |
18 | char *password; | |
19 | { | |
20 | char* r; | |
21 | + char* crpt_passwd; | |
22 | struct passwd *pwd; | |
23 | ||
24 | pwd = getpwnam(userid); | |
25 | @@ -41,7 +42,7 @@ char *password; | |
26 | else if (pwd->pw_passwd[0] == '*') { | |
27 | r = "Account disabled"; | |
28 | } | |
29 | - else if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { | |
30 | + else if (!(crpt_passwd = crypt(password, pwd->pw_passwd)) || strcmp(pwd->pw_passwd, (const char *)crpt_passwd) != 0) { | |
31 | r = "Incorrect password"; | |
32 | } | |
33 | else { | |
34 | --- cyrus-sasl2.orig/pwcheck/pwcheck_getspnam.c | |
35 | +++ cyrus-sasl2/pwcheck/pwcheck_getspnam.c | |
36 | @@ -32,13 +32,15 @@ char *userid; | |
37 | char *password; | |
38 | { | |
39 | struct spwd *pwd; | |
40 | + char *crpt_passwd; | |
41 | ||
42 | pwd = getspnam(userid); | |
43 | if (!pwd) { | |
44 | return "Userid not found"; | |
45 | } | |
46 | ||
47 | - if (strcmp(pwd->sp_pwdp, crypt(password, pwd->sp_pwdp)) != 0) { | |
48 | + crpt_passwd = crypt(password, pwd->sp_pwdp); | |
49 | + if (!crpt_passwd || strcmp(pwd->sp_pwdp, (const char *)crpt_passwd) != 0) { | |
50 | return "Incorrect password"; | |
51 | } | |
52 | else { | |
53 | --- cyrus-sasl2.orig/saslauthd/auth_getpwent.c | |
54 | +++ cyrus-sasl2/saslauthd/auth_getpwent.c | |
55 | @@ -77,6 +77,7 @@ auth_getpwent ( | |
56 | { | |
57 | /* VARIABLES */ | |
58 | struct passwd *pw; /* pointer to passwd file entry */ | |
59 | + char *crpt_passwd; /* encrypted password */ | |
60 | int errnum; | |
61 | /* END VARIABLES */ | |
62 | ||
63 | @@ -105,7 +106,8 @@ auth_getpwent ( | |
64 | } | |
65 | } | |
66 | ||
67 | - if (strcmp(pw->pw_passwd, (const char *)crypt(password, pw->pw_passwd))) { | |
68 | + crpt_passwd = crypt(password, pw->pw_passwd); | |
69 | + if (!crpt_passwd || strcmp(pw->pw_passwd, (const char *)crpt_passwd)) { | |
70 | if (flags & VERBOSE) { | |
71 | syslog(LOG_DEBUG, "DEBUG: auth_getpwent: %s: invalid password", login); | |
72 | } | |
73 | --- cyrus-sasl2.orig/saslauthd/auth_shadow.c | |
74 | +++ cyrus-sasl2/saslauthd/auth_shadow.c | |
75 | @@ -211,8 +211,8 @@ auth_shadow ( | |
76 | RETURN("NO Insufficient permission to access NIS authentication database (saslauthd)"); | |
77 | } | |
78 | ||
79 | - cpw = strdup((const char *)crypt(password, sp->sp_pwdp)); | |
80 | - if (strcmp(sp->sp_pwdp, cpw)) { | |
81 | + cpw = crypt(password, sp->sp_pwdp); | |
82 | + if (!cpw || strcmp(sp->sp_pwdp, (const char *)cpw)) { | |
83 | if (flags & VERBOSE) { | |
84 | /* | |
85 | * This _should_ reveal the SHADOW_PW_LOCKED prefix to an | |
86 | @@ -222,10 +222,8 @@ auth_shadow ( | |
87 | syslog(LOG_DEBUG, "DEBUG: auth_shadow: pw mismatch: '%s' != '%s'", | |
88 | sp->sp_pwdp, cpw); | |
89 | } | |
90 | - free(cpw); | |
91 | RETURN("NO Incorrect password"); | |
92 | } | |
93 | - free(cpw); | |
94 | ||
95 | /* | |
96 | * The following fields will be set to -1 if: | |
97 | @@ -287,7 +285,7 @@ auth_shadow ( | |
98 | RETURN("NO Invalid username"); | |
99 | } | |
100 | ||
101 | - if (strcmp(upw->upw_passwd, crypt(password, upw->upw_passwd)) != 0) { | |
102 | + if (!(cpw = crypt(password, upw->upw_passwd)) || (strcmp(upw->upw_passwd, (const char *)cpw) != 0)) { | |
103 | if (flags & VERBOSE) { | |
104 | syslog(LOG_DEBUG, "auth_shadow: pw mismatch: %s != %s", | |
105 | password, upw->upw_passwd); |