static void save_error( MYSQL *m, MYSQL_PACKET *p ) { int ecode; p->pos = 0; // seems like we sometimes get some FFFFFF sequences before // the actual error... do { if( myp_read_byte(p) != 0xFF ) { m->errcode = -1; error(m,"Failed to decode error",NULL); return; } ecode = myp_read_ui16(p); } while( ecode == 0xFFFF ); if( m->is41 && p->buf[p->pos] == '#' ) p->pos += 6; // skip sqlstate marker error(m,"%s",myp_read_string(p)); m->errcode = ecode; }
int myp_read_bin( MYSQL_PACKET *p ) { int c = myp_read_byte(p); if( c <= 250 ) return c; if( c == 251 ) return -1; // NULL if( c == 252 ) return myp_read_ui16(p); if( c == 253 ) { c = 0; myp_read(p,&c,3); return c; } if( c == 254 ) return myp_read_int(p); p->error = 1; return 0; }
static int do_store( MYSQL *m, MYSQL_RES *r ) { int i; MYSQL_PACKET *p = &m->packet; p->pos = 0; r->nfields = myp_read_bin(p); if( p->error ) return 0; r->fields = (MYSQL_FIELD*)malloc(sizeof(MYSQL_FIELD) * r->nfields); memset(r->fields,0,sizeof(MYSQL_FIELD) * r->nfields); for(i=0;i<r->nfields;i++) { if( !myp_read_packet(m,p) ) return 0; { MYSQL_FIELD *f = r->fields + i; f->catalog = m->is41 ? myp_read_bin_str(p) : NULL; f->db = m->is41 ? myp_read_bin_str(p) : NULL; f->table = myp_read_bin_str(p); f->org_table = m->is41 ? myp_read_bin_str(p) : NULL; f->name = myp_read_bin_str(p); f->org_name = m->is41 ? myp_read_bin_str(p) : NULL; if( m->is41 ) myp_read_byte(p); f->charset = m->is41 ? myp_read_ui16(p) : 0x08; f->length = m->is41 ? myp_read_int(p) : myp_read_bin(p); f->type = (FIELD_TYPE)(m->is41 ? myp_read_byte(p) : myp_read_bin(p)); f->flags = m->is41 ? myp_read_ui16(p) : myp_read_bin(p); f->decimals = myp_read_byte(p); if( m->is41 ) myp_read_byte(p); // should be 0 if( m->is41 ) myp_read_byte(p); // should be 0 if( p->error ) return 0; } } // first EOF packet if( !myp_read_packet(m,p) ) return 0; if( myp_read_byte(p) != 0xFE || p->size >= 9 ) return 0; // reset packet buffer (to prevent to store large buffer in row data) free(p->buf); p->buf = NULL; p->mem = 0; // datas while( 1 ) { if( !myp_read_packet(m,p) ) return 0; // EOF : end of datas if( (unsigned char)p->buf[0] == 0xFE && p->size < 9 ) break; // ERROR ? if( (unsigned char)p->buf[0] == 0xFF ) { save_error(m,p); return 0; } // allocate one more row if( r->row_count == r->memory_rows ) { MYSQL_ROW_DATA *rows; r->memory_rows = r->memory_rows ? (r->memory_rows << 1) : 1; rows = (MYSQL_ROW_DATA*)malloc(r->memory_rows * sizeof(MYSQL_ROW_DATA)); memcpy(rows,r->rows,r->row_count * sizeof(MYSQL_ROW_DATA)); free(r->rows); r->rows = rows; } // read row fields { MYSQL_ROW_DATA *current = r->rows + r->row_count++; int prev = 0; current->raw = p->buf; current->lengths = (unsigned long*)malloc(sizeof(unsigned long) * r->nfields); current->datas = (char**)malloc(sizeof(char*) * r->nfields); for(i=0;i<r->nfields;i++) { int l = myp_read_bin(p); if( !p->error ) p->buf[prev] = 0; if( l == -1 ) { current->lengths[i] = 0; current->datas[i] = NULL; } else { current->lengths[i] = l; current->datas[i] = p->buf + p->pos; p->pos += l; } prev = p->pos; } if( !p->error ) p->buf[prev] = 0; } // the packet buffer as been stored, don't reuse it p->buf = NULL; p->mem = 0; if( p->error ) return 0; } return 1; }
MYSQL *mysql_real_connect( MYSQL *m, const char *host, const char *user, const char *pass, void *unused, int port, const char *socket, int options ) { PHOST h; char scramble_buf[21]; MYSQL_PACKET *p = &m->packet; int pcount = 1; if( socket && *socket ) { error(m,"Unix Socket connections are not supported",NULL); return NULL; } h = phost_resolve(host); if( h == UNRESOLVED_HOST ) { error(m,"Failed to resolve host '%s'",host); return NULL; } m->s = psock_create(); if( m->s == INVALID_SOCKET ) { error(m,"Failed to create socket",NULL); return NULL; } psock_set_fastsend(m->s,1); psock_set_timeout(m->s,50); // 50 seconds if( psock_connect(m->s,h,port) != PS_OK ) { myp_close(m); error(m,"Failed to connect on host '%s'",host); return NULL; } if( !myp_read_packet(m,p) ) { myp_close(m); error(m,"Failed to read handshake packet",NULL); return NULL; } // process handshake packet { char filler[13]; unsigned int len; m->infos.proto_version = myp_read_byte(p); // this seems like an error packet if( m->infos.proto_version == 0xFF ) { myp_close(m); save_error(m,p); return NULL; } m->infos.server_version = strdup(myp_read_string(p)); m->infos.thread_id = myp_read_int(p); myp_read(p,scramble_buf,8); myp_read_byte(p); // should be 0 m->infos.server_flags = myp_read_ui16(p); m->infos.server_charset = myp_read_byte(p); m->infos.server_status = myp_read_ui16(p); m->infos.server_flags |= myp_read_ui16(p) << 16; len = myp_read_byte(p); myp_read(p,filler,10); // try to disable 41 m->is41 = (m->infos.server_flags & FL_PROTOCOL_41) != 0; if( !p->error && m->is41 ) myp_read(p,scramble_buf + 8,13); if( p->pos != p->size ) myp_read_string(p); // 5.5+ if( p->error ) { myp_close(m); error(m,"Failed to decode server handshake",NULL); return NULL; } // fill answer packet { unsigned int flags = m->infos.server_flags; int max_packet_size = 0x01000000; SHA1_DIGEST hpass; char filler[23]; flags &= (FL_PROTOCOL_41 | FL_TRANSACTIONS | FL_SECURE_CONNECTION); myp_begin_packet(p,128); if( m->is41 ) { myp_write_int(p,flags); myp_write_int(p,max_packet_size); myp_write_byte(p,m->infos.server_charset); memset(filler,0,23); myp_write(p,filler,23); myp_write_string(p,user); if( *pass ) { myp_encrypt_password(pass,scramble_buf,hpass); myp_write_bin(p,SHA1_SIZE); myp_write(p,hpass,SHA1_SIZE); myp_write_byte(p,0); } else myp_write_bin(p,0); } else { myp_write_ui16(p,flags); // max_packet_size myp_write_byte(p,0xFF); myp_write_byte(p,0xFF); myp_write_byte(p,0xFF); myp_write_string(p,user); if( *pass ) { char hpass[SEED_LENGTH_323 + 1]; myp_encrypt_pass_323(pass,scramble_buf,hpass); hpass[SEED_LENGTH_323] = 0; myp_write(p,hpass,SEED_LENGTH_323 + 1); } else myp_write_bin(p,0); } } } // send connection packet send_cnx_packet: if( !myp_send_packet(m,p,&pcount) ) { myp_close(m); error(m,"Failed to send connection packet",NULL); return NULL; } // read answer packet if( !myp_read_packet(m,p) ) { myp_close(m); error(m,"Failed to read packet",NULL); return NULL; } // increase packet counter (because we read one packet) pcount++; // process answer { int code = myp_read_byte(p); switch( code ) { case 0: // OK packet break; case 0xFF: // ERROR myp_close(m); save_error(m,p); return NULL; case 0xFE: // EOF // we are asked to send old password authentification if( p->size == 1 ) { char hpass[SEED_LENGTH_323 + 1]; myp_encrypt_pass_323(pass,scramble_buf,hpass); hpass[SEED_LENGTH_323] = 0; myp_begin_packet(p,0); myp_write(p,hpass,SEED_LENGTH_323 + 1); goto send_cnx_packet; } // fallthrough default: myp_close(m); error(m,"Invalid packet error",NULL); return NULL; } } // we are connected, setup a longer timeout psock_set_timeout(m->s,18000); return m; }