summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth-pam.c35
-rw-r--r--auth-passwd.c12
-rw-r--r--debian/.git-dpm4
-rw-r--r--debian/changelog1
-rw-r--r--debian/patches/CVE-2016-6210-1.patch114
-rw-r--r--debian/patches/CVE-2016-6210-2.patch111
-rw-r--r--debian/patches/CVE-2016-6210-3.patch60
-rw-r--r--debian/patches/series3
-rw-r--r--openbsd-compat/xcrypt.c40
9 files changed, 370 insertions, 10 deletions
diff --git a/auth-pam.c b/auth-pam.c
index 8425af1ea..abd6a5e1b 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -232,7 +232,6 @@ static int sshpam_account_status = -1;
232static char **sshpam_env = NULL; 232static char **sshpam_env = NULL;
233static Authctxt *sshpam_authctxt = NULL; 233static Authctxt *sshpam_authctxt = NULL;
234static const char *sshpam_password = NULL; 234static const char *sshpam_password = NULL;
235static char badpw[] = "\b\n\r\177INCORRECT";
236 235
237/* Some PAM implementations don't implement this */ 236/* Some PAM implementations don't implement this */
238#ifndef HAVE_PAM_GETENVLIST 237#ifndef HAVE_PAM_GETENVLIST
@@ -810,12 +809,35 @@ sshpam_query(void *ctx, char **name, char **info,
810 return (-1); 809 return (-1);
811} 810}
812 811
812/*
813 * Returns a junk password of identical length to that the user supplied.
814 * Used to mitigate timing attacks against crypt(3)/PAM stacks that
815 * vary processing time in proportion to password length.
816 */
817static char *
818fake_password(const char *wire_password)
819{
820 const char junk[] = "\b\n\r\177INCORRECT";
821 char *ret = NULL;
822 size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
823
824 if (l >= INT_MAX)
825 fatal("%s: password length too long: %zu", __func__, l);
826
827 ret = malloc(l + 1);
828 for (i = 0; i < l; i++)
829 ret[i] = junk[i % (sizeof(junk) - 1)];
830 ret[i] = '\0';
831 return ret;
832}
833
813/* XXX - see also comment in auth-chall.c:verify_response */ 834/* XXX - see also comment in auth-chall.c:verify_response */
814static int 835static int
815sshpam_respond(void *ctx, u_int num, char **resp) 836sshpam_respond(void *ctx, u_int num, char **resp)
816{ 837{
817 Buffer buffer; 838 Buffer buffer;
818 struct pam_ctxt *ctxt = ctx; 839 struct pam_ctxt *ctxt = ctx;
840 char *fake;
819 841
820 debug2("PAM: %s entering, %u responses", __func__, num); 842 debug2("PAM: %s entering, %u responses", __func__, num);
821 switch (ctxt->pam_done) { 843 switch (ctxt->pam_done) {
@@ -836,8 +858,11 @@ sshpam_respond(void *ctx, u_int num, char **resp)
836 (sshpam_authctxt->pw->pw_uid != 0 || 858 (sshpam_authctxt->pw->pw_uid != 0 ||
837 options.permit_root_login == PERMIT_YES)) 859 options.permit_root_login == PERMIT_YES))
838 buffer_put_cstring(&buffer, *resp); 860 buffer_put_cstring(&buffer, *resp);
839 else 861 else {
840 buffer_put_cstring(&buffer, badpw); 862 fake = fake_password(*resp);
863 buffer_put_cstring(&buffer, fake);
864 free(fake);
865 }
841 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) { 866 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
842 buffer_free(&buffer); 867 buffer_free(&buffer);
843 return (-1); 868 return (-1);
@@ -1181,6 +1206,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1181{ 1206{
1182 int flags = (options.permit_empty_passwd == 0 ? 1207 int flags = (options.permit_empty_passwd == 0 ?
1183 PAM_DISALLOW_NULL_AUTHTOK : 0); 1208 PAM_DISALLOW_NULL_AUTHTOK : 0);
1209 char *fake = NULL;
1184 1210
1185 if (!options.use_pam || sshpam_handle == NULL) 1211 if (!options.use_pam || sshpam_handle == NULL)
1186 fatal("PAM: %s called when PAM disabled or failed to " 1212 fatal("PAM: %s called when PAM disabled or failed to "
@@ -1196,7 +1222,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1196 */ 1222 */
1197 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && 1223 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
1198 options.permit_root_login != PERMIT_YES)) 1224 options.permit_root_login != PERMIT_YES))
1199 sshpam_password = badpw; 1225 sshpam_password = fake = fake_password(password);
1200 1226
1201 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 1227 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1202 (const void *)&passwd_conv); 1228 (const void *)&passwd_conv);
@@ -1206,6 +1232,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1206 1232
1207 sshpam_err = pam_authenticate(sshpam_handle, flags); 1233 sshpam_err = pam_authenticate(sshpam_handle, flags);
1208 sshpam_password = NULL; 1234 sshpam_password = NULL;
1235 free(fake);
1209 if (sshpam_err == PAM_SUCCESS && authctxt->valid) { 1236 if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1210 debug("PAM: password authentication accepted for %.100s", 1237 debug("PAM: password authentication accepted for %.100s",
1211 authctxt->user); 1238 authctxt->user);
diff --git a/auth-passwd.c b/auth-passwd.c
index 63ccf3cab..530b5d4f7 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -193,7 +193,7 @@ int
193sys_auth_passwd(Authctxt *authctxt, const char *password) 193sys_auth_passwd(Authctxt *authctxt, const char *password)
194{ 194{
195 struct passwd *pw = authctxt->pw; 195 struct passwd *pw = authctxt->pw;
196 char *encrypted_password; 196 char *encrypted_password, *salt = NULL;
197 197
198 /* Just use the supplied fake password if authctxt is invalid */ 198 /* Just use the supplied fake password if authctxt is invalid */
199 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; 199 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
@@ -202,9 +202,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
202 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) 202 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
203 return (1); 203 return (1);
204 204
205 /* Encrypt the candidate password using the proper salt. */ 205 /*
206 encrypted_password = xcrypt(password, 206 * Encrypt the candidate password using the proper salt, or pass a
207 (pw_password[0] && pw_password[1]) ? pw_password : "xx"); 207 * NULL and let xcrypt pick one.
208 */
209 if (authctxt->valid && pw_password[0] && pw_password[1])
210 salt = pw_password;
211 encrypted_password = xcrypt(password, salt);
208 212
209 /* 213 /*
210 * Authentication is accepted if the encrypted passwords 214 * Authentication is accepted if the encrypted passwords
diff --git a/debian/.git-dpm b/debian/.git-dpm
index 4d6e084d7..8da19debc 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,6 +1,6 @@
1# see git-dpm(1) from git-dpm package 1# see git-dpm(1) from git-dpm package
243a633de1cabe77e652125dac394a99ad9cac3b4 2abde8dda29c2db2405d6fbca2fe022430e2c1177
343a633de1cabe77e652125dac394a99ad9cac3b4 3abde8dda29c2db2405d6fbca2fe022430e2c1177
4f0329aac23c61e1a5197d6d57349a63f459bccb0 4f0329aac23c61e1a5197d6d57349a63f459bccb0
5f0329aac23c61e1a5197d6d57349a63f459bccb0 5f0329aac23c61e1a5197d6d57349a63f459bccb0
6openssh_7.2p2.orig.tar.gz 6openssh_7.2p2.orig.tar.gz
diff --git a/debian/changelog b/debian/changelog
index ac2268f2e..45cae471b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,7 @@ openssh (1:7.2p2-6) UNRELEASED; urgency=medium
9 scp1 works (reported by Olivier MATZ). 9 scp1 works (reported by Olivier MATZ).
10 * Retroactively add a NEWS.Debian entry for the UseDNS change in 6.9 (see 10 * Retroactively add a NEWS.Debian entry for the UseDNS change in 6.9 (see
11 LP #1588457). 11 LP #1588457).
12 * CVE-2016-6210: Mitigate user enumeration via covert timing channel.
12 13
13 -- Colin Watson <cjwatson@debian.org> Sat, 30 Apr 2016 11:29:20 +0100 14 -- Colin Watson <cjwatson@debian.org> Sat, 30 Apr 2016 11:29:20 +0100
14 15
diff --git a/debian/patches/CVE-2016-6210-1.patch b/debian/patches/CVE-2016-6210-1.patch
new file mode 100644
index 000000000..9b46ec12a
--- /dev/null
+++ b/debian/patches/CVE-2016-6210-1.patch
@@ -0,0 +1,114 @@
1From e5ef9d3942cebda819a6fd81647b51c8d87d23df Mon Sep 17 00:00:00 2001
2From: Darren Tucker <dtucker@zip.com.au>
3Date: Fri, 15 Jul 2016 13:32:45 +1000
4Subject: Determine appropriate salt for invalid users.
5
6When sshd is processing a non-PAM login for a non-existent user it uses
7the string from the fakepw structure as the salt for crypt(3)ing the
8password supplied by the client. That string has a Blowfish prefix, so on
9systems that don't understand that crypt will fail fast due to an invalid
10salt, and even on those that do it may have significantly different timing
11from the hash methods used for real accounts (eg sha512). This allows
12user enumeration by, eg, sending large password strings. This was noted
13by EddieEzra.Harari at verint.com (CVE-2016-6210).
14
15To mitigate, use the same hash algorithm that root uses for hashing
16passwords for users that do not exist on the system. ok djm@
17
18Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=9286875a73b2de7736b5e50692739d314cd8d9dc
19Bug-Debian: https://bugs.debian.org/831902
20Last-Update: 2016-07-22
21
22Patch-Name: CVE-2016-6210-1.patch
23---
24 auth-passwd.c | 12 ++++++++----
25 openbsd-compat/xcrypt.c | 34 ++++++++++++++++++++++++++++++++++
26 2 files changed, 42 insertions(+), 4 deletions(-)
27
28diff --git a/auth-passwd.c b/auth-passwd.c
29index 63ccf3c..530b5d4 100644
30--- a/auth-passwd.c
31+++ b/auth-passwd.c
32@@ -193,7 +193,7 @@ int
33 sys_auth_passwd(Authctxt *authctxt, const char *password)
34 {
35 struct passwd *pw = authctxt->pw;
36- char *encrypted_password;
37+ char *encrypted_password, *salt = NULL;
38
39 /* Just use the supplied fake password if authctxt is invalid */
40 char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
41@@ -202,9 +202,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
42 if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
43 return (1);
44
45- /* Encrypt the candidate password using the proper salt. */
46- encrypted_password = xcrypt(password,
47- (pw_password[0] && pw_password[1]) ? pw_password : "xx");
48+ /*
49+ * Encrypt the candidate password using the proper salt, or pass a
50+ * NULL and let xcrypt pick one.
51+ */
52+ if (authctxt->valid && pw_password[0] && pw_password[1])
53+ salt = pw_password;
54+ encrypted_password = xcrypt(password, salt);
55
56 /*
57 * Authentication is accepted if the encrypted passwords
58diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
59index 8577cbd..8913bb8 100644
60--- a/openbsd-compat/xcrypt.c
61+++ b/openbsd-compat/xcrypt.c
62@@ -25,6 +25,7 @@
63 #include "includes.h"
64
65 #include <sys/types.h>
66+#include <string.h>
67 #include <unistd.h>
68 #include <pwd.h>
69
70@@ -62,11 +63,44 @@
71 # define crypt DES_crypt
72 # endif
73
74+/*
75+ * Pick an appropriate password encryption type and salt for the running
76+ * system.
77+ */
78+static const char *
79+pick_salt(void)
80+{
81+ struct passwd *pw;
82+ char *passwd, *p;
83+ size_t typelen;
84+ static char salt[32];
85+
86+ if (salt[0] != '\0')
87+ return salt;
88+ strlcpy(salt, "xx", sizeof(salt));
89+ if ((pw = getpwuid(0)) == NULL)
90+ return salt;
91+ passwd = shadow_pw(pw);
92+ if (passwd[0] != '$' || (p = strrchr(passwd + 1, '$')) == NULL)
93+ return salt; /* no $, DES */
94+ typelen = p - passwd + 1;
95+ strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
96+ explicit_bzero(passwd, strlen(passwd));
97+ return salt;
98+}
99+
100 char *
101 xcrypt(const char *password, const char *salt)
102 {
103 char *crypted;
104
105+ /*
106+ * If we don't have a salt we are encrypting a fake password for
107+ * for timing purposes. Pick an appropriate salt.
108+ */
109+ if (salt == NULL)
110+ salt = pick_salt();
111+
112 # ifdef HAVE_MD5_PASSWORDS
113 if (is_md5_salt(salt))
114 crypted = md5_crypt(password, salt);
diff --git a/debian/patches/CVE-2016-6210-2.patch b/debian/patches/CVE-2016-6210-2.patch
new file mode 100644
index 000000000..1c580f90b
--- /dev/null
+++ b/debian/patches/CVE-2016-6210-2.patch
@@ -0,0 +1,111 @@
1From dde63f7f998ac3812a26bbb2c1b2947f24fcd060 Mon Sep 17 00:00:00 2001
2From: Darren Tucker <dtucker@zip.com.au>
3Date: Fri, 15 Jul 2016 13:49:44 +1000
4Subject: Mitigate timing of disallowed users PAM logins.
5
6When sshd decides to not allow a login (eg PermitRootLogin=no) and
7it's using PAM, it sends a fake password to PAM so that the timing for
8the failure is not noticeably different whether or not the password
9is correct. This behaviour can be detected by sending a very long
10password string which is slower to hash than the fake password.
11
12Mitigate by constructing an invalid password that is the same length
13as the one from the client and thus takes the same time to hash.
14Diff from djm@
15
16Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=283b97ff33ea2c641161950849931bd578de6946
17Bug-Debian: https://bugs.debian.org/831902
18Last-Update: 2016-07-22
19
20Patch-Name: CVE-2016-6210-2.patch
21---
22 auth-pam.c | 35 +++++++++++++++++++++++++++++++----
23 1 file changed, 31 insertions(+), 4 deletions(-)
24
25diff --git a/auth-pam.c b/auth-pam.c
26index 8425af1..abd6a5e 100644
27--- a/auth-pam.c
28+++ b/auth-pam.c
29@@ -232,7 +232,6 @@ static int sshpam_account_status = -1;
30 static char **sshpam_env = NULL;
31 static Authctxt *sshpam_authctxt = NULL;
32 static const char *sshpam_password = NULL;
33-static char badpw[] = "\b\n\r\177INCORRECT";
34
35 /* Some PAM implementations don't implement this */
36 #ifndef HAVE_PAM_GETENVLIST
37@@ -810,12 +809,35 @@ sshpam_query(void *ctx, char **name, char **info,
38 return (-1);
39 }
40
41+/*
42+ * Returns a junk password of identical length to that the user supplied.
43+ * Used to mitigate timing attacks against crypt(3)/PAM stacks that
44+ * vary processing time in proportion to password length.
45+ */
46+static char *
47+fake_password(const char *wire_password)
48+{
49+ const char junk[] = "\b\n\r\177INCORRECT";
50+ char *ret = NULL;
51+ size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
52+
53+ if (l >= INT_MAX)
54+ fatal("%s: password length too long: %zu", __func__, l);
55+
56+ ret = malloc(l + 1);
57+ for (i = 0; i < l; i++)
58+ ret[i] = junk[i % (sizeof(junk) - 1)];
59+ ret[i] = '\0';
60+ return ret;
61+}
62+
63 /* XXX - see also comment in auth-chall.c:verify_response */
64 static int
65 sshpam_respond(void *ctx, u_int num, char **resp)
66 {
67 Buffer buffer;
68 struct pam_ctxt *ctxt = ctx;
69+ char *fake;
70
71 debug2("PAM: %s entering, %u responses", __func__, num);
72 switch (ctxt->pam_done) {
73@@ -836,8 +858,11 @@ sshpam_respond(void *ctx, u_int num, char **resp)
74 (sshpam_authctxt->pw->pw_uid != 0 ||
75 options.permit_root_login == PERMIT_YES))
76 buffer_put_cstring(&buffer, *resp);
77- else
78- buffer_put_cstring(&buffer, badpw);
79+ else {
80+ fake = fake_password(*resp);
81+ buffer_put_cstring(&buffer, fake);
82+ free(fake);
83+ }
84 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
85 buffer_free(&buffer);
86 return (-1);
87@@ -1181,6 +1206,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
88 {
89 int flags = (options.permit_empty_passwd == 0 ?
90 PAM_DISALLOW_NULL_AUTHTOK : 0);
91+ char *fake = NULL;
92
93 if (!options.use_pam || sshpam_handle == NULL)
94 fatal("PAM: %s called when PAM disabled or failed to "
95@@ -1196,7 +1222,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
96 */
97 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
98 options.permit_root_login != PERMIT_YES))
99- sshpam_password = badpw;
100+ sshpam_password = fake = fake_password(password);
101
102 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
103 (const void *)&passwd_conv);
104@@ -1206,6 +1232,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
105
106 sshpam_err = pam_authenticate(sshpam_handle, flags);
107 sshpam_password = NULL;
108+ free(fake);
109 if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
110 debug("PAM: password authentication accepted for %.100s",
111 authctxt->user);
diff --git a/debian/patches/CVE-2016-6210-3.patch b/debian/patches/CVE-2016-6210-3.patch
new file mode 100644
index 000000000..303c34ee1
--- /dev/null
+++ b/debian/patches/CVE-2016-6210-3.patch
@@ -0,0 +1,60 @@
1From abde8dda29c2db2405d6fbca2fe022430e2c1177 Mon Sep 17 00:00:00 2001
2From: Darren Tucker <dtucker@zip.com.au>
3Date: Thu, 21 Jul 2016 14:17:31 +1000
4Subject: Search users for one with a valid salt.
5
6If the root account is locked (eg password "!!" or "*LK*") keep looking
7until we find a user with a valid salt to use for crypting passwords of
8invalid users. ok djm@
9
10Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=dbf788b4d9d9490a5fff08a7b09888272bb10fcc
11Bug-Debian: https://bugs.debian.org/831902
12Last-Update: 2016-07-22
13
14Patch-Name: CVE-2016-6210-3.patch
15---
16 openbsd-compat/xcrypt.c | 24 +++++++++++++++---------
17 1 file changed, 15 insertions(+), 9 deletions(-)
18
19diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
20index 8913bb8..cf6a9b9 100644
21--- a/openbsd-compat/xcrypt.c
22+++ b/openbsd-compat/xcrypt.c
23@@ -65,7 +65,9 @@
24
25 /*
26 * Pick an appropriate password encryption type and salt for the running
27- * system.
28+ * system by searching through accounts until we find one that has a valid
29+ * salt. Usually this will be root unless the root account is locked out.
30+ * If we don't find one we return a traditional DES-based salt.
31 */
32 static const char *
33 pick_salt(void)
34@@ -78,14 +80,18 @@ pick_salt(void)
35 if (salt[0] != '\0')
36 return salt;
37 strlcpy(salt, "xx", sizeof(salt));
38- if ((pw = getpwuid(0)) == NULL)
39- return salt;
40- passwd = shadow_pw(pw);
41- if (passwd[0] != '$' || (p = strrchr(passwd + 1, '$')) == NULL)
42- return salt; /* no $, DES */
43- typelen = p - passwd + 1;
44- strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
45- explicit_bzero(passwd, strlen(passwd));
46+ setpwent();
47+ while ((pw = getpwent()) != NULL) {
48+ passwd = shadow_pw(pw);
49+ if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
50+ typelen = p - passwd + 1;
51+ strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
52+ explicit_bzero(passwd, strlen(passwd));
53+ goto out;
54+ }
55+ }
56+ out:
57+ endpwent();
58 return salt;
59 }
60
diff --git a/debian/patches/series b/debian/patches/series
index d2d89669f..363475c20 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -27,3 +27,6 @@ systemd-readiness.patch
27debian-config.patch 27debian-config.patch
28CVE-2015-8325.patch 28CVE-2015-8325.patch
29unbreak-certificate-auth.patch 29unbreak-certificate-auth.patch
30CVE-2016-6210-1.patch
31CVE-2016-6210-2.patch
32CVE-2016-6210-3.patch
diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c
index 8577cbd8a..cf6a9b99f 100644
--- a/openbsd-compat/xcrypt.c
+++ b/openbsd-compat/xcrypt.c
@@ -25,6 +25,7 @@
25#include "includes.h" 25#include "includes.h"
26 26
27#include <sys/types.h> 27#include <sys/types.h>
28#include <string.h>
28#include <unistd.h> 29#include <unistd.h>
29#include <pwd.h> 30#include <pwd.h>
30 31
@@ -62,11 +63,50 @@
62# define crypt DES_crypt 63# define crypt DES_crypt
63# endif 64# endif
64 65
66/*
67 * Pick an appropriate password encryption type and salt for the running
68 * system by searching through accounts until we find one that has a valid
69 * salt. Usually this will be root unless the root account is locked out.
70 * If we don't find one we return a traditional DES-based salt.
71 */
72static const char *
73pick_salt(void)
74{
75 struct passwd *pw;
76 char *passwd, *p;
77 size_t typelen;
78 static char salt[32];
79
80 if (salt[0] != '\0')
81 return salt;
82 strlcpy(salt, "xx", sizeof(salt));
83 setpwent();
84 while ((pw = getpwent()) != NULL) {
85 passwd = shadow_pw(pw);
86 if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
87 typelen = p - passwd + 1;
88 strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
89 explicit_bzero(passwd, strlen(passwd));
90 goto out;
91 }
92 }
93 out:
94 endpwent();
95 return salt;
96}
97
65char * 98char *
66xcrypt(const char *password, const char *salt) 99xcrypt(const char *password, const char *salt)
67{ 100{
68 char *crypted; 101 char *crypted;
69 102
103 /*
104 * If we don't have a salt we are encrypting a fake password for
105 * for timing purposes. Pick an appropriate salt.
106 */
107 if (salt == NULL)
108 salt = pick_salt();
109
70# ifdef HAVE_MD5_PASSWORDS 110# ifdef HAVE_MD5_PASSWORDS
71 if (is_md5_salt(salt)) 111 if (is_md5_salt(salt))
72 crypted = md5_crypt(password, salt); 112 crypted = md5_crypt(password, salt);