From f1155a98a4b1c4ed11e6f3397c6bae8e3aa5f914 Mon Sep 17 00:00:00 2001
From: "peter@mysql.com" <>
Date: Wed, 2 Oct 2002 23:43:27 +0400
Subject: [PATCH] Changeset to deal with 4.1 -> 4.0 merge

---
 BitKeeper/etc/logging_ok |  1 +
 include/mysql_com.h      |  1 +
 sql/item_strfunc.cc      |  4 ++-
 sql/item_strfunc.h       |  4 +--
 sql/mysqld.cc            |  9 ++++--
 sql/password.c           | 61 ++++++++++++++++++++++++++++++++++++++--
 6 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 31c8d0a325..9f6edf9eb3 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -74,3 +74,4 @@ WAX@sergbook.mysql.com
 bar@bar.udmsearch.izhnet.ru
 nick@mysql.com
 bar@bar.mysql.r18.ru
+peter@mysql.com
diff --git a/include/mysql_com.h b/include/mysql_com.h
index c259259c9e..58c1bb062e 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -268,6 +268,7 @@ void randominit(struct rand_struct *,unsigned long seed1,
 		unsigned long seed2);
 double rnd(struct rand_struct *);
 void make_scrambled_password(char *to,const char *password);
+uint get_password_length();
 void get_salt_from_password(unsigned long *res,const char *password);
 void make_password_from_salt(char *to, unsigned long *hash_res);
 char *scramble(char *to,const char *message,const char *password,
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 243f11db10..917396d313 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1155,7 +1155,9 @@ String *Item_func_password::val_str(String *str)
   if (res->length() == 0)
     return &empty_string;
   make_scrambled_password(tmp_value,res->c_ptr());
-  str->set(tmp_value,16,res->charset());
+  printf("Returned to the function\n");
+  str->set(tmp_value,get_password_length(),res->charset());
+  printf("At the exit\n");
   return str;
 }
 
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index af94e38771..90b843f5fd 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -224,11 +224,11 @@ public:
 
 class Item_func_password :public Item_str_func
 {
-  char tmp_value[17];
+  char tmp_value[64]; /* This should be enough for new password format */
 public:
   Item_func_password(Item *a) :Item_str_func(a) {}
   String *val_str(String *);
-  void fix_length_and_dec() { max_length = 16; }
+  void fix_length_and_dec() { max_length = get_password_length(); }
   const char *func_name() const { return "password"; }
 };
 
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 59630644e5..30e20e79f9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -379,6 +379,8 @@ const char *sql_mode_str="OFF";
 const char *default_tx_isolation_name;
 enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;
 
+bool old_passwords=0; // force using old passwords when creating users
+
 uint rpl_recovery_rank=0;
 
 my_string mysql_unix_port=NULL, mysql_tmpdir=NULL, allocated_mysql_tmpdir=NULL;
@@ -2819,7 +2821,8 @@ enum options {
 	       OPT_INNODB_FORCE_RECOVERY,
 	       OPT_BDB_CACHE_SIZE,
 	       OPT_BDB_LOG_BUFFER_SIZE,
-	       OPT_BDB_MAX_LOCK
+	       OPT_BDB_MAX_LOCK,
+	       OPT_OLD_PASSWORDS
 };
 
 
@@ -3535,7 +3538,9 @@ static struct my_option my_long_options[] =
    "The number of seconds the server waits for activity on a connection before closing it",
    (gptr*) &net_wait_timeout, (gptr*) &net_wait_timeout, 0, GET_ULONG,
    REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
-  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"old_passwords",OPT_OLD_PASSWORDS,"Use old password hash functions then storing passwords",
+    (gptr*) &old_passwords, (gptr*) &old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
 struct show_var_st init_vars[]= {
diff --git a/sql/password.c b/sql/password.c
index 48181ea18e..f3dc950f03 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -37,9 +37,20 @@
 #include <my_global.h>
 #include <my_sys.h>
 #include <m_string.h>
+/* To be replaced by SHA1 as Monty will do the Merge */
+#include <md5.h>
 #include "mysql.h"
 
 
+
+/* Character to use as version identifier for version 4.1 */
+#define PVERSION41_CHAR '*'
+
+
+extern uint old_passwords; /* If prior 4.1 functions to be used */
+
+
+
 void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
 {						/* For mysql 3.21.# */
 #ifdef HAVE_purify
@@ -84,13 +95,57 @@ void hash_password(ulong *result, const char *password)
   return;
 }
 
+
 void make_scrambled_password(char *to,const char *password)
+{ 
+  ulong hash_res[2];  /* Used for pre 4.1 password hashing */
+  static uint salt=0; /* Salt for 4.1 version password */
+  unsigned char* slt=(unsigned char*)&salt;
+  my_MD5_CTX context; 
+  unsigned char digest[16];
+  if (old_passwords) /* Pre 4.1 password encryption */
+  {
+    hash_password(hash_res,password);
+    sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+  }
+  else /* New password 4.1 password scrambling */ 
+  {
+    to[0]=PVERSION41_CHAR; /* New passwords have version prefix */
+    /* We do not need too strong salt generation so this should be enough */
+    salt+=getpid()+time(NULL)+0x01010101;
+    /* Use only 2 first bytes from it */ 
+    sprintf(&(to[1]),"%02x%02x",slt[0],slt[1]);
+    /* Waiting for Monty to do the merge */
+    my_MD5Init(&context);
+    /* Use Salt for Hash */
+    my_MD5Update(&context,(unsigned char*)&salt,2);
+    
+    for (; *password ; password++)
+    {
+      if (*password == ' ' || *password == '\t')
+        continue;/* skip space in password */
+      my_MD5Update(&context,(unsigned char*)&password[0],1);	
+    }
+    my_MD5Final(digest,&context);
+    /* Print resulting hash into the password*/
+/*    sprintf(&(to[5]),
+      "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+      digest[0],digest[1],digest[2],digest[3],digest[4],digest[5],digest[6],
+      digest[7],digest[8],digest[9],digest[10],digest[11],digest[12],digest[13],
+      digest[14],digest[15]);  */
+      sprintf(&to[5],"1234567890123456789012345");
+      
+  }
+}
+
+uint get_password_length()
 {
-  ulong hash_res[2];
-  hash_password(hash_res,password);
-  sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
+  if (old_passwords)
+    return 16;
+  else return 37;
 }
 
+
 inline uint char_val(char X)
 {
   return (uint) (X >= '0' && X <= '9' ? X-'0' :
-- 
2.30.9