~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzleclient/password.c

  • Committer: Brian Aker
  • Date: 2009-02-21 00:18:15 UTC
  • Revision ID: brian@tangent.org-20090221001815-x20e8h71e984lvs1
Completion (?) of uint conversion.

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=drizzleclient_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_priv.h"
 
66
#include "password.h"
 
67
 
 
68
#include <stdlib.h>
 
69
#include <string.h>
 
70
 
 
71
/************ MySQL 3.23-4.0 authentication routines: untouched ***********/
 
72
 
 
73
/*
 
74
  New (MySQL 3.21+) random generation structure initialization
 
75
  SYNOPSIS
 
76
    drizzleclient_drizzleclient_randominit()
 
77
    rand_st    OUT  Structure to initialize
 
78
    seed1      IN   First initialization parameter
 
79
    seed2      IN   Second initialization parameter
 
80
*/
 
81
 
 
82
void drizzleclient_drizzleclient_randominit(struct rand_struct *rand_st, uint32_t seed1, uint32_t seed2)
 
83
{                                               /* For mysql 3.21.# */
 
84
  memset(rand_st, 0, sizeof(*rand_st));      /* Avoid UMC varnings */
 
85
  rand_st->max_value= 0x3FFFFFFFL;
 
86
  rand_st->max_value_dbl=(double) rand_st->max_value;
 
87
  rand_st->seed1=seed1%rand_st->max_value ;
 
88
  rand_st->seed2=seed2%rand_st->max_value;
 
89
}
 
90
 
 
91
 
 
92
/*
 
93
    Generate random number.
 
94
  SYNOPSIS
 
95
    drizzleclient_my_rnd()
 
96
    rand_st    INOUT  Structure used for number generation
 
97
  RETURN VALUE
 
98
    generated pseudo random number
 
99
*/
 
100
 
 
101
double drizzleclient_my_rnd(struct rand_struct *rand_st)
 
102
{
 
103
  rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
 
104
  rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
 
105
  return (((double) rand_st->seed1)/rand_st->max_value_dbl);
 
106
}
 
107
 
 
108
 
 
109
/*
 
110
    Generate binary hash from raw text string
 
111
    Used for Pre-4.1 password handling
 
112
  SYNOPSIS
 
113
    drizzleclient_hash_password()
 
114
    result       OUT store hash in this location
 
115
    password     IN  plain text password to build hash
 
116
    password_len IN  password length (password may be not null-terminated)
 
117
*/
 
118
 
 
119
void drizzleclient_hash_password(uint32_t *result, const char *password, uint32_t password_len)
 
120
{
 
121
  register uint32_t nr=1345345333L, add=7, nr2=0x12345671L;
 
122
  uint32_t tmp;
 
123
  const char *password_end= password + password_len;
 
124
  for (; password < password_end; password++)
 
125
  {
 
126
    if (*password == ' ' || *password == '\t')
 
127
      continue;                                 /* skip space in password */
 
128
    tmp= (uint32_t) (unsigned char) *password;
 
129
    nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
 
130
    nr2+=(nr2 << 8) ^ nr;
 
131
    add+=tmp;
 
132
  }
 
133
  result[0]=nr & (((uint32_t) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
 
134
  result[1]=nr2 & (((uint32_t) 1L << 31) -1L);
 
135
}
 
136
 
 
137
static inline uint8_t char_val(uint8_t X)
 
138
{
 
139
  return (uint32_t) (X >= '0' && X <= '9' ? X-'0' :
 
140
      X >= 'A' && X <= 'Z' ? X-'A'+10 : X-'a'+10);
 
141
}
 
142
 
 
143
 
 
144
/*
 
145
     **************** MySQL 4.1.1 authentication routines *************
 
146
*/
 
147
 
 
148
/*
 
149
    Generate string of printable random characters of requested length
 
150
  SYNOPSIS
 
151
    drizzleclient_create_random_string()
 
152
    to       OUT   buffer for generation; must be at least length+1 bytes
 
153
                   long; result string is always null-terminated
 
154
    length   IN    how many random characters to put in buffer
 
155
    rand_st  INOUT structure used for number generation
 
156
*/
 
157
 
 
158
void drizzleclient_create_random_string(char *to, uint32_t length, struct rand_struct *rand_st)
 
159
{
 
160
  char *end= to + length;
 
161
  /* Use pointer arithmetics as it is faster way to do so. */
 
162
  for (; to < end; to++)
 
163
    *to= (char) (drizzleclient_my_rnd(rand_st)*94+33);
 
164
  *to= '\0';
 
165
}
 
166
 
 
167
 
 
168
 
 
169
/*
 
170
    Convert given octet sequence to asciiz string of hex characters;
 
171
    str..str+len and 'to' may not overlap.
 
172
  SYNOPSIS
 
173
    drizzleclient_drizzleclient_octet2hex()
 
174
    buf       OUT output buffer. Must be at least 2*len+1 bytes
 
175
    str, len  IN  the beginning and the length of the input string
 
176
 
 
177
  RETURN
 
178
    buf+len*2
 
179
*/
 
180
 
 
181
char *drizzleclient_drizzleclient_octet2hex(char *to, const char *str, uint32_t len)
 
182
{
 
183
  static const char _dig_vec_upper[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
184
 
 
185
  const char *str_end= str + len;
 
186
  for (; str != str_end; ++str)
 
187
  {
 
188
    *to++= _dig_vec_upper[((unsigned char) *str) >> 4];
 
189
    *to++= _dig_vec_upper[((unsigned char) *str) & 0x0F];
 
190
  }
 
191
  *to= '\0';
 
192
  return to;
 
193
}