ERROR constant was conflicting on Windows
[shibboleth/cpp-sp.git] / shib-target / shib-target.h
1 /*
2  * The Shibboleth License, Version 1.
3  * Copyright (c) 2002
4  * University Corporation for Advanced Internet Development, Inc.
5  * All rights reserved
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution, if any, must include
17  * the following acknowledgment: "This product includes software developed by
18  * the University Corporation for Advanced Internet Development
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20  * may appear in the software itself, if and wherever such third-party
21  * acknowledgments normally appear.
22  *
23  * Neither the name of Shibboleth nor the names of its contributors, nor
24  * Internet2, nor the University Corporation for Advanced Internet Development,
25  * Inc., nor UCAID may be used to endorse or promote products derived from this
26  * software without specific prior written permission. For written permission,
27  * please contact shibboleth@shibboleth.org
28  *
29  * Products derived from this software may not be called Shibboleth, Internet2,
30  * UCAID, or the University Corporation for Advanced Internet Development, nor
31  * may Shibboleth appear in their name, without prior written permission of the
32  * University Corporation for Advanced Internet Development.
33  *
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 /*
51  * shib-target.h -- top-level header file for the SHIB Common Target Library
52  *
53  * Created by:  Derek Atkins <derek@ihtfp.com>
54  *
55  * $Id$
56  */
57
58 #ifndef SHIB_TARGET_H
59 #define SHIB_TARGET_H
60
61 #ifdef __cplusplus
62 # include <saml/saml.h>
63 # include <shib/shib.h>
64 # include <shib/shib-threads.h>
65 #endif
66
67 #ifdef WIN32
68 # ifndef SHIBTARGET_EXPORTS
69 #  define SHIBTARGET_EXPORTS __declspec(dllimport)
70 # endif
71 #else
72 # define SHIBTARGET_EXPORTS
73 #endif
74
75 #include <shib-target/shibrpc.h>
76
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80
81 #ifdef WIN32
82
83 #include <winsock.h>
84 typedef SOCKET ShibSocket;
85 typedef const char* ShibSockName;
86 #define SHIB_SHAR_SOCKET "127.0.0.1:12345"  /* TCP host:port */
87
88 #else  /* UNIX */
89
90 typedef int ShibSocket;
91 typedef const char* ShibSockName;
92 #define SHIB_SHAR_SOCKET "/tmp/shar-socket" /* Unix domain socket */
93
94 #endif
95
96 /* shib-rpcutil.c */
97
98 /* Create an RPC Client handle for the _connected_ socket sock, attaching
99  * the RPC program and version.
100  *
101  * returns a CLIENT on success, or NULL on error.  The caller can
102  * call clnt_pcreateerror ("<string>") to output an error message from
103  * the RPC library.
104  */
105 SHIBTARGET_EXPORTS CLIENT * shibrpc_client_create (ShibSocket sock, u_long program, u_long version);
106
107 /* shib-sock.c */
108
109 /* Create a new socket and put it into sock.
110  *
111  * Returns 0 on success, non-zero on error 
112  */
113 SHIBTARGET_EXPORTS int shib_sock_create (ShibSocket *sock);
114
115 /*
116  * bind the socket s to the "port" name.
117  *
118  * Returns 0 on success; non-zero on error.
119  *
120  * SIDE EFFECT: On error, the socket is closed!
121  */
122 SHIBTARGET_EXPORTS int shib_sock_bind (ShibSocket s, ShibSockName name);
123
124 /*
125  * connect the socket s to the "port" name on the local host.
126  *
127  * Returns 0 on success; non-zero on error.
128  */
129 SHIBTARGET_EXPORTS int shib_sock_connect (ShibSocket s, ShibSockName name);
130
131 /*
132  * accept a connection.  Returns 0 on success, non-zero on failure.
133  */
134 SHIBTARGET_EXPORTS int shib_sock_accept (ShibSocket listener, ShibSocket* s);
135
136 /*
137  * close the socket
138  */
139 SHIBTARGET_EXPORTS void shib_sock_close (ShibSocket s, ShibSockName name);
140
141 /* shib-target.cpp */
142
143 /* application names */
144 #define SHIBTARGET_GENERAL  "general"
145 #define SHIBTARGET_SHAR     "shar"
146 #define SHIBTARGET_SHIRE    "shire"
147 #define SHIBTARGET_RM       "rm"
148 #define SHIBTARGET_POLICIES "policies"
149
150 /* configuration tags */
151 #define SHIBTARGET_TAG_LOGGER   "logger"
152 #define SHIBTARGET_TAG_SCHEMAS  "schemadir"
153 #define SHIBTARGET_TAG_CERTFILE "certfile"
154 #define SHIBTARGET_TAG_KEYFILE  "keyfile"
155 #define SHIBTARGET_TAG_KEYPASS  "keypass"
156 #define SHIBTARGET_TAG_CALIST   "calist"
157
158 #define SHIBTARGET_TAG_AATIMEOUT    "AATimeout"
159 #define SHIBTARGET_TAG_AACONNECTTO  "AAConnectTimeout"
160 #define SHIBTARGET_TAG_SAMLCOMPAT   "SAMLCompat"
161
162 #define SHIBTARGET_TAG_METADATA "metadata"
163
164 #define SHIBTARGET_TAG_DEFAULTLIFE  "defaultLife"
165
166 #define SHIBTARGET_TAG_CACHETYPE    "cacheType"
167 #define SHIBTARGET_TAG_CACHECLEAN   "cacheClean"
168 #define SHIBTARGET_TAG_CACHETIMEOUT "cacheTimeout"
169
170 #define SHIBTARGET_TAG_REQATTRS     "requestAttributes"
171
172 /* initialize and finalize the target library (return 0 on success, 1 on failure) */
173 SHIBTARGET_EXPORTS int shib_target_initialize (const char* application, const char* ini_file);
174 SHIBTARGET_EXPORTS void shib_target_finalize (void);
175
176 /* access socket specifics from C code */
177 SHIBTARGET_EXPORTS ShibSockName shib_target_sockname(void);
178 SHIBTARGET_EXPORTS ShibSockName shib_target_sockacl(unsigned int index);
179
180 #ifdef __cplusplus
181 }
182
183
184 namespace shibtarget {
185   class ResourcePriv;
186   class SHIBTARGET_EXPORTS Resource
187   {
188   public:
189     Resource(const char* resource_url);
190     Resource(std::string resource_url);
191     ~Resource();
192
193     const char* getResource() const;
194     const char* getURL() const;
195     bool equals(Resource*) const;
196     saml::Iterator<saml::SAMLAttribute*> getDesignators() const;
197
198   private:
199     ResourcePriv *m_priv;
200   };
201
202   class RPCHandleInternal;
203   class SHIBTARGET_EXPORTS RPCHandle
204   {
205   public:
206     RPCHandle(ShibSockName shar, u_long program, u_long version);
207     ~RPCHandle();
208
209     CLIENT *    connect(void);  /* locks the HANDLE and returns the CLIENT */
210     void        release(void);  /* unlocks the HANDLE */
211     void        disconnect(void); /* disconnects */
212
213     // A simple function to get a handle
214     // Note that it does not check that an existing handle matches the request.
215     static RPCHandle* get_handle(shibboleth::ThreadKey* key,
216                                  ShibSockName shar, u_long program,
217                                  u_long version);
218
219   private:
220     RPCHandleInternal *m_priv;
221   };
222
223   class SHIBTARGET_EXPORTS ShibTargetException : public std::exception
224   {
225   public:
226     explicit ShibTargetException() : m_origin(NULL), m_code(SHIBRPC_OK) {}
227     explicit ShibTargetException(ShibRpcStatus code, const char* msg, const XMLCh* origin = NULL) : m_code(code)
228     { if (msg) m_msg=msg; m_origin = XMLString::replicate(origin); }
229     explicit ShibTargetException(ShibRpcStatus code, const std::string& msg, const XMLCh* origin = NULL) : m_msg(msg)
230         { m_code=code; m_origin = XMLString::replicate(origin); }
231     virtual ~ShibTargetException() throw () { if (m_origin) XMLString::release(&m_origin); }
232     virtual const char* what() const throw () { return (m_msg.c_str()); }
233     virtual ShibRpcStatus which() const throw () { return (m_code); }
234     virtual const XMLCh* where() const throw () { return m_origin; }
235
236   private:
237     ShibRpcStatus m_code;
238     std::string m_msg;
239     XMLCh* m_origin;
240   };
241
242   class RPCErrorPriv;
243   class SHIBTARGET_EXPORTS RPCError
244   {
245   public:
246     RPCError() { init(0, "", NULL); }
247     RPCError(ShibRpcError* error);
248     RPCError(int s, char const* st, const XMLCh* orig = NULL) { init (s,st,orig); }
249     RPCError(ShibTargetException &exp) { init(exp.which(), exp.what(), exp.where()); }
250     ~RPCError();
251
252     bool        isError();
253     bool        isRetryable();
254
255     // Return a set of strings that corresponds to the type, text, and desc
256     const char* getType();
257     const char* getText();
258     const char* getDesc();
259     std::string getOriginErrorURL();
260     std::string getOriginContactName();
261     std::string getOriginContactEmail();
262     int getCode();
263
264   private:
265     void init(int stat, char const* msg, const XMLCh* origin);
266     RPCErrorPriv* m_priv;
267   };
268
269   // The ShibTargetError is used by the high-level SHIRE and RM methods
270   // to notify the handlers of high-level errors.
271
272   class ShibMLPPriv;
273   class SHIBTARGET_EXPORTS ShibMLP {
274   public:
275     ShibMLP();
276     ~ShibMLP();
277
278     void insert (const std::string& key, const std::string& value);
279     void insert (const std::string& key, const char* value) {
280       std::string v = value;
281       insert (key, v);
282     }
283     void insert (const char* key, const std::string& value) {
284       std::string k = key;
285       insert (k, value);
286     }
287     void insert (const char* key, const char* value) {
288       std::string k = key, v = value;
289       insert(k,v);
290     }
291     void insert (RPCError& e);
292
293     void clear () { m_map.clear(); }
294
295     std::string run (std::istream& s) const;
296     std::string run (const std::string& input) const;
297     std::string run (const char* input) const {
298       std::string i = input;
299       return run(i);
300     }
301
302   private:
303     ShibMLPPriv *m_priv;
304     std::map<std::string,std::string> m_map;
305   };
306
307   class SHIBTARGET_EXPORTS ShibTargetResponse
308   {
309   public:
310     // What to do with the response
311     enum ReturnValue {
312       OK = 0,
313       DECLINED,
314       REDIRECT,
315       INTERNAL_ERROR
316     };
317
318     // How to log the message, if any.  (NONE implies no log_msg)
319     enum LogLevel {
320       NONE = 0,
321       DEBUG,
322       INFO,
323       ERR,
324       CRIT
325     };
326
327     ReturnValue status;
328     LogLevel    log_level;
329     bool        has_mlp;
330
331     std::string log_msg;        // message to log if log_level != NONE
332     std::string redirect_to;    // where to redirect if status == REDIRECT
333     ShibMLP     mlp;            // MLP information if has_mlp == true
334   };
335
336   class SHIBTARGET_EXPORTS ShibTargetError : public std::exception
337   {
338   public:
339     explicit ShibTargetError(ShibTargetResponse *resp = NULL) { m_resp = resp; }
340     virtual ~ShibTargetError() throw () { if (m_resp) delete m_resp; }
341     virtual const ShibTargetResponse* getError() { return m_resp; }
342
343   private:
344     ShibTargetResponse *m_resp;
345   };
346
347   class SHIBTARGET_EXPORTS SHIREConfig
348   {
349   public:
350     bool        checkIPAddress;
351     time_t      lifetime;
352     time_t      timeout;
353   };
354
355   class SHIREPriv;
356   class SHIBTARGET_EXPORTS ShibINI;
357   class SHIBTARGET_EXPORTS SHIRE
358   {
359   public:
360     SHIRE(RPCHandle *rpc, SHIREConfig config, std::string shire_url);
361     ~SHIRE();
362
363     RPCError* sessionIsValid(const char* cookie, const char* ip, const char* url);
364     RPCError* sessionCreate(const char* post, const char* ip,
365                              std::string &cookie);
366
367     //ShibTargetResponse* is_valid(ShibINI& ini, const char* serverName,
368     //                   const char *cookie, const char *target_url);
369     //ShibTargetResponse* create();
370
371   private:
372     SHIREPriv *m_priv;
373   };
374
375   class SHIBTARGET_EXPORTS RMConfig
376   {
377   public:
378     bool        checkIPAddress;
379   };
380
381   class RMPriv;
382   class SHIBTARGET_EXPORTS RM
383   {
384   public:
385     RM(RPCHandle *rpc, RMConfig config);
386     ~RM();
387
388     RPCError* getAssertions(const char* cookie, const char* ip,
389                             const char* url,
390                             std::vector<saml::SAMLAssertion*> &assertions,
391                             saml::SAMLAuthenticationStatement **statement = NULL);
392     static void serialize(saml::SAMLAssertion &assertion, std::string &result);
393     static saml::Iterator<saml::SAMLAttribute*> getAttributes(saml::SAMLAssertion &assertion);
394   private:
395     RMPriv *m_priv;
396   };
397
398   class ShibINIPriv;
399   class SHIBTARGET_EXPORTS ShibINI {
400   public:
401     ShibINI (std::string& file, bool case_sensitive = true) { init(file,case_sensitive); }
402     ShibINI (const char *file, bool case_sensitive = true) {
403       std::string f = file;
404       init(f, case_sensitive);
405     }
406     ~ShibINI ();
407
408     void refresh(void);
409
410     const std::string get (const std::string& header, const std::string& tag);
411     const std::string get (const char* header, const char* tag) {
412       std::string h = header, t = tag;
413       return get(h,t);
414     }
415
416     const std::string operator() (const std::string& header, const std::string& tag)  {
417       return get(header,tag);
418     }
419     const std::string operator() (const char* header, const char* tag) {
420       std::string h = header, t = tag;
421       return get(h,t);
422     }
423
424     bool exists(const std::string& header);
425     bool exists(const std::string& header, const std::string& tag);
426
427     bool exists(const char* header) {
428       std::string s = header;
429       return exists(s);
430     }
431     bool exists(const char* header, const char* tag) {
432       std::string h = header, t = tag;
433       return exists(h,t);
434     }
435
436     // Special method to look for a tag in one header and maybe in the
437     // 'SHIBTARGET_GENERAL' header
438     bool get_tag(std::string& header, std::string& tag, bool try_general,
439                  std::string* result);
440
441     bool get_tag(std::string& header, const char* tag, bool try_general,
442                  std::string* result) {
443       std::string t = tag;
444       return get_tag (header,t,try_general,result);
445     }
446
447     bool get_tag(const char* header, const char* tag, bool try_general,
448                  std::string* result) {
449       std::string h = header, t = tag;
450       return get_tag (h,t,try_general,result);
451     }
452
453     // Dump out the inifile to the output stream
454     void dump(std::ostream& os);
455
456     // Iterators
457
458     // The begin() functions reset the iterator and return the first element
459     // (or 0 if there are no elements.)
460     // The next() functions return the next element, or 0 if there are no
461     // elements left.
462     //
463     // Example:
464     // for (const foo* current = begin(); current; current = next()) {
465     //   ...
466     // }
467     //
468     // NOTE: Holding an Iterator will lock the INI file and cause it to
469     // stop updating itself.  You should destroy the iterator as soon as
470     // you are done with it.
471     //
472     // ALSO NOTE: the string* returned from the Iterator is only valid
473     // while you hold the iterator.  You should copy the de-reference
474     // of the pointer to your own copy if you want to keep the string.
475
476     class SHIBTARGET_EXPORTS Iterator {
477     public:
478       virtual ~Iterator() {}
479       virtual const std::string* begin() = 0;
480       virtual const std::string* next() = 0;
481     };
482
483     Iterator* header_iterator();
484     Iterator* tag_iterator(const std::string& header);
485
486     static bool boolean(std::string& value);
487
488   private:
489     ShibINIPriv *m_priv;
490     void init(std::string& file, bool case_sensitive);
491   };
492
493   class SHIBTARGET_EXPORTS ShibTargetConfig
494   {
495   public:
496     static void preinit();
497     static ShibTargetConfig& init(const char* app_name, const char* inifile);
498     static ShibTargetConfig& getConfig();
499     virtual void init() = 0;
500     virtual void shutdown() = 0;
501     virtual ~ShibTargetConfig() {}
502     virtual ShibINI& getINI() = 0;
503     virtual saml::Iterator<const XMLCh*> getPolicies() = 0;
504   };
505
506 } // namespace
507 #endif
508
509 #endif /* SHIB_TARGET_H */