changeset 14:6b2a44da71b0

Change postify to satisfy more OPs; add untested invalidate_handle support
author Adam Chlipala <adam@chlipala.net>
date Sun, 02 Jan 2011 10:33:07 -0500
parents de04a3fc6b72
children 35bc4da563dd
files src/c/openid.c src/ur/openid.ur
diffstat 2 files changed, 44 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/c/openid.c	Sun Jan 02 10:11:38 2011 -0500
+++ b/src/c/openid.c	Sun Jan 02 10:33:07 2011 -0500
@@ -1,3 +1,4 @@
+#include <ctype.h>
 #include <string.h>
 
 #include <openssl/bio.h>
@@ -133,17 +134,29 @@
 }
 
 static void postify(uw_OpenidFfi_inputs buf, uw_Basis_string s) {
+  char hex[4];
+
   for (; *s; ++s) {
-    switch (*s) {
+    if (isalnum(*s))
+      uw_buffer_append(buf, s, 1);
+    else {
+      sprintf(hex, "%%%02X", (unsigned char)*s);
+      uw_buffer_append(buf, hex, 3);
+    }
+
+    /*switch (*s) {
     case '=':
       uw_buffer_append(buf, "%3D", 3);
       break;
     case '&':
       uw_buffer_append(buf, "%26", 3);
       break;
+    case '%':
+      uw_buffer_append(buf, "%25", 3);
+      break;
     default:
       uw_buffer_append(buf, s, 1);
-    }
+    }*/
   }
 }
 
@@ -151,7 +164,7 @@
   if (uw_buffer_used(buf) > 0)
     uw_buffer_append(buf, "&", 1);
 
-  postify(buf, key);
+  uw_buffer_append(buf, key, strlen(key));
   uw_buffer_append(buf, "=", 1);
   postify(buf, value);
 
--- a/src/ur/openid.ur	Sun Jan 02 10:11:38 2011 -0500
+++ b/src/ur/openid.ur	Sun Jan 02 10:33:07 2011 -0500
@@ -217,14 +217,27 @@
                 else
                     return (HandleOk {Endpoint = ep, Typ = assoc.Typ, Key = assoc.Key})
 
-fun verifyStateless os ep id =
+fun verifyStateless os ep id expectInvalidation =
     os' <- OpenidFfi.direct ep (OpenidFfi.remode os "check_authentication");
     case OpenidFfi.getOutput os' "error" of
         Some msg => return (Failure ("Failure confirming message contents with OP: " ^ msg))
       | None =>
-        case OpenidFfi.getOutput os' "is_valid" of
-            Some "true" => return (AuthenticatedAs id)
-          | _ => return (Failure "OP does not confirm message contents")
+        let
+            fun finish () = case OpenidFfi.getOutput os' "is_valid" of
+                                Some "true" => return (AuthenticatedAs id)
+                              | _ => return (Failure "OP does not confirm message contents")
+        in
+            case OpenidFfi.getOutput os' "invalidate_handle" of
+                None =>
+                if expectInvalidation then
+                    return (Failure "Claimed invalidate_handle is not confirmed")
+                else
+                    finish ()
+              | Some handle =>
+                dml (DELETE FROM associations
+                     WHERE Endpoint = {[ep]} AND Handle = {[handle]});
+                finish ()
+        end
 
 table nonces : { Endpoint : string, Nonce : string, Expires : time }
   PRIMARY KEY (Endpoint, Nonce)
@@ -337,17 +350,22 @@
                                      case errO of
                                          HandleError s => after (Failure s)
                                        | NoAssociation ep =>
-                                         r <- verifyStateless os ep id;
+                                         r <- verifyStateless os ep id False;
                                          after r
                                        | HandleOk {Endpoint = ep, Typ = atype, Key = key} =>
-                                         errO <- verifyNonce os ep;
-                                         case errO of
-                                             Some s => after (Failure s)
+                                         case OpenidFfi.getOutput os "openid.invalidate_handle" of
+                                             Some _ =>
+                                             r <- verifyStateless os ep id True;
+                                             after r
                                            | None =>
-                                             errO <- verifySig os atype key;
+                                             errO <- verifyNonce os ep;
                                              case errO of
                                                  Some s => after (Failure s)
-                                               | None => after (AuthenticatedAs id))
+                                               | None =>
+                                                 errO <- verifySig os atype key;
+                                                 case errO of
+                                                     Some s => after (Failure s)
+                                                   | None => after (AuthenticatedAs id))
                           | _ => after (Failure ("Unexpected openid.mode: " ^ mode))
 
         and verifyReturnTo os =