Drizzled Public API Documentation

pack.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  *     * Redistributions of source code must retain the above copyright
00012  * notice, this list of conditions and the following disclaimer.
00013  *
00014  *     * Redistributions in binary form must reproduce the above
00015  * copyright notice, this list of conditions and the following disclaimer
00016  * in the documentation and/or other materials provided with the
00017  * distribution.
00018  *
00019  *     * The names of its contributors may not be used to endorse or
00020  * promote products derived from this software without specific prior
00021  * written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  */
00036 
00042 #include "common.h"
00043 
00044 /*
00045  * Private declarations
00046  */
00047 
00057 static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
00058                                             uint8_t *buffer);
00059 
00062 /*
00063  * Public definitions
00064  */
00065 
00066 uint8_t *drizzle_pack_length(uint64_t number, uint8_t *ptr)
00067 {
00068   if (number < 251)
00069   {
00070     ptr[0]= (uint8_t)number;
00071     ptr++;
00072   }
00073   else if (number < 65536)
00074   {
00075     ptr[0]= 252;
00076     ptr++;
00077     drizzle_set_byte2(ptr, number);
00078     ptr+= 2;
00079   }
00080   else if (number < 16777216)
00081   {
00082     ptr[0]= 253;
00083     ptr++;
00084     drizzle_set_byte3(ptr, number);
00085     ptr+= 3;
00086   }
00087   else
00088   {
00089     ptr[0]= 254;
00090     ptr++;
00091     drizzle_set_byte8(ptr, number);
00092     ptr+= 8;
00093   }
00094 
00095   return ptr;
00096 }
00097 
00098 uint64_t drizzle_unpack_length(drizzle_con_st *con, drizzle_return_t *ret_ptr)
00099 {
00100   uint64_t length;
00101   uint8_t bytes;
00102 
00103   if (con->buffer_ptr[0] < 251)
00104   {
00105     length= (uint64_t)(con->buffer_ptr[0]);
00106     bytes= 1;
00107   }
00108   else if (con->buffer_ptr[0] == 251)
00109   {
00110     con->buffer_ptr++;
00111     con->buffer_size--;
00112     con->packet_size--;
00113 
00114     *ret_ptr= DRIZZLE_RETURN_NULL_SIZE;
00115     return 0;
00116   }
00117   else if (con->buffer_ptr[0] == 252 && con->buffer_size > 2)
00118   {
00119     length= drizzle_get_byte2(con->buffer_ptr + 1);
00120     bytes= 3;
00121   }
00122   else if (con->buffer_ptr[0] == 253 && con->buffer_size > 3)
00123   {
00124     length= drizzle_get_byte3(con->buffer_ptr + 1);
00125     bytes= 4;
00126   }
00127   else if (con->buffer_size > 8)
00128   {
00129     length= drizzle_get_byte8(con->buffer_ptr + 1);
00130     bytes= 9;
00131   }
00132   else
00133   {
00134     *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
00135     return 0;
00136   }
00137 
00138   con->buffer_ptr+= bytes;
00139   con->buffer_size-= bytes;
00140   con->packet_size-= bytes;
00141 
00142   *ret_ptr= DRIZZLE_RETURN_OK;
00143   return length;
00144 }
00145 
00146 uint8_t *drizzle_pack_string(char *string, uint8_t *ptr)
00147 {
00148   uint64_t size= strlen(string);
00149 
00150   ptr= drizzle_pack_length(size, ptr);
00151   if (size > 0)
00152   {
00153     memcpy(ptr, string, (size_t)size);
00154     ptr+= size;
00155   }
00156 
00157   return ptr;
00158 }
00159 
00160 drizzle_return_t drizzle_unpack_string(drizzle_con_st *con, char *buffer,
00161                                        uint64_t max_length)
00162 {
00163   drizzle_return_t ret= DRIZZLE_RETURN_OK;
00164   uint64_t length;
00165 
00166   length= drizzle_unpack_length(con, &ret);
00167   if (ret != DRIZZLE_RETURN_OK)
00168   {
00169     if (ret == DRIZZLE_RETURN_NULL_SIZE)
00170     {
00171       drizzle_set_error(con->drizzle, "drizzle_unpack_string",
00172                         "unexpected NULL length");
00173     }
00174 
00175     return ret;
00176   }
00177 
00178   if (length < max_length)
00179   {
00180     if (length > 0)
00181       memcpy(buffer, con->buffer_ptr, (size_t)length);
00182 
00183     buffer[length]= 0;
00184   }
00185   else
00186   {
00187     memcpy(buffer, con->buffer_ptr, (size_t)(max_length - 1));
00188     buffer[max_length - 1]= 0;
00189   }
00190   
00191   con->buffer_ptr+= length;
00192   con->buffer_size-= (size_t)length;
00193   con->packet_size-= (size_t)length;
00194 
00195   return DRIZZLE_RETURN_OK;
00196 }
00197 
00198 uint8_t *drizzle_pack_auth(drizzle_con_st *con, uint8_t *ptr,
00199                            drizzle_return_t *ret_ptr)
00200 {
00201   if (con->user[0] != 0)
00202   {
00203     memcpy(ptr, con->user, strlen(con->user));
00204     ptr+= strlen(con->user);
00205   }
00206 
00207   ptr[0]= 0;
00208   ptr++;
00209 
00210   if (con->options & DRIZZLE_CON_RAW_SCRAMBLE && con->scramble != NULL)
00211   {
00212     ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
00213     ptr++;
00214 
00215     memcpy(ptr, con->scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
00216     ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
00217   }
00218   else if (con->password[0] == 0)
00219   {
00220     ptr[0]= 0;
00221     ptr++;
00222     con->packet_size-= DRIZZLE_MAX_SCRAMBLE_SIZE;
00223   }
00224   else
00225   {
00226     ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
00227     ptr++;
00228 
00229     if (con->options & DRIZZLE_CON_MYSQL && con->options & DRIZZLE_CON_AUTH_PLUGIN)
00230     {
00231       snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
00232     }
00233     else if (con->options & DRIZZLE_CON_MYSQL)
00234     {
00235       *ret_ptr= _pack_scramble_hash(con, ptr);
00236       if (*ret_ptr != DRIZZLE_RETURN_OK)
00237         return ptr;
00238     }
00239     else // We assume Drizzle
00240     {
00241       snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
00242     }
00243 
00244     ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
00245   }
00246 
00247   if (con->db[0] != 0)
00248   {
00249     memcpy(ptr, con->db, strlen(con->db));
00250     ptr+= strlen(con->db);
00251   }
00252 
00253   ptr[0]= 0;
00254   ptr++;
00255 
00256   *ret_ptr= DRIZZLE_RETURN_OK;
00257   return ptr;
00258 }
00259 
00260 /*
00261  * Private definitions
00262  */
00263 
00264 static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
00265                                             uint8_t *buffer)
00266 {
00267   SHA1_CTX ctx;
00268   uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
00269   uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
00270 
00271   if (SHA1_DIGEST_LENGTH != DRIZZLE_MAX_SCRAMBLE_SIZE)
00272   {
00273     drizzle_set_error(con->drizzle, "_pack_scramble_hash",
00274                       "SHA1 hash size mismatch:%u:%u", SHA1_DIGEST_LENGTH,
00275                       DRIZZLE_MAX_SCRAMBLE_SIZE);
00276     return DRIZZLE_RETURN_INTERNAL_ERROR;
00277   }
00278 
00279   if (con->scramble == NULL)
00280   {
00281     drizzle_set_error(con->drizzle, "_pack_scramble_hash",
00282                       "no scramble buffer");
00283     return DRIZZLE_RETURN_NO_SCRAMBLE;
00284   }
00285 
00286   /* First hash the password. */
00287   SHA1Init(&ctx);
00288   SHA1Update(&ctx, (uint8_t *)(con->password), strlen(con->password));
00289   SHA1Final(hash_tmp1, &ctx);
00290 
00291   /* Second, hash the password hash. */
00292   SHA1Init(&ctx);
00293   SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
00294   SHA1Final(hash_tmp2, &ctx);
00295 
00296   /* Third, hash the scramble and the double password hash. */
00297   SHA1Init(&ctx);
00298   SHA1Update(&ctx, con->scramble, SHA1_DIGEST_LENGTH);
00299   SHA1Update(&ctx, hash_tmp2, SHA1_DIGEST_LENGTH);
00300   SHA1Final(buffer, &ctx);
00301 
00302   /* Fourth, xor the last hash against the first password hash. */
00303   uint32_t x= 0;
00304   for (; x < SHA1_DIGEST_LENGTH; x++)
00305     buffer[x]= buffer[x] ^ hash_tmp1[x];
00306 
00307   return DRIZZLE_RETURN_OK;
00308 }