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)
113 SPConfig& conf=SPConfig::getConfig();
116 // Initialize the SP library.
122 SPConfig::Credentials |
123 SPConfig::AttributeResolution |
125 SPConfig::OutOfProcess |
126 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
128 if (!conf.init(shar_schemadir, shar_prefix)) {
129 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
133 if (!conf.instantiate(shar_config)) {
134 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
139 // If just a test run, bail.
140 if (shar_checkonly) {
141 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
147 //_CrtSetAllocHook(MyAllocHook);
149 if (!shar_checkonly) {
151 ListenerService* listener = conf.getServiceProvider()->getListenerService();
152 if (!listener->init(unlink_socket)) {
153 fprintf(stderr, "listener failed to initialize\n");
157 else if (!listener->run(&shibd_shutdown)) {
158 fprintf(stderr, "listener failed during service\n");
174 bool shibd_running = false;
175 bool daemonize = true;
176 const char* runasuser = nullptr;
177 const char* runasgroup = nullptr;
179 static void term_handler(int arg)
181 shibd_shutdown = true;
184 static void run_handler(int arg)
186 shibd_running = true;
189 static void child_handler(int arg)
191 // Terminate the parent's wait/sleep if the newly born daemon dies early.
194 static int setup_signals(void)
197 memset(&sa, 0, sizeof (sa));
198 sa.sa_handler = SIG_IGN;
199 sa.sa_flags = SA_RESTART;
201 if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
205 memset(&sa, 0, sizeof (sa));
206 sa.sa_handler = term_handler;
207 sa.sa_flags = SA_RESTART;
209 if (sigaction(SIGHUP, &sa, nullptr) < 0) {
212 if (sigaction(SIGINT, &sa, nullptr) < 0) {
215 if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
218 if (sigaction(SIGTERM, &sa, nullptr) < 0) {
223 memset(&sa, 0, sizeof (sa));
224 sa.sa_handler = run_handler;
226 if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
230 memset(&sa, 0, sizeof (sa));
231 sa.sa_handler = child_handler;
233 if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
241 static void usage(char* whoami)
243 fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
244 fprintf(stderr, " -d\tinstallation prefix to use\n");
245 fprintf(stderr, " -c\tconfig file to use\n");
246 fprintf(stderr, " -x\tXML schema catalogs to use\n");
247 fprintf(stderr, " -t\ttest configuration file for problems\n");
248 fprintf(stderr, " -f\tforce removal of listener socket\n");
249 fprintf(stderr, " -F\tstay in the foreground\n");
250 fprintf(stderr, " -p\tpid file to use\n");
251 fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
252 fprintf(stderr, " -u\tuser to run under\n");
253 fprintf(stderr, " -g\tgroup to run under\n");
254 fprintf(stderr, " -v\tprint software version\n");
255 fprintf(stderr, " -h\tprint this help message\n");
259 static int parse_args(int argc, char* argv[])
263 while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
272 shar_schemadir=optarg;
275 unlink_socket = true;
292 daemon_wait = atoi(optarg);
293 if (daemon_wait <= 0)
311 int main(int argc, char *argv[])
313 if (parse_args(argc, argv) != 0)
315 else if (shar_version) {
316 fprintf(stdout, PACKAGE_STRING"\n");
320 if (setup_signals() != 0)
325 struct group* grp = getgrnam(runasgroup);
327 fprintf(stderr, "getgrnam failed, check -g option\n");
330 if (setgid(grp->gr_gid) != 0) {
331 fprintf(stderr, "setgid failed, check -g option\n");
335 fprintf(stderr, "-g not supported on this platform");
342 struct passwd* pwd = getpwnam(runasuser);
344 fprintf(stderr, "getpwnam failed, check -u option\n");
347 if (setuid(pwd->pw_uid) != 0) {
348 fprintf(stderr, "setuid failed, check -u option\n");
352 fprintf(stderr, "-u not supported on this platform");
357 // initialize the shib-target library
358 SPConfig& conf=SPConfig::getConfig();
364 SPConfig::Credentials |
365 SPConfig::AttributeResolution |
367 SPConfig::OutOfProcess |
368 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
370 if (!conf.init(shar_schemadir, shar_prefix)) {
371 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
376 // We must fork() early, while we're single threaded.
377 // StorageService cleanup thread is about to start.
386 exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
390 if (!conf.instantiate(shar_config)) {
391 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
397 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
399 // Init the listener.
400 ListenerService* listener = conf.getServiceProvider()->getListenerService();
401 if (!listener->init(unlink_socket)) {
402 fprintf(stderr, "listener failed to initialize\n");
408 if (setsid() == -1) {
412 if (chdir("/") == -1) {
413 perror("chdir to root");
418 FILE* pidf = fopen(pidfile, "w");
420 fprintf(pidf, "%d\n", getpid());
428 freopen("/dev/null", "r", stdin);
429 freopen("/dev/null", "w", stdout);
430 freopen("/dev/null", "w", stderr);
432 // Signal our parent that we are A-OK.
433 kill(getppid(), SIGUSR1);
437 if (!listener->run(&shibd_shutdown)) {
438 fprintf(stderr, "listener failure during service\n");
441 if (daemonize && pidfile)
449 if (daemonize && pidfile)