Mercurial > openid
comparison src/ur/openid.ur @ 9:426dd5c88df1
Fixed checking of nonce timestamp range
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 29 Dec 2010 14:17:27 -0500 |
parents | 870d99055dd1 |
children | 194577b60771 |
comparison
equal
deleted
inserted
replaced
8:870d99055dd1 | 9:426dd5c88df1 |
---|---|
1 val discoveryExpiry = 3600 | 1 val discoveryExpiry = 3600 |
2 val nonceExpiry = 3600 | 2 val nonceExpiry = 3600 |
3 val nonceSkew = 3600 | |
3 | 4 |
4 task initialize = fn () => OpenidFfi.init | 5 task initialize = fn () => OpenidFfi.init |
5 | 6 |
6 table discoveries : { Identifier : string, Endpoint : string, Expires : time } | 7 table discoveries : { Identifier : string, Endpoint : string, Expires : time } |
7 PRIMARY KEY Identifier | 8 PRIMARY KEY Identifier |
220 | Some nonce => | 221 | Some nonce => |
221 case timeOfNonce nonce of | 222 case timeOfNonce nonce of |
222 None => return (Some "Invalid timestamp in nonce") | 223 None => return (Some "Invalid timestamp in nonce") |
223 | Some tm => | 224 | Some tm => |
224 now <- now; | 225 now <- now; |
225 exp <- return (addSeconds now nonceExpiry); | 226 if tm < addSeconds now (-nonceExpiry) then |
226 if tm < exp then | |
227 return (Some "Nonce timestamp is too old") | 227 return (Some "Nonce timestamp is too old") |
228 else if tm > addSeconds now nonceSkew then | |
229 return (Some ("Nonce timestamp is too far in the future: " ^ show tm ^ " (from " ^ nonce ^ ")")) | |
228 else | 230 else |
229 b <- oneRowE1 (SELECT COUNT( * ) > 0 | 231 b <- oneRowE1 (SELECT COUNT( * ) > 0 |
230 FROM nonces | 232 FROM nonces |
231 WHERE nonces.Endpoint = {[ep]} | 233 WHERE nonces.Endpoint = {[ep]} |
232 AND nonces.Nonce = {[nonce]}); | 234 AND nonces.Nonce = {[nonce]}); |
233 | 235 |
234 if b then | 236 if b then |
235 return (Some "Duplicate nonce") | 237 return (Some "Duplicate nonce") |
236 else | 238 else |
237 debug ("Nonce expires: " ^ show exp); | |
238 dml (INSERT INTO nonces (Endpoint, Nonce, Expires) | 239 dml (INSERT INTO nonces (Endpoint, Nonce, Expires) |
239 VALUES ({[ep]}, {[nonce]}, {[exp]})); | 240 VALUES ({[ep]}, {[nonce]}, {[addSeconds now nonceExpiry]})); |
240 return None | 241 return None |
241 | 242 |
242 fun verifySig os atype key = | 243 fun verifySig os atype key = |
243 case OpenidFfi.getOutput os "openid.signed" of | 244 case OpenidFfi.getOutput os "openid.signed" of |
244 None => return (Some "Missing openid.signed in OP response") | 245 None => return (Some "Missing openid.signed in OP response") |
245 | Some signed => | 246 | Some signed => |
246 case OpenidFfi.getOutput os "openid.sig" of | 247 case OpenidFfi.getOutput os "openid.sig" of |
247 None => return (Some "Missing openid.sig in OP response") | 248 None => return (Some "Missing openid.sig in OP response") |
248 | Some sign => let | 249 | Some sign => let |
249 fun gatherNvps signed acc = | 250 fun gatherNvps signed required acc = |
250 let | 251 let |
251 val (this, next) = | 252 val (this, next) = |
252 case String.split signed #"," of | 253 case String.split signed #"," of |
253 None => (signed, None) | 254 None => (signed, None) |
254 | Some (this, next) => (this, Some next) | 255 | Some (this, next) => (this, Some next) |
255 in | 256 in |
256 case OpenidFfi.getOutput os ("openid." ^ this) of | 257 case OpenidFfi.getOutput os ("openid." ^ this) of |
257 None => None | 258 None => None |
258 | Some value => | 259 | Some value => |
259 let | 260 let |
261 val required = List.filter (fn other => other <> this) required | |
260 val acc = acc ^ this ^ ":" ^ value ^ "\n" | 262 val acc = acc ^ this ^ ":" ^ value ^ "\n" |
261 in | 263 in |
262 case next of | 264 case next of |
263 None => Some acc | 265 None => Some (required, acc) |
264 | Some next => gatherNvps next acc | 266 | Some next => gatherNvps next required acc |
265 end | 267 end |
266 end | 268 end |
267 in | 269 in |
268 case gatherNvps signed "" of | 270 case gatherNvps signed ("op_endpoint" :: "return_to" :: "response_nonce" :: "assoc_handle" :: "claimed_id" :: "identity" :: []) "" of |
269 None => return (Some "openid.signed mentions missing field") | 271 None => return (Some "openid.signed mentions missing field") |
270 | Some nvps => | 272 | Some ([], nvps) => |
271 let | 273 let |
272 val sign' = case atype of | 274 val sign' = case atype of |
273 HMAC_SHA256 => OpenidFfi.sha256 key nvps | 275 HMAC_SHA256 => OpenidFfi.sha256 key nvps |
274 | HMAC_SHA1 => OpenidFfi.sha1 key nvps | 276 | HMAC_SHA1 => OpenidFfi.sha1 key nvps |
275 in | 277 in |
276 debug ("Fields: " ^ signed); | 278 (*debug ("Fields: " ^ signed); |
277 debug ("Nvps: " ^ nvps); | 279 debug ("Nvps: " ^ nvps); |
278 debug ("Key: " ^ key); | 280 debug ("Key: " ^ key); |
279 debug ("His: " ^ sign); | 281 debug ("His: " ^ sign); |
280 debug ("Mine: " ^ sign'); | 282 debug ("Mine: " ^ sign');*) |
281 if sign' = sign then | 283 if sign' = sign then |
282 return None | 284 return None |
283 else | 285 else |
284 return (Some "Signatures don't match") | 286 return (Some "Signatures don't match") |
285 end | 287 end |
288 | Some (left, _) => return (Some ("openid.signed is missing required fields: " ^ show left)) | |
286 end | 289 end |
287 | 290 |
288 fun returnTo (qs : option queryString) = | 291 fun returnTo (qs : option queryString) = |
289 case qs of | 292 case qs of |
290 None => error <xml>Empty query string for OpenID callback</xml> | 293 None => error <xml>Empty query string for OpenID callback</xml> |