~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/session.cc

  • Committer: Brian Aker
  • Date: 2009-04-05 19:53:29 UTC
  • mfrom: (971.3.11 eday-dev)
  • Revision ID: brian@tangent.org-20090405195329-k2vpiwhlri9oaedq
MergeĀ fromĀ Eric.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include <drizzled/item/empty_string.h>
33
33
#include <drizzled/show.h>
34
34
#include <drizzled/scheduling.h>
35
 
#include <libdrizzleclient/errmsg.h>
36
35
 
37
36
/*
38
37
  The following is used to initialise Table_ident with a internal
234
233
  replication_data= 0;
235
234
  mysys_var=0;
236
235
  dbug_sentry=Session_SENTRY_MAGIC;
237
 
  net.vio= 0;
238
236
  client_capabilities= 0;                       // minimalistic client
239
237
  cleanup_done= abort_on_warning= no_warnings_for_error= false;
240
238
  peer_port= 0;                                 // For SHOW PROCESSLIST
241
239
  transaction.on= 1;
 
240
  compression= 0;
242
241
  pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
243
242
 
244
243
  /* Variables with default values */
246
245
  where= Session::DEFAULT_WHERE;
247
246
  server_id = ::server_id;
248
247
  command=COM_CONNECT;
249
 
  *scramble= '\0';
250
248
 
251
249
  init();
252
250
  /* Initialize sub structures */
262
260
  const Query_id& local_query_id= Query_id::get_query_id();
263
261
  tablespace_op= false;
264
262
  tmp= sql_rnd();
265
 
  drizzleclient_randominit(&rand, tmp + (uint64_t) &rand,
266
 
                           tmp + (uint64_t)local_query_id.value());
 
263
  protocol->init_random(tmp + (uint64_t) &protocol,
 
264
                        tmp + (uint64_t)local_query_id.value());
267
265
  substitute_null_with_insert_id = false;
268
266
  thr_lock_info_init(&lock_info); /* safety: will be reset after start */
269
267
  thr_lock_owner_init(&main_lock_id, &lock_info);
432
430
  Session_CHECK_SENTRY(this);
433
431
  add_to_status(&global_status_var, &status_var);
434
432
 
435
 
  if (drizzleclient_vio_ok())
 
433
  if (protocol->io_ok())
436
434
  {
437
435
    if (global_system_variables.log_warnings)
438
436
        errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
443
441
  }
444
442
 
445
443
  /* Close connection */
446
 
  if (net.vio)
447
 
  {
448
 
    drizzleclient_net_close(&net);
449
 
    drizzleclient_net_end(&net);
450
 
  }
 
444
  protocol->close();
 
445
 
451
446
  if (cleanup_done == false)
452
447
    cleanup();
453
448
 
606
601
  if (variables.max_join_size == HA_POS_ERROR)
607
602
    options |= OPTION_BIG_SELECTS;
608
603
  if (client_capabilities & CLIENT_COMPRESS)
609
 
    net.compress= true;
 
604
  {
 
605
    compression= 1;
 
606
    protocol->enable_compression();
 
607
  }
610
608
 
611
609
  version= refresh_version;
612
610
  set_proc_info(NULL);
651
649
 
652
650
bool Session::authenticate()
653
651
{
654
 
  /* Use "connect_timeout" value during connection phase */
655
 
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
656
 
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
657
 
 
658
652
  lex_start(this);
659
 
 
660
 
  bool connection_is_valid= _checkConnection();
661
 
  drizzleclient_net_end_statement(this);
662
 
 
663
 
  if (! connection_is_valid)
664
 
  {     
665
 
    /* We got wrong permissions from _checkConnection() */
666
 
    statistic_increment(aborted_connects, &LOCK_status);
667
 
    return false;
668
 
  }
669
 
 
670
 
  /* Connect completed, set read/write timeouts back to default */
671
 
  drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
672
 
  drizzleclient_net_set_write_timeout(&net, variables.net_write_timeout);
673
 
  return true;
674
 
}
675
 
 
676
 
bool Session::_checkConnection()
677
 
{
678
 
  uint32_t pkt_len= 0;
679
 
  char *end;
680
 
 
681
 
  // TCP/IP connection
682
 
  {
683
 
    char ip[NI_MAXHOST];
684
 
 
685
 
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
686
 
    {
687
 
      my_error(ER_BAD_HOST_ERROR, MYF(0), security_ctx.ip.c_str());
688
 
      return false;
689
 
    }
690
 
 
691
 
    security_ctx.ip.assign(ip);
692
 
  }
693
 
  drizzleclient_net_keepalive(&net, true);
694
 
 
695
 
  uint32_t server_capabilites;
696
 
  {
697
 
    /* buff[] needs to big enough to hold the server_version variable */
698
 
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
699
 
 
700
 
    server_capabilites= CLIENT_BASIC_FLAGS;
701
 
 
702
 
#ifdef HAVE_COMPRESS
703
 
    server_capabilites|= CLIENT_COMPRESS;
704
 
#endif /* HAVE_COMPRESS */
705
 
 
706
 
    end= buff + strlen(server_version);
707
 
    if ((end - buff) >= SERVER_VERSION_LENGTH)
708
 
      end= buff + (SERVER_VERSION_LENGTH - 1);
709
 
    memcpy(buff, server_version, end - buff);
710
 
    *end= 0;
711
 
    end++;
712
 
 
713
 
    int4store((unsigned char*) end, thread_id);
714
 
    end+= 4;
715
 
    /*
716
 
      So as _checkConnection is the only entry point to authorization
717
 
      procedure, scramble is set here. This gives us new scramble for
718
 
      each handshake.
719
 
    */
720
 
    drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
721
 
    /*
722
 
      Old clients does not understand long scrambles, but can ignore packet
723
 
      tail: that's why first part of the scramble is placed here, and second
724
 
      part at the end of packet.
725
 
    */
726
 
    end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
727
 
    end+= SCRAMBLE_LENGTH_323;
728
 
 
729
 
    *end++= 0; /* an empty byte for some reason */
730
 
 
731
 
    int2store(end, server_capabilites);
732
 
    /* write server characteristics: up to 16 bytes allowed */
733
 
    end[2]=(char) default_charset_info->number;
734
 
    int2store(end+3, server_status);
735
 
    memset(end+5, 0, 13);
736
 
    end+= 18;
737
 
    /* write scramble tail */
738
 
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
739
 
    end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
740
 
    end+= scramble_len;
741
 
 
742
 
    *end++= 0; /* an empty byte for some reason */
743
 
 
744
 
    /* At this point we write connection message and read reply */
745
 
    if (drizzleclient_net_write_command(&net
746
 
          , (unsigned char) protocol_version
747
 
          , (unsigned char*) ""
748
 
          , 0
749
 
          , (unsigned char*) buff
750
 
          , (size_t) (end-buff)) 
751
 
        ||      (pkt_len= drizzleclient_net_read(&net)) == packet_error 
752
 
        || pkt_len < MIN_HANDSHAKE_SIZE)
753
 
    {
754
 
      my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
755
 
      return false;
756
 
    }
757
 
  }
758
 
  if (packet.alloc(variables.net_buffer_length))
759
 
    return false; /* The error is set by alloc(). */
760
 
 
761
 
  client_capabilities= uint2korr(net.read_pos);
762
 
 
763
 
 
764
 
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
765
 
  max_client_packet_length= uint4korr(net.read_pos + 4);
766
 
  update_charset();
767
 
  end= (char*) net.read_pos + 32;
768
 
 
769
 
  /*
770
 
    Disable those bits which are not supported by the server.
771
 
    This is a precautionary measure, if the client lies. See Bug#27944.
772
 
  */
773
 
  client_capabilities&= server_capabilites;
774
 
 
775
 
  if (end >= (char*) net.read_pos + pkt_len + 2)
776
 
  {
777
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
778
 
    return false;
779
 
  }
780
 
 
781
 
  net.return_status= &server_status;
782
 
 
783
 
  char *user= end;
784
 
  char *passwd= strchr(user, '\0')+1;
785
 
  uint32_t user_len= passwd - user - 1;
786
 
  char *l_db= passwd;
787
 
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
788
 
  char user_buff[USERNAME_LENGTH + 1];  // buffer to store user in utf8
789
 
  uint32_t dummy_errors;
790
 
 
791
 
  /*
792
 
    Old clients send null-terminated string as password; new clients send
793
 
    the size (1 byte) + string (not null-terminated). Hence in case of empty
794
 
    password both send '\0'.
795
 
 
796
 
    This strlen() can't be easily deleted without changing protocol.
797
 
 
798
 
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
799
 
    *passwd > 127 and become 2**32-127+ after casting to uint.
800
 
  */
801
 
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
802
 
    (unsigned char)(*passwd++) : strlen(passwd);
803
 
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
804
 
 
805
 
  /* strlen() can't be easily deleted without changing protocol */
806
 
  uint32_t db_len= l_db ? strlen(l_db) : 0;
807
 
 
808
 
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
809
 
  {
810
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
811
 
    return false;
812
 
  }
813
 
 
814
 
  /* Since 4.1 all database names are stored in utf8 */
815
 
  if (l_db)
816
 
  {
817
 
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
818
 
                             system_charset_info,
819
 
                             l_db, db_len,
820
 
                             charset(), &dummy_errors)]= 0;
821
 
    l_db= db_buff;
822
 
  }
823
 
 
824
 
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
825
 
                                       system_charset_info, user, user_len,
826
 
                                       charset(), &dummy_errors)]= '\0';
827
 
  user= user_buff;
828
 
 
829
 
  /* If username starts and ends in "'", chop them off */
830
 
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
831
 
  {
832
 
    user[user_len-1]= 0;
833
 
    user++;
834
 
    user_len-= 2;
835
 
  }
836
 
 
837
 
  security_ctx.user.assign(user);
838
 
 
839
 
  return checkUser(passwd, passwd_len, l_db);
 
653
  if (protocol->authenticate())
 
654
    return true;
 
655
 
 
656
  statistic_increment(aborted_connects, &LOCK_status);
 
657
  return false;
840
658
}
841
659
 
842
660
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
890
708
 
891
709
bool Session::executeStatement()
892
710
{
893
 
  bool return_value;
894
711
  char *l_packet= 0;
895
712
  uint32_t packet_length;
896
713
 
902
719
  */
903
720
  lex->current_select= 0;
904
721
 
905
 
  /*
906
 
    This thread will do a blocking read from the client which
907
 
    will be interrupted when the next command is received from
908
 
    the client, the connection is closed or "net_wait_timeout"
909
 
    number of seconds has passed
910
 
  */
911
 
  drizzleclient_net_set_read_timeout(&net, variables.net_wait_timeout);
912
 
 
913
 
  /*
914
 
    XXX: this code is here only to clear possible errors of init_connect.
915
 
    Consider moving to init_connect() instead.
916
 
  */
917
 
  clear_error();                                // Clear error message
918
 
  main_da.reset_diagnostics_area();
919
 
 
920
 
  net_new_transaction(&net);
921
 
 
922
 
  packet_length= drizzleclient_net_read(&net);
923
 
  if (packet_length == packet_error)
924
 
  {
925
 
    /* Check if we can continue without closing the connection */
926
 
 
927
 
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
928
 
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
929
 
    /* Assert is invalid for dirty connection shutdown
930
 
     *     assert(session->is_error());
931
 
     */
932
 
    drizzleclient_net_end_statement(this);
933
 
 
934
 
    if (net.error != 3)
935
 
    {
936
 
      return_value= false;                       // We have to close it.
937
 
      goto out;
938
 
    }
939
 
 
940
 
    net.error= 0;
941
 
    return_value= true;
942
 
    goto out;
943
 
  }
944
 
 
945
 
  l_packet= (char*) net.read_pos;
946
 
  /*
947
 
    'packet_length' contains length of data, as it was stored in packet
948
 
    header. In case of malformed header, drizzleclient_net_read returns zero.
949
 
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
950
 
    number of bytes was actually read from network.
951
 
    There is also an extra safety measure in drizzleclient_net_read:
952
 
    it sets packet[packet_length]= 0, but only for non-zero packets.
953
 
  */
954
 
  if (packet_length == 0)                       /* safety */
955
 
  {
956
 
    /* Initialize with COM_SLEEP packet */
957
 
    l_packet[0]= (unsigned char) COM_SLEEP;
958
 
    packet_length= 1;
959
 
  }
960
 
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
961
 
  l_packet[packet_length]= '\0';                  /* safety */
 
722
  if (protocol->read_command(&l_packet, &packet_length) == false)
 
723
    return false;
 
724
 
 
725
  if (packet_length == 0)
 
726
    return true;
962
727
 
963
728
  l_command= (enum enum_server_command) (unsigned char) l_packet[0];
964
729
 
965
730
  if (command >= COM_END)
966
731
    command= COM_END;                           // Wrong command
967
732
 
968
 
  /* Restore read timeout value */
969
 
  drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
970
 
 
971
733
  assert(packet_length);
972
 
  return_value= ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
973
 
 
974
 
out:
975
 
  return return_value;
 
734
  return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
976
735
}
977
736
 
978
737
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
2213
1972
  plugin_sessionvar_cleanup(this);
2214
1973
 
2215
1974
  /* If necessary, log any aborted or unauthorized connections */
2216
 
  if (killed || (net.error && net.vio != 0))
 
1975
  if (killed || protocol->was_aborted())
2217
1976
    statistic_increment(aborted_threads, &LOCK_status);
2218
1977
 
2219
 
  if (net.error && net.vio != 0)
 
1978
  if (protocol->was_aborted())
2220
1979
  {
2221
1980
    if (! killed && variables.log_warnings > 1)
2222
1981
    {
2232
1991
  }
2233
1992
 
2234
1993
  /* Close out our connection to the client */
2235
 
  st_vio *vio;
2236
1994
  if (should_lock)
2237
1995
    (void) pthread_mutex_lock(&LOCK_thread_count);
2238
1996
  killed= Session::KILL_CONNECTION;
2239
 
  if ((vio= net.vio) != 0)
 
1997
  if (protocol->io_ok())
2240
1998
  {
2241
1999
    if (errcode)
2242
 
      net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
2243
 
    drizzleclient_net_close(&net);              /* vio is freed in delete session */
 
2000
      protocol->send_error(errcode, ER(errcode)); /* purecov: inspected */
 
2001
    protocol->close();
2244
2002
  }
2245
2003
  if (should_lock)
2246
2004
    (void) pthread_mutex_unlock(&LOCK_thread_count);