Moved declaration over.
[shibboleth/sp.git] / shar / shar.cpp
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  * shar.cpp -- the SHAR "main" code.  All the functionality is elsewhere
52  *           (in case you want to turn this into a library later).
53  *
54  * Created By:  Derek Atkins <derek@ihtfp.com>
55  *
56  * $Id$
57  */
58
59 // eventually we might be able to support autoconf via cygwin...
60 #if defined (_MSC_VER) || defined(__BORLANDC__)
61 # include "config_win32.h"
62 #else
63 # include "config.h"
64 #endif
65
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #include <sys/select.h>
69 #endif
70
71 #include <stdio.h>
72 #include <errno.h>
73 #include <signal.h>
74
75 #include "shar-utils.h"
76
77 using namespace std;
78 using namespace saml;
79 using namespace shibboleth;
80 using namespace shibtarget;
81
82 #ifndef FD_SETSIZE
83 # define FD_SETSIZE 1024
84 #endif
85
86 extern "C" void shibrpc_prog_1(struct svc_req* rqstp, register SVCXPRT* transp);
87
88 int shar_run = 1;
89 const char* config = NULL;
90 const char* schemadir = NULL;
91 static int unlink_socket = 0;
92
93 static bool new_connection(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
94 {
95     IListener::ShibSocket sock;
96
97     // Accept the connection.
98     if (ShibTargetConfig::getConfig().getINI()->getListener()->accept(listener, sock))
99         return false;
100
101     // We throw away the result because the children manage themselves...
102     new SharChild(sock,protos);
103     return true;
104 }
105
106 static void shar_svc_run(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
107 {
108     NDC ndc("shar_svc_run");
109
110     while (shar_run) {
111         fd_set readfds;
112         FD_ZERO(&readfds);
113         FD_SET(listener, &readfds);
114         struct timeval tv = { 0, 0 };
115         tv.tv_sec = 5;
116     
117         switch (select(FD_SETSIZE, &readfds, 0, 0, &tv)) {
118             case -1:
119                 if (errno == EINTR) continue;
120                 SHARUtils::log_error();
121                 return;
122         
123             case 0:
124                 continue;
125         
126             default:
127                 new_connection(listener, protos);
128         }
129     }
130     printf("shar_svc_run ended\n");
131 }
132
133 #ifdef WIN32
134
135 int real_main(int preinit)
136 {
137     static IListener::ShibSocket sock;
138     ShibRPCProtocols protos[1] = {
139         { SHIBRPC_PROG, SHIBRPC_VERS_1, shibrpc_prog_1 }
140     };
141
142     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
143     if (preinit) {
144
145         // initialize the shib-target library
146         conf.setFeatures(
147             ShibTargetConfig::Listener |
148             ShibTargetConfig::SessionCache |
149             ShibTargetConfig::Metadata |
150             ShibTargetConfig::Trust |
151             ShibTargetConfig::Credentials |
152             ShibTargetConfig::AAP |
153             ShibTargetConfig::SHARExtensions
154             );
155         if (!config)
156             config=getenv("SHIBCONFIG");
157         if (!schemadir)
158             schemadir=getenv("SHIBSCHEMAS");
159         if (!conf.init(schemadir,config))
160             return -2;
161
162         const IListener* listener=conf.getINI()->getListener();
163         
164         // Create the SHAR listener socket
165         if (!listener->create(sock))
166             return -3;
167
168         // Bind to the proper port
169         if (!listener->bind(sock))
170             return -4;
171
172         // Initialize the SHAR Utilitites
173         SHARUtils::init();
174     }
175     else {
176         // Run the listener
177         shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
178         fprintf(stderr,"shar_svc_run returned\n");
179
180         // Finalize the SHAR, close all clients
181         SHARUtils::fini();
182         conf.getINI()->getListener()->close(sock);
183         conf.shutdown();
184     }
185     return 0;
186 }
187
188 #else
189
190 static void term_handler(int arg)
191 {
192     shar_run = 0;
193 }
194
195 static int setup_signals(void)
196 {
197     NDC ndc("setup_signals");
198     
199     struct sigaction sa;
200     memset(&sa, 0, sizeof (sa));
201     sa.sa_handler = SIG_IGN;
202     sa.sa_flags = SA_RESTART;
203
204     if (sigaction(SIGPIPE, &sa, NULL) < 0) {
205         SHARUtils::log_error();
206         return -1;
207     }
208
209     memset(&sa, 0, sizeof (sa));
210     sa.sa_handler = term_handler;
211     sa.sa_flags = SA_RESTART;
212
213     if (sigaction(SIGHUP, &sa, NULL) < 0) {
214         SHARUtils::log_error();
215         return -1;
216     }
217     if (sigaction(SIGINT, &sa, NULL) < 0) {
218         SHARUtils::log_error();
219         return -1;
220     }
221     if (sigaction(SIGQUIT, &sa, NULL) < 0) {
222         SHARUtils::log_error();
223         return -1;
224     }
225     if (sigaction(SIGTERM, &sa, NULL) < 0) {
226         SHARUtils::log_error();
227         return -1;
228     }
229     return 0;
230 }
231
232 static void usage(char* whoami)
233 {
234     fprintf(stderr, "usage: %s [-f]\n", whoami);
235     fprintf(stderr, "  -c\tconfig file to use.\n");
236     fprintf(stderr, "  -f\tforce removal of listener socket.\n");
237     fprintf(stderr, "  -h\tprint this help message.\n");
238     exit(1);
239 }
240
241 static int parse_args(int argc, char* argv[])
242 {
243     int opt;
244
245     while ((opt = getopt(argc, argv, "cfFh")) > 0) {
246         switch (opt) {
247             case 'c':
248                 config=optarg;
249                 break;
250             case 'd':
251                 schemadir=optarg;
252                 break;
253             case 'f':
254                 unlink_socket = 1;
255                 break;
256             default:
257                 return -1;
258         }
259     }
260     return 0;
261 }
262
263 int main(int argc, char *argv[])
264 {
265     IListener::ShibSocket sock;
266     ShibRPCProtocols protos[] = {
267         { SHIBRPC_PROG, SHIBRPC_VERS_1, shibrpc_prog_1 }
268     };
269
270     if (setup_signals() != 0)
271         return -1;
272
273     if (parse_args(argc, argv) != 0)
274         usage(argv[0]);
275
276     if (!schemadir)
277         schemadir=getenv("SHIBSCHEMAS");
278     if (!config)
279         config=getenv("SHIBCONFIG");
280
281     // initialize the shib-target library
282     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
283     conf.setFeatures(
284         ShibTargetConfig::Listener |
285         ShibTargetConfig::SessionCache |
286         ShibTargetConfig::Metadata |
287         ShibTargetConfig::Trust |
288         ShibTargetConfig::Credentials |
289         ShibTargetConfig::AAP |
290         ShibTargetConfig::SHARExtensions
291         );
292     if (!conf.init(schemadir,config))
293         return -2;
294
295     const IListener* listener=conf.getINI()->getListener();
296     
297     // Create the SHAR listener socket
298     if (!listener->create(sock))
299         return -3;
300
301     // Bind to the proper port
302     if (!listener->bind(sock, unlink_socket==1))
303         return -4;
304
305     // Initialize the SHAR Utilitites
306     SHARUtils::init();
307
308     // Run the listener
309     shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
310
311     /* Finalize the SHAR, close all clients */
312     SHARUtils::fini();
313     fprintf(stderr, "shar utils finalized\n");
314
315     listener->close(sock);
316     fprintf(stderr, "shib socket closed\n");
317
318     conf.shutdown();
319     fprintf(stderr, "shar finished.  bye bye.\n");
320     return 0;
321 }
322
323 #endif