# HG changeset patch # User Adam Chlipala # Date 1293650247 18000 # Node ID 426dd5c88df1399d9ecbf913c8675b0e0d2d1ff4 # Parent 870d99055dd1f20189d9e92450e6282a05ac08eb Fixed checking of nonce timestamp range diff -r 870d99055dd1 -r 426dd5c88df1 src/ur/lib.urp --- a/src/ur/lib.urp Wed Dec 29 12:16:32 2010 -0500 +++ b/src/ur/lib.urp Wed Dec 29 14:17:27 2010 -0500 @@ -12,4 +12,5 @@ $/string $/option +$/list openid diff -r 870d99055dd1 -r 426dd5c88df1 src/ur/openid.ur --- a/src/ur/openid.ur Wed Dec 29 12:16:32 2010 -0500 +++ b/src/ur/openid.ur Wed Dec 29 14:17:27 2010 -0500 @@ -1,5 +1,6 @@ val discoveryExpiry = 3600 val nonceExpiry = 3600 +val nonceSkew = 3600 task initialize = fn () => OpenidFfi.init @@ -222,9 +223,10 @@ None => return (Some "Invalid timestamp in nonce") | Some tm => now <- now; - exp <- return (addSeconds now nonceExpiry); - if tm < exp then + if tm < addSeconds now (-nonceExpiry) then return (Some "Nonce timestamp is too old") + else if tm > addSeconds now nonceSkew then + return (Some ("Nonce timestamp is too far in the future: " ^ show tm ^ " (from " ^ nonce ^ ")")) else b <- oneRowE1 (SELECT COUNT( * ) > 0 FROM nonces @@ -234,9 +236,8 @@ if b then return (Some "Duplicate nonce") else - debug ("Nonce expires: " ^ show exp); dml (INSERT INTO nonces (Endpoint, Nonce, Expires) - VALUES ({[ep]}, {[nonce]}, {[exp]})); + VALUES ({[ep]}, {[nonce]}, {[addSeconds now nonceExpiry]})); return None fun verifySig os atype key = @@ -246,7 +247,7 @@ case OpenidFfi.getOutput os "openid.sig" of None => return (Some "Missing openid.sig in OP response") | Some sign => let - fun gatherNvps signed acc = + fun gatherNvps signed required acc = let val (this, next) = case String.split signed #"," of @@ -257,32 +258,34 @@ None => None | Some value => let + val required = List.filter (fn other => other <> this) required val acc = acc ^ this ^ ":" ^ value ^ "\n" in case next of - None => Some acc - | Some next => gatherNvps next acc + None => Some (required, acc) + | Some next => gatherNvps next required acc end end in - case gatherNvps signed "" of + case gatherNvps signed ("op_endpoint" :: "return_to" :: "response_nonce" :: "assoc_handle" :: "claimed_id" :: "identity" :: []) "" of None => return (Some "openid.signed mentions missing field") - | Some nvps => + | Some ([], nvps) => let val sign' = case atype of HMAC_SHA256 => OpenidFfi.sha256 key nvps | HMAC_SHA1 => OpenidFfi.sha1 key nvps in - debug ("Fields: " ^ signed); + (*debug ("Fields: " ^ signed); debug ("Nvps: " ^ nvps); debug ("Key: " ^ key); debug ("His: " ^ sign); - debug ("Mine: " ^ sign'); + debug ("Mine: " ^ sign');*) if sign' = sign then return None else return (Some "Signatures don't match") end + | Some (left, _) => return (Some ("openid.signed is missing required fields: " ^ show left)) end fun returnTo (qs : option queryString) =