Package: proftpd-mod-mysql
Version: 1.3.6-4+deb10u5
Tags: patch

I am using an admin tool that saves account information in a MySQL / MariaDB-Datbase and uses the "password()" function to obfuscate stored passwords.

This has been working "out of the box" in the Stretch version of ProFTPD using the configuration option "SQLAUthTypes Backend". It doesn't work anymore in the Buster version; users can't authenticate anymore.

Apparently, the function contrib/mod_sql_mysql.c tries to use an undocumented function of libmysqlclient to create the obfuscated password; it switches between my_make_scrambled_password, my_make_scrambled_password_323, make_scrambled_password and make_scrammbed_password_323. It appears that in the Buster version of libmysqlcilent, none of these are available and thus it can't ever create an obfuscated password from what the user logging in has provided.



Googling led me to a similar problem in pure-ftpd that had a patch here:

https://serverfault.com/questions/861176/pure-ftpd-mysql-wont-start-after-updating-mariadb-to-10-2

This patch basically recreates the function of the *make_scrambled_password* functions using the SHA-1 implementation in libmd.

I have modified this to apply to ProFTPD and attached the patch to this e-mail. In my tests, this has worked.

Kind regards

--
Andreas Trottmann

--- proftpd-dfsg-1.3.6.orig/contrib/mod_sql_mysql.c
+++ proftpd-dfsg-1.3.6/contrib/mod_sql_mysql.c
@@ -23,7 +23,7 @@
  * the source distribution.
  *
  * -----DO NOT EDIT-----
- * $Libraries: -lm -lmysqlclient -lz$
+ * $Libraries: -lm -lmd -lmysqlclient -lz$
  */
 
 /* INTRO:
@@ -133,6 +133,8 @@
 
 #include <mysql/mysql.h>
 
+#include <sha1.h>
+
 /* The my_make_scrambled_password{,_323} functions are not part of the public
  * MySQL API and are not declared in any of the MySQL header files. But the
  * use of these functions are required for implementing the "Backend"
@@ -1624,6 +1626,27 @@ static int get_mysql_passwd_fmt(const ch
   return MYSQL_PASSWD_FMT_UNKNOWN;
 }
 
+char *hexify(char * const result, const unsigned char *digest,
+	    const size_t size_result, size_t size_digest)
+{
+   static const char * const hexchars = "0123456789ABCDEF";
+   char *result_pnt = result;
+
+   if (size_digest <= (size_t) 0 ||
+       size_result <= (size_digest * (size_t) 2U)) {
+       return NULL;
+   }
+   do {
+       *result_pnt++ = hexchars[(*digest >> 4) & 0xf];
+       *result_pnt++ = hexchars[*digest & 0xf];
+       digest++;
+       size_digest--;
+   } while (size_digest > (size_t) 0U);
+   *result_pnt = 0;
+
+   return result;
+}
+
 static int match_mysql_passwds(const char *hashed, size_t hashed_len,
     const char *scrambled, size_t scrambled_len, const char *scramble_func) {
   int hashed_fmt = 0, scrambled_fmt = 0, matched = FALSE;
@@ -1831,6 +1854,27 @@ MODRET cmd_checkauth(cmd_rec *cmd) {
 #endif /* HAVE_MYSQL_MAKE_SCRAMBLED_PASSWORD_323 */
 
   if (success == FALSE) {
+    SHA1_CTX      ctx;
+    unsigned char h0[20], h1[20];
+    SHA1Init(&ctx);
+    SHA1Update(&ctx, plaintxt, strlen(plaintxt));
+    SHA1Final(h0, &ctx);
+    SHA1Init(&ctx);
+    SHA1Update(&ctx, h0, sizeof h0);
+    memset(h0, '\0', sizeof h0);
+    SHA1Final(h1, &ctx);
+
+    hexify(scrambled + 1U, h1, (sizeof scrambled) - 1U, sizeof h1);
+    *scrambled = '*';
+    sql_log(DEBUG_FUNC, "comparing scrambled password %s to %s", scrambled, hashed);
+
+    scrambled_len = strlen(scrambled);
+   
+    success = match_mysql_passwds(hashed, hashed_len, scrambled, scrambled_len,
+      "selfmade_sha1");
+  }
+
+  if (success == FALSE) {
     sql_log(DEBUG_FUNC, "%s", "password mismatch");
   }
 

Reply via email to