changeset 26:ee97bc0e08fa

Some default OPs, along with some tweaks to keep them happy
author Adam Chlipala <adam@chlipala.net>
date Sun, 23 Jan 2011 14:57:49 -0500
parents c560ec5bf514
children f129ddee75f3
files src/c/openid.c src/ur/openid.ur src/ur/openidUser.ur src/ur/openidUser.urs
diffstat 4 files changed, 142 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/c/openid.c	Thu Jan 20 12:23:44 2011 -0500
+++ b/src/c/openid.c	Sun Jan 23 14:57:49 2011 -0500
@@ -10,13 +10,17 @@
 #include <curl/curl.h>
 #include <expat.h>
 
+#include <pthread.h>
+
 #include <openid.h>
 
 #define BUF_MAX 10240
 #define BUF_INIT 1024
 
-#define PRIME_LEN 64
-#define GENERATOR DH_GENERATOR_5
+#define DEFAULT_PRIME "DCF93A0B883972EC0E19989AC5A2CE310E1D37717E8D9571BB7623731866E61EF75A2E27898B057F9891C2E27A639C3F29B60814581CD3B2CA3986D2683705577D45C2E7E52DC81C7A171876E5CEA74B1448BFDFAF18828EFD2519F14E45E3826634AF1949E5B535CC829A483B8A76223E5D490A257F05BDFF16F2FB22C583AB"
+#define DEFAULT_GENERATOR "2"
+
+static BIGNUM *default_prime, *default_generator;
 
 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) {
   return d.endpoint;
@@ -26,9 +30,32 @@
   return d.localId;
 }
 
+static pthread_mutex_t *locks;
+
+static void locking_function(int mode, int n, const char *file, int line) {
+  if (mode & CRYPTO_LOCK)
+    pthread_mutex_lock(&locks[n]);
+  else
+    pthread_mutex_unlock(&locks[n]);
+}
+
+static unsigned long id_function() {
+  return pthread_self();
+}
+
 uw_unit uw_OpenidFfi_init(uw_context ctx) {
+  int nl = CRYPTO_num_locks(), i;
+  locks = malloc(sizeof(pthread_mutex_t) * nl);
+  for (i = 0; i < nl; ++i)
+    pthread_mutex_init(&locks[i], NULL);
+
+  CRYPTO_set_locking_callback(locking_function);
+  CRYPTO_set_id_callback(id_function);
   curl_global_init(CURL_GLOBAL_ALL);
 
+  BN_hex2bn(&default_prime, DEFAULT_PRIME);
+  BN_dec2bn(&default_generator, DEFAULT_GENERATOR);
+
   return uw_unit_v;
 }
 
@@ -44,14 +71,20 @@
   return r;
 }
 
+typedef enum { NONE, SERVICE, TYPE, MATCHED, URI } xrds_mode;
+
 typedef struct {
   uw_context ctx;
   uw_OpenidFfi_discovery *d;
+  xrds_mode mode;
 } endpoint;
 
 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
   endpoint *ep = userData;
 
+  if (!strncmp(name, "xrd:", 4))
+    name += 4;
+
   if (!strcmp(name, "link")) {
     const XML_Char **attp;
     int found = 0;
@@ -72,6 +105,54 @@
       }
     }
   }
+  else if (!strcmp(name, "Service"))
+    ep->mode = SERVICE;
+  else if (!strcmp(name, "Type")) {
+    if (ep->mode == SERVICE)
+      ep->mode = TYPE;
+  }
+  else if (!strcmp(name, "URI")) {
+    if (ep->mode == MATCHED)
+      ep->mode = URI;
+  }
+}
+
+static char server[] = "http://specs.openid.net/auth/2.0/server";
+static char signon[] = "http://specs.openid.net/auth/2.0/signon";
+
+static void XMLCALL cdata(void *userData, const XML_Char *s, int len) {
+  endpoint *ep = userData;
+
+  switch (ep->mode) {
+  case TYPE:
+    if ((len == sizeof(server)-1 && !memcmp(server, s, sizeof(server)-1))
+        || (len == sizeof(signon)-1 && !memcmp(signon, s, sizeof(signon)-1)))
+      ep->mode = MATCHED;
+    break;
+  case URI:
+    ep->d->endpoint = uw_malloc(ep->ctx, len+1);
+    memcpy(ep->d->endpoint, s, len);
+    ep->d->endpoint[len] = 0;
+    break;
+  default:
+    break;
+  }
+}
+
+static void XMLCALL endElement(void *userData, const XML_Char *name) {
+  endpoint *ep = userData;
+
+  if (!strncmp(name, "xrd:", 4))
+    name += 4;
+
+  if (!strcmp(name, "Service"))
+    ep->mode = NONE;
+  else if (!strcmp(name, "Type")) {
+    if (ep->mode != MATCHED)
+      ep->mode = SERVICE;
+  }
+  else if (!strcmp(name, "URI"))
+    ep->mode = MATCHED;
 }
 
 typedef struct {
@@ -93,7 +174,7 @@
   CURL *c = curl(ctx);
   curl_discovery_data cd = {};
   uw_OpenidFfi_discovery *dy = uw_malloc(ctx, sizeof(uw_OpenidFfi_discovery));
-  endpoint ep = {ctx, dy};
+  endpoint ep = {ctx, dy, NONE};
   CURLcode code;
 
   dy->endpoint = dy->localId = NULL;
@@ -112,8 +193,10 @@
   cd.parser = XML_ParserCreate(NULL);
   XML_SetUserData(cd.parser, &ep);
   uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
-  XML_SetStartElementHandler(cd.parser, startElement);
+  XML_SetElementHandler(cd.parser, startElement, endElement);
+  XML_SetCharacterDataHandler(cd.parser, cdata);
 
+  curl_easy_reset(c);
   curl_easy_setopt(c, CURLOPT_URL, id);
   curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data);
   curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
@@ -143,20 +226,6 @@
       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);
-    }*/
   }
 }
 
@@ -200,13 +269,13 @@
 
   uw_buffer_append(inps, "", 1);
 
+  curl_easy_reset(c);
   curl_easy_setopt(c, CURLOPT_URL, url);
   curl_easy_setopt(c, CURLOPT_POSTFIELDS, inps->start);
   curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_buffer_data);
   curl_easy_setopt(c, CURLOPT_WRITEDATA, buf);
 
   code = curl_easy_perform(c);
-
   uw_buffer_append(buf, "", 1);
 
   if (code) {
@@ -388,16 +457,18 @@
 
 static void free_DH(void *data, int will_retry) {
   DH *dh = data;
+  dh->p = NULL;
+  dh->g = NULL;
   DH_free(dh);
 }
 
 uw_OpenidFfi_dh uw_OpenidFfi_generate(uw_context ctx) {
   DH *dh = DH_new();
 
+  dh->p = default_prime;
+  dh->g = default_generator;
   uw_register_transactional(ctx, dh, NULL, NULL, free_DH);
 
-  DH_generate_parameters_ex(dh, PRIME_LEN, GENERATOR, NULL);
-
   if (DH_generate_key(dh) != 1)
     uw_error(ctx, FATAL, "Diffie-Hellman key generation failed");
 
--- a/src/ur/openid.ur	Thu Jan 20 12:23:44 2011 -0500
+++ b/src/ur/openid.ur	Sun Jan 23 14:57:49 2011 -0500
@@ -383,18 +383,18 @@
           | Some dy =>
             case r.Association of
                 Stateless =>
-                redirect (bless (dy ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.claimed_id="
-                                 ^ eatFragment r.Identifier
-                                 ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.return_to="
-                                 ^ show (effectfulUrl returnTo) ^ realmString))
+                redirect (bless (dy ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup"
+                                 ^ "&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select"
+                                 ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.assoc_handle="
+                                 ^ "&openid.return_to=" ^ show (effectfulUrl returnTo) ^ realmString))
               | Stateful ar =>
                 assoc <- association ar.AssociationType ar.AssociationSessionType dy;
                 case assoc of
                     AssError msg => return ("Association failure: " ^ msg)
                   | AssAlternate _ => return "Association failure: server didn't accept its own alternate association modes"
                   | Association assoc =>
-                    redirect (bless (dy ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.claimed_id="
-                                     ^ eatFragment r.Identifier
+                    redirect (bless (dy ^ "?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup"
+                                     ^ "&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select"
                                      ^ "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.assoc_handle="
                                      ^ assoc.Handle ^ "&openid.return_to=" ^ show (effectfulUrl returnTo) ^ realmString))
     end
--- a/src/ur/openidUser.ur	Thu Jan 20 12:23:44 2011 -0500
+++ b/src/ur/openidUser.ur	Sun Jan 23 14:57:49 2011 -0500
@@ -1,3 +1,10 @@
+style provider
+
+style aol
+style google
+style myspace
+style yahoo
+
 functor Make(M: sig
                  con cols :: {Type}
                  constraint [Id] ~ cols
@@ -251,12 +258,33 @@
                     error <xml>Login with your identity provider failed: {[msg]}</xml>
 
             fun signup after =
-                wrap "Account Signup" <xml>
-                  <form>
-                    OpenID Identifier: <textbox{#Identifier}/><br/>
-                    <submit value="Sign Up" action={doSignup after}/>
-                  </form>
-                </xml>
+                let
+                    fun fixed cls label url =
+                        let
+                            fun doFixedButton () =
+                                doSignup after {Identifier = url}
+                        in
+                            <xml><form class={provider}>
+                              <submit class={cls} value={label} action={doFixedButton}/>
+                            </form></xml>
+                        end
+                in
+                    wrap "Account Signup" <xml>
+                      <p>This web site uses the <b><a href="http://openid.net/">OpenID</a></b> standard, which lets you log in using your account from one of several popular web sites, without revealing your password to us.</p>
+
+                      <p>You may click one of these buttons to choose to use your account from that site:</p>
+                      {fixed aol "AOL" "https://openid.aol.com/"}
+                      {fixed google "Google" "https://www.google.com/accounts/o8/id"}
+                      {fixed myspace "Myspace" "https://www.myspace.com/openid"}
+                      {fixed yahoo "Yahoo!" "https://me.yahoo.com/"}
+
+                      <p>Visitors familiar with the details of OpenID may also enter their own identifiers:</p>
+                      <form>
+                        OpenID Identifier: <textbox{#Identifier}/><br/>
+                        <submit value="Sign Up" action={doSignup after}/>
+                      </form>
+                    </xml>
+                end
         in
             cur <- current;
             here <- currentUrl;
--- a/src/ur/openidUser.urs	Thu Jan 20 12:23:44 2011 -0500
+++ b/src/ur/openidUser.urs	Sun Jan 23 14:57:49 2011 -0500
@@ -87,3 +87,13 @@
      * which will be a log out or sign up link. *)
 
 end
+
+(* Functor outputs will contain buttons specialized to particular well-known
+ * OpenID providers.  Use these CSS classes to style those buttons. *)
+style aol
+style google
+style myspace
+style yahoo
+
+(* This style is used by forms containing the above buttons. *)
+style provider