-/*
- * Copyright 2001-2010 Internet2
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
*/
/*
- * shibd.cpp -- the shibd "main" code. All the functionality is elsewhere
+ * shibd.cpp -- the shibd "main" code.
*/
#include <shibsp/SPConfig.h>
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#include <sys/select.h>
+# include <unistd.h>
+# include <sys/select.h>
+#endif
+
+#if defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
+# include <pwd.h>
+# include <grp.h>
#endif
#include <stdio.h>
#include <xmltooling/util/XMLConstants.h>
#include <xmltooling/util/XMLHelper.h>
+#ifdef HAVE_SD_NOTIFY
+#include <systemd/sd-daemon.h>
+#else
+#define SD_EMERG ""
+#define SD_ALERT ""
+#define SD_CRIT ""
+#define SD_ERR ""
+#define SD_WARNING ""
+#define SD_NOTICE ""
+#define SD_INFO ""
+#define SD_DEBUG ""
+#endif
+
using namespace shibsp;
using namespace xmltooling;
using namespace std;
int real_main(int preinit)
{
- SPConfig& conf=SPConfig::getConfig();
- if (preinit) {
+ if (shar_version) {
+ if (preinit)
+ fprintf(stdout, PACKAGE_STRING"\n");
+ return 0;
+ }
+ SPConfig& conf = SPConfig::getConfig();
+ if (preinit) {
// Initialize the SP library.
conf.setFeatures(
SPConfig::Listener |
int daemon_wait = 3;
bool shibd_running = false;
bool daemonize = true;
+const char* runasuser = nullptr;
+const char* runasgroup = nullptr;
static void term_handler(int arg)
{
static void usage(char* whoami)
{
- fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);
- fprintf(stderr, " -d\tinstallation prefix to use.\n");
- fprintf(stderr, " -c\tconfig file to use.\n");
- fprintf(stderr, " -x\tXML schema catalogs to use.\n");
- fprintf(stderr, " -t\ttest configuration file for problems.\n");
- fprintf(stderr, " -f\tforce removal of listener socket.\n");
- fprintf(stderr, " -F\tstay in the foreground.\n");
- fprintf(stderr, " -p\tpid file to use.\n");
- fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");
- fprintf(stderr, " -v\tprint software version.\n");
- fprintf(stderr, " -h\tprint this help message.\n");
+ fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
+ fprintf(stderr, " -d\tinstallation prefix to use\n");
+ fprintf(stderr, " -c\tconfig file to use\n");
+ fprintf(stderr, " -x\tXML schema catalogs to use\n");
+ fprintf(stderr, " -t\ttest configuration file for problems\n");
+ fprintf(stderr, " -f\tforce removal of listener socket\n");
+ fprintf(stderr, " -F\tstay in the foreground\n");
+ fprintf(stderr, " -p\tpid file to use\n");
+ fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
+ fprintf(stderr, " -u\tuser to run under\n");
+ fprintf(stderr, " -g\tgroup to run under\n");
+ fprintf(stderr, " -v\tprint software version\n");
+ fprintf(stderr, " -h\tprint this help message\n");
exit(1);
}
{
int opt;
- while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {
+ while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
switch (opt) {
case 'd':
shar_prefix=optarg;
if (daemon_wait <= 0)
daemon_wait = 3;
break;
+ case 'u':
+ if (optarg)
+ runasuser = optarg;
+ break;
+ case 'g':
+ if (optarg)
+ runasgroup = optarg;
+ break;
default:
return -1;
}
if (setup_signals() != 0)
return -1;
+ if (runasgroup) {
+#ifdef HAVE_GETGRNAM
+ struct group* grp = getgrnam(runasgroup);
+ if (!grp) {
+ fprintf(stderr, "getgrnam failed, check -g option\n");
+ return -1;
+ }
+ if (setgid(grp->gr_gid) != 0) {
+ fprintf(stderr, "setgid failed, check -g option\n");
+ return -1;
+ }
+#else
+ fprintf(stderr, "-g not supported on this platform");
+ return -1;
+#endif
+ }
+
+ if (runasuser) {
+#ifdef HAVE_GETPWNAM
+ struct passwd* pwd = getpwnam(runasuser);
+ if (!pwd) {
+ fprintf(stderr, "getpwnam failed, check -u option\n");
+ return -1;
+ }
+#ifdef HAVE_INITGROUPS
+ // w/out initgroups/setgroups process retains supplementary groups
+ if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
+ fprintf(stderr, "initgroups failed, check -u option\n");
+ return -1;
+ }
+#endif
+ if (setuid(pwd->pw_uid) != 0) {
+ fprintf(stderr, "setuid failed, check -u option\n");
+ return -1;
+ }
+#else
+ fprintf(stderr, "-u not supported on this platform");
+ return -1;
+#endif
+ }
+
// initialize the shib-target library
SPConfig& conf=SPConfig::getConfig();
conf.setFeatures(
(shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
);
if (!conf.init(shar_schemadir, shar_prefix)) {
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
return -1;
}
}
if (!conf.instantiate(shar_config)) {
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
conf.term();
return -2;
}
// Init the listener.
ListenerService* listener = conf.getServiceProvider()->getListenerService();
if (!listener->init(unlink_socket)) {
- fprintf(stderr, "listener failed to initialize\n");
+ fprintf(stderr, SD_ERR "listener failed to initialize\n");
conf.term();
return -3;
}
}
// Run the listener.
+#ifdef HAVE_SD_NOTIFY
+ sd_notify(0, "READY=1");
+#endif
if (!listener->run(&shibd_shutdown)) {
- fprintf(stderr, "listener failure during service\n");
+ fprintf(stderr, SD_ERR "listener failure during service\n");
listener->term();
conf.term();
if (daemonize && pidfile)
}
listener->term();
}
-
+#ifdef HAVE_SD_NOTIFY
+ sd_notify(0, "STOPPING=1");
+#endif
conf.term();
if (daemonize && pidfile)
unlink(pidfile);