~stewart/drizzle/docs-improvements-1

« back to all changes in this revision

Viewing changes to plugin/mysql_protocol/mysql_protocol.cc

merged with up to date trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
5
 *
6
6
 * This program is free software; you can redistribute it and/or modify
7
7
 * it under the terms of the GNU General Public License as published by
27
27
#include <algorithm>
28
28
#include <boost/program_options.hpp>
29
29
#include <drizzled/module/option_map.h>
 
30
#include "drizzled/util/tokenize.h"
30
31
#include "errmsg.h"
31
32
#include "mysql_protocol.h"
32
33
#include "mysql_password.h"
33
34
#include "options.h"
34
35
#include "table_function.h"
35
36
 
 
37
#include "drizzled/identifier.h"
 
38
 
36
39
#define PROTOCOL_VERSION 10
37
40
 
38
41
namespace po= boost::program_options;
42
45
namespace drizzle_plugin
43
46
{
44
47
 
 
48
std::vector<std::string> ClientMySQLProtocol::mysql_admin_ip_addresses;
45
49
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
46
50
 
47
51
static port_constraint port;
83
87
}
84
88
 
85
89
ClientMySQLProtocol::ClientMySQLProtocol(int fd, bool using_mysql41_protocol, ProtocolCounters *set_counters):
 
90
  is_admin_connection(false),
86
91
  _using_mysql41_protocol(using_mysql41_protocol),
87
92
  counters(set_counters)
88
93
{
142
147
  { 
143
148
    drizzleclient_net_close(&net);
144
149
    drizzleclient_net_end(&net);
145
 
    counters->connected.decrement();
 
150
    if (is_admin_connection)
 
151
      counters->adminConnected.decrement();
 
152
    else
 
153
      counters->connected.decrement();
146
154
  }
147
155
}
148
156
 
149
157
bool ClientMySQLProtocol::authenticate()
150
158
{
151
159
  bool connection_is_valid;
152
 
 
153
 
  counters->connectionCount.increment();
154
 
  counters->connected.increment();
 
160
  if (is_admin_connection)
 
161
  {
 
162
    counters->adminConnectionCount.increment();
 
163
    counters->adminConnected.increment();
 
164
  }
 
165
  else
 
166
  {
 
167
    counters->connectionCount.increment();
 
168
    counters->connected.increment();
 
169
  }
155
170
 
156
171
  /* Use "connect_timeout" value during connection phase */
157
172
  drizzleclient_net_set_read_timeout(&net, connect_timeout.get());
160
175
  connection_is_valid= checkConnection();
161
176
 
162
177
  if (connection_is_valid)
163
 
    if (counters->connected > counters->max_connections)
 
178
  {
 
179
    if (not is_admin_connection and (counters->connected > counters->max_connections))
164
180
    {
165
181
      std::string errmsg(ER(ER_CON_COUNT_ERROR));
166
182
      sendError(ER_CON_COUNT_ERROR, errmsg.c_str());
 
183
      counters->failedConnections.increment();
167
184
    }
168
185
    else
 
186
    {
169
187
      sendOK();
 
188
    }
 
189
  }
170
190
  else
171
191
  {
172
192
    sendError(session->main_da.sql_errno(), session->main_da.message());
511
531
        pos[6]= 12;
512
532
        break;
513
533
 
 
534
      case DRIZZLE_TYPE_TIME:
 
535
        pos[6]= 13;
 
536
        break;
 
537
 
514
538
      case DRIZZLE_TYPE_DATE:
515
539
        pos[6]= 14;
516
540
        break;
519
543
        pos[6]= 15;
520
544
        break;
521
545
 
 
546
      case DRIZZLE_TYPE_UUID:
 
547
        pos[6]= 15;
 
548
        break;
 
549
 
 
550
      case DRIZZLE_TYPE_BOOLEAN:
 
551
        pos[6]= 15;
 
552
        break;
 
553
 
522
554
      case DRIZZLE_TYPE_DECIMAL:
523
555
        pos[6]= (char)246;
524
556
        break;
570
602
  char buff[MAX_FIELD_WIDTH];
571
603
  String str(buff,sizeof(buff), &my_charset_bin);
572
604
 
573
 
  from->val_str(&str);
 
605
  from->val_str_internal(&str);
574
606
 
575
607
  return netStoreData((const unsigned char *)str.ptr(), str.length());
576
608
}
641
673
  uint32_t pkt_len= 0;
642
674
  char *end;
643
675
  char scramble[SCRAMBLE_LENGTH];
 
676
  identifier::User::shared_ptr user_identifier= identifier::User::make_shared();
644
677
 
645
678
  makeScramble(scramble);
646
679
 
651
684
 
652
685
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
653
686
    {
654
 
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
687
      my_error(ER_BAD_HOST_ERROR, MYF(0), ip);
655
688
      return false;
656
689
    }
657
690
 
658
 
    session->getSecurityContext().setIp(ip);
 
691
    user_identifier->setAddress(ip);
659
692
  }
660
693
  drizzleclient_net_keepalive(&net, true);
661
694
 
710
743
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
711
744
        || pkt_len < MIN_HANDSHAKE_SIZE)
712
745
    {
713
 
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
746
      my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
714
747
      return false;
715
748
    }
716
749
  }
720
753
  client_capabilities= uint2korr(net.read_pos);
721
754
  if (!(client_capabilities & CLIENT_PROTOCOL_MYSQL41))
722
755
  {
723
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
756
    my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
724
757
    return false;
725
758
  }
726
759
 
736
769
 
737
770
  if (end >= (char*) net.read_pos + pkt_len + 2)
738
771
  {
739
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
772
    my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
740
773
    return false;
741
774
  }
742
775
 
760
793
    passwd_len= (unsigned char)(*passwd++);
761
794
    if (passwd_len > 0)
762
795
    {
763
 
      session->getSecurityContext().setPasswordType(SecurityContext::MYSQL_HASH);
764
 
      session->getSecurityContext().setPasswordContext(scramble, SCRAMBLE_LENGTH);
 
796
      user_identifier->setPasswordType(identifier::User::MYSQL_HASH);
 
797
      user_identifier->setPasswordContext(scramble, SCRAMBLE_LENGTH);
765
798
    }
766
799
  }
767
800
  else
 
801
  {
768
802
    passwd_len= 0;
 
803
  }
769
804
 
770
805
  if (client_capabilities & CLIENT_CONNECT_WITH_DB &&
771
806
      passwd < (char *) net.read_pos + pkt_len)
773
808
    l_db= l_db + passwd_len + 1;
774
809
  }
775
810
  else
 
811
  {
776
812
    l_db= NULL;
 
813
  }
777
814
 
778
815
  /* strlen() can't be easily deleted without changing client */
779
816
  uint32_t db_len= l_db ? strlen(l_db) : 0;
780
817
 
781
818
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
782
819
  {
783
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
 
820
    my_error(ER_HANDSHAKE_ERROR, MYF(0), user_identifier->address().c_str());
784
821
    return false;
785
822
  }
786
823
 
792
829
    user_len-= 2;
793
830
  }
794
831
 
795
 
  session->getSecurityContext().setUser(user);
 
832
  if (client_capabilities & CLIENT_ADMIN)
 
833
  {
 
834
    if ((strncmp(user, "root", 4) == 0) and isAdminAllowed())
 
835
    {
 
836
      is_admin_connection= true;
 
837
    }
 
838
    else
 
839
    {
 
840
      my_error(ER_ADMIN_ACCESS, MYF(0));
 
841
      return false;
 
842
    }
 
843
  }
 
844
 
 
845
  user_identifier->setUser(user);
 
846
  session->setUser(user_identifier);
796
847
 
797
848
  return session->checkUser(string(passwd, passwd_len),
798
849
                            string(l_db ? l_db : ""));
799
850
 
800
851
}
801
852
 
 
853
bool ClientMySQLProtocol::isAdminAllowed(void)
 
854
{
 
855
  if (std::find(mysql_admin_ip_addresses.begin(), mysql_admin_ip_addresses.end(), session->user()->address()) != mysql_admin_ip_addresses.end())
 
856
    return true;
 
857
 
 
858
  return false;
 
859
}
 
860
 
802
861
bool ClientMySQLProtocol::netStoreData(const unsigned char *from, size_t length)
803
862
{
804
863
  size_t packet_length= packet.length();
901
960
  }
902
961
}
903
962
 
 
963
void ClientMySQLProtocol::mysql_compose_ip_addresses(vector<string> options)
 
964
{
 
965
  for (vector<string>::iterator it= options.begin();
 
966
       it != options.end();
 
967
       ++it)
 
968
  {
 
969
    tokenize(*it, mysql_admin_ip_addresses, ",", true);
 
970
  }
 
971
}
 
972
 
904
973
static ListenMySQLProtocol *listen_obj= NULL;
905
974
plugin::Create_function<MySQLPassword> *mysql_password= NULL;
906
975
 
961
1030
  context("max-connections",
962
1031
          po::value<uint32_t>(&ListenMySQLProtocol::mysql_counters->max_connections)->default_value(1000),
963
1032
          N_("Maximum simultaneous connections."));
 
1033
  context("admin-ip-addresses",
 
1034
          po::value<vector<string> >()->composing()->notifier(&ClientMySQLProtocol::mysql_compose_ip_addresses),
 
1035
          N_("A restrictive IP address list for incoming admin connections."));
964
1036
}
965
1037
 
966
1038
static int mysql_protocol_connection_count_func(drizzle_show_var *var, char *buff)