]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/openid/serv_openid_rp.c
* cmd_oidf(): if we don't have ha Server to authenticate against, bail with ILLEGAL_VALUE
[citadel.git] / citadel / modules / openid / serv_openid_rp.c
index 2fb909784a37cb1e940594f113aebd0497e7b107..16f189e0d2f58e2f04591bd14a8b226db709d12d 100644 (file)
@@ -3,6 +3,21 @@
  *
  * This is an implementation of OpenID 1.1 Relying Party support, in stateless mode.
  *
+ * Copyright (c) 2007-2009 by the citadel.org team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include "sysdep.h"
@@ -114,7 +129,7 @@ int attach_openid(struct ctdluser *who, char *claimed_id)
 
        snprintf(buf, sizeof buf, "User <%s> (#%ld) has claimed the OpenID URL %s\n",
                who->fullname, who->usernum, claimed_id);
-       aide_message(buf, "OpenID claim");
+       CtdlAideMessage(buf, "OpenID claim");
        CtdlLogPrintf(CTDL_INFO, "%s", buf);
        return(0);
 }
@@ -131,7 +146,8 @@ void openid_purge(struct ctdluser *usbuf) {
        char *deleteme = NULL;
        long len;
        void *Value;
-       char *Key;
+       const char *Key;
+       long usernum = 0L;
 
        keys = NewHash(1, NULL);
        if (!keys) return;
@@ -140,7 +156,8 @@ void openid_purge(struct ctdluser *usbuf) {
        cdb_rewind(CDB_OPENID);
        while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) {
                if (cdboi->len > sizeof(long)) {
-                       if (((long)*(cdboi->ptr)) == usbuf->usernum) {
+                       memcpy(&usernum, cdboi->ptr, sizeof(long));
+                       if (usernum == usbuf->usernum) {
                                deleteme = strdup(cdboi->ptr + sizeof(long)),
                                Put(keys, deleteme, strlen(deleteme), deleteme, generic_free_handler);
                        }
@@ -150,7 +167,7 @@ void openid_purge(struct ctdluser *usbuf) {
 
        /* Go through the hash list, deleting keys we stored in it */
 
-       HashPos = GetNewHashPos();
+       HashPos = GetNewHashPos(keys, 0);
        while (GetNextHashPos(keys, HashPos, &len, &Key, &Value)!=0)
        {
                CtdlLogPrintf(CTDL_DEBUG, "Deleting associated OpenID <%s>\n", Value);
@@ -168,6 +185,7 @@ void openid_purge(struct ctdluser *usbuf) {
  */
 void cmd_oidl(char *argbuf) {
        struct cdbdata *cdboi;
+       long usernum = 0L;
 
        if (CtdlAccessCheck(ac_logged_in)) return;
        cdb_rewind(CDB_OPENID);
@@ -175,7 +193,8 @@ void cmd_oidl(char *argbuf) {
 
        while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) {
                if (cdboi->len > sizeof(long)) {
-                       if (((long)*(cdboi->ptr)) == CC->user.usernum) {
+                       memcpy(&usernum, cdboi->ptr, sizeof(long));
+                       if (usernum == CC->user.usernum) {
                                cprintf("%s\n", cdboi->ptr + sizeof(long));
                        }
                }
@@ -185,6 +204,36 @@ void cmd_oidl(char *argbuf) {
 }
 
 
+/*
+ * List ALL OpenIDs in the database
+ */
+void cmd_oida(char *argbuf) {
+       struct cdbdata *cdboi;
+       long usernum;
+       struct ctdluser usbuf;
+
+       if (CtdlAccessCheck(ac_aide)) return;
+       cdb_rewind(CDB_OPENID);
+       cprintf("%d List of all OpenIDs in the database:\n", LISTING_FOLLOWS);
+
+       while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) {
+               if (cdboi->len > sizeof(long)) {
+                       memcpy(&usernum, cdboi->ptr, sizeof(long));
+                       if (CtdlGetUserByNumber(&usbuf, usernum) != 0) {
+                               usbuf.fullname[0] = 0;
+                       } 
+                       cprintf("%s|%ld|%s\n",
+                               cdboi->ptr + sizeof(long),
+                               usernum,
+                               usbuf.fullname
+                       );
+               }
+               cdb_free(cdboi);
+       }
+       cprintf("000\n");
+}
+
+
 /*
  * Attempt to register (populate the vCard) the currently-logged-in user
  * using the data from Simple Registration Extension, if present.
@@ -274,6 +323,11 @@ void populate_vcard_from_sreg(HashList *sreg_keys) {
 void cmd_oidc(char *argbuf) {
        struct ctdl_openid *oiddata = (struct ctdl_openid *) CC->openid_data;
 
+       if (!oiddata) {
+               cprintf("%d You have not verified an OpenID yet.\n", ERROR);
+               return;
+       }
+
        if (!oiddata->verified) {
                cprintf("%d You have not verified an OpenID yet.\n", ERROR);
                return;
@@ -304,6 +358,7 @@ void cmd_oidd(char *argbuf) {
        struct cdbdata *cdboi;
        char id_to_detach[1024];
        int this_is_mine = 0;
+       long usernum = 0L;
 
        if (CtdlAccessCheck(ac_logged_in)) return;
        extract_token(id_to_detach, argbuf, 0, '|', sizeof id_to_detach);
@@ -314,7 +369,8 @@ void cmd_oidd(char *argbuf) {
        cdb_rewind(CDB_OPENID);
        while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) {
                if (cdboi->len > sizeof(long)) {
-                       if (((long)*(cdboi->ptr)) == CC->user.usernum) {
+                       memcpy(&usernum, cdboi->ptr, sizeof(long));
+                       if (usernum == CC->user.usernum) {
                                this_is_mine = 1;
                        }
                }
@@ -348,7 +404,7 @@ int openid_create_user_via_sreg(char *claimed_id, HashList *sreg_keys)
 
        CtdlLogPrintf(CTDL_DEBUG, "The desired account name is <%s>\n", desired_name);
 
-       if (!getuser(&CC->user, desired_name)) {
+       if (!CtdlGetUser(&CC->user, desired_name)) {
                CtdlLogPrintf(CTDL_DEBUG, "<%s> is already taken by another user.\n", desired_name);
                memset(&CC->user, 0, sizeof(struct ctdluser));
                return(5);
@@ -382,7 +438,7 @@ int login_via_openid(char *claimed_id)
        memcpy(&usernum, cdboi->ptr, sizeof(long));
        cdb_free(cdboi);
 
-       if (!getuserbynumber(&CC->user, usernum)) {
+       if (!CtdlGetUserByNumber(&CC->user, usernum)) {
                /* Now become the user we just created */
                safestrncpy(CC->curr_user, CC->user.fullname, sizeof CC->curr_user);
                do_login();
@@ -409,7 +465,7 @@ int login_via_openid(char *claimed_id)
  */
 void extract_link(char *target_buf, int target_size, char *rel, char *source_buf)
 {
-       char *ptr = source_buf;
+       const char *ptr = source_buf;
 
        if (!target_buf) return;
        if (!rel) return;
@@ -437,7 +493,7 @@ void extract_link(char *target_buf, int target_size, char *rel, char *source_buf
                        if (len > sizeof work_buffer) len = sizeof work_buffer;
                        memcpy(work_buffer, link_tag_start, len);
                
-                       char *rel_start = NULL;
+                       const char *rel_start = NULL;
                        char *rel_end = NULL;
                        rel_start = bmstrcasestr(work_buffer, "rel=");
                        if (rel_start) {
@@ -540,7 +596,12 @@ int fetch_http(char *url, char *target_buf, int maxbytes, int normalize_len)
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fh_callback);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+#ifdef CURLOPT_HTTP_CONTENT_DECODING
+       curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 1);
+       curl_easy_setopt(curl, CURLOPT_ENCODING, "");
+#endif
        curl_easy_setopt(curl, CURLOPT_USERAGENT, CITADEL);
+       curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);           /* die after 180 seconds */
        if (!IsEmptyStr(config.c_ip_addr)) {
                curl_easy_setopt(curl, CURLOPT_INTERFACE, config.c_ip_addr);
        }
@@ -662,6 +723,10 @@ void cmd_oidf(char *argbuf) {
                cprintf("%d NewHash() failed\n", ERROR + INTERNAL_ERROR);
                return;
        }
+       if (IsEmptyStr(oiddata->server)){
+               cprintf("%d need a remote server to authenticate against\n", ERROR + ILLEGAL_VALUE);
+               return;
+       }
        
        cprintf("%d Transmit OpenID data now\n", START_CHAT_MODE);
 
@@ -755,7 +820,12 @@ void cmd_oidf(char *argbuf) {
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+#ifdef CURLOPT_HTTP_CONTENT_DECODING
+       curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 1);
+       curl_easy_setopt(curl, CURLOPT_ENCODING, "");
+#endif
        curl_easy_setopt(curl, CURLOPT_USERAGENT, CITADEL);
+       curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);           /* die after 180 seconds */
        if (!IsEmptyStr(config.c_ip_addr)) {
                curl_easy_setopt(curl, CURLOPT_INTERFACE, config.c_ip_addr);
        }
@@ -783,9 +853,11 @@ void cmd_oidf(char *argbuf) {
                if (CC->logged_in) {
                        if (attach_openid(&CC->user, oiddata->claimed_id) == 0) {
                                cprintf("attach\n");
+                               CtdlLogPrintf(CTDL_DEBUG, "OpenID attach succeeded\n");
                        }
                        else {
                                cprintf("fail\n");
+                               CtdlLogPrintf(CTDL_DEBUG, "OpenID attach failed\n");
                        }
                }
 
@@ -802,6 +874,7 @@ void cmd_oidf(char *argbuf) {
                        if (login_via_openid(oiddata->claimed_id) == 0) {
                                cprintf("authenticate\n%s\n%s\n", CC->user.fullname, CC->user.password);
                                logged_in_response();
+                               CtdlLogPrintf(CTDL_DEBUG, "Logged in using previously claimed OpenID\n");
                        }
 
                        /*
@@ -810,6 +883,7 @@ void cmd_oidf(char *argbuf) {
                         */
                        else if (config.c_disable_newu) {
                                cprintf("fail\n");
+                               CtdlLogPrintf(CTDL_DEBUG, "Creating user failed due to local policy\n");
                        }
 
                        /*
@@ -818,6 +892,7 @@ void cmd_oidf(char *argbuf) {
                        else if (openid_create_user_via_sreg(oiddata->claimed_id, keys) == 0) {
                                cprintf("authenticate\n%s\n%s\n", CC->user.fullname, CC->user.password);
                                logged_in_response();
+                               CtdlLogPrintf(CTDL_DEBUG, "Successfully auto-created new user\n");
                        }
 
                        /*
@@ -834,6 +909,7 @@ void cmd_oidf(char *argbuf) {
                                else {
                                        cprintf("\n");
                                }
+                               CtdlLogPrintf(CTDL_DEBUG, "The desired Simple Registration name is already taken.\n");
                        }
                }
        }
@@ -887,6 +963,7 @@ CTDL_MODULE_INIT(openid_rp)
                        CtdlRegisterProtoHook(cmd_oidl, "OIDL", "List OpenIDs associated with an account");
                        CtdlRegisterProtoHook(cmd_oidd, "OIDD", "Detach an OpenID from an account");
                        CtdlRegisterProtoHook(cmd_oidc, "OIDC", "Create new user after validating OpenID");
+                       CtdlRegisterProtoHook(cmd_oida, "OIDA", "List all OpenIDs in the database");
                }
                CtdlRegisterSessionHook(openid_cleanup_function, EVT_LOGOUT);
                CtdlRegisterUserHook(openid_purge, EVT_PURGEUSER);