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.
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>
45 #if defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
52 #include <shibsp/ServiceProvider.h>
53 #include <shibsp/remoting/ListenerService.h>
54 #include <xercesc/util/XMLUniDefs.hpp>
55 #include <xmltooling/XMLToolingConfig.h>
56 #include <xmltooling/util/XMLConstants.h>
57 #include <xmltooling/util/XMLHelper.h>
59 using namespace shibsp;
60 using namespace xmltooling;
63 bool shibd_shutdown = false;
64 const char* shar_config = nullptr;
65 const char* shar_schemadir = nullptr;
66 const char* shar_prefix = nullptr;
67 bool shar_checkonly = false;
68 bool shar_version = false;
69 static bool unlink_socket = false;
70 const char* pidfile = nullptr;
76 #define nNoMansLandSize 4
77 typedef struct _CrtMemBlockHeader
79 struct _CrtMemBlockHeader * pBlockHeaderNext;
80 struct _CrtMemBlockHeader * pBlockHeaderPrev;
86 unsigned char gap[nNoMansLandSize];
88 * unsigned char data[nDataSize];
89 * unsigned char anotherGap[nNoMansLandSize];
94 int MyAllocHook(int nAllocType, void *pvData,
95 size_t nSize, int nBlockUse, long lRequest,
96 const unsigned char * szFileName, int nLine)
98 if ( nBlockUse == _CRT_BLOCK )
100 if (nAllocType == _HOOK_FREE) {
101 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
102 if (ptr->nDataSize == 8192)
103 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
105 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
106 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
111 int real_main(int preinit)
115 fprintf(stdout, PACKAGE_STRING"\n");
119 SPConfig& conf = SPConfig::getConfig();
121 // Initialize the SP library.
127 SPConfig::Credentials |
128 SPConfig::AttributeResolution |
130 SPConfig::OutOfProcess |
131 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
133 if (!conf.init(shar_schemadir, shar_prefix)) {
134 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
138 if (!conf.instantiate(shar_config)) {
139 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
144 // If just a test run, bail.
145 if (shar_checkonly) {
146 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
152 //_CrtSetAllocHook(MyAllocHook);
154 if (!shar_checkonly) {
156 ListenerService* listener = conf.getServiceProvider()->getListenerService();
157 if (!listener->init(unlink_socket)) {
158 fprintf(stderr, "listener failed to initialize\n");
162 else if (!listener->run(&shibd_shutdown)) {
163 fprintf(stderr, "listener failed during service\n");
179 bool shibd_running = false;
180 bool daemonize = true;
181 const char* runasuser = nullptr;
182 const char* runasgroup = nullptr;
184 static void term_handler(int arg)
186 shibd_shutdown = true;
189 static void run_handler(int arg)
191 shibd_running = true;
194 static void child_handler(int arg)
196 // Terminate the parent's wait/sleep if the newly born daemon dies early.
199 static int setup_signals(void)
202 memset(&sa, 0, sizeof (sa));
203 sa.sa_handler = SIG_IGN;
204 sa.sa_flags = SA_RESTART;
206 if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
210 memset(&sa, 0, sizeof (sa));
211 sa.sa_handler = term_handler;
212 sa.sa_flags = SA_RESTART;
214 if (sigaction(SIGHUP, &sa, nullptr) < 0) {
217 if (sigaction(SIGINT, &sa, nullptr) < 0) {
220 if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
223 if (sigaction(SIGTERM, &sa, nullptr) < 0) {
228 memset(&sa, 0, sizeof (sa));
229 sa.sa_handler = run_handler;
231 if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
235 memset(&sa, 0, sizeof (sa));
236 sa.sa_handler = child_handler;
238 if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
246 static void usage(char* whoami)
248 fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
249 fprintf(stderr, " -d\tinstallation prefix to use\n");
250 fprintf(stderr, " -c\tconfig file to use\n");
251 fprintf(stderr, " -x\tXML schema catalogs to use\n");
252 fprintf(stderr, " -t\ttest configuration file for problems\n");
253 fprintf(stderr, " -f\tforce removal of listener socket\n");
254 fprintf(stderr, " -F\tstay in the foreground\n");
255 fprintf(stderr, " -p\tpid file to use\n");
256 fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
257 fprintf(stderr, " -u\tuser to run under\n");
258 fprintf(stderr, " -g\tgroup to run under\n");
259 fprintf(stderr, " -v\tprint software version\n");
260 fprintf(stderr, " -h\tprint this help message\n");
264 static int parse_args(int argc, char* argv[])
268 while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
277 shar_schemadir=optarg;
280 unlink_socket = true;
297 daemon_wait = atoi(optarg);
298 if (daemon_wait <= 0)
316 int main(int argc, char *argv[])
318 if (parse_args(argc, argv) != 0)
320 else if (shar_version) {
321 fprintf(stdout, PACKAGE_STRING"\n");
325 if (setup_signals() != 0)
330 struct group* grp = getgrnam(runasgroup);
332 fprintf(stderr, "getgrnam failed, check -g option\n");
335 if (setgid(grp->gr_gid) != 0) {
336 fprintf(stderr, "setgid failed, check -g option\n");
340 fprintf(stderr, "-g not supported on this platform");
347 struct passwd* pwd = getpwnam(runasuser);
349 fprintf(stderr, "getpwnam failed, check -u option\n");
352 #ifdef HAVE_INITGROUPS
353 // w/out initgroups/setgroups process retains supplementary groups
354 if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
355 fprintf(stderr, "initgroups failed, check -u option\n");
359 if (setuid(pwd->pw_uid) != 0) {
360 fprintf(stderr, "setuid failed, check -u option\n");
364 fprintf(stderr, "-u not supported on this platform");
369 // initialize the shib-target library
370 SPConfig& conf=SPConfig::getConfig();
376 SPConfig::Credentials |
377 SPConfig::AttributeResolution |
379 SPConfig::OutOfProcess |
380 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
382 if (!conf.init(shar_schemadir, shar_prefix)) {
383 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
388 // We must fork() early, while we're single threaded.
389 // StorageService cleanup thread is about to start.
398 exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
402 if (!conf.instantiate(shar_config)) {
403 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
409 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
411 // Init the listener.
412 ListenerService* listener = conf.getServiceProvider()->getListenerService();
413 if (!listener->init(unlink_socket)) {
414 fprintf(stderr, "listener failed to initialize\n");
420 if (setsid() == -1) {
424 if (chdir("/") == -1) {
425 perror("chdir to root");
430 FILE* pidf = fopen(pidfile, "w");
432 fprintf(pidf, "%d\n", getpid());
440 freopen("/dev/null", "r", stdin);
441 freopen("/dev/null", "w", stdout);
442 freopen("/dev/null", "w", stderr);
444 // Signal our parent that we are A-OK.
445 kill(getppid(), SIGUSR1);
449 if (!listener->run(&shibd_shutdown)) {
450 fprintf(stderr, "listener failure during service\n");
453 if (daemonize && pidfile)
461 if (daemonize && pidfile)