# HG changeset patch # User Adam Chlipala # Date 1293584245 18000 # Node ID 976121190b2d092f64699b0ef456b7c0bc55d297 # Parent 99496175078bc818724ffbce14f7d34823472a53 Authentication verification almost working: signatures not computing correctly diff -r 99496175078b -r 976121190b2d include/openid.h --- a/include/openid.h Mon Dec 27 13:18:02 2010 -0500 +++ b/include/openid.h Tue Dec 28 19:57:25 2010 -0500 @@ -20,4 +20,4 @@ uw_OpenidFfi_outputs uw_OpenidFfi_direct(uw_context, uw_Basis_string url, uw_OpenidFfi_inputs); uw_OpenidFfi_outputs uw_OpenidFfi_indirect(uw_context, uw_Basis_string fields); -uw_Basis_string uw_OpenidFfi_sha256(uw_context, uw_Basis_string); +uw_Basis_string uw_OpenidFfi_sha256(uw_context, uw_Basis_string key, uw_Basis_string data); diff -r 99496175078b -r 976121190b2d src/c/openid.c --- a/src/c/openid.c Mon Dec 27 13:18:02 2010 -0500 +++ b/src/c/openid.c Tue Dec 28 19:57:25 2010 -0500 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -25,8 +26,6 @@ } uw_unit uw_OpenidFfi_init(uw_context ctx) { - - curl_global_init(CURL_GLOBAL_ALL); return uw_unit_v; @@ -74,9 +73,6 @@ } } -static void XMLCALL endElement(void *userData, const XML_Char *name) { -} - typedef struct { XML_Parser parser; int any_errors; @@ -115,7 +111,7 @@ cd.parser = XML_ParserCreate(NULL); XML_SetUserData(cd.parser, &ep); uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); - XML_SetElementHandler(cd.parser, startElement, endElement); + XML_SetStartElementHandler(cd.parser, startElement); curl_easy_setopt(c, CURLOPT_URL, id); curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data); @@ -215,14 +211,13 @@ break; } + *colon = 0; + newline = strchr(colon+1, '\n'); - if (!newline) { - *s = 0; + if (!newline) break; - } - *colon = 0; *newline = 0; s = newline+1; } @@ -284,28 +279,44 @@ static uw_Basis_string base64(uw_context ctx, unsigned char *input, int length) { BIO *bmem, *b64; - BUF_MEM *bptr; b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bmem = BIO_new(BIO_s_mem()); - b64 = BIO_push(b64, bmem); + BIO_push(b64, bmem); BIO_write(b64, input, length); (void)BIO_flush(b64); - BIO_get_mem_ptr(b64, &bptr); - char *buff = uw_malloc(ctx, bptr->length); - memcpy(buff, bptr->data, bptr->length-1); - buff[bptr->length-1] = 0; + int len = BIO_ctrl_pending(bmem); + char *buff = uw_malloc(ctx, len+1); + BIO_read(bmem, buff, len); + buff[len] = 0; BIO_free_all(b64); return buff; } -uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string s) { - unsigned char out[SHA256_DIGEST_LENGTH]; +static void unbase64(unsigned char *input, int length, unsigned char *buffer, int bufferLength) +{ + BIO *b64, *bmem; - SHA256((unsigned char *)s, strlen(s), out); + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bmem = BIO_new_mem_buf(input, length); + BIO_push(b64, bmem); + BIO_read(b64, buffer, bufferLength); - return base64(ctx, out, sizeof out); + BIO_free_all(bmem); } + +uw_Basis_string uw_OpenidFfi_sha256(uw_context ctx, uw_Basis_string key, uw_Basis_string data) { + unsigned char keyBin[SHA256_DIGEST_LENGTH], out[EVP_MAX_MD_SIZE]; + unsigned outLen; + + unbase64((unsigned char *)key, strlen(key), keyBin, sizeof keyBin); + memset(key, sizeof key, 0); + + HMAC(EVP_sha256(), keyBin, sizeof keyBin, (unsigned char *)data, strlen(data), out, &outLen); + return base64(ctx, out, outLen); +} diff -r 99496175078b -r 976121190b2d src/ur/openid.ur --- a/src/ur/openid.ur Mon Dec 27 13:18:02 2010 -0500 +++ b/src/ur/openid.ur Tue Dec 28 19:57:25 2010 -0500 @@ -34,8 +34,8 @@ fun association url = secret <- oneOrNoRows1 (SELECT associations.Handle, associations.Key - FROM associations - WHERE associations.Endpoint = {[url]}); + FROM associations + WHERE associations.Endpoint = {[url]}); case secret of Some r => return (Association r) | None => @@ -44,6 +44,8 @@ OpenidFfi.addInput is "openid.assoc_type" "HMAC-SHA256"; OpenidFfi.addInput is "openid.session_type" "no-encryption"; + debug ("Contacting " ^ url); + os <- OpenidFfi.direct url is; case OpenidFfi.getOutput os "error" of Some v => return (AssError v) @@ -57,6 +59,8 @@ dml (INSERT INTO associations (Endpoint, Handle, Key, Expires) VALUES ({[url]}, {[handle]}, {[key]}, {[addSeconds tm expires]})); return (Association {Handle = handle, Key = key})) + | (None, _, _) => return (AssError "Missing assoc_handle") + | (_, None, _) => return (AssError "Missing mac_key") | _ => return (AssError "Missing fields in response from OP") fun eatFragment s = @@ -64,7 +68,7 @@ Some (_, s') => s' | _ => s -datatype handle_result = HandleOk of string | HandleError of string +datatype handle_result = HandleOk of {Endpoint : string, Key : string} | HandleError of string fun verifyHandle os id = ep <- discover (eatFragment id); @@ -81,7 +85,7 @@ if assoc.Handle <> handle then return (HandleError "Association handles don't match") else - return (HandleOk ep) + return (HandleOk {Endpoint = ep, Key = assoc.Key}) table nonces : { Endpoint : string, Nonce : string, Expires : time } PRIMARY KEY (Endpoint, Nonce) @@ -92,7 +96,7 @@ | Some (date, s) => case String.split s #"Z" of None => None - | Some (time, _) => read (date ^ " " ^ time) + | Some (time, _) => readUtc (date ^ " " ^ time) fun verifyNonce os ep = case OpenidFfi.getOutput os "openid.response_nonce" of @@ -114,11 +118,12 @@ if b then return (Some "Duplicate nonce") else + debug ("Nonce expires: " ^ show exp); dml (INSERT INTO nonces (Endpoint, Nonce, Expires) VALUES ({[ep]}, {[nonce]}, {[exp]})); return None -fun verifySig os = +fun verifySig os key = case OpenidFfi.getOutput os "openid.signed" of None => return (Some "Missing openid.signed in OP response") | Some signed => @@ -148,10 +153,11 @@ None => return (Some "openid.signed mentions missing field") | Some nvps => let - val sign' = OpenidFfi.sha256 nvps + val sign' = OpenidFfi.sha256 key nvps in debug ("Fields: " ^ signed); debug ("Nvps: " ^ nvps); + debug ("Key: " ^ key); debug ("His: " ^ sign); debug ("Mine: " ^ sign'); if sign' = sign then @@ -181,7 +187,7 @@ errO <- verifyHandle os id; case errO of HandleError s => error {[s]} - | HandleOk ep => + | HandleOk {Endpoint = ep, Key = key} => errO <- verifyReturnTo os; case errO of Some s => error {[s]} @@ -190,7 +196,7 @@ case errO of Some s => error {[s]} | None => - errO <- verifySig os; + errO <- verifySig os key; case errO of Some s => error {[s]} | None => return Identity: {[id]}) diff -r 99496175078b -r 976121190b2d src/ur/openidFfi.urs --- a/src/ur/openidFfi.urs Mon Dec 27 13:18:02 2010 -0500 +++ b/src/ur/openidFfi.urs Tue Dec 28 19:57:25 2010 -0500 @@ -15,4 +15,4 @@ val direct : string -> inputs -> transaction outputs val indirect : queryString -> transaction outputs -val sha256 : string -> string +val sha256 : string -> string -> string