mongo 2.7.2 → 2.8.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -3
- data/lib/mongo/address.rb +17 -20
- data/lib/mongo/address/ipv4.rb +6 -3
- data/lib/mongo/address/ipv6.rb +6 -3
- data/lib/mongo/address/unix.rb +5 -2
- data/lib/mongo/auth.rb +15 -2
- data/lib/mongo/auth/cr/conversation.rb +4 -2
- data/lib/mongo/auth/ldap/conversation.rb +4 -2
- data/lib/mongo/auth/scram.rb +3 -7
- data/lib/mongo/auth/scram/conversation.rb +28 -19
- data/lib/mongo/auth/user.rb +45 -10
- data/lib/mongo/auth/x509/conversation.rb +4 -2
- data/lib/mongo/cluster.rb +9 -17
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/error/missing_password.rb +29 -0
- data/lib/mongo/error/operation_failure.rb +7 -3
- data/lib/mongo/error/parser.rb +2 -1
- data/lib/mongo/error/sdam_error_detection.rb +54 -0
- data/lib/mongo/operation/aggregate/command.rb +1 -16
- data/lib/mongo/operation/aggregate/op_msg.rb +1 -1
- data/lib/mongo/operation/collections_info.rb +2 -3
- data/lib/mongo/operation/delete/command.rb +2 -15
- data/lib/mongo/operation/delete/legacy.rb +1 -16
- data/lib/mongo/operation/explain/command.rb +1 -16
- data/lib/mongo/operation/explain/legacy.rb +1 -16
- data/lib/mongo/operation/find/command.rb +1 -16
- data/lib/mongo/operation/find/legacy.rb +1 -16
- data/lib/mongo/operation/get_more/command.rb +1 -16
- data/lib/mongo/operation/indexes/command.rb +1 -16
- data/lib/mongo/operation/indexes/legacy.rb +4 -16
- data/lib/mongo/operation/list_collections/command.rb +1 -16
- data/lib/mongo/operation/map_reduce/command.rb +1 -16
- data/lib/mongo/operation/parallel_scan/command.rb +1 -16
- data/lib/mongo/operation/result.rb +3 -0
- data/lib/mongo/operation/shared/executable.rb +4 -0
- data/lib/mongo/operation/shared/polymorphic_lookup.rb +1 -1
- data/lib/mongo/operation/shared/polymorphic_result.rb +8 -1
- data/lib/mongo/operation/shared/result/aggregatable.rb +0 -5
- data/lib/mongo/operation/update/command.rb +2 -15
- data/lib/mongo/operation/update/legacy.rb +1 -16
- data/lib/mongo/operation/users_info/command.rb +1 -16
- data/lib/mongo/retryable.rb +22 -10
- data/lib/mongo/server.rb +10 -1
- data/lib/mongo/server/app_metadata.rb +7 -2
- data/lib/mongo/server/connectable.rb +0 -6
- data/lib/mongo/server/connection.rb +86 -135
- data/lib/mongo/server/connection_base.rb +133 -0
- data/lib/mongo/server/connection_pool.rb +11 -24
- data/lib/mongo/server/connection_pool/queue.rb +41 -41
- data/lib/mongo/server/description.rb +1 -1
- data/lib/mongo/server/monitor.rb +4 -4
- data/lib/mongo/server/monitor/connection.rb +26 -7
- data/lib/mongo/server/pending_connection.rb +36 -0
- data/lib/mongo/server_selector/selectable.rb +9 -1
- data/lib/mongo/session.rb +0 -1
- data/lib/mongo/socket.rb +23 -6
- data/lib/mongo/socket/ssl.rb +11 -18
- data/lib/mongo/socket/tcp.rb +13 -14
- data/lib/mongo/socket/unix.rb +9 -27
- data/lib/mongo/uri.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/spec/integration/auth_spec.rb +160 -0
- data/spec/integration/retryable_writes_spec.rb +55 -58
- data/spec/integration/sdam_error_handling_spec.rb +115 -0
- data/spec/mongo/address/ipv4_spec.rb +4 -0
- data/spec/mongo/address/ipv6_spec.rb +4 -0
- data/spec/mongo/auth/scram/conversation_spec.rb +6 -5
- data/spec/mongo/auth/scram/negotiation_spec.rb +25 -36
- data/spec/mongo/auth/scram_spec.rb +2 -2
- data/spec/mongo/auth/user_spec.rb +97 -0
- data/spec/mongo/client_construction_spec.rb +1 -1
- data/spec/mongo/error/operation_failure_spec.rb +125 -1
- data/spec/mongo/retryable_spec.rb +17 -8
- data/spec/mongo/server/connection_pool/queue_spec.rb +24 -10
- data/spec/mongo/server/connection_pool_spec.rb +30 -117
- data/spec/mongo/server/connection_spec.rb +147 -25
- data/spec/mongo/server/description_spec.rb +0 -14
- data/spec/mongo/server/monitor/connection_spec.rb +22 -0
- data/spec/mongo/server_selector_spec.rb +1 -0
- data/spec/mongo/server_spec.rb +6 -6
- data/spec/mongo/socket/ssl_spec.rb +48 -116
- data/spec/mongo/socket/tcp_spec.rb +22 -0
- data/spec/mongo/socket/unix_spec.rb +9 -9
- data/spec/mongo/socket_spec.rb +15 -3
- data/spec/spec_tests/server_selection_spec.rb +2 -0
- data/spec/support/client_registry.rb +8 -2
- data/spec/support/common_shortcuts.rb +20 -1
- data/spec/support/constraints.rb +10 -2
- data/spec/support/lite_constraints.rb +8 -0
- data/spec/support/spec_config.rb +9 -1
- metadata +14 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c0c1dd6dd1ce8ec0ce98e4f038bb188a743d65b0fd45f42383e732b8a9fe6e0
|
4
|
+
data.tar.gz: 69a9fcd5c2284e95b7af207ae381bc5fb4b9a0d00d941b54bb7d86a126a62e70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb0c350dc452f0eb60656e0a2e6657e0002a7760de5bb3af7820af77876046f48bd7946e8d7d39a727dd80eda43e48656db52b941c2ab45ea6096ba826049a4d
|
7
|
+
data.tar.gz: d13ac4eec40c58e932f61fe5cb3f52259ca77a8ed08f079edf910927b9bb5e0c0ec77e0461374ab6c0f783726b1a5c7972e12c63c8a6d2eb46a6170a80543538
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1,3 +1 @@
|
|
1
|
-
|
2
|
-
(�GIB�U"oS��8����x|�F}WG�H�-*Ĝr`��f�%�R�M{Go_c'g��˛�'u��?����5LxI�@�x�R<���TԤ���*h�>��.�Fd�*��{������$u~����E�mmE�@pE
|
3
|
-
kRd���)C�&�q��CM*��K���?mܴن�1#K$f렸E��u�}6N�
|
1
|
+
��zW�Y���MH{�zG.�vr�fτ#V���?�Y���b�;�86�o\z�E^����V�b��K=��:����G���壘s��yҌ�uA[݁XSG�Z9>�|�<DZ�Ԍ~2�&�v2�Ȭf/p�n�������-�WLfU�rl,�s_��h'nn����q�;7��vD#�0y}�j"r����H�Rj�N�8=4����YQ�@d#�ԉޮf��.�:��r�b�ӯ�Eʎ��ӗ,��j�_��
|
data/lib/mongo/address.rb
CHANGED
@@ -147,12 +147,15 @@ module Mongo
|
|
147
147
|
#
|
148
148
|
# @param [ Float ] socket_timeout The socket timeout.
|
149
149
|
# @param [ Hash ] ssl_options SSL options.
|
150
|
+
# @param [ Hash ] options The options.
|
151
|
+
#
|
152
|
+
# @option options [ Float ] :connect_timeout Connect timeout.
|
150
153
|
#
|
151
154
|
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP, Mongo::Socket::Unix ] The socket.
|
152
155
|
#
|
153
156
|
# @since 2.0.0
|
154
|
-
def socket(socket_timeout, ssl_options = {})
|
155
|
-
create_resolver(ssl_options).socket(socket_timeout, ssl_options)
|
157
|
+
def socket(socket_timeout, ssl_options = {}, options = {})
|
158
|
+
create_resolver(ssl_options).socket(socket_timeout, ssl_options, options)
|
156
159
|
end
|
157
160
|
|
158
161
|
# Get the address as a string.
|
@@ -175,25 +178,17 @@ module Mongo
|
|
175
178
|
end
|
176
179
|
end
|
177
180
|
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# @example Connect a socket.
|
181
|
-
# address.connect_socket!(socket)
|
182
|
-
#
|
183
|
-
# @since 2.4.3
|
184
|
-
def connect_socket!(socket)
|
185
|
-
socket.connect!(connect_timeout)
|
186
|
-
end
|
187
|
-
|
188
|
-
private
|
189
|
-
|
181
|
+
# @api private
|
190
182
|
def connect_timeout
|
191
183
|
@connect_timeout ||= @options[:connect_timeout] || Server::CONNECT_TIMEOUT
|
192
184
|
end
|
193
185
|
|
194
|
-
|
195
|
-
|
196
|
-
#
|
186
|
+
private
|
187
|
+
|
188
|
+
# To determine which address the socket will connect to, the driver will
|
189
|
+
# attempt to connect to each IP address returned by Socket::getaddrinfo in
|
190
|
+
# sequence. Once a successful connection is made, a resolver with that
|
191
|
+
# IP address specified is returned. If no successful connection is
|
197
192
|
# made, the error made by the last connection attempt is raised.
|
198
193
|
def create_resolver(ssl_options)
|
199
194
|
return Unix.new(seed.downcase) if seed.downcase =~ Unix::MATCH
|
@@ -202,9 +197,11 @@ module Mongo
|
|
202
197
|
error = nil
|
203
198
|
::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM).each do |info|
|
204
199
|
begin
|
205
|
-
|
206
|
-
|
207
|
-
|
200
|
+
specific_address = FAMILY_MAP[info[4]].new(info[3], port, host)
|
201
|
+
socket = specific_address.socket(
|
202
|
+
connect_timeout, ssl_options, connect_timeout: connect_timeout)
|
203
|
+
socket.close
|
204
|
+
return specific_address
|
208
205
|
rescue IOError, SystemCallError, Error::SocketTimeoutError, Error::SocketError => e
|
209
206
|
error = e
|
210
207
|
end
|
data/lib/mongo/address/ipv4.rb
CHANGED
@@ -79,15 +79,18 @@ module Mongo
|
|
79
79
|
#
|
80
80
|
# @param [ Float ] socket_timeout The socket timeout.
|
81
81
|
# @param [ Hash ] ssl_options SSL options.
|
82
|
+
# @param [ Hash ] options The options.
|
83
|
+
#
|
84
|
+
# @option options [ Float ] :connect_timeout Connect timeout.
|
82
85
|
#
|
83
86
|
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
|
84
87
|
#
|
85
88
|
# @since 2.0.0
|
86
|
-
def socket(socket_timeout, ssl_options = {})
|
89
|
+
def socket(socket_timeout, ssl_options = {}, options = {})
|
87
90
|
unless ssl_options.empty?
|
88
|
-
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET, ssl_options)
|
91
|
+
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET, ssl_options.merge(options))
|
89
92
|
else
|
90
|
-
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET)
|
93
|
+
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET, options)
|
91
94
|
end
|
92
95
|
end
|
93
96
|
end
|
data/lib/mongo/address/ipv6.rb
CHANGED
@@ -95,15 +95,18 @@ module Mongo
|
|
95
95
|
#
|
96
96
|
# @param [ Float ] socket_timeout The socket timeout.
|
97
97
|
# @param [ Hash ] ssl_options SSL options.
|
98
|
+
# @param [ Hash ] options The options.
|
99
|
+
#
|
100
|
+
# @option options [ Float ] :connect_timeout Connect timeout.
|
98
101
|
#
|
99
102
|
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
|
100
103
|
#
|
101
104
|
# @since 2.0.0
|
102
|
-
def socket(socket_timeout, ssl_options = {})
|
105
|
+
def socket(socket_timeout, ssl_options = {}, options = {})
|
103
106
|
unless ssl_options.empty?
|
104
|
-
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET6, ssl_options)
|
107
|
+
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET6, ssl_options.merge(options))
|
105
108
|
else
|
106
|
-
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET6)
|
109
|
+
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET6, options)
|
107
110
|
end
|
108
111
|
end
|
109
112
|
end
|
data/lib/mongo/address/unix.rb
CHANGED
@@ -64,12 +64,15 @@ module Mongo
|
|
64
64
|
#
|
65
65
|
# @param [ Float ] socket_timeout The socket timeout.
|
66
66
|
# @param [ Hash ] ssl_options SSL options - ignored.
|
67
|
+
# @param [ Hash ] options The options.
|
68
|
+
#
|
69
|
+
# @option options [ Float ] :connect_timeout Connect timeout.
|
67
70
|
#
|
68
71
|
# @return [ Mongo::Socket::Unix ] The socket.
|
69
72
|
#
|
70
73
|
# @since 2.0.0
|
71
|
-
def socket(socket_timeout, ssl_options = {})
|
72
|
-
Socket::Unix.new(host, socket_timeout)
|
74
|
+
def socket(socket_timeout, ssl_options = {}, options = {})
|
75
|
+
Socket::Unix.new(host, socket_timeout, options)
|
73
76
|
end
|
74
77
|
end
|
75
78
|
end
|
data/lib/mongo/auth.rb
CHANGED
@@ -102,10 +102,23 @@ module Mongo
|
|
102
102
|
# Mongo::Auth::Unauthorized.new(user)
|
103
103
|
#
|
104
104
|
# @param [ Mongo::Auth::User ] user The unauthorized user.
|
105
|
+
# @param [ String ] used_mechanism Auth mechanism actually used for
|
106
|
+
# authentication. This is a full string like SCRAM-SHA-256.
|
105
107
|
#
|
106
108
|
# @since 2.0.0
|
107
|
-
def initialize(user)
|
108
|
-
|
109
|
+
def initialize(user, used_mechanism = nil)
|
110
|
+
specified_mechanism = if user.mechanism
|
111
|
+
" (mechanism: #{user.mechanism})"
|
112
|
+
else
|
113
|
+
''
|
114
|
+
end
|
115
|
+
used_mechanism = if used_mechanism
|
116
|
+
" (used mechanism: #{used_mechanism})"
|
117
|
+
else
|
118
|
+
''
|
119
|
+
end
|
120
|
+
msg = "User #{user.name}#{specified_mechanism} is not authorized to access #{user.database}#{used_mechanism}"
|
121
|
+
super(msg)
|
109
122
|
end
|
110
123
|
end
|
111
124
|
end
|
@@ -92,7 +92,7 @@ module Mongo
|
|
92
92
|
end
|
93
93
|
|
94
94
|
# Start the CR conversation. This returns the first message that
|
95
|
-
# needs to be
|
95
|
+
# needs to be sent to the server.
|
96
96
|
#
|
97
97
|
# @example Start the conversation.
|
98
98
|
# conversation.start
|
@@ -130,7 +130,9 @@ module Mongo
|
|
130
130
|
private
|
131
131
|
|
132
132
|
def validate!(reply)
|
133
|
-
|
133
|
+
if reply.documents[0][Operation::Result::OK] != 1
|
134
|
+
raise Unauthorized.new(user, MECHANISM)
|
135
|
+
end
|
134
136
|
@nonce = reply.documents[0][Auth::NONCE]
|
135
137
|
@reply = reply
|
136
138
|
end
|
@@ -51,7 +51,7 @@ module Mongo
|
|
51
51
|
end
|
52
52
|
|
53
53
|
# Start the PLAIN conversation. This returns the first message that
|
54
|
-
# needs to be
|
54
|
+
# needs to be sent to the server.
|
55
55
|
#
|
56
56
|
# @example Start the conversation.
|
57
57
|
# conversation.start
|
@@ -97,7 +97,9 @@ module Mongo
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def validate!(reply)
|
100
|
-
|
100
|
+
if reply.documents[0][Operation::Result::OK] != 1
|
101
|
+
raise Unauthorized.new(user, MECHANISM)
|
102
|
+
end
|
101
103
|
@reply = reply
|
102
104
|
end
|
103
105
|
end
|
data/lib/mongo/auth/scram.rb
CHANGED
@@ -32,7 +32,6 @@ module Mongo
|
|
32
32
|
# @since 2.6.0
|
33
33
|
SCRAM_SHA_256_MECHANISM = 'SCRAM-SHA-256'.freeze
|
34
34
|
|
35
|
-
|
36
35
|
# Map the user-specified authentication mechanism to the proper names of the mechanisms.
|
37
36
|
#
|
38
37
|
# @since 2.6.0
|
@@ -62,16 +61,13 @@ module Mongo
|
|
62
61
|
# user.login(connection)
|
63
62
|
#
|
64
63
|
# @param [ Mongo::Connection ] connection The connection to log into.
|
65
|
-
# on.
|
66
|
-
# @param [ String ] mechanism The auth mechanism to use (either 'SCRAM-SHA-1' or
|
67
|
-
# 'SCRAM-SHA-256');
|
68
64
|
#
|
69
65
|
# @return [ Protocol::Message ] The authentication response.
|
70
66
|
#
|
71
67
|
# @since 2.0.0
|
72
|
-
def login(connection
|
73
|
-
mechanism
|
74
|
-
conversation = Conversation.new(user,
|
68
|
+
def login(connection)
|
69
|
+
mechanism = user.mechanism || :scram
|
70
|
+
conversation = Conversation.new(user, mechanism)
|
75
71
|
reply = connection.dispatch([ conversation.start(connection) ])
|
76
72
|
connection.update_cluster_time(Operation::Result.new(reply))
|
77
73
|
reply = connection.dispatch([ conversation.continue(reply, connection) ])
|
@@ -19,8 +19,8 @@ module Mongo
|
|
19
19
|
module Auth
|
20
20
|
class SCRAM
|
21
21
|
|
22
|
-
# Defines behavior around a single SCRAM-SHA-1 conversation between
|
23
|
-
# client and server.
|
22
|
+
# Defines behavior around a single SCRAM-SHA-1/256 conversation between
|
23
|
+
# the client and server.
|
24
24
|
#
|
25
25
|
# @since 2.0.0
|
26
26
|
class Conversation
|
@@ -168,7 +168,7 @@ module Mongo
|
|
168
168
|
end
|
169
169
|
|
170
170
|
# Start the SCRAM conversation. This returns the first message that
|
171
|
-
# needs to be
|
171
|
+
# needs to be sent to the server.
|
172
172
|
#
|
173
173
|
# @example Start the conversation.
|
174
174
|
# conversation.start
|
@@ -180,7 +180,8 @@ module Mongo
|
|
180
180
|
# @since 2.0.0
|
181
181
|
def start(connection = nil)
|
182
182
|
if connection && connection.features.op_msg_enabled?
|
183
|
-
selector = CLIENT_FIRST_MESSAGE.merge(
|
183
|
+
selector = CLIENT_FIRST_MESSAGE.merge(
|
184
|
+
payload: client_first_message, mechanism: full_mechanism)
|
184
185
|
selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
|
185
186
|
cluster_time = connection.mongos? && connection.cluster_time
|
186
187
|
selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
|
@@ -189,12 +190,17 @@ module Mongo
|
|
189
190
|
Protocol::Query.new(
|
190
191
|
user.auth_source,
|
191
192
|
Database::COMMAND,
|
192
|
-
CLIENT_FIRST_MESSAGE.merge(
|
193
|
+
CLIENT_FIRST_MESSAGE.merge(
|
194
|
+
payload: client_first_message, mechanism: full_mechanism),
|
193
195
|
limit: -1
|
194
196
|
)
|
195
197
|
end
|
196
198
|
end
|
197
199
|
|
200
|
+
def full_mechanism
|
201
|
+
MECHANISMS[@mechanism]
|
202
|
+
end
|
203
|
+
|
198
204
|
# Get the id of the conversation.
|
199
205
|
#
|
200
206
|
# @example Get the id of the conversation.
|
@@ -213,9 +219,14 @@ module Mongo
|
|
213
219
|
# Conversation.new(user, mechanism)
|
214
220
|
#
|
215
221
|
# @param [ Auth::User ] user The user to converse about.
|
222
|
+
# @param [ Symbol ] mechanism Authentication mechanism.
|
216
223
|
#
|
217
224
|
# @since 2.0.0
|
218
225
|
def initialize(user, mechanism)
|
226
|
+
unless [:scram, :scram256].include?(mechanism)
|
227
|
+
raise InvalidMechanism.new(mechanism)
|
228
|
+
end
|
229
|
+
|
219
230
|
@user = user
|
220
231
|
@nonce = SecureRandom.base64
|
221
232
|
@client_key = user.send(:client_key)
|
@@ -343,7 +354,7 @@ module Mongo
|
|
343
354
|
# @since 2.0.0
|
344
355
|
def hi(data)
|
345
356
|
case @mechanism
|
346
|
-
when
|
357
|
+
when :scram256
|
347
358
|
OpenSSL::PKCS5.pbkdf2_hmac(
|
348
359
|
data,
|
349
360
|
Base64.strict_decode64(salt),
|
@@ -381,7 +392,7 @@ module Mongo
|
|
381
392
|
@iterations ||= payload_data.match(ITERATIONS)[1].to_i.tap do |i|
|
382
393
|
if i < MIN_ITER_COUNT
|
383
394
|
raise Error::InsufficientIterationCount.new(
|
384
|
-
Error::InsufficientIterationCount.message(MIN_ITER_COUNT,
|
395
|
+
Error::InsufficientIterationCount.message(MIN_ITER_COUNT, i))
|
385
396
|
end
|
386
397
|
end
|
387
398
|
end
|
@@ -421,7 +432,12 @@ module Mongo
|
|
421
432
|
#
|
422
433
|
# @since 2.0.0
|
423
434
|
def salted_password
|
424
|
-
@salted_password ||=
|
435
|
+
@salted_password ||= case @mechanism
|
436
|
+
when :scram256
|
437
|
+
hi(user.sasl_prepped_password)
|
438
|
+
else
|
439
|
+
hi(user.hashed_password)
|
440
|
+
end
|
425
441
|
end
|
426
442
|
|
427
443
|
# Server key algorithm implementation.
|
@@ -505,24 +521,17 @@ module Mongo
|
|
505
521
|
end
|
506
522
|
|
507
523
|
def validate!(reply)
|
508
|
-
|
524
|
+
if reply.documents[0][Operation::Result::OK] != 1
|
525
|
+
raise Unauthorized.new(user, full_mechanism)
|
526
|
+
end
|
509
527
|
@reply = reply
|
510
528
|
end
|
511
529
|
|
512
530
|
private
|
513
531
|
|
514
|
-
def hashed_password
|
515
|
-
case @mechanism
|
516
|
-
when SCRAM::SCRAM_SHA_256_MECHANISM
|
517
|
-
user.sasl_prepped_hashed_password
|
518
|
-
else
|
519
|
-
user.hashed_password
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
532
|
def digest
|
524
533
|
@digest ||= case @mechanism
|
525
|
-
when
|
534
|
+
when :scram256
|
526
535
|
OpenSSL::Digest::SHA256.new.freeze
|
527
536
|
else
|
528
537
|
OpenSSL::Digest::SHA1.new.freeze
|
data/lib/mongo/auth/user.rb
CHANGED
@@ -21,6 +21,7 @@ module Mongo
|
|
21
21
|
#
|
22
22
|
# @since 2.0.0
|
23
23
|
class User
|
24
|
+
include Loggable
|
24
25
|
|
25
26
|
# @return [ String ] The authorization source, either a database or
|
26
27
|
# external name.
|
@@ -44,6 +45,14 @@ module Mongo
|
|
44
45
|
# @return [ Array<String> ] roles The user roles.
|
45
46
|
attr_reader :roles
|
46
47
|
|
48
|
+
# Loggable requires an options attribute. We don't have any options
|
49
|
+
# hence provide this as a stub.
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
def options
|
53
|
+
{}
|
54
|
+
end
|
55
|
+
|
47
56
|
# Determine if this user is equal to another.
|
48
57
|
#
|
49
58
|
# @example Check user equality.
|
@@ -99,7 +108,7 @@ module Mongo
|
|
99
108
|
[ name, database, password ].hash
|
100
109
|
end
|
101
110
|
|
102
|
-
# Get the user's hashed password.
|
111
|
+
# Get the user's hashed password for SCRAM-SHA-1.
|
103
112
|
#
|
104
113
|
# @example Get the user's hashed password.
|
105
114
|
# user.hashed_password
|
@@ -108,11 +117,25 @@ module Mongo
|
|
108
117
|
#
|
109
118
|
# @since 2.0.0
|
110
119
|
def hashed_password
|
120
|
+
unless password
|
121
|
+
raise Error::MissingPassword
|
122
|
+
end
|
123
|
+
|
111
124
|
@hashed_password ||= Digest::MD5.hexdigest("#{name}:mongo:#{password}").encode(BSON::UTF8)
|
112
125
|
end
|
113
126
|
|
114
|
-
|
115
|
-
|
127
|
+
# Get the user's stringprepped password for SCRAM-SHA-256.
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
def sasl_prepped_password
|
131
|
+
unless password
|
132
|
+
raise Error::MissingPassword
|
133
|
+
end
|
134
|
+
|
135
|
+
@sasl_prepped_password ||= StringPrep.prepare(password,
|
136
|
+
StringPrep::Profiles::SASL::MAPPINGS,
|
137
|
+
StringPrep::Profiles::SASL::PROHIBITED,
|
138
|
+
normalize: true, bidi: true).encode(BSON::UTF8)
|
116
139
|
end
|
117
140
|
|
118
141
|
# Create the new user.
|
@@ -140,6 +163,25 @@ module Mongo
|
|
140
163
|
@name = options[:user]
|
141
164
|
@password = options[:password] || options[:pwd]
|
142
165
|
@mechanism = options[:auth_mech]
|
166
|
+
if @mechanism
|
167
|
+
# Since the driver must select an authentication class for
|
168
|
+
# the specified mechanism, mechanisms that the driver does not
|
169
|
+
# know about, and cannot translate to an authentication class,
|
170
|
+
# need to be rejected.
|
171
|
+
unless @mechanism.is_a?(Symbol)
|
172
|
+
# Although we documented auth_mech option as being a symbol, we
|
173
|
+
# have not enforced this; warn, reject in lint mode
|
174
|
+
if Lint.enabled?
|
175
|
+
raise Error::LintError, "Auth mechanism #{@mechanism.inspect} must be specified as a symbol"
|
176
|
+
else
|
177
|
+
log_warn("Auth mechanism #{@mechanism.inspect} should be specified as a symbol")
|
178
|
+
@mechanism = @mechanism.to_sym
|
179
|
+
end
|
180
|
+
end
|
181
|
+
unless Auth::SOURCES.key?(@mechanism)
|
182
|
+
raise InvalidMechanism.new(options[:auth_mech])
|
183
|
+
end
|
184
|
+
end
|
143
185
|
@auth_mech_properties = options[:auth_mech_properties] || {}
|
144
186
|
@roles = options[:roles] || []
|
145
187
|
@client_key = options[:client_key]
|
@@ -159,13 +201,6 @@ module Mongo
|
|
159
201
|
|
160
202
|
private
|
161
203
|
|
162
|
-
def sasl_prepped_password
|
163
|
-
StringPrep.prepare(password,
|
164
|
-
StringPrep::Profiles::SASL::MAPPINGS,
|
165
|
-
StringPrep::Profiles::SASL::PROHIBITED,
|
166
|
-
normalize: true, bidi: true)
|
167
|
-
end
|
168
|
-
|
169
204
|
# The client key for the user.
|
170
205
|
#
|
171
206
|
# @return [ String ] The client key for the user.
|