Porting changes from 1.2 branch
[shibboleth/sp.git] / shib-target / shib-shire.cpp
index 908fdb5..eacb67a 100644 (file)
@@ -90,7 +90,7 @@ static char *makeword(char *line, char stop)
     return word;
 }
 
-static char *fmakeword(char stop, int *cl, const char** ppch)
+static char *fmakeword(char stop, unsigned int *cl, const char** ppch)
 {
     int wsize;
     char *word;
@@ -180,7 +180,7 @@ namespace shibtarget {
     class CgiParse
     {
     public:
-        CgiParse(const char* data);
+        CgiParse(const char* data, unsigned int len);
         ~CgiParse();
         const char* get_value(const char* name) const;
     
@@ -189,10 +189,10 @@ namespace shibtarget {
     };
 }
 
-CgiParse::CgiParse(const char* data)
+CgiParse::CgiParse(const char* data, unsigned int len)
 {
     const char* pch = data;
-    int cl = strlen(data);
+    unsigned int cl = len;
         
     while (cl && pch) {
         char *name;
@@ -225,7 +225,33 @@ SHIRE::~SHIRE()
     delete m_parser;
 }
 
-const char* SHIRE::getShireURL(const char* resource)
+pair<const char*,const char*> SHIRE::getCookieNameProps() const
+{
+    static const char* defProps="; path=/";
+    static const char* defName="_shibsession_";
+    
+    const IPropertySet* props=m_app->getPropertySet("Sessions");
+    if (props) {
+        pair<bool,const char*> p=props->getString("cookieProps");
+        if (!p.first)
+            p.second=defProps;
+        if (!m_cookieName.empty())
+            return pair<const char*,const char*>(m_cookieName.c_str(),p.second);
+        pair<bool,const char*> p2=props->getString("cookieName");
+        if (p2.first) {
+            m_cookieName=p2.second;
+            return pair<const char*,const char*>(p2.second,p.second);
+        }
+        m_cookieName=defName;
+        m_cookieName+=m_app->getId();
+        return pair<const char*,const char*>(m_cookieName.c_str(),p.second);
+    }
+    m_cookieName=defName;
+    m_cookieName+=m_app->getId();
+    return pair<const char*,const char*>(m_cookieName.c_str(),defProps);
+}
+
+const char* SHIRE::getShireURL(const char* resource) const
 {
     if (!m_shireURL.empty())
         return m_shireURL.c_str();
@@ -243,7 +269,7 @@ const char* SHIRE::getShireURL(const char* resource)
     }
     
     // Should never happen...
-    if (!shire)
+    if (!shire || (*shire!='/' && strncmp(shire,"http:",5) && strncmp(shire,"https:",6)))
         return NULL;
 
     // The "shireURL" property can be in one of three formats:
@@ -299,7 +325,7 @@ const char* SHIRE::getShireURL(const char* resource)
     return m_shireURL.c_str();
 }
 
-const char* SHIRE::getAuthnRequest(const char* resource)
+const char* SHIRE::getAuthnRequest(const char* resource) const
 {
     if (!m_authnRequest.empty())
         return m_authnRequest.c_str();
@@ -313,30 +339,33 @@ const char* SHIRE::getAuthnRequest(const char* resource)
         if (wayf.first) {
             m_authnRequest=m_authnRequest + wayf.second + "?shire=" + url_encode(getShireURL(resource)) +
                 "&target=" + url_encode(resource) + "&time=" + timebuf;
-            wayf=m_app->getString("providerId");
-            if (wayf.first)
-                m_authnRequest=m_authnRequest + "&provider_id=" + wayf.second;
+            pair<bool,bool> old=m_app->getBool("oldAuthnRequest");
+            if (!old.first || !old.second) {
+                wayf=m_app->getString("providerId");
+                if (wayf.first)
+                    m_authnRequest=m_authnRequest + "&providerId=" + url_encode(wayf.second);
+            }
         }
     }
     return m_authnRequest.c_str();
 }
 
-const char* SHIRE::getLazyAuthnRequest(const char* query_string)
+const char* SHIRE::getLazyAuthnRequest(const char* query_string) const
 {
-    CgiParse parser(query_string);
+    CgiParse parser(query_string,strlen(query_string));
     const char* target=parser.get_value("target");
     if (!target || !*target)
         return NULL;
     return getAuthnRequest(target);
 }
 
-pair<const char*,const char*> SHIRE::getFormSubmission(const char* post)
+pair<const char*,const char*> SHIRE::getFormSubmission(const char* post, unsigned int len) const
 {
-    m_parser = new CgiParse(post);
+    m_parser = new CgiParse(post,len);
     return pair<const char*,const char*>(m_parser->get_value("SAMLResponse"),m_parser->get_value("TARGET"));
 }
 
-RPCError* SHIRE::sessionIsValid(const char* session_id, const char* ip)
+RPCError* SHIRE::sessionIsValid(const char* session_id, const char* ip) const
 {
   saml::NDC ndc("sessionIsValid");
   Category& log = Category::getInstance("shibtarget.SHIRE");
@@ -386,20 +415,18 @@ RPCError* SHIRE::sessionIsValid(const char* session_id, const char* ip)
   RPC rpc;
   do {
     clnt = rpc->connect();
-    if (shibrpc_session_is_valid_1(&arg, &ret, clnt) != RPC_SUCCESS) {
+    clnt_stat status = shibrpc_session_is_valid_1(&arg, &ret, clnt);
+    if (status != RPC_SUCCESS) {
       // FAILED.  Release, disconnect, and try again...
-      log.debug("RPC Failure: %p (%p): %s", this, clnt, clnt_spcreateerror(""));
+      log.error("RPC Failure: %p (%p) (%d) %s", this, clnt, status, clnt_spcreateerror("shibrpc_session_is_valid_1"));
       rpc->disconnect();
       if (retry)
           retry--;
-      else {
-        log.error("RPC Failure: %p (%p)", this, clnt);
-        return new RPCError(-1, "RPC Failure");
-      }
+      else
+          return new RPCError(-1, "RPC Failure");
     }
     else {
-      // SUCCESS.  Return to the pool.
-      rpc.pool();
+      // SUCCESS
       retry = -1;
     }
   } while (retry>=0);
@@ -413,12 +440,13 @@ RPCError* SHIRE::sessionIsValid(const char* session_id, const char* ip)
     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;
 }
 
-RPCError* SHIRE::sessionCreate(const char* response, const char* ip, string& cookie)
+RPCError* SHIRE::sessionCreate(const char* response, const char* ip, string& cookie) const
 {
   saml::NDC ndc("sessionCreate");
   Category& log = Category::getInstance("shibtarget.SHIRE");
@@ -458,20 +486,18 @@ RPCError* SHIRE::sessionCreate(const char* response, const char* ip, string& coo
   RPC rpc;
   do {
     clnt = rpc->connect();
-    if (shibrpc_new_session_1 (&arg, &ret, clnt) != RPC_SUCCESS) {
+    clnt_stat status = shibrpc_new_session_1 (&arg, &ret, clnt);
+    if (status != RPC_SUCCESS) {
       // FAILED.  Release, disconnect, and retry
-      log.debug("RPC Failure: %p (%p): %s", this, clnt, clnt_spcreateerror (""));
+      log.error("RPC Failure: %p (%p) (%d): %s", this, clnt, status, clnt_spcreateerror("shibrpc_new_session_1"));
       rpc->disconnect();
       if (retry)
-       retry--;
-      else {
-        log.error("RPC Failure: %p (%p)", this, clnt);
+        retry--;
+      else
         return new RPCError(-1, "RPC Failure");
-      }
     }
     else {
       // SUCCESS.  Pool and continue
-      rpc.pool();
       retry = -1;
     }
   } while (retry>=0);
@@ -488,6 +514,7 @@ RPCError* SHIRE::sessionCreate(const char* response, const char* ip, string& coo
   }
 
   clnt_freeres(clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_1, (caddr_t)&ret);
+  rpc.pool();
 
   log.debug("returning");
   return retval;