X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fopenid%2Fserv_openid_rp.c;h=e2ff01f6d12a34a223233987caddc308df182811;hb=c09546736e26b737e1e5c6b5aca5be8463ecb00e;hp=e9bfcf199d4e2751201909c6ea4fff62e1595b6a;hpb=b657b0f030809ce7ddca08e49b1a91fef359eca4;p=citadel.git diff --git a/citadel/modules/openid/serv_openid_rp.c b/citadel/modules/openid/serv_openid_rp.c index e9bfcf199..e2ff01f6d 100644 --- a/citadel/modules/openid/serv_openid_rp.c +++ b/citadel/modules/openid/serv_openid_rp.c @@ -1,9 +1,5 @@ /* - * This is an implementation of OpenID 2.0 RELYING PARTY SUPPORT CURRENTLY B0RKEN AND BEING DEVEL0PZ0RED - - - OPENID2 BRANCH -- NEEDS TO BE MERGEZ0RED !!!!!!111 - + * This is an implementation of OpenID 2.0 relying party support in stateless mode. * * Copyright (c) 2007-2011 by the citadel.org team * @@ -261,7 +257,7 @@ void cmd_oida(char *argbuf) { cprintf("000\n"); } - +#if 0 /* * Attempt to register (populate the vCard) the currently-logged-in user * using the data from Simple Registration Extension, if present. @@ -342,6 +338,7 @@ void populate_vcard_from_sreg(HashList *sreg_keys) { } vcard_free(v); } +#endif /* @@ -365,7 +362,7 @@ void cmd_oidc(char *argbuf) { if (CC->logged_in) { attach_openid(&CC->user, oiddata->claimed_id); if (oiddata->sreg_keys != NULL) { - populate_vcard_from_sreg(oiddata->sreg_keys); + /* populate_vcard_from_sreg(oiddata->sreg_keys); */ } } @@ -438,7 +435,7 @@ int openid_create_user_via_sreg(StrBuf *claimed_id, HashList *sreg_keys) snprintf(new_password, sizeof new_password, "%08lx%08lx", random(), random()); CtdlSetPassword(new_password); attach_openid(&CC->user, claimed_id); - populate_vcard_from_sreg(sreg_keys); + /* populate_vcard_from_sreg(sreg_keys); */ return(0); } @@ -639,6 +636,12 @@ void xrds_xml_end(void *data, const char *supplied_el) { ) { xrds->current_service_is_oid2auth = 1; } + if ( (xrds->in_xrd) + && (!strcasecmp(ChrPtr(xrds->CharData), "http://specs.openid.net/auth/2.0/signon")) + ) { + xrds->current_service_is_oid2auth = 1; + /* FIXME in this case, the Claimed ID should be considered immutable */ + } } else if (!strcasecmp(supplied_el, "uri")) { @@ -681,7 +684,7 @@ int parse_xrds_document(StrBuf *ReplyBuf) { struct xrds xrds; int return_value = 0; - // syslog(LOG_DEBUG, "\033[32m --- XRDS DOCUMENT --- \n%s\033[0m", ChrPtr(ReplyBuf)); + /* syslog(LOG_DEBUG, "XRDS document:\n%s\n", ChrPtr(ReplyBuf)); */ memset(&xrds, 0, sizeof (struct xrds)); xrds.selected_service_priority = INT_MAX; @@ -746,7 +749,7 @@ size_t yadis_headerfunction(void *ptr, size_t size, size_t nmemb, void *userdata * If successful, returns nonzero and calls parse_xrds_document() to act upon the received data. * If fails, returns 0 and does nothing else. */ -int perform_openid2_discovery(StrBuf *YadisURL) { +int perform_openid2_discovery(StrBuf *SuppliedURL) { ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data; int docbytes = (-1); StrBuf *ReplyBuf = NULL; @@ -757,9 +760,9 @@ int perform_openid2_discovery(StrBuf *YadisURL) { struct curl_slist *my_headers = NULL; StrBuf *x_xrds_location = NULL; - if (!YadisURL) return(0); - syslog(LOG_DEBUG, "perform_openid2_discovery(%s)", ChrPtr(YadisURL)); - if (StrLength(YadisURL) == 0) return(0); + if (!SuppliedURL) return(0); + syslog(LOG_DEBUG, "perform_openid2_discovery(%s)", ChrPtr(SuppliedURL)); + if (StrLength(SuppliedURL) == 0) return(0); ReplyBuf = NewStrBuf(); if (!ReplyBuf) return(0); @@ -767,7 +770,7 @@ int perform_openid2_discovery(StrBuf *YadisURL) { curl = ctdl_openid_curl_easy_init(errmsg); if (!curl) return(0); - curl_easy_setopt(curl, CURLOPT_URL, ChrPtr(YadisURL)); + curl_easy_setopt(curl, CURLOPT_URL, ChrPtr(SuppliedURL)); curl_easy_setopt(curl, CURLOPT_WRITEDATA, ReplyBuf); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback); @@ -791,8 +794,9 @@ int perform_openid2_discovery(StrBuf *YadisURL) { * * Option 1: An HTML document with a element that includes a element with http-equiv * attribute, X-XRDS-Location, + * + * Does any provider actually do this? If so then we will implement it in the future. */ - /* FIXME handle this somehow */ /* * Option 2: HTTP response-headers that include an X-XRDS-Location response-header, @@ -804,7 +808,7 @@ int perform_openid2_discovery(StrBuf *YadisURL) { * If the X-XRDS-Location header was delivered, we know about it at this point... */ if ( (x_xrds_location) - && (strcmp(ChrPtr(x_xrds_location), ChrPtr(YadisURL))) + && (strcmp(ChrPtr(x_xrds_location), ChrPtr(SuppliedURL))) ) { syslog(LOG_DEBUG, "X-XRDS-Location: %s ... recursing!", ChrPtr(x_xrds_location)); return_value = perform_openid2_discovery(x_xrds_location); @@ -814,15 +818,14 @@ int perform_openid2_discovery(StrBuf *YadisURL) { /* * Option 4: the returned web page may *be* an XRDS document. Try to parse it. */ - else if (docbytes >= 0) { + if ( (return_value == 0) && (docbytes >= 0)) { return_value = parse_xrds_document(ReplyBuf); } /* * Option 5: if all else fails, attempt HTML based discovery. */ - if (return_value == 0) { - syslog(LOG_DEBUG, "Attempting HTML discovery"); + if ( (return_value == 0) && (docbytes >= 0)) { if (oiddata->op_url == NULL) { oiddata->op_url = NewStrBuf(); } @@ -913,7 +916,8 @@ void cmd_oids(char *argbuf) { RedirectUrl = NewStrBufDup(oiddata->op_url); - StrBufAppendBufPlain(RedirectUrl, HKEY("?openid.ns=http:%2F%2Fspecs.openid.net%2Fauth%2F2.0"), 0); + StrBufAppendBufPlain(RedirectUrl, HKEY("?openid.ns="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://specs.openid.net/auth/2.0"); StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.mode=checkid_setup"), 0); @@ -923,15 +927,37 @@ void cmd_oids(char *argbuf) { StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.identity="), 0); StrBufUrlescAppend(RedirectUrl, oiddata->claimed_id, NULL); + /* return_to completes the round trip */ StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.return_to="), 0); StrBufUrlescAppend(RedirectUrl, return_to, NULL); -/* - StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.sreg.optional="), 0); - StrBufUrlescAppend(RedirectUrl, NULL, "nickname,email,fullname,postcode,country,dob,gender"); -*/ - - syslog(LOG_DEBUG, "\033[36m%s\033[0m", ChrPtr(RedirectUrl)); + /* Attribute Exchange + * See: + * http://openid.net/specs/openid-attribute-exchange-1_0.html + * http://code.google.com/apis/accounts/docs/OpenID.html#endpoint + * http://test-id.net/OP/AXFetch.aspx + */ + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ns.ax="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://openid.net/srv/ax/1.0"); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.mode=fetch_request"), 0); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.required=firstname,lastname,friendly,nickname"), 0); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.type.firstname="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://axschema.org/namePerson/first"); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.type.lastname="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://axschema.org/namePerson/last"); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.type.friendly="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://axschema.org/namePerson/friendly"); + + StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.ax.type.nickname="), 0); + StrBufUrlescAppend(RedirectUrl, NULL, "http://axschema.org/namePerson/nickname"); + + syslog(LOG_DEBUG, "OpenID: redirecting client to %s", ChrPtr(RedirectUrl)); cprintf("%d %s\n", CIT_OK, ChrPtr(RedirectUrl)); } @@ -951,6 +977,8 @@ void cmd_oidf(char *argbuf) { char thiskey[1024]; char thisdata[1024]; HashList *keys = NULL; + const char *Key; + void *Value; ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data; if (oiddata == NULL) { @@ -970,81 +998,69 @@ void cmd_oidf(char *argbuf) { while (client_getln(buf, sizeof buf), strcmp(buf, "000")) { len = extract_token(thiskey, buf, 0, '|', sizeof thiskey); - if (len < 0) + if (len < 0) { len = sizeof(thiskey) - 1; + } extract_token(thisdata, buf, 1, '|', sizeof thisdata); - syslog(LOG_DEBUG, "%s: ["SIZE_T_FMT"] %s", thiskey, strlen(thisdata), thisdata); Put(keys, thiskey, len, strdup(thisdata), NULL); } - /* Now that we have all of the parameters, we have to validate the signature against the server */ - syslog(LOG_DEBUG, "Validating signature..."); + /* Check to see if this is a correct response. + * Start with verified=1 but then set it to 0 if anything looks wrong. + */ + oiddata->verified = 1; + + char *openid_ns = NULL; + if ( (!GetHash(keys, "ns", 2, (void *) &openid_ns)) + || (strcasecmp(openid_ns, "http://specs.openid.net/auth/2.0")) + ) { + syslog(LOG_DEBUG, "This is not an an OpenID assertion"); + oiddata->verified = 0; + } + + char *openid_mode = NULL; + if ( (!GetHash(keys, "mode", 4, (void *) &openid_mode)) + || (strcasecmp(openid_mode, "id_res")) + ) { + oiddata->verified = 0; + } + + char *openid_claimed_id = NULL; + if (GetHash(keys, "claimed_id", 10, (void *) &openid_claimed_id)) { + FreeStrBuf(&oiddata->claimed_id); + oiddata->claimed_id = NewStrBufPlain(openid_claimed_id, -1); + syslog(LOG_DEBUG, "Provider is asserting the Claimed ID '%s'", ChrPtr(oiddata->claimed_id)); + } + + /* Validate the assertion against the server */ + syslog(LOG_DEBUG, "Validating..."); CURL *curl; CURLcode res; struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; char errmsg[1024] = ""; - char *o_assoc_handle = NULL; - char *o_sig = NULL; - char *o_signed = NULL; - int num_signed_values; - int i; - char k_keyname[128]; - char k_o_keyname[128]; - char *k_value = NULL; - StrBuf *ReplyBuf; + StrBuf *ReplyBuf = NewStrBuf(); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "openid.mode", CURLFORM_COPYCONTENTS, "check_authentication", - CURLFORM_END); - syslog(LOG_DEBUG, "%25s : %s", "openid.mode", "check_authentication"); - - if (GetHash(keys, "assoc_handle", 12, (void *) &o_assoc_handle)) { - curl_formadd(&formpost, &lastptr, - CURLFORM_COPYNAME, "openid.assoc_handle", - CURLFORM_COPYCONTENTS, o_assoc_handle, - CURLFORM_END); - syslog(LOG_DEBUG, "%25s : %s", "openid.assoc_handle", o_assoc_handle); - } - - if (GetHash(keys, "sig", 3, (void *) &o_sig)) { - curl_formadd(&formpost, &lastptr, - CURLFORM_COPYNAME, "openid.sig", - CURLFORM_COPYCONTENTS, o_sig, - CURLFORM_END); - syslog(LOG_DEBUG, "%25s : %s", "openid.sig", o_sig); - } - - if (GetHash(keys, "signed", 6, (void *) &o_signed)) { - curl_formadd(&formpost, &lastptr, - CURLFORM_COPYNAME, "openid.signed", - CURLFORM_COPYCONTENTS, o_signed, - CURLFORM_END); - syslog(LOG_DEBUG, "%25s : %s", "openid.signed", o_signed); - - num_signed_values = num_tokens(o_signed, ','); - for (i=0; iop_url)); @@ -1055,20 +1071,18 @@ void cmd_oidf(char *argbuf) { res = curl_easy_perform(curl); if (res) { syslog(LOG_DEBUG, "cmd_oidf() libcurl error %d: %s", res, errmsg); + oiddata->verified = 0; } curl_easy_cleanup(curl); curl_formfree(formpost); - - syslog(LOG_DEBUG, "\033[36m --- VALIDATION REPLY ---\n%s\033[0m", ChrPtr(ReplyBuf)); - - - if (cbmstrcasestr(ChrPtr(ReplyBuf), "is_valid:true")) { - oiddata->verified = 1; + /* syslog(LOG_DEBUG, "Validation reply: \n%s", ChrPtr(ReplyBuf)); */ + if (cbmstrcasestr(ChrPtr(ReplyBuf), "is_valid:true") == NULL) { + oiddata->verified = 0; } FreeStrBuf(&ReplyBuf); - syslog(LOG_DEBUG, "Authentication %s.", (oiddata->verified ? "succeeded" : "failed") ); + syslog(LOG_DEBUG, "OpenID authentication %s", (oiddata->verified ? "succeeded" : "failed") ); /* Respond to the client */ @@ -1134,7 +1148,7 @@ void cmd_oidf(char *argbuf) { else { cprintf("\n"); } - syslog(LOG_DEBUG, "The desired Simple Registration name is already taken."); + syslog(LOG_DEBUG, "The desired display name is already taken."); } } }