ruby-mysql 2.9.13 → 2.11.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 202d13ae653ae79671fbe568f53f258bebcb453c
4
- data.tar.gz: dc69e58cf536f1e10195296f247e81efd9503887
2
+ SHA256:
3
+ metadata.gz: 178673e0e53a16263b882308afca1831d674e96057828c2115d34ec3669dc58e
4
+ data.tar.gz: 23e9fc852a81f976f1d8130fbcd0c623dc234c8e741e60c0fd58094079fb02bd
5
5
  SHA512:
6
- metadata.gz: 390ae9a82ceca9c89c30c4837cc2fa06c00c8e2570bbd4bce5896f83dfb5c8cf5a082434f13b0729daf6c5513bf220be1c59342d1c548525e860c0321b1fb573
7
- data.tar.gz: 8986d9a99784a45f52d122426be397f7d9c956dce6f54303ba75311fa68d924e253abd9720379ae912d0ff52053e60ac915f6c35f08bde156f26296a51bec7fa
6
+ metadata.gz: dc51341a75ae3373d2b375632781809abc68ac30fbee593761b67a304ef33b3d52538762dfd144f5ddad0b63416b68c0f9ce1f68ab89228f0f5b0e4f82a2332f
7
+ data.tar.gz: 8ee78f4d06f1714b2c0cb83537b3efe643e968a212c64c71cd3e19dda422a4f9961a16578dab45d1c43f147a2551d7499447645576a6545698e00419c5cae7c9
data/README.rdoc CHANGED
@@ -33,15 +33,16 @@ MySQL connector for Ruby.
33
33
 
34
34
  == Incompatible with MySQL/Ruby 2.8.x
35
35
 
36
- * Ruby 1.8.x ではシフトJISのような安全でないマルチバイト文字セットに対して Mysql#escape_string を使用すると例外が発生します。
37
-
38
36
  * いくつかのメソッドがありません: Mysql#debug, Mysql#change_user,
39
37
  Mysql#create_db, Mysql#drop_db, Mysql#dump_debug_info,
40
38
  Mysql#ssl_set, Mysql#reconnect
41
39
 
42
40
  * Mysql#options でサポートしているオプションは次のものだけです:
43
41
  Mysql::INIT_COMMAND, Mysql::OPT_CONNECT_TIMEOUT,
42
+ Mysql::OPT_GET_SERVER_PUBLIC_KEY,
43
+ Mysql::OPT_LOAD_DATA_LOCAL_DIR,
44
44
  Mysql::OPT_LOCAL_INFILE, Mysql::OPT_READ_TIMEOUT,
45
+ Mysql::OPT_SSL_MODE,
45
46
  Mysql::OPT_WRITE_TIMEOUT, Mysql::SET_CHARSET_NAME.
46
47
  これら以外を指定すると "option not implementted" という warning が標準エラー出力に出力されます。
47
48
 
@@ -64,5 +65,5 @@ MySQL connector for Ruby.
64
65
  == Copyright
65
66
 
66
67
  Author :: TOMITA Masahiro <tommy@tmtm.org>
67
- Copyright :: Copyright (c) 2009-2012 TOMITA Masahiro
68
+ Copyright :: Copyright (c) 2008 TOMITA Masahiro
68
69
  License :: Ruby's
@@ -0,0 +1,62 @@
1
+ require 'digest/sha2'
2
+
3
+ class Mysql
4
+ class Authenticator
5
+ class CachingSha2Password
6
+ # @param protocol [Mysql::Protocol]
7
+ def initialize(protocol)
8
+ @protocol = protocol
9
+ end
10
+
11
+ # @return [String]
12
+ def name
13
+ 'caching_sha2_password'
14
+ end
15
+
16
+ # @param passwd [String]
17
+ # @param scramble [String]
18
+ # @yield [String] hashed password
19
+ # @return [Mysql::Packet]
20
+ def authenticate(passwd, scramble)
21
+ yield hash_password(passwd, scramble)
22
+ pkt = @protocol.read
23
+ data = pkt.to_s
24
+ if data.size == 2 && data[0] == "\x01"
25
+ case data[1]
26
+ when "\x03" # fast_auth_success
27
+ # OK
28
+ when "\x04" # perform_full_authentication
29
+ if @protocol.client_flags & CLIENT_SSL != 0
30
+ @protocol.write passwd+"\0"
31
+ elsif !@protocol.get_server_public_key
32
+ raise 'Authentication requires secure connection'
33
+ else
34
+ @protocol.write "\2" # request public key
35
+ pkt = @protocol.read
36
+ pkt.utiny # skip
37
+ pubkey = pkt.to_s
38
+ hash = (passwd+"\0").unpack("C*").zip(scramble.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
39
+ enc = OpenSSL::PKey::RSA.new(pubkey).public_encrypt(hash, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
40
+ @protocol.write enc
41
+ end
42
+ else
43
+ raise "invalid auth reply packet: #{data.inspect}"
44
+ end
45
+ pkt = @protocol.read
46
+ end
47
+ return pkt
48
+ end
49
+
50
+ # @param passwd [String]
51
+ # @param scramble [String]
52
+ # @return [String] hashed password
53
+ def hash_password(passwd, scramble)
54
+ return '' if passwd.nil? or passwd.empty?
55
+ hash1 = Digest::SHA256.digest(passwd)
56
+ hash2 = Digest::SHA256.digest(hash1)
57
+ hash3 = Digest::SHA256.digest(hash2 + scramble)
58
+ hash1.unpack("C*").zip(hash3.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,37 @@
1
+ require 'digest/sha1'
2
+
3
+ class Mysql
4
+ class Authenticator
5
+ class MysqlNativePassword
6
+ # @param protocol [Mysql::Protocol]
7
+ def initialize(protocol)
8
+ @protocol = protocol
9
+ end
10
+
11
+ # @return [String]
12
+ def name
13
+ 'mysql_native_password'
14
+ end
15
+
16
+ # @param passwd [String]
17
+ # @param scramble [String]
18
+ # @yield [String] hashed password
19
+ # @return [Mysql::Packet]
20
+ def authenticate(passwd, scramble)
21
+ yield hash_password(passwd, scramble)
22
+ @protocol.read
23
+ end
24
+
25
+ # @param passwd [String]
26
+ # @param scramble [String]
27
+ # @return [String] hashed password
28
+ def hash_password(passwd, scramble)
29
+ return '' if passwd.nil? or passwd.empty?
30
+ hash1 = Digest::SHA1.digest(passwd)
31
+ hash2 = Digest::SHA1.digest(hash1)
32
+ hash3 = Digest::SHA1.digest(scramble + hash2)
33
+ hash1.unpack("C*").zip(hash3.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ require 'openssl'
2
+
3
+ class Mysql
4
+ class Authenticator
5
+ class Sha256Password
6
+ # @param protocol [Mysql::Protocol]
7
+ def initialize(protocol)
8
+ @protocol = protocol
9
+ end
10
+
11
+ # @return [String]
12
+ def name
13
+ 'sha256_password'
14
+ end
15
+
16
+ # @param passwd [String]
17
+ # @param scramble [String]
18
+ # @yield [String] hashed password
19
+ # @return [Mysql::Packet]
20
+ def authenticate(passwd, scramble)
21
+ if @protocol.client_flags & CLIENT_SSL != 0
22
+ yield passwd+"\0"
23
+ return @protocol.read
24
+ end
25
+ yield "\x01" # request public key
26
+ pkt = @protocol.read
27
+ data = pkt.to_s
28
+ if data[0] == "\x01"
29
+ pkt.utiny # skip
30
+ pubkey = pkt.to_s
31
+ hash = (passwd+"\0").unpack("C*").zip(scramble.unpack("C*")).map{|a, b| a ^ b}.pack("C*")
32
+ enc = OpenSSL::PKey::RSA.new(pubkey).public_encrypt(hash, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
33
+ @protocol.write enc
34
+ pkt = @protocol.read
35
+ end
36
+ return pkt
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,84 @@
1
+ class Mysql
2
+ class Authenticator
3
+ @plugins = {}
4
+
5
+ # @param plugin [String]
6
+ def self.plugin_class(plugin)
7
+ return @plugins[plugin] if @plugins[plugin]
8
+
9
+ raise ClientError, "invalid plugin name: #{plugin}" unless plugin.match?(/\A\w+\z/)
10
+ begin
11
+ require_relative "authenticator/#{plugin}"
12
+ rescue LoadError
13
+ return nil
14
+ end
15
+ class_name = plugin.gsub(/(?:^|_)(.)/){$1.upcase}
16
+ raise ClientError, "#{class_name} is undefined" unless self.const_defined? class_name
17
+ klass = self.const_get(class_name)
18
+ @plugins[plugin] = klass
19
+ return klass
20
+ end
21
+
22
+ def initialize(protocol)
23
+ @protocol = protocol
24
+ end
25
+
26
+ # @param plugin [String]
27
+ def get(plugin)
28
+ self.class.plugin_class(plugin)
29
+ end
30
+
31
+ # @param plugin [String]
32
+ def get!(plugin)
33
+ get(plugin) or raise ClientError, "unknown plugin: #{plugin}"
34
+ end
35
+
36
+ def authenticate(user, passwd, db, scramble, plugin_name)
37
+ plugin = (get(plugin_name) || DummyPlugin).new(@protocol)
38
+ pkt = plugin.authenticate(passwd, scramble) do |hashed|
39
+ @protocol.write Protocol::AuthenticationPacket.serialize(@protocol.client_flags, 1024**3, @protocol.charset.number, user, hashed, db, plugin.name)
40
+ end
41
+ while true
42
+ res = Protocol::AuthenticationResultPacket.parse(pkt)
43
+ case res.result
44
+ when 0 # OK
45
+ break
46
+ when 2 # multi factor auth
47
+ raise ClientError, 'multi factor authentication is not supported'
48
+ when 254 # change auth plugin
49
+ plugin = get!(res.auth_plugin).new(@protocol)
50
+ pkt = plugin.authenticate(passwd, res.scramble) do |hashed|
51
+ if passwd.nil? || passwd.empty?
52
+ @protocol.write "\0"
53
+ else
54
+ @protocol.write hashed
55
+ end
56
+ end
57
+ else
58
+ raise ClientError, "invalid packet: #{pkt.to_s}"
59
+ end
60
+ end
61
+ end
62
+
63
+ class DummyPlugin
64
+ # @param protocol [Mysql::Protocol]
65
+ def initialize(protocol)
66
+ @protocol = protocol
67
+ end
68
+
69
+ # @return [String]
70
+ def name
71
+ ''
72
+ end
73
+
74
+ # @param passwd [String]
75
+ # @param scramble [String]
76
+ # @yield [String] hashed password
77
+ # @return [Mysql::Packet]
78
+ def authenticate(passwd, scramble)
79
+ yield ''
80
+ @protocol.read
81
+ end
82
+ end
83
+ end
84
+ end