Dependents:   TimeZoneDemo EthernetJackTestCode MMEx_Challenge ntp_mem ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mycrypt.c Source File

mycrypt.c

00001 /* Copyright (C) 2007 MySQL AB & Michael Widenius
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
00015 
00016 #define SCRAMBLE_LENGTH_323 8
00017 
00018 #include <string.h>
00019 #include <math.h>
00020 
00021 typedef unsigned int uint;
00022 typedef unsigned long ulong;
00023 typedef unsigned char uchar;
00024 
00025 struct my_rnd_struct {
00026   unsigned long seed1,seed2,max_value;
00027   double max_value_dbl;
00028 };
00029 
00030 static void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2);
00031 static double my_rnd(struct my_rnd_struct *rand_st);
00032 static void hash_password(ulong *result, const char *password, uint password_len);
00033 
00034 /*
00035   Initialize random generator
00036 
00037   NOTES
00038     MySQL's password checks depends on this, so don't do any changes
00039     that changes the random numbers that are generated!
00040 */
00041 
00042 static void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2)
00043 {
00044   rand_st->max_value= 0x3FFFFFFFL;
00045   rand_st->max_value_dbl=(double) rand_st->max_value;
00046   rand_st->seed1=seed1%rand_st->max_value ;
00047   rand_st->seed2=seed2%rand_st->max_value;
00048 }
00049 
00050 /*
00051   Generate random number.
00052 
00053   SYNOPSIS
00054     my_rnd()
00055     rand_st    INOUT  Structure used for number generation
00056     
00057   RETURN VALUE
00058     generated pseudo random number
00059 */
00060 
00061 static double my_rnd(struct my_rnd_struct *rand_st)
00062 {
00063   rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
00064   rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
00065   return (((double) rand_st->seed1)/rand_st->max_value_dbl);
00066 }
00067 
00068 /*
00069     Generate binary hash from raw text string 
00070     Used for Pre-4.1 password handling
00071   SYNOPSIS
00072     hash_password()
00073     result       OUT store hash in this location
00074     password     IN  plain text password to build hash
00075     password_len IN  password length (password may be not null-terminated)
00076 */
00077 
00078 static void hash_password(ulong *result, const char *password, uint password_len)
00079 {
00080   register ulong nr=1345345333L, add=7, nr2=0x12345671L;
00081   ulong tmp;
00082   const char *password_end= password + password_len;
00083   for (; password < password_end; password++)
00084   {
00085     if (*password == ' ' || *password == '\t')
00086       continue;                                 /* skip space in password */
00087     tmp= (ulong) (uchar) *password;
00088     nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
00089     nr2+=(nr2 << 8) ^ nr;
00090     add+=tmp;
00091   }
00092   result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
00093   result[1]=nr2 & (((ulong) 1L << 31) -1L);
00094 }
00095 
00096 
00097 
00098 /*
00099     Scramble string with password.
00100     Used in pre 4.1 authentication phase.
00101   SYNOPSIS
00102     scramble_323()
00103     to       OUT Store scrambled message here. Buffer must be at least
00104                  SCRAMBLE_LENGTH_323+1 bytes long
00105     message  IN  Message to scramble. Message must be at least
00106                  SRAMBLE_LENGTH_323 bytes long.
00107     password IN  Password to use while scrambling
00108 */
00109 
00110 void scramble_323(char *to, const char *message, const char *password)
00111 {
00112   struct my_rnd_struct rand_st;
00113   ulong hash_pass[2], hash_message[2];
00114 
00115   if (password && password[0])
00116   {
00117     char extra, *to_start=to;
00118     const char *message_end= message + SCRAMBLE_LENGTH_323;
00119     hash_password(hash_pass,password, (uint) strlen(password));
00120     hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
00121     my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0],
00122                hash_pass[1] ^ hash_message[1]);
00123     for (; message < message_end; message++)
00124       *to++= (char) (floor(my_rnd(&rand_st)*31)+64);
00125     extra=(char) (floor(my_rnd(&rand_st)*31));
00126     while (to_start != to)
00127       *(to_start++)^=extra;
00128   }
00129   *to= 0;
00130 }
00131