#include "securityserver.h"
#include "server.h"
#include <MacYarrow/yarrowseed.h>
#include <Security/daemon.h>
#include <Security/osxsigner.h>
#include "authority.h"
#include "session.h"
#include <unistd.h>
#include <Security/machserver.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <Security/acl_any.h>
#include <Security/acl_password.h>
#include <Security/acl_threshold.h>
#include <Security/acl_codesigning.h>
#include <Security/acl_comment.h>
#include "acl_keychain.h"
namespace Security
{
uint32 debugMode = 0;
}
static void usage(const char *me);
static void handleSIGCHLD(int);
static void handleSIGOther(int);
int main(int argc, char *argv[])
{
bool forceCssmInit = false;
int workerTimeout = 0;
int maxThreads = 0;
const char *authorizationConfig = "/etc/authorization";
const char *bootstrapName = "SecurityServer";
extern char *optarg;
extern int optind;
int arg;
while ((arg = getopt(argc, argv, "a:dfN:t:T:")) != -1) {
switch (arg) {
case 'a':
authorizationConfig = optarg;
break;
case 'd':
debugMode++;
break;
case 'f':
forceCssmInit = true;
break;
case 'N':
bootstrapName = optarg;
break;
case 't':
if ((maxThreads = atoi(optarg)) < 0)
maxThreads = 0;
break;
case 'T':
if ((workerTimeout = atoi(optarg)) < 0)
workerTimeout = 0;
break;
default:
usage(argv[0]);
}
}
if (optind < argc)
usage(argv[0]);
if (debugMode) {
Syslog::open(argv[0], LOG_AUTHPRIV, LOG_PERROR);
Syslog::notice("SecurityServer started in debug mode");
} else {
Syslog::open(argv[0], LOG_AUTHPRIV, LOG_CONS);
}
if (uid_t uid = getuid()) {
#if defined(NDEBUG)
Syslog::alert("Unprivileged SecurityServer aborted (uid=%d)", uid);
fprintf(stderr, "You are not allowed to run SecurityServer\n");
exit(1);
#else
debug("SS", "Running unprivileged (uid=%d); some features may not work", uid);
#endif //NDEBUG
}
if (!debugMode && !Daemon::incarnate())
exit(1);
CodeSigning::OSXSigner signer;
Authority authority(authorizationConfig);
new AnyAclSubject::Maker();
new PasswordAclSubject::Maker();
new ThresholdAclSubject::Maker();
new KeychainPromptAclSubject::Maker();
new CommentAclSubject::Maker();
new CodeSignatureAclSubject::Maker(signer);
RootSession rootSession;
Server server(authority, bootstrapName);
if (workerTimeout)
server.timeout(workerTimeout);
if (maxThreads)
server.maxThreads(maxThreads);
YarrowTimer yarrow(server);
if (signal(SIGCHLD, handleSIGCHLD) == SIG_ERR)
debug("SS", "Cannot ignore SIGCHLD: errno=%d", errno);
if (signal(SIGINT, handleSIGOther) == SIG_ERR)
debug("SS", "Cannot handle SIGINT: errno=%d", errno);
if (signal(SIGTERM, handleSIGOther) == SIG_ERR)
debug("SS", "Cannot handle SIGTERM: errno=%d", errno);
if (forceCssmInit)
server.loadCssm();
Syslog::notice("Entering service");
debug("SS", "Entering service run loop");
server.run();
Syslog::alert("Aborting");
return 1;
}
static void usage(const char *me)
{
fprintf(stderr, "Usage: %s [-df] [-t maxthreads] [-T threadTimeout]"
"\t[-N bootstrapName] [-a authConfigFile]\n", me);
exit(2);
}
static void handleSIGCHLD(int)
{
int status;
switch (pid_t pid = waitpid(-1, &status, WNOHANG)) {
case 0:
debug("SS", "Spurious SIGCHLD ignored");
return;
case -1:
debug("SS", "waitpid after SIGCHLD failed: errno=%d", errno);
return;
default:
debug("SS", "Reaping child pid=%d", pid);
return;
}
}
static void handleSIGOther(int sig)
{
switch (sig) {
case SIGINT:
debug("SS", "Interrupt signal; terminating");
exit(0);
case SIGTERM:
debug("SS", "Termination signal; terminating");
exit(0);
}
}