2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * shibd.cpp -- the shibd "main" code. All the functionality is elsewhere
26 // eventually we might be able to support autoconf via cygwin...
27 #if defined (_MSC_VER) || defined(__BORLANDC__)
28 # include "config_win32.h"
34 # define _CRT_NONSTDC_NO_DEPRECATE 1
35 # define _CRT_SECURE_NO_DEPRECATE 1
38 #include <shibsp/SPConfig.h>
42 #include <sys/select.h>
47 #include <shibsp/ServiceProvider.h>
48 #include <shibsp/remoting/ListenerService.h>
49 #include <xercesc/util/XMLUniDefs.hpp>
50 #include <xmltooling/XMLToolingConfig.h>
51 #include <xmltooling/util/XMLConstants.h>
52 #include <xmltooling/util/XMLHelper.h>
54 using namespace shibsp;
55 using namespace xmltooling;
58 bool shibd_shutdown = false;
59 const char* shar_config = nullptr;
60 const char* shar_schemadir = nullptr;
61 const char* shar_prefix = nullptr;
62 bool shar_checkonly = false;
63 bool shar_version = false;
64 static bool unlink_socket = false;
65 const char* pidfile = nullptr;
71 #define nNoMansLandSize 4
72 typedef struct _CrtMemBlockHeader
74 struct _CrtMemBlockHeader * pBlockHeaderNext;
75 struct _CrtMemBlockHeader * pBlockHeaderPrev;
81 unsigned char gap[nNoMansLandSize];
83 * unsigned char data[nDataSize];
84 * unsigned char anotherGap[nNoMansLandSize];
89 int MyAllocHook(int nAllocType, void *pvData,
90 size_t nSize, int nBlockUse, long lRequest,
91 const unsigned char * szFileName, int nLine)
93 if ( nBlockUse == _CRT_BLOCK )
95 if (nAllocType == _HOOK_FREE) {
96 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
97 if (ptr->nDataSize == 8192)
98 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
100 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
101 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
106 int real_main(int preinit)
108 SPConfig& conf=SPConfig::getConfig();
111 // Initialize the SP library.
117 SPConfig::Credentials |
118 SPConfig::AttributeResolution |
120 SPConfig::OutOfProcess |
121 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
123 if (!conf.init(shar_schemadir, shar_prefix)) {
124 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
128 if (!conf.instantiate(shar_config)) {
129 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
134 // If just a test run, bail.
135 if (shar_checkonly) {
136 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
142 //_CrtSetAllocHook(MyAllocHook);
144 if (!shar_checkonly) {
146 ListenerService* listener = conf.getServiceProvider()->getListenerService();
147 if (!listener->init(unlink_socket)) {
148 fprintf(stderr, "listener failed to initialize\n");
152 else if (!listener->run(&shibd_shutdown)) {
153 fprintf(stderr, "listener failed during service\n");
169 bool shibd_running = false;
170 bool daemonize = true;
172 gid_t runasgroup = 0;
174 static void term_handler(int arg)
176 shibd_shutdown = true;
179 static void run_handler(int arg)
181 shibd_running = true;
184 static void child_handler(int arg)
186 // Terminate the parent's wait/sleep if the newly born daemon dies early.
189 static int setup_signals(void)
192 memset(&sa, 0, sizeof (sa));
193 sa.sa_handler = SIG_IGN;
194 sa.sa_flags = SA_RESTART;
196 if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
200 memset(&sa, 0, sizeof (sa));
201 sa.sa_handler = term_handler;
202 sa.sa_flags = SA_RESTART;
204 if (sigaction(SIGHUP, &sa, nullptr) < 0) {
207 if (sigaction(SIGINT, &sa, nullptr) < 0) {
210 if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
213 if (sigaction(SIGTERM, &sa, nullptr) < 0) {
218 memset(&sa, 0, sizeof (sa));
219 sa.sa_handler = run_handler;
221 if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
225 memset(&sa, 0, sizeof (sa));
226 sa.sa_handler = child_handler;
228 if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
236 static void usage(char* whoami)
238 fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);
239 fprintf(stderr, " -d\tinstallation prefix to use\n");
240 fprintf(stderr, " -c\tconfig file to use\n");
241 fprintf(stderr, " -x\tXML schema catalogs to use\n");
242 fprintf(stderr, " -t\ttest configuration file for problems\n");
243 fprintf(stderr, " -f\tforce removal of listener socket\n");
244 fprintf(stderr, " -F\tstay in the foreground\n");
245 fprintf(stderr, " -p\tpid file to use\n");
246 fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
247 fprintf(stderr, " -u\tuid to run under\n");
248 fprintf(stderr, " -g\tgid to run under\n");
249 fprintf(stderr, " -v\tprint software version\n");
250 fprintf(stderr, " -h\tprint this help message\n");
254 static int parse_args(int argc, char* argv[])
258 while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
267 shar_schemadir=optarg;
270 unlink_socket = true;
287 daemon_wait = atoi(optarg);
288 if (daemon_wait <= 0)
293 runasuser = atoi(optarg);
297 runasgroup = atoi(optarg);
306 int main(int argc, char *argv[])
308 if (parse_args(argc, argv) != 0)
310 else if (shar_version) {
311 fprintf(stdout, PACKAGE_STRING"\n");
315 if (setup_signals() != 0)
318 if (runasgroup > 0 && setgid(runasgroup) != 0) {
319 fprintf(stderr, "setgid failed, check -g option");
323 if (runasuser > 0 && setuid(runasuser) != 0) {
324 fprintf(stderr, "setuid failed, check -u option");
328 // initialize the shib-target library
329 SPConfig& conf=SPConfig::getConfig();
335 SPConfig::Credentials |
336 SPConfig::AttributeResolution |
338 SPConfig::OutOfProcess |
339 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
341 if (!conf.init(shar_schemadir, shar_prefix)) {
342 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
347 // We must fork() early, while we're single threaded.
348 // StorageService cleanup thread is about to start.
357 exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
361 if (!conf.instantiate(shar_config)) {
362 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
368 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
370 // Init the listener.
371 ListenerService* listener = conf.getServiceProvider()->getListenerService();
372 if (!listener->init(unlink_socket)) {
373 fprintf(stderr, "listener failed to initialize\n");
379 if (setsid() == -1) {
383 if (chdir("/") == -1) {
384 perror("chdir to root");
389 FILE* pidf = fopen(pidfile, "w");
391 fprintf(pidf, "%d\n", getpid());
399 freopen("/dev/null", "r", stdin);
400 freopen("/dev/null", "w", stdout);
401 freopen("/dev/null", "w", stderr);
403 // Signal our parent that we are A-OK.
404 kill(getppid(), SIGUSR1);
408 if (!listener->run(&shibd_shutdown)) {
409 fprintf(stderr, "listener failure during service\n");
412 if (daemonize && pidfile)
420 if (daemonize && pidfile)