@@ -16,9 +16,12 @@ use error::Result;
16
16
use rustc_serialize:: base64:: { self , FromBase64 , ToBase64 } ;
17
17
use textnonce:: TextNonce ;
18
18
19
- const B64_CONFIG : base64:: Config = base64:: Config { char_set : base64:: CharacterSet :: Standard ,
20
- newline : base64:: Newline :: LF ,
21
- pad : true , line_length : None } ;
19
+ const B64_CONFIG : base64:: Config = base64:: Config {
20
+ char_set : base64:: CharacterSet :: Standard ,
21
+ newline : base64:: Newline :: LF ,
22
+ pad : true ,
23
+ line_length : None ,
24
+ } ;
22
25
23
26
/// Handles SCRAM-SHA-1 authentication logic.
24
27
pub struct Authenticator {
@@ -57,7 +60,7 @@ impl Authenticator {
57
60
fn start ( & self , user : & str ) -> Result < InitialData > {
58
61
let text_nonce = match TextNonce :: sized ( 64 ) {
59
62
Ok ( text_nonce) => text_nonce,
60
- Err ( string) => return Err ( DefaultError ( string) )
63
+ Err ( string) => return Err ( DefaultError ( string) ) ,
61
64
} ;
62
65
63
66
let nonce = format ! ( "{}" , text_nonce) ;
@@ -76,51 +79,59 @@ impl Authenticator {
76
79
77
80
let data = match doc. get ( "payload" ) {
78
81
Some ( & Binary ( _, ref payload) ) => payload. to_owned ( ) ,
79
- _ => return Err ( ResponseError ( "Invalid payload returned" . to_owned ( ) ) )
82
+ _ => return Err ( ResponseError ( String :: from ( "Invalid payload returned" ) ) ) ,
80
83
} ;
81
84
82
85
let id = match doc. get ( "conversationId" ) {
83
86
Some ( bson) => bson. clone ( ) ,
84
- None => return Err ( ResponseError ( "No conversationId returned" . to_owned ( ) ) )
87
+ None => return Err ( ResponseError ( String :: from ( "No conversationId returned" ) ) ) ,
85
88
} ;
86
89
87
90
let response = match String :: from_utf8 ( data) {
88
91
Ok ( string) => string,
89
- Err ( _) => return Err ( ResponseError ( "Invalid UTF-8 payload returned" . to_owned ( ) ) )
92
+ Err ( _) => return Err ( ResponseError ( String :: from ( "Invalid UTF-8 payload returned" ) ) ) ,
90
93
} ;
91
94
92
- Ok ( InitialData { message : message, response : response, nonce : nonce,
93
- conversation_id : id } )
95
+ Ok ( InitialData {
96
+ message : message,
97
+ response : response,
98
+ nonce : nonce,
99
+ conversation_id : id,
100
+ } )
94
101
}
95
102
96
103
fn next ( & self , password : String , initial_data : InitialData ) -> Result < AuthData > {
97
104
// Parse out rnonce, salt, and iteration count
98
- let ( rnonce_opt, salt_opt, i_opt) = scan_fmt ! ( & initial_data. response[ ..] , "r={},s={},i={}" , String , String , u32 ) ;
105
+ let ( rnonce_opt, salt_opt, i_opt) = scan_fmt ! ( & initial_data. response[ ..] ,
106
+ "r={},s={},i={}" ,
107
+ String ,
108
+ String ,
109
+ u32 ) ;
99
110
100
111
let rnonce_b64 = match rnonce_opt {
101
112
Some ( val) => val,
102
- None => return Err ( ResponseError ( "Invalid rnonce returned" . to_owned ( ) ) )
113
+ None => return Err ( ResponseError ( String :: from ( "Invalid rnonce returned" ) ) ) ,
103
114
} ;
104
115
105
116
// Validate rnonce to make sure server isn't malicious
106
117
if !rnonce_b64. starts_with ( & initial_data. nonce [ ..] ) {
107
- return Err ( MaliciousServerError ( MaliciousServerErrorType :: InvalidRnonce ) )
118
+ return Err ( MaliciousServerError ( MaliciousServerErrorType :: InvalidRnonce ) ) ;
108
119
}
109
120
110
121
let salt_b64 = match salt_opt {
111
122
Some ( val) => val,
112
- None => return Err ( ResponseError ( "Invalid salt returned" . to_owned ( ) ) )
123
+ None => return Err ( ResponseError ( String :: from ( "Invalid salt returned" ) ) ) ,
113
124
} ;
114
125
115
126
let salt = match salt_b64. from_base64 ( ) {
116
127
Ok ( val) => val,
117
- Err ( _) => return Err ( ResponseError ( "Invalid base64 salt returned" . to_owned ( ) ) )
128
+ Err ( _) => return Err ( ResponseError ( String :: from ( "Invalid base64 salt returned" ) ) ) ,
118
129
} ;
119
130
120
131
121
132
let i = match i_opt {
122
133
Some ( val) => val,
123
- None => return Err ( ResponseError ( "Invalid iteration count returned" . to_owned ( ) ) )
134
+ None => return Err ( ResponseError ( String :: from ( "Invalid iteration count returned" ) ) ) ,
124
135
} ;
125
136
126
137
// Hash password
@@ -130,24 +141,27 @@ impl Authenticator {
130
141
131
142
// Salt password
132
143
let mut hmac = Hmac :: new ( Sha1 :: new ( ) , hashed_password. as_bytes ( ) ) ;
133
- let mut salted_password : Vec < _ > = ( 0 ..hmac. output_bytes ( ) ) . map ( |_| 0 ) . collect ( ) ;
144
+ let mut salted_password: Vec < _ > = ( 0 ..hmac. output_bytes ( ) ) . map ( |_| 0 ) . collect ( ) ;
134
145
pbkdf2:: pbkdf2 ( & mut hmac, & salt[ ..] , i, & mut salted_password) ;
135
146
136
147
// Compute client key
137
148
let mut client_key_hmac = Hmac :: new ( Sha1 :: new ( ) , & salted_password[ ..] ) ;
138
- let client_key_bytes = "Client Key" . as_bytes ( ) ;
149
+ let client_key_bytes = b "Client Key";
139
150
client_key_hmac. input ( client_key_bytes) ;
140
151
let client_key = client_key_hmac. result ( ) . code ( ) . to_owned ( ) ;
141
152
142
153
// Hash into stored key
143
154
let mut stored_key_sha1 = Sha1 :: new ( ) ;
144
155
stored_key_sha1. input ( & client_key[ ..] ) ;
145
- let mut stored_key : Vec < _ > = ( 0 ..stored_key_sha1. output_bytes ( ) ) . map ( |_| 0 ) . collect ( ) ;
156
+ let mut stored_key: Vec < _ > = ( 0 ..stored_key_sha1. output_bytes ( ) ) . map ( |_| 0 ) . collect ( ) ;
146
157
stored_key_sha1. result ( & mut stored_key) ;
147
158
148
159
// Create auth message
149
160
let without_proof = format ! ( "c=biws,r={}" , rnonce_b64) ;
150
- let auth_message = format ! ( "{},{},{}" , initial_data. message, initial_data. response, without_proof) ;
161
+ let auth_message = format ! ( "{},{},{}" ,
162
+ initial_data. message,
163
+ initial_data. response,
164
+ without_proof) ;
151
165
152
166
// Compute client signature
153
167
let mut client_signature_hmac = Hmac :: new ( Sha1 :: new ( ) , & stored_key[ ..] ) ;
@@ -156,7 +170,8 @@ impl Authenticator {
156
170
157
171
// Sanity check
158
172
if client_key. len ( ) != client_signature. len ( ) {
159
- return Err ( DefaultError ( "Generated client key and/or client signature is invalid" . to_owned ( ) ) ) ;
173
+ return Err ( DefaultError ( String :: from ( "Generated client key and/or client signature \
174
+ is invalid") ) ) ;
160
175
}
161
176
162
177
// Compute proof by xor'ing key and signature
@@ -178,8 +193,11 @@ impl Authenticator {
178
193
179
194
let response = try!( self . db . command ( next_doc, Suppressed , None ) ) ;
180
195
181
- Ok ( AuthData { salted_password : salted_password, message : auth_message,
182
- response : response } )
196
+ Ok ( AuthData {
197
+ salted_password : salted_password,
198
+ message : auth_message,
199
+ response : response,
200
+ } )
183
201
}
184
202
185
203
fn finish ( & self , conversation_id : Bson , auth_data : AuthData ) -> Result < ( ) > {
@@ -191,7 +209,7 @@ impl Authenticator {
191
209
192
210
// Compute server key
193
211
let mut server_key_hmac = Hmac :: new ( Sha1 :: new ( ) , & auth_data. salted_password [ ..] ) ;
194
- let server_key_bytes = "Server Key" . as_bytes ( ) ;
212
+ let server_key_bytes = b "Server Key";
195
213
server_key_hmac. input ( server_key_bytes) ;
196
214
let server_key = server_key_hmac. result ( ) . code ( ) . to_owned ( ) ;
197
215
@@ -207,25 +225,29 @@ impl Authenticator {
207
225
if let Some ( & Binary ( _, ref payload) ) = doc. get ( "payload" ) {
208
226
let payload_str = match String :: from_utf8 ( payload. to_owned ( ) ) {
209
227
Ok ( string) => string,
210
- Err ( _) => return Err ( ResponseError ( "Invalid UTF-8 payload returned" . to_owned ( ) ) )
228
+ Err ( _) => {
229
+ return Err ( ResponseError ( String :: from ( "Invalid UTF-8 payload returned" ) ) )
230
+ }
211
231
} ;
212
232
213
233
// Check that the signature exists
214
234
let verifier = match scan_fmt ! ( & payload_str[ ..] , "v={}" , String ) {
215
235
Some ( string) => string,
216
- None => return Err ( MaliciousServerError ( MaliciousServerErrorType :: NoServerSignature ) ) ,
236
+ None => return Err (
237
+ MaliciousServerError ( MaliciousServerErrorType :: NoServerSignature ) ) ,
217
238
} ;
218
239
219
240
// Check that the signature is valid
220
241
if verifier. ne ( & server_signature. to_base64 ( B64_CONFIG ) [ ..] ) {
221
- return Err ( MaliciousServerError ( MaliciousServerErrorType :: InvalidServerSignature ) ) ;
242
+ return Err (
243
+ MaliciousServerError ( MaliciousServerErrorType :: InvalidServerSignature ) ) ;
222
244
}
223
245
}
224
246
225
247
doc = try!( self . db . command ( final_doc. clone ( ) , Suppressed , None ) ) ;
226
248
227
249
if let Some ( & Bson :: Boolean ( true ) ) = doc. get ( "done" ) {
228
- return Ok ( ( ) )
250
+ return Ok ( ( ) ) ;
229
251
}
230
252
}
231
253
}
0 commit comments