1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
From: UnyfiOnGithub <kyrian@ore.org>
Date: Sat, 29 Aug 2020 21:17:13 +0100
Subject: apply patch for missing 323 code in more modern mysql client libs
and appropriate readme warnings
---
README | 5 +++
compat_323_password.h | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++
pam_mysql.c | 20 +++++++++-
3 files changed, 129 insertions(+), 2 deletions(-)
create mode 100644 compat_323_password.h
diff --git a/README b/README
index 1408fda..94a61eb 100644
--- a/README
+++ b/README
@@ -144,6 +144,11 @@ use_323_passwd (false)
This option appeared since 0.7pre2 and 0.6.1.
+ Note that the code for this to work has been dropped from client libraries
+ for mysql 5.x (or so) onwards, so a workaround has been patched in to
+ pam-mysql. If at all possible you should upgrade your password encryption
+ method instead and not rely on this feature.
+
where
Additional criteria for the query. For example:
diff --git a/compat_323_password.h b/compat_323_password.h
new file mode 100644
index 0000000..9807d07
--- /dev/null
+++ b/compat_323_password.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* password checking routines */
+/*****************************************************************************
+ The main idea is that no password are sent between client & server on
+ connection and that no password are saved in mysql in a decodable form.
+
+ On connection a random string is generated and sent to the client.
+ The client generates a new string with a random generator inited with
+ the hash values from the password and the sent string.
+ This 'check' string is sent to the server where it is compared with
+ a string generated from the stored hash_value of the password and the
+ random string.
+
+ The password is saved (in user.password) by using the PASSWORD() function in
+ mysql.
+
+ This is .c file because it's used in libmysqlclient, which is entirely in C.
+ (we need it to be portable to a variety of systems).
+ Example:
+ update user set password=PASSWORD("hello") where user="test"
+ This saves a hashed number as a string in the password field.
+
+ The new authentication is performed in following manner:
+
+ SERVER: public_seed=create_random_string()
+ send(public_seed)
+
+ CLIENT: recv(public_seed)
+ hash_stage1=sha1("password")
+ hash_stage2=sha1(hash_stage1)
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
+
+ // this three steps are done in scramble()
+
+ send(reply)
+
+
+ SERVER: recv(reply)
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
+ candidate_hash2=sha1(hash_stage1)
+ check(candidate_hash2==hash_stage2)
+
+ // this three steps are done in check_scramble()
+
+*****************************************************************************/
+
+
+/*
+ Generate binary hash from raw text string
+ Used for Pre-4.1 password handling
+ SYNOPSIS
+ hash_password()
+ result OUT store hash in this location
+ password IN plain text password to build hash
+ password_len IN password length (password may be not null-terminated)
+*/
+
+void compat_323_hash_password(ulong *result, const char *password, uint password_len)
+{
+ register ulong nr=1345345333L, add=7, nr2=0x12345671L;
+ ulong tmp;
+ const char *password_end= password + password_len;
+ for (; password < password_end; password++)
+ {
+ if (*password == ' ' || *password == '\t')
+ continue; /* skip space in password */
+ tmp= (ulong) (unsigned char) *password;
+ nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
+ nr2+=(nr2 << 8) ^ nr;
+ add+=tmp;
+ }
+ result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
+ result[1]=nr2 & (((ulong) 1L << 31) -1L);
+}
+
+
+/*
+ Create password to be stored in user database from raw string
+ Used for pre-4.1 password handling
+ SYNOPSIS
+ make_scrambled_password_323()
+ to OUT store scrambled password here
+ password IN user-supplied password
+*/
+
+void compat_make_scrambled_password_323(char *to, const char *password)
+{
+ ulong hash_res[2];
+ compat_323_hash_password(hash_res, password, (uint) strlen(password));
+ sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
+}
diff --git a/pam_mysql.c b/pam_mysql.c
index f4dac29..593f4ca 100644
--- a/pam_mysql.c
+++ b/pam_mysql.c
@@ -3724,12 +3724,20 @@ static pam_mysql_err_t pam_mysql_check_passwd(pam_mysql_ctx_t *ctx,
char buf[42];
#ifdef HAVE_MAKE_SCRAMBLED_PASSWORD_323
if (ctx->use_323_passwd) {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd defined and enabled in pam_mysql_check_passwd");
make_scrambled_password_323(buf, passwd);
} else {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd defined and not enabled in pam_mysql_check_passwd");
make_scrambled_password(buf, passwd);
}
#else
- make_scrambled_password(buf, passwd);
+ if (ctx->use_323_passwd) {
+ syslog(LOG_WARNING, PAM_MYSQL_LOG_PREFIX "Workaround applied. use_323_passwd not defined but use attempted in pam_mysql_check_passwd");
+ compat_make_scrambled_password_323(buf, passwd);
+ } else {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd not defined and use not attempted in pam_mysql_check_passwd");
+ make_scrambled_password(buf, passwd);
+ }
#endif
vresult = strcmp(row[0], buf);
@@ -4048,12 +4056,20 @@ static pam_mysql_err_t pam_mysql_update_passwd(pam_mysql_ctx_t *ctx, const char
}
#ifdef HAVE_MAKE_SCRAMBLED_PASSWORD_323
if (ctx->use_323_passwd) {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd defined and enabled in pam_mysql_update_passwd");
make_scrambled_password_323(encrypted_passwd, new_passwd);
} else {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd defined and not enabled in pam_mysql_update_passwd");
make_scrambled_password(encrypted_passwd, new_passwd);
}
#else
- make_scrambled_password(encrypted_passwd, new_passwd);
+ if (ctx->use_323_passwd) {
+ syslog(LOG_WARNING, PAM_MYSQL_LOG_PREFIX "Workaround applied. use_323_passwd not defined but use attempted in pam_mysql_update_passwd");
+ compat_make_scrambled_password_323(encrypted_passwd, new_passwd);
+ } else {
+ syslog(LOG_DEBUG, PAM_MYSQL_LOG_PREFIX "use_323_passwd not defined and use not attempted in pam_mysql_update_passwd");
+ make_scrambled_password(encrypted_passwd, new_passwd);
+ }
#endif
break;
|