Added export specifiers.
[shibboleth/sp.git] / shib-target / shib-shire.cpp
1 /*
2  * shib-shire.cpp -- Shibboleth SHIRE functions
3  *
4  * Created by:  Derek Atkins <derek@ihtfp.com>
5  *
6  * $Id$
7  */
8
9 #ifdef HAVE_UNISTD_H
10 # include <unistd.h>
11 #endif
12
13 #ifdef WIN32
14 # define SHIBTARGET_EXPORTS __declspec(dllexport)
15 #endif
16
17 #include "shib-target.h"
18
19 #include <log4cpp/Category.hh>
20
21 #include <stdexcept>
22
23 using namespace std;
24 using namespace saml;
25 using namespace shibboleth;
26 using namespace shibtarget;
27
28 class shibtarget::SHIREPriv
29 {
30 public:
31   SHIREPriv(RPCHandle *rpc, SHIREConfig cfg, string shire_url);
32   ~SHIREPriv();
33
34   RPCHandle *   m_rpc;
35   SHIREConfig   m_config;
36   string        m_url;
37
38   log4cpp::Category* log;
39 };
40
41 SHIREPriv::SHIREPriv(RPCHandle *rpc, SHIREConfig cfg, string shire_url)
42 {
43   string ctx = "shibtarget.SHIRE";
44   log = &(log4cpp::Category::getInstance(ctx));
45   m_rpc = rpc;
46   m_config = cfg;
47   m_url = shire_url;
48 }
49
50 SHIREPriv::~SHIREPriv() {}
51
52
53 SHIRE::SHIRE(RPCHandle *rpc, SHIREConfig cfg, string shire_url)
54 {
55   m_priv = new SHIREPriv(rpc, cfg, shire_url);
56   m_priv->log->info ("New SHIRE handle created: %p", m_priv);
57 }
58
59 SHIRE::~SHIRE()
60 {
61   delete m_priv;
62 }
63
64
65 RPCError* SHIRE::sessionIsValid(const char* cookie, const char* ip, const char* url)
66 {
67   saml::NDC ndc("sessionIsValid");
68
69   if (!cookie || *cookie == '\0') {
70     m_priv->log->error ("No cookie");
71     return new RPCError(-1, "No such cookie");
72   }
73
74   if (!ip) {
75     m_priv->log->error ("No IP");
76     return new RPCError(-1, "Invalid IP Address");
77   }
78
79   // make sure we pass _something_ to the server
80   if (!url) url = "";
81
82   m_priv->log->info ("is session valid: %s", ip);
83   m_priv->log->debug ("session cookie: %s", cookie);
84
85   shibrpc_session_is_valid_args_1 arg;
86
87   arg.cookie.cookie = (char*)cookie;
88   arg.cookie.client_addr = (char *)ip;
89   arg.url = (char *)url;
90   arg.lifetime = m_priv->m_config.lifetime;
91   arg.timeout = m_priv->m_config.timeout;
92   arg.checkIPAddress = m_priv->m_config.checkIPAddress;
93
94   shibrpc_session_is_valid_ret_1 ret;
95   memset (&ret, 0, sizeof(ret));
96
97   // Loop on the RPC in case we lost contact the first time through
98   int retry = 1;
99   CLIENT *clnt;
100   do {
101     clnt = m_priv->m_rpc->connect();
102     if (shibrpc_session_is_valid_1 (&arg, &ret, clnt) != RPC_SUCCESS) {
103       // FAILED.  Release, disconnect, and try again...
104       m_priv->log->debug ("RPC Failure: %p (%p): %s", m_priv, clnt,
105                           clnt_spcreateerror (""));
106       m_priv->m_rpc->release();
107       m_priv->m_rpc->disconnect();
108       if (retry)
109         retry--;
110       else {
111         m_priv->log->error ("RPC Failure: %p (%p)", m_priv, clnt);
112         return new RPCError(-1, "RPC Failure");
113       }
114     } else {
115       // SUCCESS.  Release the lock.
116       m_priv->m_rpc->release();
117       retry = -1;
118     }
119   } while (retry >= 0);
120
121   m_priv->log->debug ("RPC completed with status %d, %p", ret.status.status, m_priv);
122
123   RPCError* retval;
124   if (ret.status.status)
125     retval = new RPCError(&ret.status);
126   else
127     retval = new RPCError();
128
129   clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_session_is_valid_ret_1, (caddr_t)&ret);
130
131   m_priv->log->debug ("returning");
132   return retval;
133 }
134
135 RPCError* SHIRE::sessionCreate(const char* post, const char* ip, string& cookie)
136 {
137   saml::NDC ndc("sessionCreate");
138
139   if (!post || *post == '\0') {
140     m_priv->log->error ("No POST");
141     return new RPCError(-1,  "Invalid POST string");
142   }
143
144   if (!ip) {
145     m_priv->log->error ("No IP");
146     return new RPCError(-1, "Invalid IP Address");
147   }
148
149   m_priv->log->info ("create session for user at %s", ip);
150
151   shibrpc_new_session_args_1 arg;
152   arg.shire_location = (char*) (m_priv->m_url.c_str());
153   arg.saml_post = (char*)post;
154   arg.client_addr = (char*)ip;
155   arg.checkIPAddress = m_priv->m_config.checkIPAddress;
156
157   shibrpc_new_session_ret_1 ret;
158   memset (&ret, 0, sizeof(ret));
159
160   // Loop on the RPC in case we lost contact the first time through
161   int retry = 1;
162   CLIENT* clnt;
163   do {
164     clnt = m_priv->m_rpc->connect();
165     if (shibrpc_new_session_1 (&arg, &ret, clnt) != RPC_SUCCESS) {
166       // FAILED.  Release, disconnect, and retry
167       m_priv->log->debug ("RPC Failure: %p (%p): %s", m_priv, clnt,
168                           clnt_spcreateerror (""));
169       m_priv->m_rpc->release();
170       m_priv->m_rpc->disconnect();
171       if (retry)
172         retry--;
173       else {
174         m_priv->log->error ("RPC Failure: %p (%p)", m_priv, clnt);
175         return new RPCError(-1, "RPC Failure");
176       }
177     } else {
178       // SUCCESS.  Release and continue
179       m_priv->m_rpc->release();
180       retry = -1;
181     }
182   } while (retry >= 0);
183
184   m_priv->log->debug ("RPC completed with status %d (%p)", ret.status.status, m_priv);
185
186   RPCError* retval;
187   if (ret.status.status)
188     retval = new RPCError(&ret.status);
189   else {
190     m_priv->log->debug ("new cookie: %s", ret.cookie);
191     cookie = ret.cookie;
192     retval = new RPCError();
193   }
194
195   clnt_freeres (clnt, (xdrproc_t)xdr_shibrpc_new_session_ret_1, (caddr_t)&ret);
196
197   m_priv->log->debug ("returning");
198   return retval;
199 }