HashList *sreg_keys;
} ctdl_openid;
+enum {
+ openid_disco_none,
+ openid_disco_xrds,
+ openid_disco_html
+};
+
+
void Free_ctdl_openid(ctdl_openid **FreeMe)
{
if (*FreeMe == NULL) {
void cmd_oidc(char *argbuf) {
ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data;
- if (!oiddata) {
- cprintf("%d You have not verified an OpenID yet.\n", ERROR);
- return;
- }
-
- if (!oiddata->verified) {
+ if ( (!oiddata) || (!oiddata->verified) ) {
cprintf("%d You have not verified an OpenID yet.\n", ERROR);
return;
}
}
-
/*
* Attempt to auto-create a new Citadel account using the nickname from Simple Registration Extension
*/
int nesting_level;
int in_xrd;
int current_service_priority;
- int selected_service_priority; /* FIXME more here later */
+ int selected_service_priority;
+ StrBuf *current_service_uri;
+ StrBuf *selected_service_uri;
+ int current_service_is_oid2auth;
};
if (!strcasecmp(supplied_el, "XRD")) {
++xrds->in_xrd;
- syslog(LOG_DEBUG, "*** XRD CONTAINER BEGIN ***");
}
else if (!strcasecmp(supplied_el, "service")) {
xrds->current_service_priority = 0;
+ xrds->current_service_is_oid2auth = 0;
for (i=0; attr[i] != NULL; i+=2) {
if (!strcasecmp(attr[i], "priority")) {
xrds->current_service_priority = atoi(attr[i+1]);
if (!strcasecmp(supplied_el, "XRD")) {
--xrds->in_xrd;
- syslog(LOG_DEBUG, "*** XRD CONTAINER END ***");
+ }
+
+ else if (!strcasecmp(supplied_el, "type")) {
+ if ( (xrds->in_xrd)
+ && (!strcasecmp(ChrPtr(xrds->CharData), "http://specs.openid.net/auth/2.0/server"))
+ ) {
+ xrds->current_service_is_oid2auth = 1;
+ }
+ }
+
+ else if (!strcasecmp(supplied_el, "uri")) {
+ if (xrds->in_xrd) {
+ FlushStrBuf(xrds->current_service_uri);
+ StrBufAppendBuf(xrds->current_service_uri, xrds->CharData, 0);
+ }
}
else if (!strcasecmp(supplied_el, "service")) {
- /* this is where we should evaluate the service and do stuff */
- xrds->current_service_priority = 0;
+ if ( (xrds->in_xrd)
+ && (xrds->current_service_priority < xrds->selected_service_priority)
+ && (xrds->current_service_is_oid2auth)
+ ) {
+ xrds->selected_service_priority = xrds->current_service_priority;
+ FlushStrBuf(xrds->selected_service_uri);
+ StrBufAppendBuf(xrds->selected_service_uri, xrds->current_service_uri, 0);
+ }
+
}
FlushStrBuf(xrds->CharData);
syslog(LOG_DEBUG, "\033[32m --- XRDS DOCUMENT --- \n%s\033[0m", ChrPtr(ReplyBuf));
memset(&xrds, 0, sizeof (struct xrds));
+ xrds.selected_service_priority = INT_MAX;
xrds.CharData = NewStrBuf();
+ xrds.current_service_uri = NewStrBuf();
+ xrds.selected_service_uri = NewStrBuf();
XML_Parser xp = XML_ParserCreate(NULL);
if (xp) {
XML_SetUserData(xp, &xrds);
else {
syslog(LOG_ALERT, "Cannot create XML parser");
}
- FreeStrBuf(&xrds.CharData);
- if (StrLength(oiddata->op_url) > 0) {
- syslog(LOG_DEBUG, "\033[31mOP VIA XRDS DISCO: %s\033[0m", ChrPtr(oiddata->op_url));
- return_value = 1;
+ if (xrds.selected_service_priority < INT_MAX) {
+ if (oiddata->op_url == NULL) {
+ oiddata->op_url = NewStrBuf();
+ }
+ FlushStrBuf(oiddata->op_url);
+ StrBufAppendBuf(oiddata->op_url, xrds.selected_service_uri, 0);
+ return_value = openid_disco_xrds;
}
+
+ FreeStrBuf(&xrds.CharData);
+ FreeStrBuf(&xrds.current_service_uri);
+ FreeStrBuf(&xrds.selected_service_uri);
+
return(return_value);
}
}
-
/* Attempt to perform Yadis discovery as specified in Yadis 1.0 section 6.2.5.
*
* If Yadis fails, we then attempt HTML discovery using the same document.
}
extract_link(oiddata->op_url, HKEY("openid2.provider"), ReplyBuf);
if (StrLength(oiddata->op_url) > 0) {
- syslog(LOG_DEBUG, "\033[31mOP VIA HTML DISCO: %s\033[0m", ChrPtr(oiddata->op_url));
- return_value = 1;
+ return_value = openid_disco_html;
}
}
StrBuf *ArgBuf = NULL;
StrBuf *ReplyBuf = NULL;
StrBuf *return_to = NULL;
- StrBuf *trust_root = NULL;
- StrBuf *openid_delegate = NULL;
StrBuf *RedirectUrl = NULL;
ctdl_openid *oiddata;
int discovery_succeeded = 0;
oiddata->verified = 0;
oiddata->claimed_id = NewStrBufPlain(NULL, StrLength(ArgBuf));
- trust_root = NewStrBufPlain(NULL, StrLength(ArgBuf));
return_to = NewStrBufPlain(NULL, StrLength(ArgBuf));
StrBufExtract_NextToken(oiddata->claimed_id, ArgBuf, &Pos, '|');
StrBufExtract_NextToken(return_to, ArgBuf, &Pos, '|');
- StrBufExtract_NextToken(trust_root, ArgBuf, &Pos, '|');
syslog(LOG_DEBUG, "User-Supplied Identifier is: %s", ChrPtr(oiddata->claimed_id));
-
/********** OpenID 2.0 section 7.3 - Discovery **********/
/* Section 7.3.1 says we have to attempt XRI based discovery.
*/
discovery_succeeded = perform_openid2_discovery(oiddata->claimed_id);
- if (StrLength(oiddata->op_url) == 0) {
+ if (discovery_succeeded == 0) {
cprintf("%d There is no OpenID identity provider at this location.\n", ERROR);
}
/*
* If we get to this point we are in possession of a valid OpenID Provider URL.
*/
+ syslog(LOG_DEBUG, "OP URI '%s' discovered using method %d",
+ ChrPtr(oiddata->op_url),
+ discovery_succeeded
+ );
- /* Empty delegate is legal; we just use the openid_url instead */
- if (StrLength(openid_delegate) == 0) {
- StrBufPlain(openid_delegate, SKEY(oiddata->claimed_id));
+ /* We have to "normalize" our Claimed ID otherwise it will cause some OP's to barf */
+ if (cbmstrcasestr(ChrPtr(oiddata->claimed_id), "://") == NULL) {
+ StrBuf *cid = oiddata->claimed_id;
+ oiddata->claimed_id = NewStrBufPlain(HKEY("http://"));
+ StrBufAppendBuf(oiddata->claimed_id, cid, 0);
+ FreeStrBuf(&cid);
}
- /* Assemble a URL to which the user-agent will be redirected. */
+ /*
+ * OpenID 2.0 section 9: request authentication
+ * Assemble a URL to which the user-agent will be redirected.
+ */
RedirectUrl = NewStrBufDup(oiddata->op_url);
-
- StrBufAppendBufPlain(RedirectUrl, HKEY("?openid.mode=checkid_setup&openid.identity="), 0);
- StrBufUrlescAppend(RedirectUrl, openid_delegate, NULL);
-
+
+ StrBufAppendBufPlain(RedirectUrl, HKEY("?openid.ns=http:%2F%2Fspecs.openid.net%2Fauth%2F2.0"), 0);
+
+ StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.mode=checkid_setup"), 0);
+
+ StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.claimed_id="), 0);
+ StrBufUrlescAppend(RedirectUrl, oiddata->claimed_id, NULL);
+
+ StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.identity="), 0);
+ StrBufUrlescAppend(RedirectUrl, oiddata->claimed_id, NULL);
+
StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.return_to="), 0);
StrBufUrlescAppend(RedirectUrl, return_to, NULL);
-
- StrBufAppendBufPlain(RedirectUrl, HKEY("&openid.trust_root="), 0);
- StrBufUrlescAppend(RedirectUrl, trust_root, 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));
cprintf("%d %s\n", CIT_OK, ChrPtr(RedirectUrl));
}
FreeStrBuf(&ArgBuf);
FreeStrBuf(&ReplyBuf);
FreeStrBuf(&return_to);
- FreeStrBuf(&trust_root);
- FreeStrBuf(&openid_delegate);
FreeStrBuf(&RedirectUrl);
}
-
-
-
/*
* Finalize an OpenID authentication
*/
return;
}
if (StrLength(oiddata->op_url) == 0){
- cprintf("%d need a remote server to authenticate against\n", ERROR + ILLEGAL_VALUE);
+ cprintf("%d No OpenID Endpoint URL has been obtained.\n", ERROR + ILLEGAL_VALUE);
return;
}
keys = NewHash(1, NULL);
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);
}
+ /* Check to see if this is a correct response */
+
+ /* oooh, really bad juju here. we're just accepting the assertion without validating it. */
+ 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));
+ }
+#if 0
/* Now that we have all of the parameters, we have to validate the signature against the server */
- syslog(LOG_DEBUG, "About to validate the signature...");
+ syslog(LOG_DEBUG, "Validating signature...");
CURL *curl;
CURLcode res;
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;
}
FreeStrBuf(&ReplyBuf);
syslog(LOG_DEBUG, "Authentication %s.", (oiddata->verified ? "succeeded" : "failed") );
+#endif
/* Respond to the client */