my_proto.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * MYSQL 5.0 Protocol Implementation
  3. * Copyright (C)2005-2016 Haxe Foundation
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <math.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include "my_proto.h"
  27. #define MAX_PACKET_LENGTH 0xFFFFFF
  28. int myp_recv( MYSQL *m, void *buf, int size ) {
  29. while( size ) {
  30. int len = psock_recv(m->s,(char*)buf,size);
  31. if( len <= 0 ) return size == 0 ? 1 : 0;
  32. buf = ((char*)buf) + len;
  33. size -= len;
  34. }
  35. return 1;
  36. }
  37. int myp_send( MYSQL *m, void *buf, int size ) {
  38. while( size ) {
  39. int len = psock_send(m->s,(char*)buf,size);
  40. if( len <= 0 ) return size == 0 ? 1 : 0;
  41. buf = ((char*)buf) + len;
  42. size -= len;
  43. }
  44. return 1;
  45. }
  46. int myp_read( MYSQL_PACKET *p, void *buf, int size ) {
  47. if( p->size - p->pos < size ) {
  48. p->error = 1;
  49. return 0;
  50. }
  51. memcpy(buf,p->buf + p->pos,size);
  52. p->pos += size;
  53. return 1;
  54. }
  55. unsigned char myp_read_byte( MYSQL_PACKET *p ) {
  56. unsigned char c;
  57. if( !myp_read(p,&c,1) )
  58. return 0;
  59. return c;
  60. }
  61. unsigned short myp_read_ui16( MYSQL_PACKET *p ) {
  62. unsigned short i;
  63. if( !myp_read(p,&i,2) )
  64. return 0;
  65. return i;
  66. }
  67. int myp_read_int( MYSQL_PACKET *p ) {
  68. int i;
  69. if( !myp_read(p,&i,4) )
  70. return 0;
  71. return i;
  72. }
  73. int myp_read_bin( MYSQL_PACKET *p ) {
  74. int c = myp_read_byte(p);
  75. if( c <= 250 )
  76. return c;
  77. if( c == 251 )
  78. return -1; // NULL
  79. if( c == 252 )
  80. return myp_read_ui16(p);
  81. if( c == 253 ) {
  82. c = 0;
  83. myp_read(p,&c,3);
  84. return c;
  85. }
  86. if( c == 254 )
  87. return myp_read_int(p);
  88. p->error = 1;
  89. return 0;
  90. }
  91. const char *myp_read_string( MYSQL_PACKET *p ) {
  92. char *str;
  93. if( p->pos >= p->size ) {
  94. p->error = 1;
  95. return "";
  96. }
  97. str = p->buf + p->pos;
  98. p->pos += strlen(str) + 1;
  99. return str;
  100. }
  101. char *myp_read_bin_str( MYSQL_PACKET *p ) {
  102. int size = myp_read_bin(p);
  103. char *str;
  104. if( size == -1 )
  105. return NULL;
  106. if( p->error || p->pos + size > p->size ) {
  107. p->error = 1;
  108. return NULL;
  109. }
  110. str = (char*)malloc(size + 1);
  111. memcpy(str,p->buf + p->pos, size);
  112. str[size] = 0;
  113. p->pos += size;
  114. return str;
  115. }
  116. int myp_read_packet( MYSQL *m, MYSQL_PACKET *p ) {
  117. unsigned int psize;
  118. p->pos = 0;
  119. p->error = 0;
  120. if( !myp_recv(m,&psize,4) ) {
  121. p->error = 1;
  122. p->size = 0;
  123. return 0;
  124. }
  125. //p->id = (psize >> 24);
  126. psize &= 0xFFFFFF;
  127. p->size = psize;
  128. if( p->mem < (int)psize ) {
  129. free(p->buf);
  130. p->buf = (char*)malloc(psize + 1);
  131. p->mem = psize;
  132. }
  133. p->buf[psize] = 0;
  134. if( psize == 0 || !myp_recv(m,p->buf,psize) ) {
  135. p->error = 1;
  136. p->size = 0;
  137. p->buf[0] = 0;
  138. return 0;
  139. }
  140. return 1;
  141. }
  142. int myp_send_packet( MYSQL *m, MYSQL_PACKET *p, int *packet_counter ) {
  143. unsigned int header;
  144. char *buf = p->buf;
  145. int size = p->size;
  146. int next = 1;
  147. while( next ) {
  148. int psize;
  149. if( size >= MAX_PACKET_LENGTH )
  150. psize = MAX_PACKET_LENGTH;
  151. else {
  152. psize = size;
  153. next = 0;
  154. }
  155. header = psize | (((*packet_counter)++) << 24);
  156. if( !myp_send(m,&header,4) || !myp_send(m,buf,psize) ) {
  157. p->error = 1;
  158. return 0;
  159. }
  160. buf += psize;
  161. size -= psize;
  162. }
  163. return 1;
  164. }
  165. void myp_begin_packet( MYSQL_PACKET *p, int minsize ) {
  166. if( p->mem < minsize ) {
  167. free(p->buf);
  168. p->buf = (char*)malloc(minsize + 1);
  169. p->mem = minsize;
  170. }
  171. p->error = 0;
  172. p->size = 0;
  173. }
  174. void myp_write( MYSQL_PACKET *p, const void *data, int size ) {
  175. if( p->size + size > p->mem ) {
  176. char *buf2;
  177. if( p->mem == 0 ) p->mem = 32;
  178. do {
  179. p->mem <<= 1;
  180. } while( p->size + size > p->mem );
  181. buf2 = (char*)malloc(p->mem + 1);
  182. memcpy(buf2,p->buf,p->size);
  183. free(p->buf);
  184. p->buf = buf2;
  185. }
  186. memcpy( p->buf + p->size , data, size );
  187. p->size += size;
  188. }
  189. void myp_write_byte( MYSQL_PACKET *p, int i ) {
  190. unsigned char c = (unsigned char)i;
  191. myp_write(p,&c,1);
  192. }
  193. void myp_write_ui16( MYSQL_PACKET *p, int i ) {
  194. unsigned short c = (unsigned char)i;
  195. myp_write(p,&c,2);
  196. }
  197. void myp_write_int( MYSQL_PACKET *p, int i ) {
  198. myp_write(p,&i,4);
  199. }
  200. void myp_write_string( MYSQL_PACKET *p, const char *str ) {
  201. myp_write(p,str,strlen(str) + 1);
  202. }
  203. void myp_write_string_eof( MYSQL_PACKET *p, const char *str ) {
  204. myp_write(p,str,strlen(str));
  205. }
  206. void myp_write_bin( MYSQL_PACKET *p, int size ) {
  207. if( size <= 250 ) {
  208. unsigned char l = (unsigned char)size;
  209. myp_write(p,&l,1);
  210. } else if( size < 0x10000 ) {
  211. unsigned char c = 252;
  212. unsigned short l = (unsigned short)size;
  213. myp_write(p,&c,1);
  214. myp_write(p,&l,2);
  215. } else if( size < 0x1000000 ) {
  216. unsigned char c = 253;
  217. unsigned int l = (unsigned short)size;
  218. myp_write(p,&c,1);
  219. myp_write(p,&l,3);
  220. } else {
  221. unsigned char c = 254;
  222. myp_write(p,&c,1);
  223. myp_write(p,&size,4);
  224. }
  225. }
  226. void myp_crypt( unsigned char *out, const unsigned char *s1, const unsigned char *s2, unsigned int len ) {
  227. unsigned int i;
  228. for(i=0;i<len;i++)
  229. out[i] = s1[i] ^ s2[i];
  230. }
  231. void myp_encrypt_password( const char *pass, const char *seed, SHA1_DIGEST out ) {
  232. SHA1_CTX ctx;
  233. SHA1_DIGEST hash_stage1, hash_stage2;
  234. // stage 1: hash password
  235. sha1_init(&ctx);
  236. sha1_update(&ctx,(unsigned char*)pass,strlen(pass));;
  237. sha1_final(&ctx,hash_stage1);
  238. // stage 2: hash stage 1; note that hash_stage2 is stored in the database
  239. sha1_init(&ctx);
  240. sha1_update(&ctx, hash_stage1, SHA1_SIZE);
  241. sha1_final(&ctx, hash_stage2);
  242. // create crypt string as sha1(message, hash_stage2)
  243. sha1_init(&ctx);
  244. sha1_update(&ctx, (unsigned char*)seed, SHA1_SIZE);
  245. sha1_update(&ctx, hash_stage2, SHA1_SIZE);
  246. sha1_final( &ctx, out );
  247. // xor the result
  248. myp_crypt(out,out,hash_stage1,SHA1_SIZE);
  249. }
  250. typedef struct {
  251. unsigned long seed1;
  252. unsigned long seed2;
  253. unsigned long max_value;
  254. double max_value_dbl;
  255. } rand_ctx;
  256. static void random_init( rand_ctx *r, unsigned long seed1, unsigned long seed2 ) {
  257. r->max_value = 0x3FFFFFFFL;
  258. r->max_value_dbl = (double)r->max_value;
  259. r->seed1 = seed1 % r->max_value ;
  260. r->seed2 = seed2 % r->max_value;
  261. }
  262. static double myp_rnd( rand_ctx *r ) {
  263. r->seed1 = (r->seed1 * 3 + r->seed2) % r->max_value;
  264. r->seed2 = (r->seed1 + r->seed2 + 33) % r->max_value;
  265. return (((double) r->seed1)/r->max_value_dbl);
  266. }
  267. static void hash_password( unsigned long *result, const char *password, int password_len ) {
  268. register unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;
  269. unsigned long tmp;
  270. const char *password_end = password + password_len;
  271. for(; password < password_end; password++) {
  272. if( *password == ' ' || *password == '\t' )
  273. continue;
  274. tmp = (unsigned long)(unsigned char)*password;
  275. nr ^= (((nr & 63)+add)*tmp)+(nr << 8);
  276. nr2 += (nr2 << 8) ^ nr;
  277. add += tmp;
  278. }
  279. result[0] = nr & (((unsigned long) 1L << 31) -1L);
  280. result[1] = nr2 & (((unsigned long) 1L << 31) -1L);
  281. }
  282. void myp_encrypt_pass_323( const char *password, const char seed[SEED_LENGTH_323], char to[SEED_LENGTH_323] ) {
  283. rand_ctx r;
  284. unsigned long hash_pass[2], hash_seed[2];
  285. char extra, *to_start = to;
  286. const char *seed_end = seed + SEED_LENGTH_323;
  287. hash_password(hash_pass,password,(unsigned int)strlen(password));
  288. hash_password(hash_seed,seed,SEED_LENGTH_323);
  289. random_init(&r,hash_pass[0] ^ hash_seed[0],hash_pass[1] ^ hash_seed[1]);
  290. while( seed < seed_end ) {
  291. *to++ = (char)(floor(myp_rnd(&r)*31)+64);
  292. seed++;
  293. }
  294. extra= (char)(floor(myp_rnd(&r)*31));
  295. while( to_start != to )
  296. *(to_start++) ^= extra;
  297. }
  298. // defined in mysql/strings/ctype-*.c
  299. const char *myp_charset_name( int charset ) {
  300. switch( charset ) {
  301. case 8:
  302. case 31:
  303. case 47:
  304. return "latin1";
  305. case 63:
  306. return "binary";
  307. // 101+ : utf16
  308. // 160+ : utf32
  309. case 33:
  310. case 83:
  311. case 223:
  312. case 254:
  313. return "utf8";
  314. case 45:
  315. case 46:
  316. return "utf8mb4"; // superset of utf8 with up to 4 bytes per-char
  317. default:
  318. if( charset >= 192 && charset <= 211 )
  319. return "utf8";
  320. if( charset >= 224 && charset <= 243 )
  321. return "utf8mb4";
  322. }
  323. return NULL;
  324. }
  325. int myp_supported_charset( int charset ) {
  326. return myp_charset_name(charset) != NULL;
  327. }
  328. int myp_escape_string( int charset, char *sout, const char *sin, int length ) {
  329. // this is safe for UTF8 as well since mysql protects against invalid UTF8 char injection
  330. const char *send = sin + length;
  331. char *sbegin = sout;
  332. while( sin != send ) {
  333. char c = *sin++;
  334. switch( c ) {
  335. case 0:
  336. *sout++ = '\\';
  337. *sout++ = '0';
  338. break;
  339. case '\n':
  340. *sout++ = '\\';
  341. *sout++ = 'n';
  342. break;
  343. case '\r':
  344. *sout++ = '\\';
  345. *sout++ = 'r';
  346. break;
  347. case '\\':
  348. *sout++ = '\\';
  349. *sout++ = '\\';
  350. break;
  351. case '\'':
  352. *sout++ = '\\';
  353. *sout++ = '\'';
  354. break;
  355. case '"':
  356. *sout++ = '\\';
  357. *sout++ = '"';
  358. break;
  359. case '\032':
  360. *sout++ = '\\';
  361. *sout++ = 'Z';
  362. break;
  363. default:
  364. *sout++ = c;
  365. }
  366. }
  367. *sout = 0;
  368. return sout - sbegin;
  369. }
  370. int myp_escape_quotes( int charset, char *sout, const char *sin, int length ) {
  371. const char *send = sin + length;
  372. char *sbegin = sout;
  373. while( sin != send ) {
  374. char c = *sin++;
  375. *sout++ = c;
  376. if( c == '\'' )
  377. *sout++ = c;
  378. }
  379. *sout = 0;
  380. return sout - sbegin;
  381. }
  382. /* ************************************************************************ */