New profile API, consolidated RPCs, simplified cache.
authorcantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Tue, 8 Feb 2005 21:29:16 +0000 (21:29 +0000)
committercantor <cantor@cb58f699-b61c-0410-a6fe-9272a202ed29>
Tue, 8 Feb 2005 21:29:16 +0000 (21:29 +0000)
git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@1349 cb58f699-b61c-0410-a6fe-9272a202ed29

28 files changed:
apache/mod_apache.cpp
isapi_shib/isapi_shib.cpp
shar/shar.cpp
shar/test-client.cpp
shar/testclient.dsp
shib-mysql-ccache/shib-mysql-ccache.cpp
shib-target/Makefile.am
shib-target/shib-ccache.cpp
shib-target/shib-config.cpp
shib-target/shib-ini.cpp
shib-target/shib-rpchandle.cpp
shib-target/shib-target.cpp
shib-target/shib-target.h
shib-target/shibrpc-clnt.c
shib-target/shibrpc-server-stubs.c
shib-target/shibrpc-server.cpp
shib-target/shibrpc-svc.c
shib-target/shibrpc-xdr.c
shib-target/shibrpc.h
shib-target/shibrpc.x
shib-target/shibtarget.dsp
shib/Makefile.am
shib/ShibBinding.cpp
shib/ShibBrowserProfile.cpp [new file with mode: 0644]
shib/ShibPOSTProfile.cpp [deleted file]
shib/shib.dsp
shib/shib.h
test/posttest.cpp

index e4f0d8a..5f423df 100644 (file)
@@ -378,10 +378,17 @@ public:
     return NULL;
   }
 
-  virtual void* sendPage(const string &msg, const string content_type,
-                        const pair<string, string> headers[], int code) {
+  virtual void* sendPage(
+    const string &msg,
+    const string content_type,
+       const saml::Iterator<header_t>& headers=EMPTY(header_t),
+    int code=200
+    ) {
     m_req->content_type = ap_psprintf(m_req->pool, content_type.c_str());
-    // XXX: push headers and code into the response
+    while (headers.hasNext()) {
+        const header_t& h=headers.next();
+        ap_table_setn(m_req->headers_out, h.first.c_str(), h.second.c_str());
+    }
     ap_send_http_header(m_req);
     ap_rprintf(m_req, msg.c_str());
     return (void*)DONE;
@@ -462,11 +469,11 @@ extern "C" int shib_post_handler(request_rec* r)
 #endif
     ShibTargetApache sta(r);
 
-    pair<bool,void*> res = sta.doHandlePOST();
+    pair<bool,void*> res = sta.doHandleProfile();
     if (res.first) return (int)res.second;
 
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r),
-                 "doHandlePOST() did not do anything.");
+                 "doHandleProfile() did not do anything.");
     return SERVER_ERROR;
 
 #ifndef _DEBUG
index 9e15c04..82b439b 100644 (file)
@@ -355,7 +355,7 @@ void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
 class ShibTargetIsapiF : public ShibTarget
 {
 public:
-  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPRC_HEADERS pn,
+  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn,
                   const site_t& site) {
 
     // URL path always come from IIS.
@@ -393,20 +393,17 @@ public:
   ~ShibTargetIsapiF() { }
 
   virtual void log(ShibLogLevel level, const string &msg) {
-    LogEvent(NULL, (level == LogLevelDebug : EVENTLOG_DEBUG_TYPE ?
-                   (level == LogLevelInfo : EVENTLOG_INFORMATION_TYPE ?
-                    (level == LogLevelWarn : EVENTLOG_WARNING_TYPE ?
-                     EVENTLOG_ERROR_TYPE))),
+      LogEvent(NULL, (level == LogLevelDebug ? EVENTLOG_INFORMATION_TYPE :
+                      (level == LogLevelInfo ? EVENTLOG_INFORMATION_TYPE :
+                      (level == LogLevelWarn ? EVENTLOG_WARNING_TYPE : EVENTLOG_ERROR_TYPE))),
             2100, NULL, msg.c_str());
   }
   virtual string getCookies(void) {
     dynabuf buf(128);
     GetHeader(m_pn, m_pfc, "Cookie:", buf, 128, false);
+    return buf.empty() ? "" : buf;
   }
-  // XXX: the filter never processes the POST.
-  //virtual void setCookie(const string &name, const string &value) {  }
-  //virtual string getArgs(void) {  }
-  //virtual string getPostData(void) {  }
+  
   virtual void clearHeader(const string &name) {
     string hdr = name + ":";
     m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), "");
@@ -419,7 +416,7 @@ public:
   virtual string getHeader(const string &name) {
     string hdr = name + ":";
     dynabuf buf(1024);
-    GetHeader(m_pn, m_pfc, hdr.c_str(), buf, 1024, false);
+    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 1024, false);
     return string(buf);
   }
   virtual void setRemoteUser(const string &user) {
@@ -429,15 +426,15 @@ public:
     return getHeader(string("remote-user"));
   }
   virtual void* sendPage(const string &msg, const string content_type,
-                        const pair<string, string> headers[], int code) {
+      const Iterator<header_t>& headers=EMPTY(header_t), int code=200) {
     string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
-    for (int k = 0; k < headers.size(); k++) {
-      hdr += headers[k].first + ": " + headers[k].second + "\r\n";
+    while (headers.hasNext()) {
+        const header_t& h=headers.next();
+        hdr += h.first + ": " + h.second + "\r\n";
     }
     hdr += "\r\n";
     // XXX Need to handle "code"
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "200 OK",
-                                (dword)hdr.c_str(), 0);
+    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "200 OK", (DWORD)hdr.c_str(), 0);
     DWORD resplen = msg.size();
     m_pfc->WriteClient(m_pfc, (LPVOID)msg.c_str(), &resplen, 0);
     return (void*)SF_STATUS_REQ_FINISHED;
@@ -454,14 +451,19 @@ public:
     static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
     DWORD resplen=40;
     m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
-    return SF_STATUS_REQ_FINISHED;
+    return reinterpret_cast<void*>(SF_STATUS_REQ_FINISHED);
   }
   // XXX: We might not ever hit the 'decline' status in this filter.
   //virtual void* returnDecline(void) { }
   virtual void* returnOK(void) { return (void*) SF_STATUS_REQ_NEXT_NOTIFICATION; }
 
+  // The filter never processes the POST, so stub these methods.
+  virtual void setCookie(const string &name, const string &value) { throw runtime_error("setCookie not implemented"); }
+  virtual string getArgs(void) { throw runtime_error("getArgs not implemented"); }
+  virtual string getPostData(void) { throw runtime_error("getPostData not implemented"); }
+  
   PHTTP_FILTER_CONTEXT m_pfc;
-  PHTTP_FILTER_PREPRC_HEADERS m_pn
+  PHTTP_FILTER_PREPROC_HEADERS m_pn;
 };
 
 DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
@@ -510,14 +512,14 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
        ShibTargetIsapiF stf(pfc, pn, map_i->second);
 
        // "false" because we don't override the Shib settings
-       pair<bool,void*> res = ste.doCheckAuthN();
+       pair<bool,void*> res = stf.doCheckAuthN();
        if (res.first) return (DWORD)res.second;
 
        // "false" because we don't override the Shib settings
-       res = ste.doExportAssertions();
+       res = stf.doExportAssertions();
        if (res.first) return (DWORD)res.second;
 
-       res = ste.doCheckAuthZ();
+       res = stf.doCheckAuthZ();
        if (res.first) return (DWORD)res.second;
 
         return SF_STATUS_REQ_NEXT_NOTIFICATION;
@@ -988,6 +990,23 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
 /****************************************************************************/
 // ISAPI Extension
 
+DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
+{
+    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
+    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
+    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
+    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
+    DWORD resplen=strlen(xmsg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
+    resplen=strlen(msg);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
+    static const char* xmsg2="</BODY></HTML>";
+    resplen=strlen(xmsg2);
+    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
+    return HSE_STATUS_SUCCESS;
+}
+
+
 class ShibTargetIsapiE : public ShibTarget
 {
 public:
@@ -1031,14 +1050,11 @@ public:
   ~ShibTargetIsapiE() { }
 
   virtual void log(ShibLogLevel level, const string &msg) {
-    LogEvent(NULL, (level == LogLevelDebug : EVENTLOG_DEBUG_TYPE ?
-                   (level == LogLevelInfo : EVENTLOG_INFORMATION_TYPE ?
-                    (level == LogLevelWarn : EVENTLOG_WARNING_TYPE ?
-                     EVENTLOG_ERROR_TYPE))),
+      LogEvent(NULL, (level == LogLevelDebug ? EVENTLOG_INFORMATION_TYPE :
+                        (level == LogLevelInfo ? EVENTLOG_INFORMATION_TYPE :
+                        (level == LogLevelWarn ? EVENTLOG_WARNING_TYPE : EVENTLOG_ERROR_TYPE))),
             2100, NULL, msg.c_str());
   }
-  // Not used in the extension.
-  //virtual string getCookies(void) { }
   virtual void setCookie(const string &name, const string &value) {
     // Set the cookie for later.  Use it during the redirect.
     m_cookie += "Set-Cookie: " + name + "=" + value + "\r\n";
@@ -1050,7 +1066,7 @@ public:
     if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
       throw ShibTargetException(SHIBRPC_OK,
                                "blocked too-large a post to SHIRE POST processor");
-    else if (m_lpECB->cbTotalBytes != lpECB->cbAvailable) {
+    else if (m_lpECB->cbTotalBytes != m_lpECB->cbAvailable) {
       string cgistr;
       char buf[8192];
       DWORD datalen=m_lpECB->cbTotalBytes;
@@ -1068,14 +1084,8 @@ public:
     else
       return string(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
   }
-  // Not used in the Extension
-  //virtual void clearHeader(const string &name) {  }
-  //virtual void setHeader(const string &name, const string &value) {  }
-  //virtual string getHeader(const string &name) {  }
-  //virtual void setRemoteUser(const string &user) { }
-  //virtual string getRemoteUser(void) { }
   virtual void* sendPage(const string &msg, const string content_type,
-                        const pair<string, string> headers[], int code) {
+                        const Iterator<header_t>& headers=EMPTY(header_t), int code=200) {
     string hdr = string ("Connection: close\r\nContent-type: ") + content_type + "\r\n";
     for (int k = 0; k < headers.size(); k++) {
       hdr += headers[k].first + ": " + headers[k].second + "\r\n";
@@ -1083,7 +1093,7 @@ public:
     hdr += "\r\n";
     // XXX Need to handle "code"
     m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
-                                  "200 OK", (LPDWORD)hdr.c_str());
+                                  "200 OK", 0, (LPDWORD)hdr.c_str());
     DWORD resplen = msg.size();
     m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)msg.c_str(), &resplen, HSE_IO_SYNC);
     return (void*)HSE_STATUS_SUCCESS;
@@ -1111,26 +1121,18 @@ public:
   }
   virtual void* returnOK(void) { return (void*) HSE_STATUS_SUCCESS; }
 
+  // Not used in the extension.
+  virtual string getCookies(void) { throw runtime_error("getCookies not implemented"); }
+  virtual void clearHeader(const string &name) { throw runtime_error("clearHeader not implemented"); }
+  virtual void setHeader(const string &name, const string &value) { throw runtime_error("setHeader not implemented"); }
+  virtual string getHeader(const string &name) { throw runtime_error("getHeader not implemented"); }
+  virtual void setRemoteUser(const string &user) { throw runtime_error("setRemoteUser not implemented"); }
+  virtual string getRemoteUser(void) { throw runtime_error("getRemoteUser not implemented"); }
+
   LPEXTENSION_CONTROL_BLOCK m_lpECB;
   string m_cookie;
 };
 
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
-{
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
-    resplen=strlen(msg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
-    static const char* xmsg2="</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);
-    return HSE_STATUS_SUCCESS;
-}
-
 extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
 {
     string targeturl;
@@ -1151,7 +1153,7 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
             return WriteClientError(lpECB, "Shibboleth Extension not configured for this web site.");
 
        ShibTargetIsapiE ste(lpECB, map_i->second);
-       pair<bool,void*> res = ste.doHandlePOST();
+       pair<bool,void*> res = ste.doHandleProfile();
        if (res.first) return (DWORD)res.second;
 
        return WriteClientError(lpECB, "Shibboleth Extension failed to process POST");
index fae5859..cd12cf1 100644 (file)
@@ -85,7 +85,7 @@ using namespace log4cpp;
 # define FD_SETSIZE 1024
 #endif
 
-extern "C" void shibrpc_prog_1(struct svc_req* rqstp, register SVCXPRT* transp);
+extern "C" void shibrpc_prog_2(struct svc_req* rqstp, register SVCXPRT* transp);
 
 int shar_run = 1;
 const char* shar_config = NULL;
@@ -154,7 +154,7 @@ int real_main(int preinit)
 {
     static IListener::ShibSocket sock;
     ShibRPCProtocols protos[1] = {
-        { SHIBRPC_PROG, SHIBRPC_VERS_1, shibrpc_prog_1 }
+        { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
     };
 
     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
index c54b84d..72ab5d6 100644 (file)
@@ -35,7 +35,7 @@ int main (int argc, char *argv[])
     return -2;
   }
 
-  CLIENT* clnt = listener->getClientHandle(sock,SHIBRPC_PROG, SHIBRPC_VERS_1);
+  CLIENT* clnt = listener->getClientHandle(sock,SHIBRPC_PROG, SHIBRPC_VERS_2);
   if (!clnt) {
     clnt_pcreateerror("shibrpc_client_create");
     cerr << "shibrpc_client_create failed\n";
@@ -43,7 +43,7 @@ int main (int argc, char *argv[])
   }
 
   res = start = 0;
-  clnt_stat = shibrpc_ping_1 (&start, &res, clnt);
+  clnt_stat = shibrpc_ping_2 (&start, &res, clnt);
 
   if (clnt_stat != RPC_SUCCESS) {
     clnt_perror (clnt, "rpc");
index 4ab92e0..03ff088 100644 (file)
@@ -59,16 +59,16 @@ LINK32=link.exe
 # PROP BASE Output_Dir "testclient___Win32_Debug"\r
 # PROP BASE Intermediate_Dir "testclient___Win32_Debug"\r
 # PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
+# PROP Use_MFC 2\r
 # PROP Use_Debug_Libraries 1\r
 # PROP Output_Dir "testclient___Win32_Debug"\r
 # PROP Intermediate_Dir "testclient___Win32_Debug"\r
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "../oncrpc" /I "..\..\..\opensaml\c" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "../oncrpc" /I "..\..\..\opensaml\c" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_AFXDLL" /FR /YX /FD /GZ /c\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"\r
 BSC32=bscmake.exe\r
 # ADD BASE BSC32 /nologo\r
 # ADD BSC32 /nologo\r
index 1a3029b..47baeaf 100644 (file)
@@ -78,10 +78,8 @@ public:
   virtual void unlock() { m_cacheEntry->unlock(); delete this; }
   virtual bool isValid(time_t lifetime, time_t timeout) const;
   virtual const char* getClientAddress() const { return m_cacheEntry->getClientAddress(); }
-  virtual const char* getSerializedStatement() const { return m_cacheEntry->getSerializedStatement(); }
-  virtual const SAMLAuthenticationStatement* getStatement() const { return m_cacheEntry->getStatement(); }
+  virtual const SAMLAuthenticationStatement* getAuthnStatement() const { return m_cacheEntry->getAuthnStatement(); }
   virtual Iterator<SAMLAssertion*> getAssertions() { return m_cacheEntry->getAssertions(); }
-  virtual void preFetch(int prefetch_window) { m_cacheEntry->preFetch(prefetch_window); }
 
 private:
   bool touch() const;
index db78557..eaf436e 100644 (file)
@@ -22,7 +22,6 @@ libshib_target_la_SOURCES = \
        shib-config.cpp \
        shib-ini.cpp \
        shib-mlp.cpp \
-       shib-rm.cpp \
        shib-rpcerror.cpp \
        shib-rpchandle.cpp \
        shib-sock.cpp \
index b5bec51..c6d9d0e 100644 (file)
@@ -131,11 +131,8 @@ public:
 
   bool isValid(time_t lifetime, time_t timeout) const;
   const char* getClientAddress() const { return m_clientAddress.c_str(); }
-  const char* getSerializedStatement() const { return m_statement.c_str(); }
-  const SAMLAuthenticationStatement* getStatement() const { return p_auth; }
-
+  const SAMLAuthenticationStatement* getAuthnStatement() const { return p_auth; }
   Iterator<SAMLAssertion*> getAssertions();
-  void preFetch(int prefetch_window);
 
   void setCache(InternalCCache *cache) { m_cache = cache; }
   time_t lastAccess() const { return m_lastAccess; }
@@ -143,13 +140,14 @@ public:
   bool checkApplication(const IApplication* application) { return (m_application_id==application->getId()); }
 
 private:
-  bool responseValid(int slop);
-  void populate(int slop);
-  SAMLResponse* getNewResponse();
+  void populate();                  // wraps process of checking cache, and repopulating if need be
+  bool responseValid();             // checks validity of existing response
+  SAMLResponse* getNewResponse();   // wraps an actual query
+  
+  void filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source);
   
   string m_id;
   string m_application_id;
-  string m_statement;
   string m_originSite;
   string m_clientAddress;
   time_t m_sessionCreated;
@@ -451,7 +449,12 @@ void* InternalCCache::cleanup_fcn(void* cache_p)
 /******************************************************************************/
 
 InternalCCacheEntry::InternalCCacheEntry(
-    const char* id, const IApplication* application, SAMLAuthenticationStatement *s, const char* client_addr, SAMLResponse* r, const IRoleDescriptor* source
+    const char* id,
+    const IApplication* application,
+    SAMLAuthenticationStatement *s,
+    const char* client_addr,
+    SAMLResponse* r,
+    const IRoleDescriptor* source
     ) : m_response(r), m_responseCreated(r ? time(NULL) : 0), m_lastRetry(0),
         log(&Category::getInstance("shibtarget::InternalCCacheEntry"))
 {
@@ -473,25 +476,9 @@ InternalCCacheEntry::InternalCCacheEntry(
   // Save for later.
   p_auth = s;
   
-  // Save the serialized version of the auth statement
-  ostringstream os;
-  os << *s;
-  m_statement = os.str();
-
-  if (r) {
-    // Run pushed data through the AAP. Note that we could end up with an empty response!
-    Iterator<SAMLAssertion*> assertions=r->getAssertions();
-    for (unsigned long i=0; i < assertions.size();) {
-        try {
-            AAP::apply(application->getAAPProviders(),*(assertions[i]),source);
-            i++;
-        }
-        catch (SAMLException&) {
-            log->info("no statements remain, removing assertion");
-            r->removeAssertion(i);
-        }
-    }
-  }
+  // If pushing attributes, filter the response.
+  if (r)
+    filter(r, application, source);
 
   m_lock = Mutex::create();
 
@@ -512,16 +499,21 @@ InternalCCacheEntry::~InternalCCacheEntry()
 
 bool InternalCCacheEntry::isValid(time_t lifetime, time_t timeout) const
 {
+#ifdef _DEBUG
   saml::NDC ndc("isValid");
-  log->debug("testing session (ID: %s) (lifetime=%ld, timeout=%ld)", m_id.c_str(), lifetime, timeout);
+#endif
+  
+  log->debug("testing session (ID: %s) (lifetime=%ld, timeout=%ld)",
+    m_id.c_str(), lifetime, timeout);
+    
   time_t now=time(NULL);
   if (lifetime > 0 && now > m_sessionCreated+lifetime) {
-    log->debug("session beyond lifetime (ID: %s)", m_id.c_str());
+    log->info("session beyond lifetime (ID: %s)", m_id.c_str());
     return false;
   }
 
   if (timeout > 0 && now-m_lastAccess >= timeout) {
-    log->debug("session timed out (ID: %s)", m_id.c_str());
+    log->info("session timed out (ID: %s)", m_id.c_str());
     return false;
   }
   m_lastAccess=now;
@@ -530,22 +522,20 @@ bool InternalCCacheEntry::isValid(time_t lifetime, time_t timeout) const
 
 Iterator<SAMLAssertion*> InternalCCacheEntry::getAssertions()
 {
+#ifdef _DEBUG
   saml::NDC ndc("getAssertions");
-  populate(0);
+#endif
+  populate();
   return (m_response) ? m_response->getAssertions() : EMPTY(SAMLAssertion*);
 }
 
-void InternalCCacheEntry::preFetch(int prefetch_window)
-{
-  saml::NDC ndc("preFetch");
-  populate(prefetch_window);
-}
-
-bool InternalCCacheEntry::responseValid(int slop)
+bool InternalCCacheEntry::responseValid()
 {
+#ifdef _DEBUG
   saml::NDC ndc("responseValid");
-
-  log->debug("checking AA response validity");
+#endif
+  log->debug("checking attribute data validity");
+  time_t now=time(NULL) - SAMLConfig::getConfig().clock_skew_secs;
 
   int count = 0;
   Iterator<SAMLAssertion*> iter = m_response->getAssertions();
@@ -562,7 +552,7 @@ bool InternalCCacheEntry::responseValid(int slop)
 
     count++;
 
-    if (time(NULL)+slop >= thistime->getEpoch()) {
+    if (now >= thistime->getEpoch()) {
       log->debug("nope, not still valid");
       return false;
     }
@@ -571,7 +561,7 @@ bool InternalCCacheEntry::responseValid(int slop)
   // If we didn't find any assertions with times, then see if we're
   // older than the default response lifetime.
   if (!count) {
-      if ((time(NULL)+slop - m_responseCreated) > m_cache->m_defaultLifetime) {
+      if ((now - m_responseCreated) > m_cache->m_defaultLifetime) {
         log->debug("response is beyond default life, so it's invalid");
         return false;
       }
@@ -581,15 +571,17 @@ bool InternalCCacheEntry::responseValid(int slop)
   return true;
 }
 
-void InternalCCacheEntry::populate(int slop)
+void InternalCCacheEntry::populate()
 {
+#ifdef _DEBUG
   saml::NDC ndc("populate");
+#endif
   log->debug("populating attributes for session (ID: %s)", m_id.c_str());
 
   // Do we have any data cached?
   if (m_response) {
       // Can we use what we have?
-      if (responseValid(slop))
+      if (responseValid())
         return;
       
       // If we're being strict, dump what we have and reset timestamps.
@@ -602,10 +594,7 @@ void InternalCCacheEntry::populate(int slop)
       }
   }
 
-  // Need to try and get a new response.
-
   try {
-
     // Transaction Logging
     STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
     stc.getTransactionLog().infoStream() <<
@@ -643,14 +632,17 @@ void InternalCCacheEntry::populate(int slop)
 
 SAMLResponse* InternalCCacheEntry::getNewResponse()
 {
+#ifdef _DEBUG
     saml::NDC ndc("getNewResponse");
+#endif
 
     // The retryInterval determines how often to poll an AA that might be down.
-    if ((time(NULL) - m_lastRetry) < m_cache->m_retryInterval)
+    time_t now=time(NULL);
+    if ((now - m_lastRetry) < m_cache->m_retryInterval)
         return NULL;
     if (m_lastRetry)
         log->debug("retry interval exceeded, so trying again");
-    m_lastRetry=time(NULL);
+    m_lastRetry=now;
     
     log->info("trying to get new attributes for session (ID=%s)", m_id.c_str());
 
@@ -668,10 +660,9 @@ SAMLResponse* InternalCCacheEntry::getNewResponse()
         throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to determine ProviderID for application, not set?");
     }
 
-    // Get signing policies.
+    // Get protocol signing policy.
     pair<bool,bool> signRequest=application->getBool("signRequest");
     pair<bool,bool> signedResponse=application->getBool("signedResponse");
-    pair<bool,bool> signedAssertions=application->getBool("signedAssertions");
     
     // Try this request. The binding wrapper class handles most of the details.
     Metadata m(application->getMetadataProviders());
@@ -688,7 +679,6 @@ SAMLResponse* InternalCCacheEntry::getNewResponse()
         throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate metadata for identity provider's Attribute Authority.",site);
     }
 
-
     SAMLResponse* response = NULL;
     try {
         // Build a SAML Request....
@@ -713,6 +703,16 @@ SAMLResponse* InternalCCacheEntry::getNewResponse()
         bindconf.conn_timeout=m_cache->m_AAConnectTimeout;
         ShibBinding binding(application->getRevocationProviders(),application->getTrustProviders(),conf->getCredentialsProviders());
         response=binding.send(*req,AA,application->getTLSCred(site),application->getAudiences(),p_auth->getBindings(),bindconf);
+
+        if (signedResponse.first && signedResponse.second && !response->isSigned()) {
+            delete response;
+            response=NULL;
+            log->error("unsigned response obtained, but we were told it must be signed.");
+        }
+        else {
+            // Run it through the filter. Note that we could end up with an empty response.
+            filter(response,application,AA);
+        }
     }
     catch (SAMLException& e) {
         log->error("caught SAML exception during query to AA: %s", e.what());
@@ -726,31 +726,56 @@ SAMLResponse* InternalCCacheEntry::getNewResponse()
     // See if we got a response.
     if (!response) {
         log->error("no response obtained");
-        throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's origin site.",AA);
-    }
-    else if (signedResponse.first && signedResponse.second && !response->isSigned()) {
-        delete response;
-        log->error("unsigned response obtained, but we were told it must be signed.");
-        throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's origin site.",AA);
+        throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to obtain attributes from user's identity provider.",AA);
     }
+    return response;
+}
+
+void InternalCCacheEntry::filter(SAMLResponse* r, const IApplication* application, const IRoleDescriptor* source)
+{
+    Trust t(application->getTrustProviders());
+    pair<bool,bool> signedAssertions=application->getBool("signedAssertions");
 
-    // Run it through the AAP. Note that we could end up with an empty response!
-    Iterator<SAMLAssertion*> a=response->getAssertions();
-    for (unsigned long i=0; i < a.size();) {
+    // Examine each new assertion...
+    Iterator<SAMLAssertion*> assertions=r->getAssertions();
+    for (unsigned long i=0; i < assertions.size();) {
         try {
-            if (signedAssertions.first && signedAssertions.second && !(a[i]->isSigned())) {
+            // Check signing policy.
+            if (signedAssertions.first && signedAssertions.second && !(assertions[i]->isSigned())) {
                 log->warn("removing unsigned assertion from response, in accordance with signedAssertions policy");
-                response->removeAssertion(i);
+                r->removeAssertion(i);
                 continue;
             }
-            AAP::apply(application->getAAPProviders(),*(a[i]),AA);
+
+            // Check any conditions.
+            bool pruned=false;
+            Iterator<SAMLCondition*> conds=assertions[i]->getConditions();
+            while (conds.hasNext()) {
+                SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
+                if (!cond || !cond->eval(application->getAudiences())) {
+                    log->warn("assertion condition invalid, removing it");
+                    r->removeAssertion(i);
+                    pruned=true;
+                    break;
+                }
+            }
+            if (pruned)
+                continue;
+            
+            // Check token signature.
+            if (assertions[i]->isSigned() && !t.validate(application->getRevocationProviders(),source,*(assertions[i]))) {
+                log->warn("signed assertion failed to validate, removing it");
+                r->removeAssertion(i);
+                continue;
+            }
+
+            // Finally, filter the content.
+            AAP::apply(application->getAAPProviders(),*(assertions[i]),source);
             i++;
         }
         catch (SAMLException&) {
-            log->info("no statements remain, removing assertion");
-            response->removeAssertion(i);
+            log->info("no statements remain after AAP, removing assertion");
+            r->removeAssertion(i);
         }
     }
-
-    return response;
 }
index 3b2aac9..03c7d85 100644 (file)
@@ -159,7 +159,9 @@ bool STConfig::init(const char* schemadir, const char* config)
         return false;
     }
 
+#ifndef _DEBUG
     try {
+#endif
         // Register plugin types.
 #ifndef WIN32
         samlConf.m_plugMgr.regFactory(shibtarget::XML::UnixListenerType,&UnixListenerFactory);
@@ -188,6 +190,7 @@ bool STConfig::init(const char* schemadir, const char* config)
         m_tranLogLock = Mutex::create();
 
         m_rpcpool = new RPCHandlePool;
+#ifndef _DEBUG
     }
     catch (...) {
         log.fatal("caught exception while loading/initializing configuration");
@@ -197,6 +200,7 @@ bool STConfig::init(const char* schemadir, const char* config)
         samlConf.term();
         return false;
     }
+#endif
   
     log.info("finished initializing");
 
index f5a9a05..12494f1 100644 (file)
@@ -74,7 +74,7 @@ namespace shibtarget {
     class XMLApplication : public virtual IApplication, public XMLPropertySet, public DOMNodeFilter
     {
     public:
-        XMLApplication(const DOMElement* e, const XMLApplication* base=NULL);
+        XMLApplication(const IConfig*, const DOMElement* e, const XMLApplication* base=NULL);
         ~XMLApplication();
     
         // IPropertySet
@@ -95,11 +95,13 @@ namespace shibtarget {
         Iterator<const XMLCh*> getAudiences() const;
         const char* getTLSCred(const IEntityDescriptor* provider) const {return getCredentialUse(provider).first.c_str();}
         const char* getSigningCred(const IEntityDescriptor* provider) const {return getCredentialUse(provider).second.c_str();}
+        SAMLBrowserProfile* getBrowserProfile() const {return m_profile;}
         
         // Provides filter to exclude special config elements.
         short acceptNode(const DOMNode* node) const;
     
     private:
+        const IConfig* m_ini;   // this is ok because its locking scope includes us
         const XMLApplication* m_base;
         vector<SAMLAttributeDesignator*> m_designators;
         vector<IAAP*> m_aaps;
@@ -108,6 +110,7 @@ namespace shibtarget {
         vector<IRevocation*> m_revocations;
         vector<const XMLCh*> m_audiences;
         pair<string,string> m_credDefault;
+        ShibBrowserProfile* m_profile;
 #ifdef HAVE_GOOD_STL
         map<xstring,pair<string,string> > m_credMap;
 #else
@@ -142,8 +145,8 @@ namespace shibtarget {
     class XMLConfig : public IConfig, public ReloadableXMLFile
     {
     public:
-        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e), m_listener(NULL), m_cache(NULL) {}
-        ~XMLConfig() {delete m_listener; delete m_cache;}
+        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e), m_listener(NULL), m_sessionCache(NULL), m_replayCache(NULL) {}
+        ~XMLConfig() {delete m_listener; delete m_sessionCache; delete m_replayCache;}
 
         // IPropertySet
         pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return static_cast<XMLConfigImpl*>(m_impl)->getBool(name,ns);}
@@ -156,7 +159,8 @@ namespace shibtarget {
 
         // IConfig
         const IListener* getListener() const {return m_listener;}
-        ISessionCache* getSessionCache() const {return m_cache;}
+        ISessionCache* getSessionCache() const {return m_sessionCache;}
+        IReplayCache* getReplayCache() const {return m_replayCache;}
         IRequestMapper* getRequestMapper() const {return static_cast<XMLConfigImpl*>(m_impl)->m_requestMapper;}
         const IApplication* getApplication(const char* applicationId) const
         {
@@ -172,7 +176,8 @@ namespace shibtarget {
     private:
         friend class XMLConfigImpl;
         mutable IListener* m_listener;
-        mutable ISessionCache* m_cache;
+        mutable ISessionCache* m_sessionCache;
+        mutable IReplayCache* m_replayCache;
     };
 }
 
@@ -347,7 +352,8 @@ const IPropertySet* XMLPropertySet::getPropertySet(const char* name, const char*
     return (i!=m_nested.end()) ? i->second : NULL;
 }
 
-XMLApplication::XMLApplication(const DOMElement* e, const XMLApplication* base) : m_base(base)
+XMLApplication::XMLApplication(const IConfig* ini, const DOMElement* e, const XMLApplication* base)
+    : m_ini(ini), m_base(base), m_profile(NULL)
 {
     NDC ndc("XMLApplication");
     Category& log=Category::getInstance("shibtarget.XMLApplication");
@@ -451,6 +457,15 @@ XMLApplication::XMLApplication(const DOMElement* e, const XMLApplication* base)
                 cu=saml::XML::getNextSiblingElement(cu,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(RelyingParty));
             }
         }
+        
+        if (conf.isEnabled(ShibTargetConfig::SessionCache)) {
+            // Really finally, build a local browser profile object.
+            m_profile=new ShibBrowserProfile(
+                getMetadataProviders(),
+                getRevocationProviders(),
+                getTrustProviders()
+                );
+        }
     }
     catch (...) {
         this->~XMLApplication();    // does this work?
@@ -460,6 +475,7 @@ XMLApplication::XMLApplication(const DOMElement* e, const XMLApplication* base)
 
 XMLApplication::~XMLApplication()
 {
+    delete m_profile;
     Iterator<SAMLAttributeDesignator*> i(m_designators);
     while (i.hasNext())
         delete i.next();
@@ -824,13 +840,17 @@ void XMLConfigImpl::init(bool first)
                 if (plugin) {
                     ISessionCache* cache=dynamic_cast<ISessionCache*>(plugin);
                     if (cache)
-                        m_outer->m_cache=cache;
+                        m_outer->m_sessionCache=cache;
                     else {
                         delete plugin;
                         log.fatal("plugin was not a Session Cache object");
                         throw UnsupportedExtensionException("plugin was not a Session Cache object");
                     }
                 }
+                
+                // For now, just default the replay cache.
+                // TODO: make it configurable/pluggable
+                m_outer->m_replayCache=IReplayCache::getInstance();
             }
         }
         
@@ -858,29 +878,8 @@ void XMLConfigImpl::init(bool first)
             }
         }
         
-        // Load the default application. This actually has a fixed ID of "default". ;-)
-        const DOMElement* app=saml::XML::getFirstChildElement(
-            ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Applications)
-            );
-        if (!app) {
-            log.fatal("can't build default Application object, missing conf:Applications element?");
-            throw SAMLException("can't build default Application object, missing conf:Applications element?");
-        }
-        XMLApplication* defapp=new XMLApplication(app);
-        m_appmap[defapp->getId()]=defapp;
-        
-        // Load any overrides.
-        DOMNodeList* nlist=app->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Application));
-        for (int i=0; nlist && i<nlist->getLength(); i++) {
-            XMLApplication* iapp=new XMLApplication(static_cast<DOMElement*>(nlist->item(i)),defapp);
-            if (m_appmap.find(iapp->getId())!=m_appmap.end()) {
-                log.fatal("found conf:Application element with duplicate Id attribute");
-                throw SAMLException("found conf:Application element with duplicate Id attribute");
-            }
-            m_appmap[iapp->getId()]=iapp;
-        }
-        
-        // Finally we load any credentials providers.
+        // Now we load any credentials providers.
+        DOMNodeList* nlist;
         if (conf.isEnabled(ShibTargetConfig::Credentials)) {
             nlist=ReloadableXMLFileImpl::m_root->getElementsByTagNameNS(
                 ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(CredentialsProvider)
@@ -901,6 +900,28 @@ void XMLConfigImpl::init(bool first)
                 }
             }
         }
+
+        // Load the default application. This actually has a fixed ID of "default". ;-)
+        const DOMElement* app=saml::XML::getFirstChildElement(
+            ReloadableXMLFileImpl::m_root,ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Applications)
+            );
+        if (!app) {
+            log.fatal("can't build default Application object, missing conf:Applications element?");
+            throw SAMLException("can't build default Application object, missing conf:Applications element?");
+        }
+        XMLApplication* defapp=new XMLApplication(m_outer, app);
+        m_appmap[defapp->getId()]=defapp;
+        
+        // Load any overrides.
+        nlist=app->getElementsByTagNameNS(ShibTargetConfig::SHIBTARGET_NS,SHIBT_L(Application));
+        for (int i=0; nlist && i<nlist->getLength(); i++) {
+            XMLApplication* iapp=new XMLApplication(m_outer,static_cast<DOMElement*>(nlist->item(i)),defapp);
+            if (m_appmap.find(iapp->getId())!=m_appmap.end()) {
+                log.fatal("found conf:Application element with duplicate Id attribute");
+                throw SAMLException("found conf:Application element with duplicate Id attribute");
+            }
+            m_appmap[iapp->getId()]=iapp;
+        }
     }
     catch (SAMLException& e) {
         log.errorStream() << "Error while loading target configuration: " << e.what() << CategoryStream::ENDLINE;
index c71d8e4..0b9ba12 100644 (file)
@@ -143,7 +143,7 @@ CLIENT* RPCHandle::connect()
         throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR, "Cannot connect to SHAR process, target site adminstrator should be notified");
     }
 
-    CLIENT *clnt = listener->getClientHandle(sock, SHIBRPC_PROG, SHIBRPC_VERS_1);
+    CLIENT *clnt = listener->getClientHandle(sock, SHIBRPC_PROG, SHIBRPC_VERS_2);
     if (!clnt) {
         const char* rpcerror = clnt_spcreateerror("RPCHandle::connect");
         log->crit("RPC failed for %p: %s", this, rpcerror);
index 28a261b..985b1d7 100644 (file)
@@ -107,17 +107,15 @@ namespace shibtarget {
     ~ShibTargetPriv();
 
     string url_encode(const char* s);
-    void get_application(string protocol, string hostname, int port, string uri);
+    void get_application(const string& protocol, const string& hostname, int port, const string& uri);
     void* sendError(ShibTarget* st, string page, ShibMLP &mlp);
     const char *getSessionId(ShibTarget* st);
-    bool get_assertions(ShibTarget *st, const char *session_id, ShibMLP &mlp);
 
     IRequestMapper::Settings m_settings;
     const IApplication *m_app;
     string m_cookieName;
     string m_shireURL;
     string m_authnRequest;
-    CgiParse* m_parser;
 
     const char *session_id;
     string m_cookies;
@@ -186,9 +184,11 @@ void ShibTarget::init(ShibTargetConfig *config,
 // The web server modules implement a subclass and then call into 
 // these methods once they instantiate their request object.
 pair<bool,void*>
-ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handlePost)
+ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handleProfile)
 {
+#ifdef _DEBUG
   saml::NDC ndc("ShibTarget::doCheckAuthN");
+#endif
 
   const char *targetURL = NULL;
   const char *procState = "Process Initialization Error";
@@ -204,10 +204,10 @@ ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handlePost)
       throw ShibTargetException(SHIBRPC_OK, "Cannot map target URL to Shire URL.  Check configuration");
 
     if (strstr(targetURL,shireURL)) {
-      if (handlePost)
-       return doHandlePOST();
+      if (handleProfile)
+        return doHandleProfile();
       else
-       return pair<bool,void*>(true, returnOK());
+        return pair<bool,void*>(true, returnOK());
     }
 
     string auth_type = getAuthType();
@@ -226,42 +226,40 @@ ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handlePost)
       // No session.  Maybe that's acceptable?
 
       if (!requireSession.second)
-       return pair<bool,void*>(true,returnOK());
+        return pair<bool,void*>(true,returnOK());
 
       // No cookie, but we require a session.  Generate an AuthnRequest.
       return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
     }
 
     procState = "Session Processing Error";
-    RPCError *status = sessionIsValid(session_id, m_priv->m_remote_addr.c_str());
+    RPCError *status = sessionGet(session_id, m_priv->m_remote_addr.c_str(), m_priv->m_assertions, &m_priv->m_sso_statement);
 
     if (status->isError()) {
 
       // If no session is required, bail now.
       if (!requireSession.second)
-       return pair<bool,void*>(true, returnOK());
+        return pair<bool,void*>(true, returnOK());
                           // XXX: Or should this be DECLINED?
                           // Has to be OK because DECLINED will just cause Apache
                           // to fail when it can't locate anything to process the
                           // AuthType.  No session plus requireSession false means
                           // do not authenticate the user at this time.
       else if (status->isRetryable()) {
-       // Session is invalid but we can retry the auth -- generate an AuthnRequest
-       delete status;
-       return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
+        // Session is invalid but we can retry the auth -- generate an AuthnRequest
+        delete status;
+        return pair<bool,void*>(true,sendRedirect(getAuthnRequest(targetURL)));
 
       } else {
-
-       string er = "Unretryable error: " ;
-       er += status->getText();
-       log(LogLevelError, er);
-       mlp.insert(*status);
-       delete status;
-       goto out;
+        string er = "Unretryable error: " ;
+        er += status->getText();
+        log(LogLevelError, er);
+        mlp.insert(*status);
+        delete status;
+        goto out;
       }
 
       delete status;
-      
     }
 
     // We're done.  Everything is okay.  Nothing to report.  Nothing to do..
@@ -290,9 +288,11 @@ ShibTarget::doCheckAuthN(bool requireSessionFlag, bool handlePost)
 }
 
 pair<bool,void*>
-ShibTarget::doHandlePOST(void)
+ShibTarget::doHandleProfile(void)
 {
-  saml::NDC ndc("ShibTarget::doHandlePOST");
+#ifdef _DEBUG
+  saml::NDC ndc("ShibTarget::doHandleProfile");
+#endif
 
   const char *targetURL = NULL;
   const char *procState = "Session Creation Service Error";
@@ -306,7 +306,7 @@ ShibTarget::doHandlePOST(void)
     const char *shireURL = getShireURL(targetURL);
 
     if (!shireURL)
-      throw ShibTargetException(SHIBRPC_OK, "doHandlePOST: unable to map request to a proper shireURL setting.  Check Configuration.");
+      throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to a proper shireURL setting.  Check Configuration.");
 
 
     // Make sure we only process the SHIRE requests.
@@ -315,7 +315,7 @@ ShibTarget::doHandlePOST(void)
 
     const IPropertySet* sessionProps=m_priv->m_app->getPropertySet("Sessions");
     if (!sessionProps)
-      throw ShibTargetException(SHIBRPC_OK, "doHandlePOST: unable to map request to application session settings.  Check configuration");
+      throw ShibTargetException(SHIBRPC_OK, "doHandleProfile() unable to map request to application session settings.  Check configuration");
 
     // this always returns something
     pair<const char*,const char*> shib_cookie=getCookieNameProps();
@@ -333,7 +333,7 @@ ShibTarget::doHandlePOST(void)
       string args = getArgs();
       const char* areq=args.empty() ? NULL : getLazyAuthnRequest(args.c_str());
       if (!areq)
-       throw ShibTargetException(SHIBRPC_OK, "malformed GET arguments to request a new session");
+        throw ShibTargetException(SHIBRPC_OK, "malformed GET arguments to request a new session");
       return pair<bool,void*>(true, sendRedirect(areq));
     }
     else if (strcasecmp(m_priv->m_method.c_str(), "POST")) {
@@ -342,44 +342,28 @@ ShibTarget::doHandlePOST(void)
 
     // Make sure this POST is an appropriate content type
     if (m_priv->m_content_type.empty() ||
-       strcasecmp(m_priv->m_content_type.c_str(),
-                  "application/x-www-form-urlencoded")) {
+        strcasecmp(m_priv->m_content_type.c_str(),"application/x-www-form-urlencoded")) {
       string er = string("blocked bad content-type to SHIRE POST processor: ") +
-       m_priv->m_content_type;
+        m_priv->m_content_type;
       throw ShibTargetException(SHIBRPC_OK, er.c_str());
     }
        
     // Read the POST Data
     string cgistr = getPostData();
 
-    // Parse the submission.
-    pair<const char*,const char*> elements =
-      getFormSubmission(cgistr.c_str(),cgistr.length());
-    
-    // Make sure the SAML Response parameter exists
-    if (!elements.first || !*elements.first)
-      throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find SAMLResponse form element");
-    
-    // Make sure the target parameter exists
-    if (!elements.second || !*elements.second)
-      throw ShibTargetException(SHIBRPC_OK, "SHIRE POST failed to find TARGET form element");
-    
-    // process the post
-    string cookie;
-    RPCError* status = sessionCreate(elements.first, m_priv->m_remote_addr.c_str(),
-                                    cookie);
+    // process the submission
+    string cookie,target;
+    RPCError* status = sessionNew(cgistr.c_str(), m_priv->m_remote_addr.c_str(),cookie,target);
 
     if (status->isError()) {
       char buf[25];
       sprintf(buf, "(%d): ", status->getCode());
-      string er = string("doHandlePost() POST process failed ") + buf +
-                        status->getText();
+      string er = string("doHandleProfile() profile processing failed ") + buf + status->getText();
       log(LogLevelError, er);
 
       if (status->isRetryable()) {
-       delete status;
-
-       return pair<bool,void*>(true, sendRedirect(getAuthnRequest(elements.second)));
+        delete status;
+        return pair<bool,void*>(true, sendRedirect(getAuthnRequest(target.c_str())));
       }
 
       // return this error to the user.
@@ -389,15 +373,14 @@ ShibTarget::doHandlePOST(void)
     }
     delete status;
 
-    log(LogLevelDebug,
-       string("doHandlePost() POST process succeeded. New session: ") + cookie);
+    log(LogLevelDebug, string("doHandleProfile() profile processing succeeded, new session(") + cookie + ")");
 
     // We've got a good session, set the cookie...
     cookie += shib_cookie.second;
     setCookie(shib_cookie.first, cookie);
 
     // ... and redirect to the target
-    return pair<bool,void*>(true, sendRedirect(elements.second));
+    return pair<bool,void*>(true, sendRedirect(target));
 
   } catch (ShibTargetException &e) {
     mlp.insert("errorText", e.what());
@@ -422,7 +405,9 @@ ShibTarget::doHandlePOST(void)
 pair<bool,void*>
 ShibTarget::doCheckAuthZ(void)
 {
+#ifdef _DEBUG
   saml::NDC ndc("ShibTarget::doCheckAuthZ");
+#endif
 
   ShibMLP mlp;
   const char *procState = "Authorization Processing Error";
@@ -437,17 +422,13 @@ ShibTarget::doCheckAuthZ(void)
     targetURL = m_priv->m_url.c_str();
     const char *session_id = m_priv->getSessionId(this);
 
-    // XXX: need to make sure that export assertions was already called.
-    //if (m_priv->get_assertions(this, session_id, mlp))
-    //goto out;
-
     // Do we have an access control plugin?
     if (m_priv->m_settings.second) {
       Locker acllock(m_priv->m_settings.second);
       if (!m_priv->m_settings.second->authorized(*m_priv->m_sso_statement,
                                                 m_priv->m_assertions)) {
-       log(LogLevelError, "doCheckAuthZ: access control provider denied access");
-       goto out;
+        log(LogLevelError, "doCheckAuthZ: access control provider denied access");
+        goto out;
       }
     }
 
@@ -476,162 +457,162 @@ ShibTarget::doCheckAuthZ(void)
       auth_OK[x] = false;
       HTAccessInfo::RequireLine *line = ht->elements[x];
       if (! line->use_line)
-       continue;
+        continue;
       method_restricted = true;
 
       const char *w = line->tokens[0].c_str();
 
       if (!strcasecmp(w,"Shibboleth")) {
-       // This is a dummy rule needed because Apache conflates authn and authz.
-       // Without some require rule, AuthType is ignored and no check_user hooks run.
-       CHECK_OK;
+        // This is a dummy rule needed because Apache conflates authn and authz.
+        // Without some require rule, AuthType is ignored and no check_user hooks run.
+        CHECK_OK;
       }
       else if (!strcmp(w,"valid-user")) {
-       log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
-       CHECK_OK;
+        log(LogLevelDebug, "doCheckAuthZ accepting valid-user");
+        CHECK_OK;
       }
       else if (!strcmp(w,"user") && !remote_user.empty()) {
-       bool regexp=false;
-       for (int i = 1; i < line->tokens.size(); i++) {
-         w = line->tokens[i].c_str();
-         if (*w == '~') {
-           regexp = true;
-           continue;
-         }
+        bool regexp=false;
+        for (int i = 1; i < line->tokens.size(); i++) {
+          w = line->tokens[i].c_str();
+          if (*w == '~') {
+            regexp = true;
+            continue;
+          }
                 
-         if (regexp) {
-           try {
-             // To do regex matching, we have to convert from UTF-8.
-             auto_ptr<XMLCh> trans(fromUTF8(w));
-             RegularExpression re(trans.get());
-             auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
-             if (re.matches(trans2.get())) {
-               log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
-               CHECK_OK;
-             }
-           }
-           catch (XMLException& ex) {
-             auto_ptr_char tmp(ex.getMessage());
-             log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
-                 + w + "): " + tmp.get());
-           }
-         }
-         else if (!strcmp(remote_user.c_str(), w)) {
-           log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
-           CHECK_OK;
-         }
-       }
+          if (regexp) {
+            try {
+              // To do regex matching, we have to convert from UTF-8.
+              auto_ptr<XMLCh> trans(fromUTF8(w));
+              RegularExpression re(trans.get());
+              auto_ptr<XMLCh> trans2(fromUTF8(remote_user.c_str()));
+              if (re.matches(trans2.get())) {
+                log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+                CHECK_OK;
+              }
+            }
+            catch (XMLException& ex) {
+              auto_ptr_char tmp(ex.getMessage());
+              log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+                 + w + "): " + tmp.get());
+            }
+          }
+          else if (!strcmp(remote_user.c_str(), w)) {
+            log(LogLevelDebug, string("doCheckAuthZ accepting user: ") + w);
+            CHECK_OK;
+          }
+        }
       }
       else if (!strcmp(w,"group")) {
-       grpstatus = getGroupTable(remote_user);
+        grpstatus = getGroupTable(remote_user);
 
-       if (!grpstatus) {
-         delete ht;
-         return pair<bool,void*>(true, returnDecline());
-       }
+        if (!grpstatus) {
+          delete ht;
+          return pair<bool,void*>(true, returnDecline());
+        }
     
-       for (int i = 1; i < line->tokens.size(); i++) {
-         w = line->tokens[i].c_str();
-         if (grpstatus->lookup(w)) {
-           log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
-           CHECK_OK;
-         }
-       }
-       delete grpstatus;
-       grpstatus = NULL;
+        for (int i = 1; i < line->tokens.size(); i++) {
+          w = line->tokens[i].c_str();
+          if (grpstatus->lookup(w)) {
+            log(LogLevelDebug, string("doCheckAuthZ accepting group: ") + w);
+            CHECK_OK;
+          }
+        }
+        delete grpstatus;
+        grpstatus = NULL;
       }
       else {
-       Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
-       AAP wrapper(provs, w);
-       if (wrapper.fail()) {
-         log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ")
-                                  + w);
-         continue;
-       }
-
-       bool regexp = false;
-       string vals = getHeader(wrapper->getHeader());
-       for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
-         w = line->tokens[i].c_str();
-         if (*w == '~') {
-           regexp = true;
-           continue;
-         }
+        Iterator<IAAP*> provs = m_priv->m_app->getAAPProviders();
+        AAP wrapper(provs, w);
+        if (wrapper.fail()) {
+          log(LogLevelWarn, string("doCheckAuthZ didn't recognize require rule: ")
+                                  + w);
+          continue;
+        }
 
-         try {
-           auto_ptr<RegularExpression> re;
-           if (regexp) {
-             delete re.release();
-             auto_ptr<XMLCh> trans(fromUTF8(w));
-             auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
-             re=temp;
-           }
+        bool regexp = false;
+        string vals = getHeader(wrapper->getHeader());
+        for (int i = 1; i < line->tokens.size() && !vals.empty(); i++) {
+          w = line->tokens[i].c_str();
+          if (*w == '~') {
+            regexp = true;
+            continue;
+          }
+
+          try {
+            auto_ptr<RegularExpression> re;
+            if (regexp) {
+              delete re.release();
+              auto_ptr<XMLCh> trans(fromUTF8(w));
+              auto_ptr<RegularExpression> temp(new RegularExpression(trans.get()));
+              re=temp;
+            }
                     
-           string vals_str(vals);
-           int j = 0;
-           for (int i = 0;  i < vals_str.length();  i++) {
-             if (vals_str.at(i) == ';') {
-               if (i == 0) {
-                 log(LogLevelError, string("doCheckAuthZ invalid header encoding")+
-                     vals + ": starts with a semicolon");
-                 goto out;
-               }
-
-               if (vals_str.at(i-1) == '\\') {
-                 vals_str.erase(i-1, 1);
-                 i--;
-                 continue;
-               }
-
-               string val = vals_str.substr(j, i-j);
-               j = i+1;
-               if (regexp) {
-                 auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
-                 if (re->matches(trans.get())) {
-                   log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                       ", got " + val + ": authorization granted");
-                   CHECK_OK;
-                 }
-               }
-               else if ((wrapper->getCaseSensitive() && val==w) ||
-                        (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
-                 log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                     ", got " + val + ": authorization granted.");
-                 CHECK_OK;
-               }
-               else {
-                 log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                     ", got " + val + ": authoritzation not granted.");
-               }
-             }
-           }
+            string vals_str(vals);
+            int j = 0;
+            for (int i = 0;  i < vals_str.length();  i++) {
+              if (vals_str.at(i) == ';') {
+                if (i == 0) {
+                  log(LogLevelError, string("doCheckAuthZ invalid header encoding")+
+                    vals + ": starts with a semicolon");
+                  goto out;
+                }
+
+                if (vals_str.at(i-1) == '\\') {
+                  vals_str.erase(i-1, 1);
+                  i--;
+                  continue;
+                }
+
+                string val = vals_str.substr(j, i-j);
+                j = i+1;
+                if (regexp) {
+                  auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+                  if (re->matches(trans.get())) {
+                    log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+                       ", got " + val + ": authorization granted");
+                    CHECK_OK;
+                  }
+                }
+                else if ((wrapper->getCaseSensitive() && val==w) ||
+                 (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+                  log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+                  ", got " + val + ": authorization granted.");
+                  CHECK_OK;
+                }
+                else {
+                    log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+                        ", got " + val + ": authoritzation not granted.");
+                }
+              }
+            }
     
-           string val = vals_str.substr(j, vals_str.length()-j);
-           if (regexp) {
-             auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
-             if (re->matches(trans.get())) {
-               log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                   ", got " + val + ": authorization granted.");
-               CHECK_OK;
-             }
-           }
-           else if ((wrapper->getCaseSensitive() && val==w) ||
-                    (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
-             log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                 ", got " + val + ": authorization granted");
-             CHECK_OK;
-           }
-           else {
-             log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
-                 ", got " + val + ": authorization not granted");
-           }
-         }
-         catch (XMLException& ex) {
-           auto_ptr_char tmp(ex.getMessage());
-           log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
-               + w + "): " + tmp.get());
-         }
-       }
+            string val = vals_str.substr(j, vals_str.length()-j);
+            if (regexp) {
+              auto_ptr<XMLCh> trans(fromUTF8(val.c_str()));
+              if (re->matches(trans.get())) {
+                log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+                    ", got " + val + ": authorization granted.");
+                CHECK_OK;
+              }
+            }
+            else if ((wrapper->getCaseSensitive() && val==w) ||
+                 (!wrapper->getCaseSensitive() && !strcasecmp(val.c_str(),w))) {
+              log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+              ", got " + val + ": authorization granted");
+              CHECK_OK;
+            }
+            else {
+              log(LogLevelDebug, string("doCheckAuthZ expecting ") + w +
+              ", got " + val + ": authorization not granted");
+            }
+          }
+          catch (XMLException& ex) {
+            auto_ptr_char tmp(ex.getMessage());
+            log(LogLevelError, string("doCheckAuthZ caught exception while parsing regular expression (")
+        + w + "): " + tmp.get());
+          }
+        }
       }
     } // for x
 
@@ -689,8 +670,20 @@ ShibTarget::doExportAssertions(bool exportAssertion)
     targetURL = m_priv->m_url.c_str();
     const char *session_id = m_priv->getSessionId(this);
 
-    if (m_priv->get_assertions(this, session_id, mlp))
-      goto out;
+    if (!m_priv->m_sso_statement) {
+        // No data yet, so we need to get the session. This can only happen
+        // if the call to doCheckAuthn doesn't happen in the same object lifetime.
+        RPCError* status = sessionGet(session_id, m_priv->m_remote_addr.c_str(), m_priv->m_assertions, &m_priv->m_sso_statement);
+        if (status->isError()) {
+            string er = "getAssertions failed: ";
+            er += status->getText();
+            log(ShibTarget::LogLevelError, er);
+            mlp.insert(*status);
+            delete status;
+            goto out;
+        }
+        delete status;
+    }
 
     // Get the AAP providers, which contain the attribute policy info.
     Iterator<IAAP*> provs=m_priv->m_app->getAAPProviders();
@@ -700,17 +693,17 @@ ShibTarget::doExportAssertions(bool exportAssertion)
       IAAP* aap=provs.next();
       aap->lock();
       try {
-       Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
-       while (rules.hasNext()) {
-         const char* header=rules.next()->getHeader();
-         if (header)
-           clearHeader(header);
-       }
+        Iterator<const IAttributeRule*> rules=aap->getAttributeRules();
+        while (rules.hasNext()) {
+          const char* header=rules.next()->getHeader();
+          if (header)
+            clearHeader(header);
+        }
       }
       catch(...) {
-       aap->unlock();
-       log(LogLevelError, "caught unexpected error while clearing headers");
-       throw;
+        aap->unlock();
+        log(LogLevelError, "caught unexpected error while clearing headers");
+        throw;
       }
       aap->unlock();
     }
@@ -721,10 +714,15 @@ ShibTarget::doExportAssertions(bool exportAssertion)
     pair<bool,bool> exp=m_priv->m_settings.first->getBool("exportAssertion");
     if (!exp.first || !exp.second)
       if (exportAssertion)
-       exp.second=true;
+        exp.second=true;
     if (exp.second && m_priv->m_assertions.size()) {
-      string assertion;
-      RM::serialize(*(m_priv->m_assertions[0]), assertion);
+      ostringstream os;
+      os << *(m_priv->m_assertions[0]);
+      unsigned int outlen;
+      char* assn = (char*)os.str().c_str();
+      XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(assn), os.str().length(), &outlen);
+      string assertion = (char*)serialized;
+      XMLString::release(&serialized);      
       setHeader("Shib-Attributes", assertion.c_str());
     }
 
@@ -746,9 +744,9 @@ ShibTarget::doExportAssertions(bool exportAssertion)
       auto_ptr_char nameid(m_priv->m_sso_statement->getSubject()->getNameIdentifier()->getName());
       setHeader("Shib-NameIdentifier-Format", form.get());
       if (!strcmp(wrapper->getHeader(),"REMOTE_USER"))
-       setRemoteUser(nameid.get());
+        setRemoteUser(nameid.get());
       else
-       setHeader(wrapper->getHeader(), nameid.get());
+        setHeader(wrapper->getHeader(), nameid.get());
     }
     
     clearHeader("Shib-Application-ID");
@@ -973,22 +971,16 @@ ShibTarget::getLazyAuthnRequest(const char* query_string) const
     return getAuthnRequest(target);
 }
         
-// Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
-std::pair<const char*,const char*>
-ShibTarget::getFormSubmission(const char* post, unsigned int len) const
-{
-    m_priv->m_parser = new CgiParse(post,len);
-    return pair<const char*,const char*>(m_priv->m_parser->get_value("SAMLResponse"),m_priv->m_parser->get_value("TARGET"));
-}
-        
 RPCError* 
-ShibTarget::sessionCreate(const char* response, const char* ip, std::string &cookie)
+ShibTarget::sessionNew(const char* packet, const char* ip, string& cookie, string& target)
   const
 {
+#ifdef _DEBUG
   saml::NDC ndc("sessionCreate");
-  Category& log = Category::getInstance("shibtarget.SHIRE");
+#endif
+  Category& log = Category::getInstance("shibtarget.ShibTarget");
 
-  if (!response || !*response) {
+  if (!packet || !*packet) {
     log.error ("Empty SAML response content");
     return new RPCError(-1,  "Empty SAML response content");
   }
@@ -998,10 +990,10 @@ ShibTarget::sessionCreate(const char* response, const char* ip, std::string &coo
     return new RPCError(-1, "Invalid IP address");
   }
   
-  shibrpc_new_session_args_1 arg;
-  arg.shire_location = (char*) m_priv->m_shireURL.c_str();
+  shibrpc_new_session_args_2 arg;
+  arg.recipient = (char*) m_priv->m_shireURL.c_str();
   arg.application_id = (char*) m_priv->m_app->getId();
-  arg.saml_post = (char*)response;
+  arg.packet = (char*)packet;
   arg.client_addr = (char*)ip;
   arg.checkIPAddress = true;
 
@@ -1014,7 +1006,7 @@ ShibTarget::sessionCreate(const char* response, const char* ip, std::string &coo
           arg.checkIPAddress = pcheck.second;
   }
 
-  shibrpc_new_session_ret_1 ret;
+  shibrpc_new_session_ret_2 ret;
   memset (&ret, 0, sizeof(ret));
 
   // Loop on the RPC in case we lost contact the first time through
@@ -1023,10 +1015,10 @@ ShibTarget::sessionCreate(const char* response, const char* ip, std::string &coo
   RPC rpc;
   do {
     clnt = rpc->connect();
-    clnt_stat status = shibrpc_new_session_1 (&arg, &ret, clnt);
+    clnt_stat status = shibrpc_new_session_2 (&arg, &ret, clnt);
     if (status != RPC_SUCCESS) {
       // FAILED.  Release, disconnect, and retry
-      log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_1"));
+      log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_2"));
       rpc->disconnect();
       if (retry)
         retry--;
@@ -1047,10 +1039,12 @@ ShibTarget::sessionCreate(const char* response, const char* ip, std::string &coo
   else {
     log.debug ("new cookie: %s", ret.cookie);
     cookie = ret.cookie;
+    if (ret.target)
+        target = ret.target;
     retval = new RPCError();
   }
 
-  clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_1, (caddr_t)&ret);
+  clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_2, (caddr_t)&ret);
   rpc.pool();
 
   log.debug("returning");
@@ -1058,16 +1052,23 @@ ShibTarget::sessionCreate(const char* response, const char* ip, std::string &coo
 }
 
 RPCError*
-ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
+ShibTarget::sessionGet(
+    const char* cookie,
+    const char* ip,
+    std::vector<saml::SAMLAssertion*>& assertions,
+    saml::SAMLAuthenticationStatement **statement
+    ) const
 {
-  saml::NDC ndc("sessionIsValid");
-  Category& log = Category::getInstance("shibtarget.SHIRE");
+#ifdef _DEBUG
+  saml::NDC ndc("sessionGet");
+#endif
+  Category& log = Category::getInstance("shibtarget.ShibTarget");
 
-  if (!session_id || !*session_id) {
+  if (!cookie || !*cookie) {
     log.error ("No cookie value was provided");
     return new RPCError(SHIBRPC_NO_SESSION, "No cookie value was provided");
   }
-  else if (strchr(session_id,'=')) {
+  else if (strchr(cookie,'=')) {
     log.error ("The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
     return new RPCError(SHIBRPC_INTERNAL_ERROR, "The cookie value wasn't extracted successfully, use a more unique cookie name for your installation.");
   }
@@ -1077,14 +1078,14 @@ ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
     return new RPCError(SHIBRPC_IPADDR_MISSING, "Invalid IP Address");
   }
 
-  log.info ("is session valid: %s", ip);
-  log.debug ("session cookie: %s", session_id);
+  log.info ("get session for client address (%s)", ip);
+  log.debug ("session cookie (%s)", cookie);
 
-  shibrpc_session_is_valid_args_1 arg;
+  shibrpc_get_session_args_2 arg;
 
-  arg.cookie.cookie = (char*)session_id;
-  arg.cookie.client_addr = (char *)ip;
-  arg.application_id = (char *)m_priv->m_app->getId();
+  arg.cookie = (char*)cookie;
+  arg.client_addr = (char*)ip;
+  arg.application_id = (char*)m_priv->m_app->getId();
   
   // Get rest of input from the application Session properties.
   arg.lifetime = 3600;
@@ -1103,7 +1104,7 @@ ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
           arg.checkIPAddress = pcheck.second;
   }
   
-  shibrpc_session_is_valid_ret_1 ret;
+  shibrpc_get_session_ret_2 ret;
   memset (&ret, 0, sizeof(ret));
 
   // Loop on the RPC in case we lost contact the first time through
@@ -1112,10 +1113,10 @@ ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
   RPC rpc;
   do {
     clnt = rpc->connect();
-    clnt_stat status = shibrpc_session_is_valid_1(&arg, &ret, clnt);
+    clnt_stat status = shibrpc_get_session_2(&arg, &ret, clnt);
     if (status != RPC_SUCCESS) {
       // FAILED.  Release, disconnect, and try again...
-      log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_session_is_valid_1"));
+      log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_session_2"));
       rpc->disconnect();
       if (retry)
           retry--;
@@ -1130,85 +1131,6 @@ ShibTarget::sessionIsValid(const char* session_id, const char* ip) const
 
   log.debug("RPC completed with status %d, %p", ret.status.status, this);
 
-  RPCError* retval;
-  if (ret.status.status)
-    retval = new RPCError(&ret.status);
-  else
-    retval = new RPCError();
-
-  clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_session_is_valid_ret_1, (caddr_t)&ret);
-  rpc.pool();
-
-  log.debug("returning");
-  return retval;
-}
-
-// RM APIS
-
-RPCError*
-ShibTarget::getAssertions(const char* cookie, const char* ip,
-                         std::vector<saml::SAMLAssertion*>& assertions,
-                         saml::SAMLAuthenticationStatement **statement
-                         ) const
-{
-  saml::NDC ndc("getAssertions");
-  Category& log=Category::getInstance("shibtarget.RM");
-  log.info("get assertions...");
-
-  if (!cookie || !*cookie) {
-    log.error ("No cookie value provided.");
-    return new RPCError(-1, "No cookie value provided.");
-  }
-
-  if (!ip || !*ip) {
-    log.error ("Invalid ip address");
-    return new RPCError(-1, "Invalid IP address");
-  }
-
-  log.debug("session cookie: %s", cookie);
-
-  shibrpc_get_assertions_args_1 arg;
-  arg.cookie.cookie = (char*)cookie;
-  arg.cookie.client_addr = (char*)ip;
-  arg.checkIPAddress = true;
-  arg.application_id = (char *)m_priv->m_app->getId();
-
-  log.info("request from %s for \"%s\"", ip, arg.application_id);
-
-  const IPropertySet* props=m_priv->m_app->getPropertySet("Sessions");
-  if (props) {
-      pair<bool,bool> pcheck=props->getBool("checkAddress");
-      if (pcheck.first)
-          arg.checkIPAddress = pcheck.second;
-  }
-
-  shibrpc_get_assertions_ret_1 ret;
-  memset (&ret, 0, sizeof(ret));
-
-  // Loop on the RPC in case we lost contact the first time through
-  int retry = 1;
-  CLIENT *clnt;
-  RPC rpc;
-  do {
-    clnt = rpc->connect();
-    clnt_stat status = shibrpc_get_assertions_1(&arg, &ret, clnt);
-    if (status != RPC_SUCCESS) {
-      // FAILED.  Release, disconnect, and try again.
-      log.debug("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_get_assertions_1"));
-      rpc->disconnect();
-      if (retry)
-        retry--;
-      else
-        return new RPCError(-1, "RPC Failure");
-    }
-    else {
-      // SUCCESS.  Release back into pool
-      retry = -1;
-    }
-  } while (retry>=0);
-
-  log.debug("RPC completed with status %d (%p)", ret.status.status, this);
-
   RPCError* retval = NULL;
   if (ret.status.status)
     retval = new RPCError(&ret.status);
@@ -1237,15 +1159,15 @@ ShibTarget::getAssertions(const char* cookie, const char* ip,
         }
       }
       catch (SAMLException& e) {
-       log.error ("SAML Exception: %s", e.what());
-       ostringstream os;
-               os << e;
-               throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str());
+        log.error ("SAML Exception: %s", e.what());
+        ostringstream os;
+        os << e;
+        throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str());
       }
       catch (XMLException& e) {
-               log.error ("XML Exception: %s", e.getMessage());
-               auto_ptr_char msg(e.getMessage());
-               throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
+        log.error ("XML Exception: %s", e.getMessage());
+        auto_ptr_char msg(e.getMessage());
+        throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
       }
     }
     catch (ShibTargetException &e) {
@@ -1256,54 +1178,29 @@ ShibTarget::getAssertions(const char* cookie, const char* ip,
       retval = new RPCError();
   }
 
-  clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_get_assertions_ret_1, (caddr_t)&ret);
+  clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_get_session_ret_2, (caddr_t)&ret);
   rpc.pool();
 
-  log.debug ("returning..");
+  log.debug("returning");
   return retval;
 }
 
-void
-ShibTarget::serialize(saml::SAMLAssertion &assertion, std::string &result)
-{
-  saml::NDC ndc("serialize");
-  Category& log=Category::getInstance("shibtarget.RM");
-
-  ostringstream os;
-  os << assertion;
-  unsigned int outlen;
-  char* assn = (char*) os.str().c_str();
-  XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(assn), os.str().length(), &outlen);
-  result = (char*) serialized;
-  XMLString::release(&serialized);
-}
-
-
 /*************************************************************************
  * Shib Target Private implementation
  */
 
-ShibTargetPriv::ShibTargetPriv() : m_parser(NULL), m_app(NULL), m_mapper(NULL),
-                                  m_conf(NULL), m_Config(NULL), m_assertions()
-{
-  session_id = NULL;
-  m_sso_statement = NULL;
-}
+ShibTargetPriv::ShibTargetPriv()
+    : m_app(NULL), m_mapper(NULL), m_conf(NULL), m_Config(NULL), session_id(NULL), m_sso_statement(NULL) {}
 
 ShibTargetPriv::~ShibTargetPriv()
 {
-  if (m_sso_statement) {
-    delete m_sso_statement;
-    m_sso_statement = NULL;
-  }
+  delete m_sso_statement;
+  m_sso_statement = NULL;
+
   for (int k = 0; k < m_assertions.size(); k++)
     delete m_assertions[k];
-  m_assertions = vector<SAMLAssertion*>(); 
+  m_assertions.clear();
 
-  if (m_parser) {
-    delete m_parser;
-    m_parser = NULL;
-  }
   if (m_mapper) {
     m_mapper->unlock();
     m_mapper = NULL;
@@ -1340,13 +1237,13 @@ ShibTargetPriv::url_encode(const char* s)
 }
 
 void
-ShibTargetPriv::get_application(string protocol, string hostname, int port,
-                               string uri)
+ShibTargetPriv::get_application(const string& protocol, const string& hostname, int port, const string& uri)
 {
   if (m_app)
     return;
 
   // XXX: Do we need to keep conf and mapper locked while we hold m_app?
+  // TODO: No, should be able to hold the conf but release the mapper.
 
   // We lock the configuration system for the duration.
   m_conf=m_Config->getINI();
@@ -1433,29 +1330,6 @@ ShibTargetPriv::getSessionId(ShibTarget* st)
   return session_id;
 }
 
-bool
-ShibTargetPriv::get_assertions(ShibTarget* st, const char *session_id, ShibMLP &mlp)
-{
-  if (m_sso_statement)
-    return false;
-
-  RPCError *status = NULL;
-  status = st->getAssertions(session_id, m_remote_addr.c_str(),
-                            m_assertions, &m_sso_statement);
-
-  if (status->isError()) {
-    string er = "getAssertions failed: ";
-    er += status->getText();
-    st->log(ShibTarget::LogLevelError, er);
-    mlp.insert(*status);
-    delete status;
-    return true;
-  }
-  delete status;
-  return false;
-}
-
-
 /*************************************************************************
  * CGI Parser implementation
  */
index 57e3a39..37b05cf 100644 (file)
@@ -194,16 +194,15 @@ namespace shibtarget {
         virtual saml::Iterator<const XMLCh*> getAudiences() const=0;
         virtual const char* getTLSCred(const shibboleth::IEntityDescriptor* provider) const=0;
         virtual const char* getSigningCred(const shibboleth::IEntityDescriptor* provider) const=0;
+        virtual saml::SAMLBrowserProfile* getBrowserProfile() const=0;
         virtual ~IApplication() {}
     };
 
-        struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
+    struct SHIBTARGET_EXPORTS ISessionCacheEntry : public virtual saml::ILockable
     {
         virtual bool isValid(time_t lifetime, time_t timeout) const=0;
         virtual const char* getClientAddress() const=0;
-        virtual const char* getSerializedStatement() const=0;
-        virtual const saml::SAMLAuthenticationStatement* getStatement() const=0;
-        virtual void preFetch(int prefetch_window)=0;
+        virtual const saml::SAMLAuthenticationStatement* getAuthnStatement() const=0;
         virtual saml::Iterator<saml::SAMLAssertion*> getAssertions()=0;
         virtual ~ISessionCacheEntry() {}
     };
@@ -230,6 +229,7 @@ namespace shibtarget {
     {
         virtual const IListener* getListener() const=0;
         virtual ISessionCache* getSessionCache() const=0;
+        virtual saml::IReplayCache* getReplayCache() const=0;
         virtual IRequestMapper* getRequestMapper() const=0;
         virtual const IApplication* getApplication(const char* applicationId) const=0;
         virtual saml::Iterator<shibboleth::ICredentials*> getCredentialsProviders() const=0;
@@ -271,24 +271,6 @@ namespace shibtarget {
         unsigned long m_features;
     };
 
-    class SHIBTARGET_EXPORTS RM
-    {
-    public:
-        RM(const IApplication* app) : m_app(app) {}
-        ~RM() {}
-    
-        RPCError* getAssertions(
-            const char* cookie,
-            const char* ip,
-            std::vector<saml::SAMLAssertion*>& assertions,
-            saml::SAMLAuthenticationStatement **statement = NULL
-            );
-        static void serialize(saml::SAMLAssertion &assertion, std::string &result);
-    
-    private:
-        const IApplication* m_app;
-    };
-
     class ShibMLPPriv;
     class SHIBTARGET_EXPORTS ShibMLP {
     public:
@@ -457,10 +439,11 @@ namespace shibtarget {
 
     // We're done.  Finish up.  Send either a result (error?) page or a redirect.
     // If there are no headers supplied assume the content-type == text/html
+    typedef std::pair<std::string, std::string> header_t;
     virtual void* sendPage(
                           const std::string &msg,
                           const std::string content_type = "text/html",
-                          const std::pair<std::string, std::string> headers[] = NULL,
+                          const saml::Iterator<header_t>& headers = EMPTY(header_t),
                           int code = 200
                           )=0;
     void* sendPage(const char *msg) {
@@ -500,14 +483,13 @@ namespace shibtarget {
     //   exportAssertion values passed in here are only used if the
     //   settings resource is negative.
     //
-    //   The handlePost argument declares whether doCheckAuthN() should
+    //   The handleProfile argument declares whether doCheckAuthN() should
     //   automatically call doHandlePOST() when it encounters a request for
     //   the ShireURL;  if false it will call returnOK() instead.
     //
-    std::pair<bool,void*> doCheckAuthN(bool requireSession = false,
-                                      bool handlePost = false);
-    std::pair<bool,void*> doHandlePOST(void);
-    std::pair<bool,void*> doCheckAuthZ(void);
+    std::pair<bool,void*> doCheckAuthN(bool requireSession = false, bool handleProfile = false);
+    std::pair<bool,void*> doHandleProfile();
+    std::pair<bool,void*> doCheckAuthZ();
     std::pair<bool,void*> doExportAssertions(bool exportAssertion = false);
 
     //**************************************************************************
@@ -528,30 +510,24 @@ namespace shibtarget {
     // Process a lazy session setup request and turn it into an AuthnRequest
     const char* getLazyAuthnRequest(const char* query_string) const;
         
-    // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
-    std::pair<const char*,const char*>
-      getFormSubmission(const char* post, unsigned int len) const;
-        
-    RPCError* sessionCreate(
-                           const char* response,
-                           const char* ip,
-                           std::string &cookie
-                           ) const;
-    RPCError* sessionIsValid(const char* session_id, const char* ip) const;
-
-    // RM APIS
-
-    RPCError* getAssertions(
-                           const char* cookie,
-                           const char* ip,
-                           std::vector<saml::SAMLAssertion*>& assertions,
-                           saml::SAMLAuthenticationStatement **statement = NULL
-                           ) const;
-    static void serialize(saml::SAMLAssertion &assertion, std::string &result);
-
-
   protected:
-    ShibTarget(void);
+    ShibTarget();
+
+    // Currently wraps remoted interface.
+    // TODO: Move this functionality behind ISessionCache
+    RPCError* sessionNew(
+               const char* packet,
+               const char* ip,
+               std::string& cookie,
+                std::string& target
+             ) const;
+
+    RPCError* sessionGet(
+             const char* cookie,
+               const char* ip,
+               std::vector<saml::SAMLAssertion*>& assertions,
+                saml::SAMLAuthenticationStatement **statement = NULL
+              ) const;
 
     // Initialize the request from the parsed URL
     // protocol == http, https, etc
@@ -567,52 +543,6 @@ namespace shibtarget {
   private:
     mutable ShibTargetPriv *m_priv;
   };
-
-  //******************************************************************************
-  // You probably don't care about much below this line
-  // unless you are using the lower-layer APIs provided by
-  // the shib target library.
-  /*
-    class SHIBTARGET_EXPORTS SHIRE
-    {
-    public:
-        SHIRE(const IApplication* app) { m_st = new ShibTarget(app); }
-        ~SHIRE() { delete m_st; }
-        
-        // Get the session cookie name and properties for the application
-        std::pair<const char*,const char*> getCookieNameProps() const
-         { return m_st->getCookieNameProps(); }
-        
-        // Find the default assertion consumer service for the resource
-        const char* getShireURL(const char* resource) const
-         { return m_st->getShireURL(resource); }
-        
-        // Generate a Shib 1.x AuthnRequest redirect URL for the resource
-        const char* getAuthnRequest(const char* resource) const
-         { return m_st->getAuthnRequest(resource); }
-        
-        // Process a lazy session setup request and turn it into an AuthnRequest
-        const char* getLazyAuthnRequest(const char* query_string) const
-         { return m_st->getLazyAuthnRequest(query_string); }
-        
-        // Process a POST profile submission, and return (SAMLResponse,TARGET) pair.
-        std::pair<const char*,const char*> getFormSubmission(const char* post, unsigned int len) const
-         { return m_st->getFormSubmission(post, len); }
-        
-        RPCError* sessionCreate(const char* response, const char* ip, std::string &cookie) const
-         { return m_st->sessionCreate(response, ip, cookie); }
-        RPCError* sessionIsValid(const char* session_id, const char* ip) const
-         { return m_st->sessionIsValid(session_id, ip); }
-    
-    private:
-       ShibTarget *m_st;
-        //const IApplication* m_app;
-        //mutable std::string m_cookieName;
-        //mutable std::string m_shireURL;
-        //mutable std::string m_authnRequest;
-        //mutable CgiParse* m_parser;
-    };
-    */
 }
 
 #endif /* SHIB_TARGET_H */
index 1794030..9b747de 100644 (file)
@@ -10,7 +10,7 @@
 static struct timeval TIMEOUT = { 25, 0 };
 
 enum clnt_stat 
-shibrpc_ping_1(int *argp, int *clnt_res, CLIENT *clnt)
+shibrpc_ping_2(int *argp, int *clnt_res, CLIENT *clnt)
 {
        return (clnt_call(clnt, shibrpc_ping,
                (xdrproc_t) xdr_int, (caddr_t) argp,
@@ -19,28 +19,19 @@ shibrpc_ping_1(int *argp, int *clnt_res, CLIENT *clnt)
 }
 
 enum clnt_stat 
-shibrpc_session_is_valid_1(shibrpc_session_is_valid_args_1 *argp, shibrpc_session_is_valid_ret_1 *clnt_res, CLIENT *clnt)
-{
-       return (clnt_call(clnt, shibrpc_session_is_valid,
-               (xdrproc_t) xdr_shibrpc_session_is_valid_args_1, (caddr_t) argp,
-               (xdrproc_t) xdr_shibrpc_session_is_valid_ret_1, (caddr_t) clnt_res,
-               TIMEOUT));
-}
-
-enum clnt_stat 
-shibrpc_new_session_1(shibrpc_new_session_args_1 *argp, shibrpc_new_session_ret_1 *clnt_res, CLIENT *clnt)
+shibrpc_new_session_2(shibrpc_new_session_args_2 *argp, shibrpc_new_session_ret_2 *clnt_res, CLIENT *clnt)
 {
        return (clnt_call(clnt, shibrpc_new_session,
-               (xdrproc_t) xdr_shibrpc_new_session_args_1, (caddr_t) argp,
-               (xdrproc_t) xdr_shibrpc_new_session_ret_1, (caddr_t) clnt_res,
+               (xdrproc_t) xdr_shibrpc_new_session_args_2, (caddr_t) argp,
+               (xdrproc_t) xdr_shibrpc_new_session_ret_2, (caddr_t) clnt_res,
                TIMEOUT));
 }
 
 enum clnt_stat 
-shibrpc_get_assertions_1(shibrpc_get_assertions_args_1 *argp, shibrpc_get_assertions_ret_1 *clnt_res, CLIENT *clnt)
+shibrpc_get_session_2(shibrpc_get_session_args_2 *argp, shibrpc_get_session_ret_2 *clnt_res, CLIENT *clnt)
 {
-       return (clnt_call(clnt, shibrpc_get_assertions,
-               (xdrproc_t) xdr_shibrpc_get_assertions_args_1, (caddr_t) argp,
-               (xdrproc_t) xdr_shibrpc_get_assertions_ret_1, (caddr_t) clnt_res,
+       return (clnt_call(clnt, shibrpc_get_session,
+               (xdrproc_t) xdr_shibrpc_get_session_args_2, (caddr_t) argp,
+               (xdrproc_t) xdr_shibrpc_get_session_ret_2, (caddr_t) clnt_res,
                TIMEOUT));
 }
index 29df71f..b99cea2 100644 (file)
@@ -7,7 +7,7 @@
 #include "shibrpc.h"
 
 bool_t
-shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
+shibrpc_ping_2_svc(int *argp, int *result, struct svc_req *rqstp)
 {
        bool_t retval;
 
@@ -19,7 +19,7 @@ shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
 }
 
 bool_t
-shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp, shibrpc_session_is_valid_ret_1 *result, struct svc_req *rqstp)
+shibrpc_new_session_2_svc(shibrpc_new_session_args_2 *argp, shibrpc_new_session_ret_2 *result, struct svc_req *rqstp)
 {
        bool_t retval;
 
@@ -31,19 +31,7 @@ shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp, shibrpc_se
 }
 
 bool_t
-shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp, shibrpc_new_session_ret_1 *result, struct svc_req *rqstp)
-{
-       bool_t retval;
-
-       /*
-        * insert server code here
-        */
-
-       return retval;
-}
-
-bool_t
-shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp, shibrpc_get_assertions_ret_1 *result, struct svc_req *rqstp)
+shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *argp, shibrpc_get_session_ret_2 *result, struct svc_req *rqstp)
 {
        bool_t retval;
 
@@ -55,7 +43,7 @@ shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp, shibrpc_get_as
 }
 
 int
-shibrpc_prog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
+shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
 {
        xdr_free (xdr_result, result);
 
index 3b0b08c..7694d38 100644 (file)
@@ -89,7 +89,7 @@ static Category& get_category (void)
 }
 
 extern "C" bool_t
-shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
+shibrpc_ping_2_svc(int *argp, int *result, struct svc_req *rqstp)
 {
   *result = (*argp)+1;
   return TRUE;
@@ -121,23 +121,12 @@ void set_rpc_status(ShibRpcError *error, ShibTargetException& exc)
   }
 }
 
-/*
-void set_rpc_status_x(ShibRpcError *error, ShibRpcStatus status,
-                        const char* msg=NULL, const XMLCh* origin=NULL)
-{
-  if (!status) {
-    set_rpc_status(error, status);
-    return;
-  }
-  auto_ptr_char orig(origin);
-  set_rpc_status(error, status, msg, orig.get());
-}
-*/
-
 extern "C" bool_t
-shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
-                              shibrpc_session_is_valid_ret_1 *result,
-                              struct svc_req *rqstp)
+shibrpc_get_session_2_svc(
+    shibrpc_get_session_args_2 *argp,
+    shibrpc_get_session_ret_2 *result,
+    struct svc_req *rqstp
+    )
 {
   Category& log = get_category();
   string ctx = get_threadid("session_is_valid");
@@ -149,12 +138,13 @@ shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
   }
 
   memset (result, 0, sizeof (*result));
+  result->auth_statement.xml_string = strdup("");
   
   log.debug ("checking: %s@%s (checkAddr=%s)",
-            argp->cookie.cookie, argp->cookie.client_addr,
-            argp->checkIPAddress ? "true" : "false");
+            argp->cookie, argp->client_addr, argp->checkIPAddress ? "true" : "false");
 
-  // See if the cookie exists...
+  // See if the session exists...
+  
   IConfig* conf=ShibTargetConfig::getConfig().getINI();
   Locker locker(conf);
   log.debug ("application: %s", argp->application_id);
@@ -166,76 +156,111 @@ shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
     return TRUE;
   }
 
-  ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie.cookie,app);
+  ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie,app);
 
   // If not, leave now..
   if (!entry) {
     log.debug ("Not found");
-    set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "No session exists for this cookie");
+    set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "No session exists for this key value");
     return TRUE;
   }
 
   // TEST the session...
   try {
     Metadata m(app->getMetadataProviders());
-    const IEntityDescriptor* origin=m.lookup(entry->getStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
+    const IEntityDescriptor* origin=m.lookup(entry->getAuthnStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
 
     // Verify the address is the same
     if (argp->checkIPAddress) {
       log.debug ("Checking address against %s", entry->getClientAddress());
-      if (strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
+      if (strcmp (argp->client_addr, entry->getClientAddress())) {
         log.debug ("IP Address mismatch");
         throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
-            "Your IP address does not match the address in the original authentication.", origin);
+            "Your IP address does not match the address recorded at the time the session was established.", origin);
       }
     }
 
     // and that the session is still valid...
     if (!entry->isValid(argp->lifetime, argp->timeout)) {
       log.debug ("Session expired");
-      throw ShibTargetException(SHIBRPC_SESSION_EXPIRED, "Your session has expired, must re-authenticate.", origin);
+      throw ShibTargetException(SHIBRPC_SESSION_EXPIRED, "Your session has expired, and you must re-authenticate.", origin);
     }
 
-    // and now try to prefetch the attributes .. this could cause an
-    // "error", which is why we call it here.
     try {
-      entry->preFetch(15);     // give a 15-second window for the RM
+      // Now grab the serialized authentication statement
+      ostringstream os;
+      os << *(entry->getAuthnStatement());
+      free(result->auth_statement.xml_string);
+      result->auth_statement.xml_string = strdup(os.str().c_str());
+     
+      // grab the attributes for this session
+      Iterator<SAMLAssertion*> iter = entry->getAssertions();
+      u_int size = iter.size();
+    
+      // if we have assertions...
+      if (size) {
+          // Build the response section
+          ShibRpcXML* av = (ShibRpcXML*) malloc (size * sizeof (ShibRpcXML));
+    
+          // and then serialize them all...
+          u_int i = 0;
+          while (iter.hasNext()) {
+            SAMLAssertion* as = iter.next();
+            ostringstream os2;
+            os2 << *as;
+            av[i++].xml_string = strdup(os2.str().c_str());
+          }
+    
+          // Set the results, once we know we've succeeded.
+          result->assertions.assertions_len = size;
+          result->assertions.assertions_val = av;
+      }
     }
     catch (SAMLException &e) {
-      log.debug ("prefetch failed with a SAML Exception: %s", e.what());
+      log.error ("caught SAML exception: %s", e.what());
       ostringstream os;
       os << e;
       throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), origin);
     }
-    catch (ShibTargetException&) {
-      // These are caught and handled down below.
-      throw;
-    }
-#ifndef _DEBUG
-    catch (...) {
-      log.error ("prefetch caught an unknown exception");
-      throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR,
-            "An unknown error occured while pre-fetching attributes.", origin);
-    }
-#endif
   }
   catch (ShibTargetException &e) {
-    entry->unlock();
-    conf->getSessionCache()->remove(argp->cookie.cookie);
-    set_rpc_status(&result->status, e);
-    // Transaction Logging
-    STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
-    stc.getTransactionLog().infoStream() <<
-        "Destroyed invalid session (ID: " <<
-            argp->cookie.cookie <<
-        ") with (applicationId: " <<
-            argp->application_id <<
-        "), request was from (ClientAddress: " <<
-            argp->cookie.client_addr <<
-        ")";
-    stc.releaseTransactionLog();
-    return TRUE;
+      entry->unlock();
+      log.error ("FAILED: %s", e.what());
+      conf->getSessionCache()->remove(argp->cookie);
+      set_rpc_status(&result->status, e);
+      // Transaction Logging
+      STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+      stc.getTransactionLog().infoStream() <<
+          "Destroyed invalid session (ID: " <<
+              argp->cookie <<
+          ") with (applicationId: " <<
+              argp->application_id <<
+          "), request was from (ClientAddress: " <<
+              argp->client_addr <<
+          ")";
+      stc.releaseTransactionLog();
+      return TRUE;
   }
+#ifndef _DEBUG
+  catch (...) {
+      entry->unlock();
+      log.error ("Unknown exception");
+      conf->getSessionCache()->remove(argp->cookie);
+      set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
+      // Transaction Logging
+      STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig());
+      stc.getTransactionLog().infoStream() <<
+          "Destroyed invalid session (ID: " <<
+              argp->cookie <<
+          ") with (applicationId: " <<
+              argp->application_id <<
+          "), request was from (ClientAddress: " <<
+              argp->client_addr <<
+          ")";
+      stc.releaseTransactionLog();
+      return TRUE;
+  }
+#endif
 
   // Ok, just release it.
   entry->unlock();
@@ -247,8 +272,11 @@ shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
 }
 
 extern "C" bool_t
-shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
-                         shibrpc_new_session_ret_1 *result, struct svc_req *rqstp)
+shibrpc_new_session_2_svc(
+    shibrpc_new_session_args_2 *argp,
+    shibrpc_new_session_ret_2 *result,
+    struct svc_req *rqstp
+    )
 {
   Category& log = get_category();
   string ctx=get_threadid("new_session");
@@ -262,13 +290,13 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
   // Initialize the result structure
   memset (result, 0, sizeof(*result));
   result->cookie = strdup ("");
+  result->target = strdup ("");
 
   log.debug ("creating session for %s", argp->client_addr);
-  log.debug ("shire location: %s", argp->shire_location);
+  log.debug ("recipient: %s", argp->recipient);
   log.debug ("application: %s", argp->application_id);
 
-  XMLByte* post=reinterpret_cast<XMLByte*>(argp->saml_post);
-  auto_ptr_XMLCh location(argp->shire_location);
+  auto_ptr_XMLCh recipient(argp->recipient);
 
   SAMLResponse* r = NULL;
   const SAMLAuthenticationStatement* auth_st = NULL;
@@ -285,6 +313,8 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
       return TRUE;
   }
 
+  // TODO: Sub in call to getReplayCache() as the determinant.
+  // For now, we always have a cache and use the flag...
   pair<bool,bool> checkReplay=pair<bool,bool>(false,false);
   const IPropertySet* props=app->getPropertySet("Sessions");
   if (props)
@@ -292,21 +322,24 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
  
   const IRoleDescriptor* role=NULL;
   Metadata m(app->getMetadataProviders());
+  SAMLBrowserProfile::BrowserProfileResponse bpr;
   try
   {
     if (!app)
         // Something's horribly wrong.
         throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,"Unable to locate application configuration, deleted?");
       
-    // And build the POST profile wrapper.
-    log.debug("create the POST profile");
-    ShibPOSTProfile profile(app->getMetadataProviders(),app->getRevocationProviders(),app->getTrustProviders());
-    
     try
     {
-      // Try and accept the response...
-      log.debug ("Trying to accept the post");
-      r = profile.accept(post,location.get(),300,app->getAudiences(),&origin);
+      // Try and run the profile.
+      log.debug ("Executing browser profile...");
+      bpr=app->getBrowserProfile()->receive(
+        &origin,
+        argp->packet,
+        recipient.get(),
+        SAMLBrowserProfile::Post,   // For now, we only handle POST.
+        (!checkReplay.first || checkReplay.second) ? conf->getReplayCache() : NULL
+        );
 
       // Try and map to metadata for support purposes.
       const IEntityDescriptor* provider=m.lookup(origin);
@@ -319,36 +352,13 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
         throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,
             "Unable to locate role-specific metadata for identity provider", provider);
     
-      // Make sure we got a response
-      if (!r)
-        throw ShibTargetException(SHIBRPC_RESPONSE_MISSING, "Failed to accept the response.", role);
-
-      // Find the SSO Assertion
-      log.debug ("Get the SSOAssertion");
-      const SAMLAssertion* ssoAssertion = profile.getSSOAssertion(*r,app->getAudiences());
-
-      // Check against the replay cache?
-      if (checkReplay.first && !checkReplay.second)
-        log.warn("replay checking is off, this is a security risk unless you're testing");
-      else {
-        log.debug ("check replay cache");
-        if (!profile.checkReplayCache(*ssoAssertion))
-            throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED, "Duplicate assertion detected.", role);
-      }
-
-      // Get the authentication statement we need.
-      log.debug ("get SSOStatement");
-      auth_st = profile.getSSOStatement(*ssoAssertion);
-
       // Maybe verify the origin address....
       if (argp->checkIPAddress) {
-        log.debug ("check IP Address");
+        log.debug ("verify client address");
 
         // Verify the client address exists
-        const XMLCh* ip = auth_st->getSubjectIP();
+        const XMLCh* ip = bpr.authnStatement->getSubjectIP();
         if (ip && *ip) {
-            log.debug ("verify client address");
-
             // Verify the client address matches authentication
             auto_ptr_char this_ip(ip);
             if (strcmp(argp->client_addr, this_ip.get()))
@@ -359,24 +369,46 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
                                     role);
         }
       }
+      
+      // Verify condition(s) on authentication assertion.
+      // Attribute assertions get filtered later, essentially just like an AAP.
+      Iterator<SAMLCondition*> conditions=bpr.assertion->getConditions();
+      while (conditions.hasNext()) {
+        SAMLCondition* cond=conditions.next();
+        const SAMLAudienceRestrictionCondition* ac=dynamic_cast<const SAMLAudienceRestrictionCondition*>(cond);
+        if (!ac) {
+            ostringstream os;
+            os << *cond;
+            log.error("Unrecognized Condition in authentication assertion (%s), tossing it.",os.str().c_str());
+            throw FatalProfileException("Unable to start session due to unrecognized condition in authentication assertion.");
+        }
+        else if (!ac->eval(app->getAudiences())) {
+            ostringstream os;
+            os << *ac;
+            log.error("Unacceptable AudienceRestrictionCondition in authentication assertion (%s), tossing it.",os.str().c_str());
+            throw FatalProfileException("Unable to start session due to unacceptable AudienceRestrictionCondition in authentication assertion.");
+        }
+      }
     }
-    catch (SAMLException &e)
-    {
+    catch (ReplayedAssertionException& e) {
+      // Specific case where we have an error code.
+      throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED, e.what(), role);
+    }
+    catch (SAMLException& e) {
       log.error ("caught SAML exception: %s", e.what());
       ostringstream os;
       os << e;
       throw ShibTargetException (SHIBRPC_SAML_EXCEPTION, os.str().c_str(), role);
     }
-    catch (XMLException &e)
-    {
-      log.error ("received XML exception");
+    catch (XMLException& e) {
+      log.error ("caught XML exception");
       auto_ptr_char msg(e.getMessage());
       throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get(), role);
     }
   }
-  catch (ShibTargetException &e) {
-    log.info ("FAILED: %s", e.what());
-    delete r;
+  catch (ShibTargetExceptione) {
+    log.error ("FAILED: %s", e.what());
+    bpr.clear();
     if (origin) XMLString::release(&origin);
     set_rpc_status(&result->status, e);
     return TRUE;
@@ -384,7 +416,7 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
 #ifndef _DEBUG
   catch (...) {
     log.error ("Unknown error");
-    delete r;
+    bpr.clear();
     if (origin) XMLString::release(&origin);
     set_rpc_status(&result->status, SHIBRPC_UNKNOWN_ERROR, "An unknown exception occurred");
     return TRUE;
@@ -394,14 +426,17 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
   // It passes all our tests -- create a new session.
   log.info ("Creating new session");
 
-  SAMLAuthenticationStatement* as=static_cast<SAMLAuthenticationStatement*>(auth_st->clone());
+  // Clone the statement so we can store it.
+  // TODO: we need to extract the Issuer and propagate that around as the origin site along
+  // with the statement and attribute assertions.
+  SAMLAuthenticationStatement* as=static_cast<SAMLAuthenticationStatement*>(bpr.authnStatement->clone());
 
-  // Create a new cookie
+  // Create a new session key.
   string cookie = conf->getSessionCache()->generateKey();
 
   // Cache this session, possibly including response if attributes appear present.
   bool attributesPushed=false;
-  Iterator<SAMLAssertion*> assertions=r->getAssertions();
+  Iterator<SAMLAssertion*> assertions=bpr.response->getAssertions();
   while (!attributesPushed && assertions.hasNext()) {
       Iterator<SAMLStatement*> statements=assertions.next()->getStatements();
       while (!attributesPushed && statements.hasNext()) {
@@ -409,17 +444,19 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
             attributesPushed=true;
       }
   }
-  conf->getSessionCache()->insert(cookie.c_str(), app, as, argp->client_addr, (attributesPushed ? r : NULL), role);
+  conf->getSessionCache()->insert(cookie.c_str(), app, as, argp->client_addr, (attributesPushed ? bpr.response : NULL), role);
   
-  // Maybe delete the response...
-  if (!attributesPushed)
-    delete r;
-
   // And let the user know.
   if (result->cookie) free(result->cookie);
+  if (result->target) free(result->target);
   result->cookie = strdup(cookie.c_str());
+  result->target = strdup(bpr.TARGET.c_str());
   set_rpc_status(&result->status, SHIBRPC_OK);
 
+  // Maybe delete the response...
+  if (!attributesPushed)
+    bpr.clear();
+
   log.debug("new session id: %s", cookie.c_str());
   
   // Transaction Logging
@@ -447,124 +484,8 @@ shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
   return TRUE;
 }
 
-extern "C" bool_t
-shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp,
-                       shibrpc_get_assertions_ret_1 *result, struct svc_req *rqstp)
-{
-  Category& log = get_category();
-  string ctx = get_threadid("get_assertions");
-  saml::NDC ndc(ctx);
-
-  if (!argp || !result) {
-    log.error ("Invalid RPC arguments");
-    return FALSE;
-  }
-
-  memset (result, 0, sizeof (*result));
-  result->auth_statement.xml_string = strdup("");
-
-  log.debug ("get attrs for client at %s", argp->cookie.client_addr);
-  log.debug ("cookie: %s", argp->cookie.cookie);
-  log.debug ("application: %s", argp->application_id);
-
-  // Find this session
-  IConfig* conf=ShibTargetConfig::getConfig().getINI();
-  Locker locker(conf);
-
-  // Try and locate support metadata for errors we throw.
-  log.debug ("application: %s", argp->application_id);
-  const IApplication* app=conf->getApplication(argp->application_id);
-  if (!app) {
-      // Something's horribly wrong.
-      log.error("couldn't find application for session");
-      set_rpc_status(&result->status, SHIBRPC_INTERNAL_ERROR, "Unable to locate application for session, deleted?");
-      return TRUE;
-  }
-
-  ISessionCacheEntry* entry = conf->getSessionCache()->find(argp->cookie.cookie,app);
-
-  // If it does not exist, leave now..
-  if (!entry) {
-    log.error ("No Session");
-    set_rpc_status(&result->status, SHIBRPC_NO_SESSION, "getattrs Internal error: no session");
-    return TRUE;
-  }
-
-  Metadata m(app->getMetadataProviders());
-  const IEntityDescriptor* origin=m.lookup(entry->getStatement()->getSubject()->getNameIdentifier()->getNameQualifier());
-
-  try {
-    try {
-      // Validate the client address (again?)
-      if (argp->checkIPAddress && strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
-        entry->unlock();
-        log.error("IP Mismatch");
-        throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
-            "Your IP address does not match the address in the original authentication.", origin);
-      }
-
-      // grab the attributes for this resource
-      Iterator<SAMLAssertion*> iter = entry->getAssertions();
-      u_int size = iter.size();
-
-      // if we have assertions...
-      if (size) {
-
-        // Build the response section
-       ShibRpcXML* av = (ShibRpcXML*) malloc (size * sizeof (ShibRpcXML));
-
-        // and then serialize them all...
-        u_int i = 0;
-        while (iter.hasNext()) {
-          SAMLAssertion* as = iter.next();
-          ostringstream os;
-          os << *as;
-          av[i++].xml_string = strdup(os.str().c_str());
-        }
-
-       // Set the results, once we know we've succeeded.
-       result->assertions.assertions_len = size;
-       result->assertions.assertions_val = av;
-      }
-    }
-    catch (SAMLException &e) {
-      entry->unlock();
-      log.error ("caught SAML exception: %s", e.what());
-      ostringstream os;
-      os << e;
-      throw ShibTargetException(SHIBRPC_SAML_EXCEPTION, os.str().c_str(), origin);
-    }
-  }
-  catch (ShibTargetException &e) {
-    entry->unlock();
-    set_rpc_status(&result->status, e);
-    return TRUE;
-  }
-#ifndef _DEBUG
-  catch (...) {
-    entry->unlock();
-    log.error ("caught an unknown exception");
-    throw ShibTargetException(SHIBRPC_UNKNOWN_ERROR,
-          "An unexpected error occured while fetching attributes.", origin);
-  }
-#endif
-
-
-  // Now grab the serialized authentication statement
-  free(result->auth_statement.xml_string);
-  result->auth_statement.xml_string = strdup(entry->getSerializedStatement());
-  entry->unlock();
-
-  // and let it fly
-  set_rpc_status(&result->status, SHIBRPC_OK);
-
-  log.debug ("returning");
-  return TRUE;
-}
-
 extern "C" int
-shibrpc_prog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
+shibrpc_prog_2_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
 {
        xdr_free (xdr_result, result);
 
index 74c22b4..7bec2e3 100644 (file)
 #endif
 
 void
-shibrpc_prog_1(struct svc_req *rqstp, register SVCXPRT *transp)
+shibrpc_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)
 {
        union {
-               int shibrpc_ping_1_arg;
-               shibrpc_session_is_valid_args_1 shibrpc_session_is_valid_1_arg;
-               shibrpc_new_session_args_1 shibrpc_new_session_1_arg;
-               shibrpc_get_assertions_args_1 shibrpc_get_assertions_1_arg;
+               int shibrpc_ping_2_arg;
+               shibrpc_new_session_args_2 shibrpc_new_session_2_arg;
+               shibrpc_get_session_args_2 shibrpc_get_session_2_arg;
        } argument;
        union {
-               int shibrpc_ping_1_res;
-               shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid_1_res;
-               shibrpc_new_session_ret_1 shibrpc_new_session_1_res;
-               shibrpc_get_assertions_ret_1 shibrpc_get_assertions_1_res;
+               int shibrpc_ping_2_res;
+               shibrpc_new_session_ret_2 shibrpc_new_session_2_res;
+               shibrpc_get_session_ret_2 shibrpc_get_session_2_res;
        } result;
        bool_t retval;
        xdrproc_t _xdr_argument, _xdr_result;
@@ -44,25 +42,19 @@ shibrpc_prog_1(struct svc_req *rqstp, register SVCXPRT *transp)
        case shibrpc_ping:
                _xdr_argument = (xdrproc_t) xdr_int;
                _xdr_result = (xdrproc_t) xdr_int;
-               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_ping_1_svc;
-               break;
-
-       case shibrpc_session_is_valid:
-               _xdr_argument = (xdrproc_t) xdr_shibrpc_session_is_valid_args_1;
-               _xdr_result = (xdrproc_t) xdr_shibrpc_session_is_valid_ret_1;
-               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_session_is_valid_1_svc;
+               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_ping_2_svc;
                break;
 
        case shibrpc_new_session:
-               _xdr_argument = (xdrproc_t) xdr_shibrpc_new_session_args_1;
-               _xdr_result = (xdrproc_t) xdr_shibrpc_new_session_ret_1;
-               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_new_session_1_svc;
+               _xdr_argument = (xdrproc_t) xdr_shibrpc_new_session_args_2;
+               _xdr_result = (xdrproc_t) xdr_shibrpc_new_session_ret_2;
+               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_new_session_2_svc;
                break;
 
-       case shibrpc_get_assertions:
-               _xdr_argument = (xdrproc_t) xdr_shibrpc_get_assertions_args_1;
-               _xdr_result = (xdrproc_t) xdr_shibrpc_get_assertions_ret_1;
-               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_get_assertions_1_svc;
+       case shibrpc_get_session:
+               _xdr_argument = (xdrproc_t) xdr_shibrpc_get_session_args_2;
+               _xdr_result = (xdrproc_t) xdr_shibrpc_get_session_ret_2;
+               local = (bool_t (*) (char *, void *,  struct svc_req *))shibrpc_get_session_2_svc;
                break;
 
        default:
@@ -70,19 +62,19 @@ shibrpc_prog_1(struct svc_req *rqstp, register SVCXPRT *transp)
                return;
        }
        memset ((char *)&argument, 0, sizeof (argument));
-       if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument)) {
+       if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
                svcerr_decode (transp);
                return;
        }
        retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp);
-       if (retval > 0 && !svc_sendreply(transp, _xdr_result, (char *)&result)) {
+       if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) {
                svcerr_systemerr (transp);
        }
-       if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) {
+       if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
                fprintf (stderr, "%s", "unable to free arguments");
                exit (1);
        }
-       if (!shibrpc_prog_1_freeresult (transp, _xdr_result, (caddr_t) &result))
+       if (!shibrpc_prog_2_freeresult (transp, _xdr_result, (caddr_t) &result))
                fprintf (stderr, "%s", "unable to free results");
 
        return;
index 2b07ff6..c0604d8 100644 (file)
@@ -58,18 +58,6 @@ xdr_ShibRpcError (XDR *xdrs, ShibRpcError *objp)
 }
 
 bool_t
-xdr_ShibRpcHttpCookie_1 (XDR *xdrs, ShibRpcHttpCookie_1 *objp)
-{
-       register int32_t *buf;
-
-        if (!xdr_string (xdrs, &objp->cookie, ~0))
-                return FALSE;
-        if (!xdr_string (xdrs, &objp->client_addr, ~0))
-                return FALSE;
-       return TRUE;
-}
-
-bool_t
 xdr_ShibRpcXML (XDR *xdrs, ShibRpcXML *objp)
 {
        register int32_t *buf;
@@ -80,43 +68,15 @@ xdr_ShibRpcXML (XDR *xdrs, ShibRpcXML *objp)
 }
 
 bool_t
-xdr_shibrpc_session_is_valid_args_1 (XDR *xdrs, shibrpc_session_is_valid_args_1 *objp)
-{
-       register int32_t *buf;
-
-        if (!xdr_ShibRpcHttpCookie_1 (xdrs, &objp->cookie))
-                return FALSE;
-        if (!xdr_string (xdrs, &objp->application_id, ~0))
-                return FALSE;
-        if (!xdr_bool (xdrs, &objp->checkIPAddress))
-                return FALSE;
-        if (!xdr_long (xdrs, &objp->lifetime))
-                return FALSE;
-        if (!xdr_long (xdrs, &objp->timeout))
-                return FALSE;
-       return TRUE;
-}
-
-bool_t
-xdr_shibrpc_session_is_valid_ret_1 (XDR *xdrs, shibrpc_session_is_valid_ret_1 *objp)
-{
-       register int32_t *buf;
-
-        if (!xdr_ShibRpcError (xdrs, &objp->status))
-                return FALSE;
-       return TRUE;
-}
-
-bool_t
-xdr_shibrpc_new_session_args_1 (XDR *xdrs, shibrpc_new_session_args_1 *objp)
+xdr_shibrpc_new_session_args_2 (XDR *xdrs, shibrpc_new_session_args_2 *objp)
 {
        register int32_t *buf;
 
         if (!xdr_string (xdrs, &objp->application_id, ~0))
                 return FALSE;
-        if (!xdr_string (xdrs, &objp->shire_location, ~0))
+        if (!xdr_string (xdrs, &objp->packet, ~0))
                 return FALSE;
-        if (!xdr_string (xdrs, &objp->saml_post, ~0))
+        if (!xdr_string (xdrs, &objp->recipient, ~0))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->client_addr, ~0))
                 return FALSE;
@@ -126,33 +86,41 @@ xdr_shibrpc_new_session_args_1 (XDR *xdrs, shibrpc_new_session_args_1 *objp)
 }
 
 bool_t
-xdr_shibrpc_new_session_ret_1 (XDR *xdrs, shibrpc_new_session_ret_1 *objp)
+xdr_shibrpc_new_session_ret_2 (XDR *xdrs, shibrpc_new_session_ret_2 *objp)
 {
        register int32_t *buf;
 
         if (!xdr_ShibRpcError (xdrs, &objp->status))
                 return FALSE;
+        if (!xdr_string (xdrs, &objp->target, ~0))
+                return FALSE;
         if (!xdr_string (xdrs, &objp->cookie, ~0))
                 return FALSE;
        return TRUE;
 }
 
 bool_t
-xdr_shibrpc_get_assertions_args_1 (XDR *xdrs, shibrpc_get_assertions_args_1 *objp)
+xdr_shibrpc_get_session_args_2 (XDR *xdrs, shibrpc_get_session_args_2 *objp)
 {
        register int32_t *buf;
 
-        if (!xdr_ShibRpcHttpCookie_1 (xdrs, &objp->cookie))
+        if (!xdr_string (xdrs, &objp->application_id, ~0))
+                return FALSE;
+        if (!xdr_string (xdrs, &objp->cookie, ~0))
+                return FALSE;
+        if (!xdr_string (xdrs, &objp->client_addr, ~0))
                 return FALSE;
         if (!xdr_bool (xdrs, &objp->checkIPAddress))
                 return FALSE;
-        if (!xdr_string (xdrs, &objp->application_id, ~0))
+        if (!xdr_long (xdrs, &objp->lifetime))
+                return FALSE;
+        if (!xdr_long (xdrs, &objp->timeout))
                 return FALSE;
        return TRUE;
 }
 
 bool_t
-xdr_shibrpc_get_assertions_ret_1 (XDR *xdrs, shibrpc_get_assertions_ret_1 *objp)
+xdr_shibrpc_get_session_ret_2 (XDR *xdrs, shibrpc_get_session_ret_2 *objp)
 {
        register int32_t *buf;
 
index 1703e66..f1f45a6 100644 (file)
@@ -50,54 +50,38 @@ struct ShibRpcError {
 };
 typedef struct ShibRpcError ShibRpcError;
 
-struct ShibRpcHttpCookie_1 {
-       char *cookie;
-       char *client_addr;
-};
-typedef struct ShibRpcHttpCookie_1 ShibRpcHttpCookie_1;
-
 struct ShibRpcXML {
        char *xml_string;
 };
 typedef struct ShibRpcXML ShibRpcXML;
 
-struct shibrpc_session_is_valid_args_1 {
-       ShibRpcHttpCookie_1 cookie;
+struct shibrpc_new_session_args_2 {
        char *application_id;
-       bool_t checkIPAddress;
-       long lifetime;
-       long timeout;
-};
-typedef struct shibrpc_session_is_valid_args_1 shibrpc_session_is_valid_args_1;
-
-struct shibrpc_session_is_valid_ret_1 {
-       ShibRpcError status;
-};
-typedef struct shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid_ret_1;
-
-struct shibrpc_new_session_args_1 {
-       char *application_id;
-       char *shire_location;
-       char *saml_post;
+       char *packet;
+       char *recipient;
        char *client_addr;
        bool_t checkIPAddress;
 };
-typedef struct shibrpc_new_session_args_1 shibrpc_new_session_args_1;
+typedef struct shibrpc_new_session_args_2 shibrpc_new_session_args_2;
 
-struct shibrpc_new_session_ret_1 {
+struct shibrpc_new_session_ret_2 {
        ShibRpcError status;
+       char *target;
        char *cookie;
 };
-typedef struct shibrpc_new_session_ret_1 shibrpc_new_session_ret_1;
+typedef struct shibrpc_new_session_ret_2 shibrpc_new_session_ret_2;
 
-struct shibrpc_get_assertions_args_1 {
-       ShibRpcHttpCookie_1 cookie;
-       bool_t checkIPAddress;
+struct shibrpc_get_session_args_2 {
        char *application_id;
+       char *cookie;
+       char *client_addr;
+       bool_t checkIPAddress;
+       long lifetime;
+       long timeout;
 };
-typedef struct shibrpc_get_assertions_args_1 shibrpc_get_assertions_args_1;
+typedef struct shibrpc_get_session_args_2 shibrpc_get_session_args_2;
 
-struct shibrpc_get_assertions_ret_1 {
+struct shibrpc_get_session_ret_2 {
        ShibRpcError status;
        ShibRpcXML auth_statement;
        struct {
@@ -105,40 +89,34 @@ struct shibrpc_get_assertions_ret_1 {
                ShibRpcXML *assertions_val;
        } assertions;
 };
-typedef struct shibrpc_get_assertions_ret_1 shibrpc_get_assertions_ret_1;
+typedef struct shibrpc_get_session_ret_2 shibrpc_get_session_ret_2;
 
 #define SHIBRPC_PROG 123456
-#define SHIBRPC_VERS_1 1
+#define SHIBRPC_VERS_2 2
 
 #if defined(__STDC__) || defined(__cplusplus)
 #define shibrpc_ping 0
-extern  enum clnt_stat shibrpc_ping_1(int *, int *, CLIENT *);
-extern  bool_t shibrpc_ping_1_svc(int *, int *, struct svc_req *);
-#define shibrpc_session_is_valid 1
-extern  enum clnt_stat shibrpc_session_is_valid_1(shibrpc_session_is_valid_args_1 *, shibrpc_session_is_valid_ret_1 *, CLIENT *);
-extern  bool_t shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *, shibrpc_session_is_valid_ret_1 *, struct svc_req *);
-#define shibrpc_new_session 2
-extern  enum clnt_stat shibrpc_new_session_1(shibrpc_new_session_args_1 *, shibrpc_new_session_ret_1 *, CLIENT *);
-extern  bool_t shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *, shibrpc_new_session_ret_1 *, struct svc_req *);
-#define shibrpc_get_assertions 3
-extern  enum clnt_stat shibrpc_get_assertions_1(shibrpc_get_assertions_args_1 *, shibrpc_get_assertions_ret_1 *, CLIENT *);
-extern  bool_t shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *, shibrpc_get_assertions_ret_1 *, struct svc_req *);
-extern int shibrpc_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+extern  enum clnt_stat shibrpc_ping_2(int *, int *, CLIENT *);
+extern  bool_t shibrpc_ping_2_svc(int *, int *, struct svc_req *);
+#define shibrpc_new_session 1
+extern  enum clnt_stat shibrpc_new_session_2(shibrpc_new_session_args_2 *, shibrpc_new_session_ret_2 *, CLIENT *);
+extern  bool_t shibrpc_new_session_2_svc(shibrpc_new_session_args_2 *, shibrpc_new_session_ret_2 *, struct svc_req *);
+#define shibrpc_get_session 2
+extern  enum clnt_stat shibrpc_get_session_2(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, CLIENT *);
+extern  bool_t shibrpc_get_session_2_svc(shibrpc_get_session_args_2 *, shibrpc_get_session_ret_2 *, struct svc_req *);
+extern int shibrpc_prog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
 
 #else /* K&R C */
 #define shibrpc_ping 0
-extern  enum clnt_stat shibrpc_ping_1();
-extern  bool_t shibrpc_ping_1_svc();
-#define shibrpc_session_is_valid 1
-extern  enum clnt_stat shibrpc_session_is_valid_1();
-extern  bool_t shibrpc_session_is_valid_1_svc();
-#define shibrpc_new_session 2
-extern  enum clnt_stat shibrpc_new_session_1();
-extern  bool_t shibrpc_new_session_1_svc();
-#define shibrpc_get_assertions 3
-extern  enum clnt_stat shibrpc_get_assertions_1();
-extern  bool_t shibrpc_get_assertions_1_svc();
-extern int shibrpc_prog_1_freeresult ();
+extern  enum clnt_stat shibrpc_ping_2();
+extern  bool_t shibrpc_ping_2_svc();
+#define shibrpc_new_session 1
+extern  enum clnt_stat shibrpc_new_session_2();
+extern  bool_t shibrpc_new_session_2_svc();
+#define shibrpc_get_session 2
+extern  enum clnt_stat shibrpc_get_session_2();
+extern  bool_t shibrpc_get_session_2_svc();
+extern int shibrpc_prog_2_freeresult ();
 #endif /* K&R C */
 
 /* the xdr functions */
@@ -147,27 +125,21 @@ extern int shibrpc_prog_1_freeresult ();
 extern  bool_t xdr_ShibRpcStatus (XDR *, ShibRpcStatus*);
 extern  bool_t xdr_ShibRpcErr (XDR *, ShibRpcErr*);
 extern  bool_t xdr_ShibRpcError (XDR *, ShibRpcError*);
-extern  bool_t xdr_ShibRpcHttpCookie_1 (XDR *, ShibRpcHttpCookie_1*);
 extern  bool_t xdr_ShibRpcXML (XDR *, ShibRpcXML*);
-extern  bool_t xdr_shibrpc_session_is_valid_args_1 (XDR *, shibrpc_session_is_valid_args_1*);
-extern  bool_t xdr_shibrpc_session_is_valid_ret_1 (XDR *, shibrpc_session_is_valid_ret_1*);
-extern  bool_t xdr_shibrpc_new_session_args_1 (XDR *, shibrpc_new_session_args_1*);
-extern  bool_t xdr_shibrpc_new_session_ret_1 (XDR *, shibrpc_new_session_ret_1*);
-extern  bool_t xdr_shibrpc_get_assertions_args_1 (XDR *, shibrpc_get_assertions_args_1*);
-extern  bool_t xdr_shibrpc_get_assertions_ret_1 (XDR *, shibrpc_get_assertions_ret_1*);
+extern  bool_t xdr_shibrpc_new_session_args_2 (XDR *, shibrpc_new_session_args_2*);
+extern  bool_t xdr_shibrpc_new_session_ret_2 (XDR *, shibrpc_new_session_ret_2*);
+extern  bool_t xdr_shibrpc_get_session_args_2 (XDR *, shibrpc_get_session_args_2*);
+extern  bool_t xdr_shibrpc_get_session_ret_2 (XDR *, shibrpc_get_session_ret_2*);
 
 #else /* K&R C */
 extern bool_t xdr_ShibRpcStatus ();
 extern bool_t xdr_ShibRpcErr ();
 extern bool_t xdr_ShibRpcError ();
-extern bool_t xdr_ShibRpcHttpCookie_1 ();
 extern bool_t xdr_ShibRpcXML ();
-extern bool_t xdr_shibrpc_session_is_valid_args_1 ();
-extern bool_t xdr_shibrpc_session_is_valid_ret_1 ();
-extern bool_t xdr_shibrpc_new_session_args_1 ();
-extern bool_t xdr_shibrpc_new_session_ret_1 ();
-extern bool_t xdr_shibrpc_get_assertions_args_1 ();
-extern bool_t xdr_shibrpc_get_assertions_ret_1 ();
+extern bool_t xdr_shibrpc_new_session_args_2 ();
+extern bool_t xdr_shibrpc_new_session_ret_2 ();
+extern bool_t xdr_shibrpc_get_session_args_2 ();
+extern bool_t xdr_shibrpc_get_session_ret_2 ();
 
 #endif /* K&R C */
 
index 1dad41d..d71177c 100644 (file)
@@ -53,78 +53,57 @@ union ShibRpcError switch(ShibRpcStatus status) {
    ShibRpcErr  e;
 };
 
-/* A type to pass a Cookie, which contains the HTTP cookie string
- * and the IP Address of the client */
-struct ShibRpcHttpCookie_1 {
-  string       cookie<>;
-  string       client_addr<>;
-};
-
 struct ShibRpcXML {
   string       xml_string<>;
 };
 
 /* function argument and response structures */
 
-struct shibrpc_session_is_valid_args_1 {
-  ShibRpcHttpCookie_1  cookie;
-  string               application_id<>;
-  bool                 checkIPAddress;
-  long                 lifetime;
-  long                 timeout;
-};
-
-struct shibrpc_session_is_valid_ret_1 {
-  ShibRpcError status;
-};
-
-struct shibrpc_new_session_args_1 {
+struct shibrpc_new_session_args_2 {
   string       application_id<>;
-  string       shire_location<>;
-  string       saml_post<>;
+  string       packet<>;
+  string       recipient<>;
   string       client_addr<>;
   bool         checkIPAddress;
 };
 
-struct shibrpc_new_session_ret_1 {
+struct shibrpc_new_session_ret_2 {
   ShibRpcError status;
+  string       target<>;
   string       cookie<>;
 };
 
-
-struct shibrpc_get_assertions_args_1 {
-  ShibRpcHttpCookie_1  cookie;
-  bool                 checkIPAddress;
+struct shibrpc_get_session_args_2 {
   string               application_id<>;
+  string               cookie<>;
+  string               client_addr<>;
+  bool                 checkIPAddress;
+  long                 lifetime;
+  long                 timeout;
 };
 
-struct shibrpc_get_assertions_ret_1 {
-  ShibRpcError         status;
-  ShibRpcXML           auth_statement;
-  ShibRpcXML           assertions<>;
+struct shibrpc_get_session_ret_2 {
+  ShibRpcError status;
+  ShibRpcXML   auth_statement;
+  ShibRpcXML   assertions<>;
 };
 
+
 /* Define the Shib Target RPC interface */
 program SHIBRPC_PROG {
-  version SHIBRPC_VERS_1 {
+  version SHIBRPC_VERS_2 {
 
     /* Ping the rpcsvc to make sure it is alive. */
     int shibrpc_ping (int) = 0;
 
-    /* SHIRE RPCs */
-
-    /* Is the HTTP Cookie valid? Is the session still active?
-     * Returns 0 for TRUE, a non-zero error code for FALSE */
-    shibrpc_session_is_valid_ret_1 shibrpc_session_is_valid (shibrpc_session_is_valid_args_1) = 1;
-
-    /* Create a new session for this user (SAML POST Profile Consumer) */
-    shibrpc_new_session_ret_1 shibrpc_new_session (shibrpc_new_session_args_1)
-      = 2;
+    /* Session Cache Remoting RPCs */
 
-    /* RM RPCs */
+    /* Create a new session for this user (SAML Browser Profile Consumer) */
+    shibrpc_new_session_ret_2 shibrpc_new_session (shibrpc_new_session_args_2) = 1;
 
-    /* Get the assertions from the SHAR */
-    shibrpc_get_assertions_ret_1 shibrpc_get_assertions (shibrpc_get_assertions_args_1) = 3;
+    /* Validate and access data associated with existing session.
+     * Returns 0 for TRUE, a non-zero error code for FALSE */
+    shibrpc_get_session_ret_2 shibrpc_get_session (shibrpc_get_session_args_2) = 2;
 
-  } = 1;
-} = 123456;                    /* XXX: Pick an RPC Program Number */
+  } = 2;
+} = 123456;                    /* Arbitrary RPC Program Number */
index eceb58c..5beae4c 100644 (file)
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 log4cpp.lib xerces-c_2.lib wsock32.lib saml_5.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_5.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cpp.lib xerces-c_2.lib wsock32.lib saml_5.lib /nologo /dll /machine:I386 /out:"Release/shibtarget_5.dll" /libpath:"../../../opensaml/c/saml/Release" /export:shibrpc_prog_2 /export:shibrpc_ping_2
 # SUBTRACT LINK32 /pdb:none
 
 !ELSEIF  "$(CFG)" == "shibtarget - Win32 Debug"
@@ -80,7 +80,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 log4cppD.lib xerces-c_2D.lib wsock32.lib saml_5D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_5D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_1 /export:shibrpc_ping_1
+# ADD LINK32 log4cppD.lib xerces-c_2D.lib wsock32.lib saml_5D.lib /nologo /dll /debug /machine:I386 /out:"Debug/shibtarget_5D.dll" /pdbtype:sept /libpath:"../../../opensaml/c/saml/Debug" /export:shibrpc_prog_2 /export:shibrpc_ping_2
 # SUBTRACT LINK32 /pdb:none
 
 !ENDIF 
@@ -115,10 +115,6 @@ SOURCE=".\shib-mlp.cpp"
 # End Source File
 # Begin Source File
 
-SOURCE=".\shib-rm.cpp"
-# End Source File
-# Begin Source File
-
 SOURCE=".\shib-rpcerror.cpp"
 # End Source File
 # Begin Source File
index 55c0187..c2e6c93 100644 (file)
@@ -13,7 +13,7 @@ libshib_la_SOURCES = \
                     Metadata.cpp \
                     ReloadableXMLFile.cpp \
                     ShibConfig.cpp \
-                    ShibPOSTProfile.cpp \
+                    ShibBrowserProfile.cpp \
                     ShibBinding.cpp \
                     shib-threads.cpp
 
index 52810cf..feeb915 100644 (file)
@@ -133,31 +133,6 @@ SAMLResponse* ShibBinding::send(
             auto_ptr<SAMLResponse> r(m_binding->send(*ab, req, conf));
             if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
                 throw TrustException("ShibBinding::send() unable to verify signed response");
-                
-            unsigned long i;
-            Iterator<SAMLAssertion*> _a=r->getAssertions();
-            for (i=0; i < _a.size(); i++) {
-                // Check any conditions.
-                Iterator<SAMLCondition*> conds=_a[i]->getConditions();
-                while (conds.hasNext()) {
-                    SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
-                    if (!cond || !cond->eval(audiences)) {
-                        log.warn("assertion condition invalid, removing it");
-                        r->removeAssertion(i);
-                        i--;
-                        break;
-                    }
-                }
-            }
-            
-            for (i=0; i < _a.size(); i++) {
-                // Check signature.
-                if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
-                    log.warn("signed assertion failed to validate, removing it");
-                    r->removeAssertion(i);
-                    i--;
-                }
-            }
             return r.release();
         }
         catch (SAMLException& e) {
@@ -190,30 +165,6 @@ SAMLResponse* ShibBinding::send(
             auto_ptr<SAMLResponse> r(m_binding->send(ab, req, conf));
             if (r->isSigned() && !t.validate(m_revocations,m_AA,*r))
                 throw TrustException("ShibBinding::send() unable to verify signed response");
-
-            unsigned long i;
-            Iterator<SAMLAssertion*> _a=r->getAssertions();
-            for (i=0; i < _a.size(); i++) {
-                // Check any conditions.
-                Iterator<SAMLCondition*> conds=_a[i]->getConditions();
-                while (conds.hasNext()) {
-                    SAMLAudienceRestrictionCondition* cond=dynamic_cast<SAMLAudienceRestrictionCondition*>(conds.next());
-                    if (!cond || !cond->eval(audiences)) {
-                        log.warn("assertion condition invalid, removing it");
-                        r->removeAssertion(i);
-                        i--;
-                    }
-                }
-            }
-            
-            for (i=0; i < _a.size(); i++) {
-                // Check signature.
-                if (_a[i]->isSigned() && !t.validate(m_revocations,m_AA,*(_a[i]))) {
-                    log.warn("signed assertion failed to validate, removing it");
-                    r->removeAssertion(i);
-                    i--;
-                }
-            }
             return r.release();
         }
         catch (SAMLException& e) {
diff --git a/shib/ShibBrowserProfile.cpp b/shib/ShibBrowserProfile.cpp
new file mode 100644 (file)
index 0000000..f89ab25
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+ * 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.
+ */
+
+/* ShibBrowserProfile.cpp - Shibboleth-specific wrapper around SAML browser profile
+
+   Scott Cantor
+   2/6/05
+
+   $History:$
+*/
+
+#include "internal.h"
+
+#include <ctime>
+
+#include <openssl/x509v3.h>
+
+using namespace shibboleth;
+using namespace saml;
+using namespace log4cpp;
+using namespace std;
+
+ShibBrowserProfile::ShibBrowserProfile(
+    const Iterator<IMetadata*>& metadatas,
+    const Iterator<IRevocation*>& revocations,
+    const Iterator<ITrust*>& trusts
+    ) : m_metadatas(metadatas), m_revocations(revocations), m_trusts(trusts)
+{
+    m_profile=SAMLBrowserProfile::getInstance();
+}
+
+ShibBrowserProfile::~ShibBrowserProfile()
+{
+    delete m_profile;
+}
+
+void ShibBrowserProfile::setVersion(int major, int minor)
+{
+    m_profile->setVersion(major,minor);
+}
+
+SAMLBrowserProfile::BrowserProfileResponse ShibBrowserProfile::receive(
+    XMLCh** pIssuer,
+    const char* packet,
+    const XMLCh* recipient,
+    int supportedProfiles,
+    IReplayCache* replayCache,
+    SAMLBinding* callback
+    )
+{
+#ifdef _DEBUG
+    saml::NDC("recieve");
+#endif
+    Category& log=Category::getInstance(SHIB_LOGCAT".ShibBrowserProfile");
+    // The built-in SAML functionality will do most of the basic non-crypto checks.
+    // Note that if the response only contains a status error, it gets tossed out
+    // as an exception.
+    SAMLBrowserProfile::BrowserProfileResponse bpr =
+        m_profile->receive(pIssuer, packet, recipient, supportedProfiles, replayCache, callback);
+
+    // Try and locate metadata for the IdP. We try Issuer first.
+    log.debug("searching metadata for assertion issuer...");
+    Metadata m(m_metadatas);
+    const IEntityDescriptor* provider=m.lookup(bpr.assertion->getIssuer());
+    if (provider) {
+        if (pIssuer)
+            *pIssuer=XMLString::replicate(bpr.assertion->getIssuer());
+        log.debug("matched assertion issuer against metadata");
+    }
+    else {
+        // Might be a down-level origin.
+        provider=m.lookup(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+        if (provider) {
+            if (pIssuer)
+                *pIssuer=XMLString::replicate(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+            log.debug("matched subject name qualifier against metadata");
+        }
+    }
+
+    // No metadata at all.
+    if (!provider) {
+        auto_ptr_char issuer(bpr.assertion->getIssuer());
+        auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+        log.error("assertion issuer not found in metadata (Issuer='%s', NameQualifier='%s'",
+            issuer.get(), (nq.get() ? nq.get() : "null"));
+        bpr.clear();
+        throw MetadataException("ShibBrowserProfile::receive() metadata lookup failed, unable to process assertion");
+    }
+
+    // Is this provider an IdP?
+    const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
+    if (role) {
+        // Use this role to evaluate the signature(s). If the response is unsigned, we know
+        // it was an artifact profile run.
+        Trust t(m_trusts);
+        if (bpr.response->isSigned()) {        
+            log.debug("passing signed response to trust layer");
+            if (!t.validate(m_revocations,role,*bpr.response)) {
+                bpr.clear();
+                throw TrustException("ShibBrowserProfile::receive() unable to verify signed response");
+            }
+        }    
+        // Assertion(s) signed?
+        Iterator<SAMLAssertion*> itera=bpr.response->getAssertions();
+        while (itera.hasNext()) {
+            SAMLAssertion* _a=itera.next();
+            if (_a->isSigned()) {
+                log.debug("passing signed assertion to trust layer"); 
+                if (!t.validate(m_revocations,role,*_a)) {
+                    bpr.clear();
+                    throw TrustException("ShibBrowserProfile::receive() unable to verify signed assertion");
+                }
+            }
+        }
+        return bpr;
+    }
+
+    auto_ptr_char issuer(bpr.assertion->getIssuer());
+    auto_ptr_char nq(bpr.authnStatement->getSubject()->getNameIdentifier()->getNameQualifier());
+    log.error("metadata for assertion issuer indicates no SAML 1.x identity provider role (Issuer='%s', NameQualifier='%s'",
+        issuer.get(), (nq.get() ? nq.get() : "null"));
+    bpr.clear();
+    throw MetadataException("ShibBrowserProfile::receive() metadata lookup failed, issuer not registered as SAML 1.x identity provider");
+}
diff --git a/shib/ShibPOSTProfile.cpp b/shib/ShibPOSTProfile.cpp
deleted file mode 100644 (file)
index 86c67d0..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/* 
- * 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.
- */
-
-/* ShibPOSTProfile.cpp - Shibboleth-specific wrapper around SAML POST profile
-
-   Scott Cantor
-   8/12/02
-
-   $History:$
-*/
-
-#include "internal.h"
-
-#include <ctime>
-
-#include <openssl/x509v3.h>
-
-using namespace shibboleth;
-using namespace saml;
-using namespace log4cpp;
-using namespace std;
-
-ShibPOSTProfile::ShibPOSTProfile(
-    const Iterator<IMetadata*>& metadatas,
-    const Iterator<IRevocation*>& revocations,
-    const Iterator<ITrust*>& trusts,
-    const Iterator<ICredentials*>& creds
-    ) : m_metadatas(metadatas), m_revocations(revocations), m_trusts(trusts), m_creds(creds) {}
-
-const SAMLAssertion* ShibPOSTProfile::getSSOAssertion(const SAMLResponse& r, const Iterator<const XMLCh*>& audiences)
-{
-    return SAMLPOSTProfile::getSSOAssertion(r,audiences);
-}
-
-const SAMLAuthenticationStatement* ShibPOSTProfile::getSSOStatement(const SAMLAssertion& a)
-{
-    return SAMLPOSTProfile::getSSOStatement(a);
-}
-
-const XMLCh* ShibPOSTProfile::getProviderId(const saml::SAMLResponse& r)
-{
-    // Switch to Issuer by itself, stop using NameQualifier.
-    Iterator<SAMLAssertion*> ia=r.getAssertions();
-    if (ia.hasNext())
-        return (ia.next())->getIssuer();
-    return NULL;
-}
-
-SAMLResponse* ShibPOSTProfile::accept(
-    const XMLByte* buf,
-    const XMLCh* recipient,
-    int ttlSeconds,
-    const saml::Iterator<const XMLCh*>& audiences,
-    XMLCh** pproviderId)
-{
-    saml::NDC("accept");
-    Category& log=Category::getInstance(SHIB_LOGCAT".ShibPOSTProfile");
-    // The built-in SAML functionality will do most of the basic non-crypto checks.
-    // Note that if the response only contains a status error, it gets tossed out
-    // as an exception.
-    auto_ptr<SAMLResponse> r(SAMLPOSTProfile::accept(buf, recipient, ttlSeconds, false));
-
-    // Now we do some more non-crypto (ie. cheap) work to match up the origin site
-    // with its associated data.
-    const SAMLAssertion* assertion = NULL;
-    const SAMLAuthenticationStatement* sso = NULL;
-
-    try {
-        assertion = getSSOAssertion(*(r.get()),audiences);
-        sso = getSSOStatement(*assertion);
-    }
-    catch (...) {
-        // We want to try our best to locate an origin site name so we can fill it in.
-        if (pproviderId)
-            *pproviderId=XMLString::replicate(getProviderId(*(r.get())));
-        throw;
-    }
-    
-    // Finish SAML processing.
-    SAMLPOSTProfile::process(*(r.get()), recipient, ttlSeconds);
-
-    // Try and locate metadata for the IdP. With this new version, we try Issuer first.
-    log.debug("searching metadata for assertion issuer...");
-    Metadata m(m_metadatas);
-    const IEntityDescriptor* provider=m.lookup(assertion->getIssuer());
-    if (provider) {
-        if (pproviderId)
-            *pproviderId=XMLString::replicate(assertion->getIssuer());
-        log.debug("matched assertion issuer against metadata");
-    }
-    else {
-        // Might be a down-level origin.
-        provider=m.lookup(sso->getSubject()->getNameIdentifier()->getNameQualifier());
-        if (provider) {
-            if (pproviderId)
-                *pproviderId=XMLString::replicate(sso->getSubject()->getNameIdentifier()->getNameQualifier());
-            log.debug("matched subject name qualifier against metadata");
-        }
-    }
-
-    // No metadata at all.        
-    if (!provider) {
-        auto_ptr_char issuer(assertion->getIssuer());
-        auto_ptr_char nq(sso->getSubject()->getNameIdentifier()->getNameQualifier());
-        log.error("assertion issuer not found in metadata (Issuer='%s', NameQualifier='%s'",
-            issuer.get(), (nq.get() ? nq.get() : "null"));
-        throw MetadataException("ShibPOSTProfile::accept() metadata lookup failed, unable to process assertion");
-    }
-
-    // Is this provider an IdP?
-    const IIDPSSODescriptor* role=provider->getIDPSSODescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
-    if (role) {
-        log.debug("passing response to trust layer");
-        
-        // Use this role to evaluate the signature.
-        Trust t(m_trusts);
-        if (!t.validate(m_revocations,role,*r))
-            throw TrustException("ShibPOSTProfile::accept() unable to verify signed response");
-        
-        // Assertion(s) signed?
-        Iterator<SAMLAssertion*> itera=r->getAssertions();
-        while (itera.hasNext()) {
-            SAMLAssertion* _a=itera.next();
-            if (_a->isSigned()) {
-                log.debug("passing signed assertion to trust layer"); 
-                if (!t.validate(m_revocations,role,*_a))
-                    throw TrustException("ShibPOSTProfile::accept() unable to verify signed assertion");
-            }
-        }
-        return r.release();
-    }
-
-    auto_ptr_char issuer(assertion->getIssuer());
-    auto_ptr_char nq(sso->getSubject()->getNameIdentifier()->getNameQualifier());
-    log.error("metadata for assertion issuer indicates no SAML 1.x identity provider role (Issuer='%s', NameQualifier='%s'",
-        issuer.get(), (nq.get() ? nq.get() : "null"));
-    throw MetadataException("ShibPOSTProfile::accept() metadata lookup failed, issuer not registered as SAML 1.x identity provider");
-}
-
-SAMLResponse* ShibPOSTProfile::prepare(
-    const IIDPSSODescriptor* role,
-    const char* credResolverId,
-    const XMLCh* recipient,
-    const XMLCh* authMethod,
-    const SAMLDateTime& authInstant,
-    const XMLCh* name,
-    const XMLCh* format,
-    const XMLCh* nameQualifier,
-    const XMLCh* subjectIP,
-    const saml::Iterator<const XMLCh*>& audiences,
-    const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings)
-{
-    SAMLResponse* r = SAMLPOSTProfile::prepare(
-        recipient,
-        role->getEntityDescriptor()->getId(),
-        audiences,
-        name,
-        nameQualifier,
-        format,
-        subjectIP,
-        authMethod,
-        authInstant,
-        bindings
-        );
-
-    Credentials c(m_creds);
-    const ICredResolver* cr=c.lookup(credResolverId);
-    if (!cr) {
-        delete r;
-        throw CredentialException("ShibPOSTProfile::prepare() unable to access credential resolver");
-    }
-    XSECCryptoKey* key=cr->getKey();
-    if (!key) {
-        delete r;
-        throw CredentialException("ShibPOSTProfile::prepare() unable to resolve signing key");
-    }
-    
-    r->sign(SIGNATURE_RSA,key,cr->getCertificates());
-    return r;
-}
-
-bool ShibPOSTProfile::checkReplayCache(const SAMLAssertion& a)
-{
-    // Default implementation uses the basic replay cache implementation.
-    return SAMLPOSTProfile::checkReplayCache(a);
-}
index c0ec584..26c8570 100644 (file)
@@ -133,11 +133,11 @@ SOURCE=.\ShibBinding.cpp
 # End Source File
 # Begin Source File
 
-SOURCE=.\ShibConfig.cpp
+SOURCE=.\ShibBrowserProfile.cpp
 # End Source File
 # Begin Source File
 
-SOURCE=.\ShibPOSTProfile.cpp
+SOURCE=.\ShibConfig.cpp
 # End Source File
 # End Target
 # End Project
index 2652007..52d6dd0 100644 (file)
@@ -462,51 +462,34 @@ namespace shibboleth
         const IAttributeRule* m_rule;
     };
 
-    // Wrapper classes around the POST profile and SAML binding
+    // Subclasses around the OpenSAML browser profile and binding interfaces,
+    // these incoporate additional functionality using Shib-defined APIs.
 
-    class SHIB_EXPORTS ShibPOSTProfile
+    class SHIB_EXPORTS ShibBrowserProfile : virtual public saml::SAMLBrowserProfile
     {
     public:
-        ShibPOSTProfile(
+        ShibBrowserProfile(
             const saml::Iterator<IMetadata*>& metadatas=EMPTY(IMetadata*),
             const saml::Iterator<IRevocation*>& revocations=EMPTY(IRevocation*),
-            const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*),
-            const saml::Iterator<ICredentials*>& creds=EMPTY(ICredentials*)
+            const saml::Iterator<ITrust*>& trusts=EMPTY(ITrust*)
             );
-        virtual ~ShibPOSTProfile() {}
+        virtual ~ShibBrowserProfile();
 
-        virtual const saml::SAMLAssertion* getSSOAssertion(
-            const saml::SAMLResponse& r, const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*)
-            );
-        virtual const saml::SAMLAuthenticationStatement* getSSOStatement(const saml::SAMLAssertion& a);
-        virtual saml::SAMLResponse* accept(
-            const XMLByte* buf,
-            const XMLCh* recipient,
-            int ttlSeconds,
-            const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
-            XMLCh** pproviderId=NULL
-            );
-        virtual saml::SAMLResponse* prepare(
-            const IIDPSSODescriptor* role,
-            const char* credResolverId,
+        virtual void setVersion(int major, int minor);
+        virtual saml::SAMLBrowserProfile::BrowserProfileResponse receive(
+            XMLCh** pIssuer,
+            const char* packet,
             const XMLCh* recipient,
-            const XMLCh* authMethod,
-            const saml::SAMLDateTime& authInstant,
-            const XMLCh* name,
-            const XMLCh* format=Constants::SHIB_NAMEID_FORMAT_URI,
-            const XMLCh* nameQualifier=NULL,
-            const XMLCh* subjectIP=NULL,
-            const saml::Iterator<const XMLCh*>& audiences=EMPTY(const XMLCh*),
-            const saml::Iterator<saml::SAMLAuthorityBinding*>& bindings=EMPTY(saml::SAMLAuthorityBinding*)
+            int supportedProfiles,
+            saml::IReplayCache* replayCache=NULL,
+            saml::SAMLBinding* callback=NULL
             );
-        virtual bool checkReplayCache(const saml::SAMLAssertion& a);
-        virtual const XMLCh* getProviderId(const saml::SAMLResponse& r);
 
-    protected:
-        const saml::Iterator<IMetadata*>& m_metadatas;
-        const saml::Iterator<IRevocation*>& m_revocations;
-        const saml::Iterator<ITrust*>& m_trusts;
-        const saml::Iterator<ICredentials*>& m_creds;
+    private:
+        saml::SAMLBrowserProfile* m_profile;
+        saml::Iterator<IMetadata*> m_metadatas;
+        saml::Iterator<IRevocation*> m_revocations;
+        saml::Iterator<ITrust*> m_trusts;
     };
 
     class SHIB_EXPORTS ShibBinding
index 69dd921..1bb7855 100644 (file)
@@ -101,7 +101,7 @@ int main(int argc,char* argv[])
         Metadata m(sites);
 
         auto_ptr<XMLCh> recip(XMLString::transcode("https://shib2.internet2.edu/shib/SHIRE"));
-        ShibPOSTProfile p (sites,EMPTY(IRevocation*),EMPTY(ITrust*),EMPTY(ICredentials*));
+        ShibBrowserProfile p (sites,EMPTY(IRevocation*),EMPTY(ITrust*));
 
         char ch;
         string buf;
@@ -112,15 +112,9 @@ int main(int argc,char* argv[])
             cin >> ch;
         }
 
-        SAMLResponse* r2=p.accept((const XMLByte*)buf.c_str(),recip.get(),300);
-        cout << "Consumed Response: " << endl << *r2 << endl;
-
-        const SAMLAssertion* a=p.getSSOAssertion(*r2);
-        const SAMLAuthenticationStatement* s=p.getSSOStatement(*a);
-        if (!p.checkReplayCache(*a))
-            throw ReplayedAssertionException("detected replay attack");
-
-        delete r2;
+        SAMLBrowserProfile::BrowserProfileResponse bpr=p.receive(NULL,buf.c_str(),recip.get(),SAMLBrowserProfile::Post);
+        cout << "Consumed Response: " << endl << *bpr.response << endl;
+        bpr.clear();
     }
     catch(SAMLException& e)
     {