port scott's cgiparse code into a C++ class.
authorDerek Atkins <derek@ihtfp.com>
Thu, 26 Feb 2004 16:06:26 +0000 (16:06 +0000)
committerDerek Atkins <derek@ihtfp.com>
Thu, 26 Feb 2004 16:06:26 +0000 (16:06 +0000)
Try to use that class in the apache2 world.
uncomment the default applications.xml in the .ini file
add more debugging in the shib-config.

note: this breaks apache2 completely!

apache-2.0/Makefile.am
apache-2.0/cgiparse.cpp [new file with mode: 0644]
apache-2.0/cgiparse.h [new file with mode: 0644]
apache-2.0/mod_shib.cpp
configs/shibboleth.ini.in
shib-target/shib-config.cpp

index 1b6fc49..bc0fed3 100644 (file)
@@ -9,7 +9,8 @@ endif
 modshibdir = $(libexecdir)
 modshib_LTLIBRARIES = mod_shib.la
 
-mod_shib_la_SOURCES = mod_shib.cpp
+mod_shib_la_SOURCES = mod_shib.cpp cgiparse.cpp
+noinst_HEADERS = cgiparse.h
 
 AM_CXXFLAGS = $(APXS2_CFLAGS) -I$(APXS2_INCLUDE) $(RPC_CFLAGS)
 
diff --git a/apache-2.0/cgiparse.cpp b/apache-2.0/cgiparse.cpp
new file mode 100644 (file)
index 0000000..07f9087
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* cgiparse.cpp - URL-encoded parameter parsing
+
+   Scott Cantor
+   7/6/03
+
+   Derek Atkins <derek@ihtfp.com>
+   2004-02-25
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <map>
+
+#include "cgiparse.h"
+
+using namespace shibtarget;
+using namespace std;
+
+class CgiParseImpl {
+public:
+  CgiParseImpl(string& cgi);
+  ~CgiParseImpl() {};
+  const char * get_value(const string& name) const;
+
+private:
+  map<string,string> kvp_map;
+};
+
+
+namespace {
+
+/* Parsing routines modified from NCSA source. */
+char *makeword(char *line, char stop)
+{
+    int x = 0,y;
+    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
+
+    for(x=0;((line[x]) && (line[x] != stop));x++)
+        word[x] = line[x];
+
+    word[x] = '\0';
+    if(line[x])
+        ++x;
+    y=0;
+
+    while(line[y++] = line[x++]);
+    return word;
+}
+
+char *fmakeword(char stop, int *cl, const char** ppch)
+{
+    int wsize;
+    char *word;
+    int ll;
+
+    wsize = 1024;
+    ll=0;
+    word = (char *) malloc(sizeof(char) * (wsize + 1));
+
+    while(1)
+    {
+        word[ll] = *((*ppch)++);
+        if(ll==wsize-1)
+        {
+            word[ll+1] = '\0';
+            wsize+=1024;
+            word = (char *)realloc(word,sizeof(char)*(wsize+1));
+        }
+        --(*cl);
+        if((word[ll] == stop) || word[ll] == EOF || (!(*cl)))
+        {
+            if(word[ll] != stop)
+                ll++;
+            word[ll] = '\0';
+            return word;
+        }
+        ++ll;
+    }
+}
+
+char x2c(char *what)
+{
+    register char digit;
+
+    digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
+    digit *= 16;
+    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
+    return(digit);
+}
+
+void unescape_url(char *url)
+{
+    register int x,y;
+
+    for(x=0,y=0;url[y];++x,++y)
+    {
+        if((url[x] = url[y]) == '%')
+        {
+            url[x] = x2c(&url[y+1]);
+            y+=2;
+        }
+    }
+    url[x] = '\0';
+}
+
+void plustospace(char *str)
+{
+    register int x;
+
+    for(x=0;str[x];x++)
+        if(str[x] == '+') str[x] = ' ';
+}
+
+};  // end of private namespace
+
+CgiParseImpl::CgiParseImpl(string& cgi)
+{
+    int cl;
+    const char* pch;
+
+#if 0
+    /* Verify method and content type. */
+    if(!stricmp(lpECB->lpszMethod,"POST"))
+    {
+        if (stricmp(lpECB->lpszContentType,"application/x-www-form-urlencoded"))
+            return NULL;
+        pch=lpECB->lpbData;
+        cl=lpECB->cbAvailable;
+    }
+    else if (!stricmp(lpECB->lpszMethod,"GET"))
+    {
+        pch=lpECB->lpszQueryString;
+        cl=strlen(pch);
+    }
+    else
+        return NULL;
+#endif
+
+    pch = cgi.c_str();
+    cl = strlen(pch);
+        
+    while (cl && pch)
+    {
+       char *name;
+       char *value;
+        value=fmakeword('&',&cl,&pch);
+        plustospace(value);
+        unescape_url(value);
+        name=makeword(value,'=');
+
+       kvp_map[name]=value;
+       free(name);
+       free(value);
+    }
+}
+
+
+const char *
+CgiParseImpl::get_value(const string& name) const
+{
+  map<string,string>::const_iterator i=kvp_map.find(name);
+  if (i==kvp_map.end())
+    return NULL;
+
+  return i->second.c_str();
+}
+
+CgiParse*
+CgiParse::ParseCGI(string& cgi)
+{
+  return (CgiParse*)(new CgiParseImpl(cgi));
+}
diff --git a/apache-2.0/cgiparse.h b/apache-2.0/cgiparse.h
new file mode 100644 (file)
index 0000000..689c1ce
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* cgiparse.h - URL-encoded parameter parsing
+
+   Scott Cantor
+   7/6/03
+
+   Derek Atkins <derek@ihtfp.com>
+   2004-02-25
+*/
+
+#ifndef __CGIPARSE__
+#define __CGIPARSE__
+
+#include <string>
+
+namespace shibtarget {
+
+  class CgiParse {
+  public:
+    virtual ~CgiParse() { };
+    virtual const char * get_value(const std::string& name) const = 0;
+
+    const char * get_value(const char* name) const {
+      std::string val(name ? name : "");
+      return get_value(val);
+    };
+
+    static CgiParse* ParseCGI(std::string& input);
+  };
+}  
+
+#endif /* __CGIPARSE__ */
index 56f621b..90b8814 100644 (file)
@@ -35,6 +35,8 @@
 //-- do we still need this? #undef _XOPEN_SOURCE               // bombs on solaris
 #include <apreq_params.h>
 
+#include "cgiparse.h"
+
 #include <unistd.h>            // for getpid()
 
 using namespace std;
@@ -558,6 +560,8 @@ extern "C" int shib_shire_handler (request_rec* r)
   ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
                "shire_post_handler() Beginning SHIRE POST processing");
       
+  CgiParse* cgi = NULL;
+
   try {
     string sslonly;
     if (!ini.get_tag(application_id, "shireSSLOnly", true, &sslonly))
@@ -587,23 +591,67 @@ extern "C" int shib_shire_handler (request_rec* r)
       throw ShibTargetException (SHIBRPC_OK,
                                 "blocked too-large a post to SHIRE POST processor");
 
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() about to run setup_client_block");
+
     // Read the posted data
-    apreq_request_t *ap_req = apreq_request(r, NULL);
-    if (!ap_req)
-      throw ShibTargetException (SHIBRPC_OK,
-                                apr_psprintf(r->pool, "apreq_request() failed"));
+    if (ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))
+      throw ShibTargetException (SHIBRPC_OK, "CGI setup_client_block failed");
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() about to run should_client_block");
+
+    if (!ap_should_client_block(r))
+      throw ShibTargetException (SHIBRPC_OK, "CGI should_client_block failed");
+
+    long length = r->remaining;
+    if (length > 1024*1024)
+      throw ShibTargetException (SHIBRPC_OK, "CGI length too long...");
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() about to read using get_client_block");
+    string cgistr;
+    char buff[BUFSIZ];
+    //ap_hard_timeout("[mod_shib] CGI Parser", r);
+
+    while (ap_get_client_block(r, buff, sizeof(buff)) > 0)
+      cgistr += buff;
+
+    //ap_kill_timeout(r);
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() about to parse cgi...");
+
+    cgi = CgiParse::ParseCGI(cgistr);
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() CGI parsed...");
+
+    if (!cgi)
+      throw ShibTargetException (SHIBRPC_OK, "CgiParse failed");
     
     // Make sure the target parameter exists
-    apreq_param_t *param = apreq_param(ap_req, "TARGET");
-    const char *target = param ? apreq_param_value(param) : NULL;
+    const string target_str = cgi->get_value("TARGET");
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() obtained target string from CGI...");
+
+    const char *target = target_str.c_str();
+
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() obtained target...");
+
     if (!target || *target == '\0')
       // invalid post
       throw ShibTargetException (SHIBRPC_OK,
                                 "SHIRE POST failed to find TARGET");
 
+    ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,0,r,
+                 "shire_post_handler() obtained target...");
+
     // Make sure the SAML Response parameter exists
-    param = apreq_param(ap_req, "SAMLResponse");
-    const char *post = param ? apreq_param_value(param) : NULL;
+    const string poststr = cgi->get_value("SAMLResponse");
+    const char *post = poststr.c_str();
     if (!post || *post == '\0')
       // invalid post
       throw ShibTargetException (SHIBRPC_OK,
@@ -667,6 +715,7 @@ extern "C" int shib_shire_handler (request_rec* r)
     // ... and redirect to the target
     char* redir=apr_pstrcat(r->pool,url_encode(r,target),NULL);
     apr_table_setn(r->headers_out, "Location", target);
+    delete cgi;
     return HTTP_MOVED_TEMPORARILY;
 
   } catch (ShibTargetException &e) {
@@ -676,6 +725,7 @@ extern "C" int shib_shire_handler (request_rec* r)
     markupProcessor.insert ("errorType", "SHIRE Processing Error");
     markupProcessor.insert ("errorText", e.what());
     markupProcessor.insert ("errorDesc", "An error occurred while processing your request.");
+    if (cgi) delete cgi;
     return shib_error_page (r, shireError.c_str(), markupProcessor);
   }
   catch (...) {
@@ -684,6 +734,7 @@ extern "C" int shib_shire_handler (request_rec* r)
     markupProcessor.insert ("errorType", "SHIRE Processing Error");
     markupProcessor.insert ("errorText", "Unexpected Exception");
     markupProcessor.insert ("errorDesc", "An error occurred while processing your request.");
+    if (cgi) delete cgi;
     return shib_error_page (r, shireError.c_str(), markupProcessor);
   }
 
index bef4887..b3fccbe 100644 (file)
@@ -32,7 +32,7 @@ logoLocation=/logo.gif
 
 [shire]
 logger=@-PKGSYSCONFDIR-@/shire.logger
-#applicationMap=@-PKGSYSCONFDIR-@/applications.xml
+applicationMap=@-PKGSYSCONFDIR-@/applications.xml
 
 [shar]
 logger=@-PKGSYSCONFDIR-@/shar.logger
index 0854e47..c200b3f 100644 (file)
@@ -305,19 +305,24 @@ void STConfig::init()
     delete iter;
   }
   
-  if (app == SHIBTARGET_SHIRE && ini->get_tag(app, SHIBTARGET_TAG_APPMAPPER, false, &tag)) {
-    saml::XML::registerSchema(shibtarget::XML::APPMAP_NS,shibtarget::XML::APPMAP_SCHEMA_ID);
-    try {
+  log.debug("about to test for AppMapper -- are we SHIRE...");
+  if (app == SHIBTARGET_SHIRE) {
+    log.debug("yep, we're a shire -- try loading the map...");
+    if (ini->get_tag(app, SHIBTARGET_TAG_APPMAPPER, false, &tag)) {
+      log.debug("loading Application Mapper");
+      saml::XML::registerSchema(shibtarget::XML::APPMAP_NS,shibtarget::XML::APPMAP_SCHEMA_ID);
+      try {
         auto_ptr_XMLCh src(tag.c_str());
         dummy->setAttributeNS(NULL,shibboleth::XML::Literals::url,src.get());
         m_applicationMapper=new XMLApplicationMapper(dummy);
         dynamic_cast<XMLApplicationMapper*>(m_applicationMapper)->getImplementation();
-    }
-    catch (exception& e) {
+      }
+      catch (exception& e) {
         log.crit("caught exception while loading URL->Application mapping file (%s)", e.what());
-    }
-    catch (...) {
+      }
+      catch (...) {
         log.crit("caught unknown exception while loading URL->Application mapping file");
+      }
     }
   }