~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/password.c

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
/* password checking routines */
 
21
/*****************************************************************************
 
22
  The main idea is that no password are sent between client & server on
 
23
  connection and that no password are saved in mysql in a decodable form.
 
24
 
 
25
  On connection a random string is generated and sent to the client.
 
26
  The client generates a new string with a random generator inited with
 
27
  the hash values from the password and the sent string.
 
28
  This 'check' string is sent to the server where it is compared with
 
29
  a string generated from the stored hash_value of the password and the
 
30
  random string.
 
31
 
 
32
  The password is saved (in user.password) by using the PASSWORD() function in
 
33
  mysql.
 
34
 
 
35
  This is .c file because it's used in libmysqlclient, which is entirely in C.
 
36
  (we need it to be portable to a variety of systems).
 
37
  Example:
 
38
    update user set password=PASSWORD("hello") where user="test"
 
39
  This saves a hashed number as a string in the password field.
 
40
 
 
41
  The new authentication is performed in following manner:
 
42
 
 
43
  SERVER:  public_seed=create_random_string()
 
44
           send(public_seed)
 
45
 
 
46
  CLIENT:  recv(public_seed)
 
47
           hash_stage1=sha1("password")
 
48
           hash_stage2=sha1(hash_stage1)
 
49
           reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
 
50
 
 
51
           // this three steps are done in scramble() 
 
52
 
 
53
           send(reply)
 
54
 
 
55
     
 
56
  SERVER:  recv(reply)
 
57
           hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
 
58
           candidate_hash2=sha1(hash_stage1)
 
59
           check(candidate_hash2==hash_stage2)
 
60
 
 
61
           // this three steps are done in check_scramble()
 
62
 
 
63
*****************************************************************************/
 
64
 
 
65
#include "libdrizzle.h"
 
66
#include "libdrizzle_priv.h"
 
67
#include <stdlib.h>
 
68
#include <string.h>
 
69
 
 
70
/************ MySQL 3.23-4.0 authentication routines: untouched ***********/
 
71
 
 
72
/*
 
73
  New (MySQL 3.21+) random generation structure initialization
 
74
  SYNOPSIS
 
75
    randominit()
 
76
    rand_st    OUT  Structure to initialize
 
77
    seed1      IN   First initialization parameter
 
78
    seed2      IN   Second initialization parameter
 
79
*/
 
80
 
 
81
void randominit(struct rand_struct *rand_st, uint32_t seed1, uint32_t seed2)
 
82
{                                               /* For mysql 3.21.# */
 
83
  memset(rand_st, 0, sizeof(*rand_st));      /* Avoid UMC varnings */
 
84
  rand_st->max_value= 0x3FFFFFFFL;
 
85
  rand_st->max_value_dbl=(double) rand_st->max_value;
 
86
  rand_st->seed1=seed1%rand_st->max_value ;
 
87
  rand_st->seed2=seed2%rand_st->max_value;
 
88
}
 
89
 
 
90
 
 
91
/*
 
92
    Generate random number.
 
93
  SYNOPSIS
 
94
    my_rnd()
 
95
    rand_st    INOUT  Structure used for number generation
 
96
  RETURN VALUE
 
97
    generated pseudo random number
 
98
*/
 
99
 
 
100
double my_rnd(struct rand_struct *rand_st)
 
101
{
 
102
  rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
 
103
  rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
 
104
  return (((double) rand_st->seed1)/rand_st->max_value_dbl);
 
105
}
 
106
 
 
107
 
 
108
/*
 
109
    Generate binary hash from raw text string 
 
110
    Used for Pre-4.1 password handling
 
111
  SYNOPSIS
 
112
    hash_password()
 
113
    result       OUT store hash in this location
 
114
    password     IN  plain text password to build hash
 
115
    password_len IN  password length (password may be not null-terminated)
 
116
*/
 
117
 
 
118
void hash_password(uint32_t *result, const char *password, uint32_t password_len)
 
119
{
 
120
  register uint32_t nr=1345345333L, add=7, nr2=0x12345671L;
 
121
  uint32_t tmp;
 
122
  const char *password_end= password + password_len;
 
123
  for (; password < password_end; password++)
 
124
  {
 
125
    if (*password == ' ' || *password == '\t')
 
126
      continue;                                 /* skip space in password */
 
127
    tmp= (uint32_t) (unsigned char) *password;
 
128
    nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
 
129
    nr2+=(nr2 << 8) ^ nr;
 
130
    add+=tmp;
 
131
  }
 
132
  result[0]=nr & (((uint32_t) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
 
133
  result[1]=nr2 & (((uint32_t) 1L << 31) -1L);
 
134
}
 
135
 
 
136
static inline uint8_t char_val(uint8_t X)
 
137
{
 
138
  return (uint32_t) (X >= '0' && X <= '9' ? X-'0' :
 
139
      X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
 
140
}
 
141
 
 
142
 
 
143
/*
 
144
     **************** MySQL 4.1.1 authentication routines *************
 
145
*/
 
146
 
 
147
/*
 
148
    Generate string of printable random characters of requested length
 
149
  SYNOPSIS
 
150
    create_random_string()
 
151
    to       OUT   buffer for generation; must be at least length+1 bytes
 
152
                   long; result string is always null-terminated
 
153
    length   IN    how many random characters to put in buffer
 
154
    rand_st  INOUT structure used for number generation
 
155
*/
 
156
 
 
157
void create_random_string(char *to, uint32_t length, struct rand_struct *rand_st)
 
158
{
 
159
  char *end= to + length;
 
160
  /* Use pointer arithmetics as it is faster way to do so. */
 
161
  for (; to < end; to++)
 
162
    *to= (char) (my_rnd(rand_st)*94+33);
 
163
  *to= '\0';
 
164
}
 
165
 
 
166
 
 
167
/* Character to use as version identifier for version 4.1 */
 
168
 
 
169
#define PVERSION41_CHAR '*'
 
170
 
 
171
 
 
172
/*
 
173
    Convert given octet sequence to asciiz string of hex characters;
 
174
    str..str+len and 'to' may not overlap.
 
175
  SYNOPSIS
 
176
    octet2hex()
 
177
    buf       OUT output buffer. Must be at least 2*len+1 bytes
 
178
    str, len  IN  the beginning and the length of the input string
 
179
 
 
180
  RETURN
 
181
    buf+len*2
 
182
*/
 
183
 
 
184
char *octet2hex(char *to, const char *str, uint32_t len)
 
185
{
 
186
  const char *str_end= str + len; 
 
187
  for (; str != str_end; ++str)
 
188
  {
 
189
    *to++= _dig_vec_upper[((unsigned char) *str) >> 4];
 
190
    *to++= _dig_vec_upper[((unsigned char) *str) & 0x0F];
 
191
  }
 
192
  *to= '\0';
 
193
  return to;
 
194
}