Fix the ShibINI::iterator destructors.
[shibboleth/sp.git] / shib-target / shib-target.h
1 /*
2  * shib-target.h -- top-level header file for the SHIB Common Target Library
3  *
4  * Created by:  Derek Atkins <derek@ihtfp.com>
5  *
6  * $Id$
7  */
8
9 #ifndef SHIB_TARGET_H
10 #define SHIB_TARGET_H
11
12 #include <shib-target/shibrpc.h>
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 #ifdef WIN32
19
20 #include <winsock.h>
21 typedef SOCKET ShibSocket;
22 typedef u_short ShibSockName;
23 #define SHIB_SHAR_SOCKET 12345  /* shar portnumber */
24
25 #else  /* UNIX */
26
27 typedef int ShibSocket;
28 typedef char * ShibSockName;
29 #define SHIB_SHAR_SOCKET "/tmp/shar-socket"
30
31 #endif
32
33 /* shib-rpcutil.c */
34
35 /* Create an RPC Client handle for the _connected_ socket sock, attaching
36  * the RPC program and version.
37  *
38  * returns a CLIENT on success, or NULL on error.  The caller can
39  * call clnt_pcreateerror ("<string>") to output an error message from
40  * the RPC library.
41  */
42 CLIENT * shibrpc_client_create (ShibSocket sock, u_long program, u_long version);
43
44 /* shib-sock.c */
45
46 /* Create a new socket and put it into sock.
47  *
48  * Returns 0 on success, non-zero on error 
49  */
50 int shib_sock_create (ShibSocket *sock);
51
52 /*
53  * bind the socket s to the "port" name.
54  *
55  * Returns 0 on success; non-zero on error.
56  *
57  * SIDE EFFECT: On error, the socket is closed!
58  */
59 int shib_sock_bind (ShibSocket s, ShibSockName name);
60
61 /*
62  * connect the socket s to the "port" name on the local host.
63  *
64  * Returns 0 on success; non-zero on error.
65  */
66 int shib_sock_connect (ShibSocket s, ShibSockName name);
67
68 /*
69  * accept a connection.  Returns 0 on success, non-zero on failure.
70  */
71 int shib_sock_accept (ShibSocket listener, ShibSocket* s);
72
73 /*
74  * close the socket
75  */
76 void shib_sock_close (ShibSocket s, ShibSockName name);
77
78 /* shib-target.cpp */
79
80 /* application names */
81 #define SHIBTARGET_GENERAL      "general"
82 #define SHIBTARGET_SHAR     "shar"
83 #define SHIBTARGET_SHIRE        "shire"
84 #define SHIBTARGET_RM           "rm"
85 #define SHIBTARGET_POLICIES "policies"
86
87 /* configuration tags */
88 #define SHIBTARGET_TAG_LOGGER   "logger"
89 #define SHIBTARGET_TAG_SCHEMAS  "schemadir"
90 #define SHIBTARGET_TAG_CERTFILE "certfile"
91 #define SHIBTARGET_TAG_KEYFILE  "keyfile"
92 #define SHIBTARGET_TAG_KEYPASS  "keypass"
93 #define SHIBTARGET_TAG_CALIST   "calist"
94
95 #define SHIBTARGET_TAG_SITES    "sitesFile"
96 #define SHIBTARGET_TAG_SITESCERT "sitesCertFile"
97 #define SHIBTARGET_TAG_SITESREFRESH "sitesRefresh"
98
99 #define SHIBTARGET_TAG_CACHETYPE        "cacheType"
100 #define SHIBTARGET_TAG_CACHECLEAN       "cacheClean"
101 #define SHIBTARGET_TAG_CACHETIMEOUT     "cacheTimeout"
102
103 #define SHIBTARGET_TAG_REQATTRS         "requestAttributes"
104
105 /* initialize and finalize the target library (return 0 on success, 1 on failure) */
106 int shib_target_initialize (const char* application, const char* ini_file);
107 void shib_target_finalize (void);
108 ShibSockName shib_target_sockname(void);
109
110 #ifdef __cplusplus
111 }
112
113
114 // SAML Runtime
115 #include <saml/saml.h>
116 #include <shib/shib.h>
117
118 namespace shibtarget {
119   class ResourcePriv;
120   class Resource
121   {
122   public:
123     Resource(const char* resource_url);
124     Resource(std::string resource_url);
125     ~Resource();
126
127     const char* getResource() const;
128     const char* getURL() const;
129     bool equals(Resource*) const;
130     saml::Iterator<saml::SAMLAttribute*> getDesignators() const;
131
132   private:
133     ResourcePriv *m_priv;
134   };
135
136
137   class CCacheEntry
138   {
139   public:
140     virtual saml::Iterator<saml::SAMLAssertion*> getAssertions(Resource& resource) = 0;
141     virtual void preFetch(Resource& resource, int prefetch_window) = 0;
142
143     virtual bool isSessionValid(time_t lifetime, time_t timeout) = 0;
144     virtual const char* getClientAddress() = 0;
145     virtual void release() = 0;
146   };
147     
148   class CCache
149   {
150   public:
151     virtual ~CCache() = 0;
152
153     virtual saml::SAMLBinding* getBinding(const XMLCh* bindingProt) = 0;
154
155     // insert() the Auth Statement into the CCache.
156     //
157     // Make sure you do not hold any open CCacheEntry objects before
158     // you call this method.
159     //
160     virtual void insert(const char* key, saml::SAMLAuthenticationStatement *s,
161                         const char *client_addr) = 0;
162
163     // find() a CCacheEntry in the CCache for the given key.
164     //
165     // This returns a LOCKED cache entry.  You should release() it
166     // when you are done using it.
167     //
168     // Note that you MUST NOT call any other CCache methods while you
169     // are holding this CCacheEntry!
170     //
171     virtual CCacheEntry* find(const char* key) = 0;
172
173     // remove() a key from the CCache
174     //
175     // NOTE: If you previously executed a find(), make sure you
176     // "release()" the CCacheEntry before you try to remove it!
177     //
178     virtual void remove(const char* key) = 0;
179     
180     // create a CCache instance of the provided type.  A NULL type
181     // implies that it should create the default cache type.
182     //
183     static CCache* getInstance(const char* type);
184   };    
185
186   extern CCache* g_shibTargetCCache;
187
188   class RPCHandleInternal;
189   class RPCHandle
190   {
191   public:
192     RPCHandle(ShibSockName shar, u_long program, u_long version);
193     ~RPCHandle();
194
195     CLIENT *    connect(void);  /* locks the HANDLE and returns the CLIENT */
196     void        release(void);  /* unlocks the HANDLE */
197     void        disconnect(void); /* disconnects */
198
199   private:
200     RPCHandleInternal *m_priv;
201   };
202
203   class ShibTargetException : public std::exception
204   {
205   public:
206     explicit ShibTargetException() { m_code = SHIBRPC_OK; m_msg=""; }
207     explicit ShibTargetException(ShibRpcStatus code, const char* msg) { m_code = code; if (msg) m_msg=msg; }
208     explicit ShibTargetException(ShibRpcStatus code, const std::string& msg) : m_msg(msg) { m_code=code; }
209     virtual ~ShibTargetException() throw () {}
210     virtual const char* what() const throw () { return (m_msg.c_str()); }
211     virtual ShibRpcStatus which() const throw () { return (m_code); }
212
213   private:
214     ShibRpcStatus       m_code;
215     std::string         m_msg;
216   };
217
218   class RPCErrorPriv;
219   class RPCError
220   {
221   public:
222     RPCError() { init(0,""); }
223     RPCError(int s, char const* st) { init(s,st); }
224     RPCError(ShibTargetException &exp) { init(exp.which(), exp.what()); }
225     ~RPCError();
226
227     bool        isError() { return (status != 0); }
228     bool        isRetryable();
229
230     // Return a string that corresponds to the "status"
231     const char* toString();
232
233     int         status;
234     std::string error_msg;
235     saml::SAMLException* m_except;
236
237   private:
238     void init(int code, char const* msg);
239     RPCErrorPriv* m_priv;
240   };
241
242   class SHIREConfig
243   {
244   public:
245     bool        checkIPAddress;
246     time_t      lifetime;
247     time_t      timeout;
248   };
249
250   class SHIREPriv;
251   class SHIRE
252   {
253   public:
254     SHIRE(RPCHandle *rpc, SHIREConfig config, std::string shire_url);
255     ~SHIRE();
256
257     RPCError* sessionIsValid(const char* cookie, const char* ip, const char* url);
258     RPCError* sessionCreate(const char* post, const char* ip,
259                              std::string &cookie);
260   private:
261     SHIREPriv *m_priv;
262   };
263
264   class RMConfig
265   {
266   public:
267     bool        checkIPAddress;
268   };
269
270   class RMPriv;
271   class RM
272   {
273   public:
274     RM(RPCHandle *rpc, RMConfig config);
275     ~RM();
276
277     RPCError* getAssertions(const char* cookie, const char* ip,
278                             const char* url,
279                             std::vector<saml::SAMLAssertion*> &assertions);
280     static void serialize(saml::SAMLAssertion &assertion, std::string &result);
281     static saml::Iterator<saml::SAMLAttribute*> getAttributes(saml::SAMLAssertion &assertion);
282   private:
283     RMPriv *m_priv;
284   };
285
286   class ShibINIPriv;
287   class ShibINI {
288   public:
289     ShibINI (std::string& file, bool case_sensitive = true) { init(file,case_sensitive); }
290     ShibINI (const char *file, bool case_sensitive = true) {
291       std::string f = file;
292       init(f, case_sensitive);
293     }
294     ~ShibINI ();
295
296     void refresh(void);
297
298     const std::string get (const std::string& header, const std::string& tag);
299     const std::string get (const char* header, const char* tag) {
300       std::string h = header, t = tag;
301       return get(h,t);
302     }
303
304     const std::string operator() (const std::string& header, const std::string& tag)  {
305       return get(header,tag);
306     }
307     const std::string operator() (const char* header, const char* tag) {
308       std::string h = header, t = tag;
309       return get(h,t);
310     }
311
312     bool exists(const std::string& header);
313     bool exists(const std::string& header, const std::string& tag);
314
315     bool exists(const char* header) {
316       std::string s = header;
317       return exists(s);
318     }
319     bool exists(const char* header, const char* tag) {
320       std::string h = header, t = tag;
321       return exists(h,t);
322     }
323
324     // Special method to look for a tag in one header and maybe in the
325     // 'SHIBTARGET_GENERAL' header
326     bool get_tag(std::string& header, std::string& tag, bool try_general,
327                  std::string* result);
328
329     bool get_tag(std::string& header, const char* tag, bool try_general,
330                  std::string* result) {
331       std::string t = tag;
332       return get_tag (header,t,try_general,result);
333     }
334
335     bool get_tag(const char* header, const char* tag, bool try_general,
336                  std::string* result) {
337       std::string h = header, t = tag;
338       return get_tag (h,t,try_general,result);
339     }
340
341     // Dump out the inifile to the output stream
342     void dump(std::ostream& os);
343
344     // Iterators
345
346     // The begin() functions reset the iterator and return the first element
347     // (or 0 if there are no elements.)
348     // The next() functions return the next element, or 0 if there are no
349     // elements left.
350     //
351     // Example:
352     // for (const foo* current = begin(); current; current = next()) {
353     //   ...
354     // }
355     //
356     // NOTE: Holding an Iterator will lock the INI file and cause it to
357     // stop updating itself.  You should destroy the iterator as soon as
358     // you are done with it.
359     //
360     // ALSO NOTE: the string* returned from the Iterator is only valid
361     // while you hold the iterator.  You should copy the de-reference
362     // of the pointer to your own copy if you want to keep the string.
363
364     class Iterator {
365     public:
366       virtual ~Iterator() = 0;
367       virtual const std::string* begin() = 0;
368       virtual const std::string* next() = 0;
369     };
370
371     Iterator* header_iterator();
372     Iterator* tag_iterator(const std::string& header);
373
374     static bool boolean(std::string& value);
375
376   private:
377     ShibINIPriv *m_priv;
378     void init(std::string& file, bool case_sensitive);
379   };
380
381   class ShibMLPPriv;
382   class ShibMLP {
383   public:
384     ShibMLP();
385     ~ShibMLP();
386
387     void insert (const std::string& key, const std::string& value) { m_map[key] = value; }
388     void insert (const std::string& key, const char* value) {
389       std::string v = value;
390       insert (key, v);
391     }
392     void insert (const char* key, const std::string& value) {
393       std::string k = key;
394       insert (k, value);
395     }
396     void insert (const char* key, const char* value) {
397       std::string k = key, v = value;
398       insert(k,v);
399     }
400     void insert (RPCError& e);
401
402     void clear () { m_map.clear(); }
403
404     std::string run (std::istream& s) const;
405     std::string run (const std::string& input) const;
406     std::string run (const char* input) const {
407       std::string i = input;
408       return run(i);
409     }
410
411   private:
412     ShibMLPPriv *m_priv;
413     std::map<std::string,std::string> m_map;
414   };
415
416   class ShibTargetConfig
417   {
418   public:
419     static void preinit();
420     static ShibTargetConfig& init(const char* app_name, const char* inifile);
421     static ShibTargetConfig& getConfig();
422     virtual void init() = 0;
423     virtual void shutdown() = 0;
424     virtual ~ShibTargetConfig();
425     virtual ShibINI& getINI() = 0;
426     virtual saml::Iterator<const XMLCh*> getPolicies() = 0;
427     
428     ShibSockName m_SocketName;
429   };
430
431 } // namespace
432 #endif
433
434 #endif /* SHIB_TARGET_H */