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>
60 #include <systemd/sd-daemon.h>
72 using namespace shibsp;
73 using namespace xmltooling;
76 bool shibd_shutdown = false;
77 const char* shar_config = nullptr;
78 const char* shar_schemadir = nullptr;
79 const char* shar_prefix = nullptr;
80 bool shar_checkonly = false;
81 bool shar_version = false;
82 static bool unlink_socket = false;
83 const char* pidfile = nullptr;
89 #define nNoMansLandSize 4
90 typedef struct _CrtMemBlockHeader
92 struct _CrtMemBlockHeader * pBlockHeaderNext;
93 struct _CrtMemBlockHeader * pBlockHeaderPrev;
99 unsigned char gap[nNoMansLandSize];
101 * unsigned char data[nDataSize];
102 * unsigned char anotherGap[nNoMansLandSize];
104 } _CrtMemBlockHeader;
107 int MyAllocHook(int nAllocType, void *pvData,
108 size_t nSize, int nBlockUse, long lRequest,
109 const unsigned char * szFileName, int nLine)
111 if ( nBlockUse == _CRT_BLOCK )
113 if (nAllocType == _HOOK_FREE) {
114 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
115 if (ptr->nDataSize == 8192)
116 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
118 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
119 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
124 int real_main(int preinit)
128 fprintf(stdout, PACKAGE_STRING"\n");
132 SPConfig& conf = SPConfig::getConfig();
134 // Initialize the SP library.
140 SPConfig::Credentials |
141 SPConfig::AttributeResolution |
143 SPConfig::OutOfProcess |
144 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
146 if (!conf.init(shar_schemadir, shar_prefix)) {
147 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
151 if (!conf.instantiate(shar_config)) {
152 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
157 // If just a test run, bail.
158 if (shar_checkonly) {
159 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
165 //_CrtSetAllocHook(MyAllocHook);
167 if (!shar_checkonly) {
169 ListenerService* listener = conf.getServiceProvider()->getListenerService();
170 if (!listener->init(unlink_socket)) {
171 fprintf(stderr, "listener failed to initialize\n");
175 else if (!listener->run(&shibd_shutdown)) {
176 fprintf(stderr, "listener failed during service\n");
192 bool shibd_running = false;
193 bool daemonize = true;
194 const char* runasuser = nullptr;
195 const char* runasgroup = nullptr;
197 static void term_handler(int arg)
199 shibd_shutdown = true;
202 static void run_handler(int arg)
204 shibd_running = true;
207 static void child_handler(int arg)
209 // Terminate the parent's wait/sleep if the newly born daemon dies early.
212 static int setup_signals(void)
215 memset(&sa, 0, sizeof (sa));
216 sa.sa_handler = SIG_IGN;
217 sa.sa_flags = SA_RESTART;
219 if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
223 memset(&sa, 0, sizeof (sa));
224 sa.sa_handler = term_handler;
225 sa.sa_flags = SA_RESTART;
227 if (sigaction(SIGHUP, &sa, nullptr) < 0) {
230 if (sigaction(SIGINT, &sa, nullptr) < 0) {
233 if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
236 if (sigaction(SIGTERM, &sa, nullptr) < 0) {
241 memset(&sa, 0, sizeof (sa));
242 sa.sa_handler = run_handler;
244 if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
248 memset(&sa, 0, sizeof (sa));
249 sa.sa_handler = child_handler;
251 if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
259 static void usage(char* whoami)
261 fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
262 fprintf(stderr, " -d\tinstallation prefix to use\n");
263 fprintf(stderr, " -c\tconfig file to use\n");
264 fprintf(stderr, " -x\tXML schema catalogs to use\n");
265 fprintf(stderr, " -t\ttest configuration file for problems\n");
266 fprintf(stderr, " -f\tforce removal of listener socket\n");
267 fprintf(stderr, " -F\tstay in the foreground\n");
268 fprintf(stderr, " -p\tpid file to use\n");
269 fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
270 fprintf(stderr, " -u\tuser to run under\n");
271 fprintf(stderr, " -g\tgroup to run under\n");
272 fprintf(stderr, " -v\tprint software version\n");
273 fprintf(stderr, " -h\tprint this help message\n");
277 static int parse_args(int argc, char* argv[])
281 while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
290 shar_schemadir=optarg;
293 unlink_socket = true;
310 daemon_wait = atoi(optarg);
311 if (daemon_wait <= 0)
329 int main(int argc, char *argv[])
331 if (parse_args(argc, argv) != 0)
333 else if (shar_version) {
334 fprintf(stdout, PACKAGE_STRING"\n");
338 if (setup_signals() != 0)
343 struct group* grp = getgrnam(runasgroup);
345 fprintf(stderr, "getgrnam failed, check -g option\n");
348 if (setgid(grp->gr_gid) != 0) {
349 fprintf(stderr, "setgid failed, check -g option\n");
353 fprintf(stderr, "-g not supported on this platform");
360 struct passwd* pwd = getpwnam(runasuser);
362 fprintf(stderr, "getpwnam failed, check -u option\n");
365 #ifdef HAVE_INITGROUPS
366 // w/out initgroups/setgroups process retains supplementary groups
367 if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
368 fprintf(stderr, "initgroups failed, check -u option\n");
372 if (setuid(pwd->pw_uid) != 0) {
373 fprintf(stderr, "setuid failed, check -u option\n");
377 fprintf(stderr, "-u not supported on this platform");
382 // initialize the shib-target library
383 SPConfig& conf=SPConfig::getConfig();
389 SPConfig::Credentials |
390 SPConfig::AttributeResolution |
392 SPConfig::OutOfProcess |
393 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
395 if (!conf.init(shar_schemadir, shar_prefix)) {
396 fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
401 // We must fork() early, while we're single threaded.
402 // StorageService cleanup thread is about to start.
411 exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
415 if (!conf.instantiate(shar_config)) {
416 fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
422 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
424 // Init the listener.
425 ListenerService* listener = conf.getServiceProvider()->getListenerService();
426 if (!listener->init(unlink_socket)) {
427 fprintf(stderr, SD_ERR "listener failed to initialize\n");
433 if (setsid() == -1) {
437 if (chdir("/") == -1) {
438 perror("chdir to root");
443 FILE* pidf = fopen(pidfile, "w");
445 fprintf(pidf, "%d\n", getpid());
453 freopen("/dev/null", "r", stdin);
454 freopen("/dev/null", "w", stdout);
455 freopen("/dev/null", "w", stderr);
457 // Signal our parent that we are A-OK.
458 kill(getppid(), SIGUSR1);
462 #ifdef HAVE_SD_NOTIFY
463 sd_notify(0, "READY=1");
465 if (!listener->run(&shibd_shutdown)) {
466 fprintf(stderr, SD_ERR "listener failure during service\n");
469 if (daemonize && pidfile)
475 #ifdef HAVE_SD_NOTIFY
476 sd_notify(0, "STOPPING=1");
479 if (daemonize && pidfile)