/*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "entropy.h"
#include "authority.h"
#include "session.h"
+#include "notifications.h"
#include "pcscmonitor.h"
+#include "auditevents.h"
#include "self.h"
#include <security_utilities/daemon.h>
#include <security_utilities/machserver.h>
#include <security_utilities/logging.h>
-#include <security_utilities/ktracecodes.h>
-#include <security_cdsa_client/osxsigner.h>
+
+#include <Security/SecKeychainPriv.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <syslog.h>
-
-// #define PERFORMANCE_MEASUREMENT 1
-
-#ifdef PERFORMANCE_MEASUREMENT
-#include <mach/mach_time.h>
-#endif
-
// ACL subject types (their makers are instantiated here)
#include <security_cdsa_utilities/acl_any.h>
#include <security_cdsa_utilities/acl_password.h>
static Port gMainServerPort;
+PCSCMonitor *gPCSC;
//
//
int main(int argc, char *argv[])
{
- #ifdef PERFORMANCE_MEASUREMENT
- // needed for automated timing of securityd startup
- uint64_t startTime = mach_absolute_time ();
- #endif
-
- Debug::trace (kSecTraceSecurityServerStart);
-
// clear the umask - we know what we're doing
secdebug("SS", "starting umask was 0%o", ::umask(0));
::umask(0);
-
+
+ // tell the keychain (client) layer to turn off the server interface
+ SecKeychainSetServerMode();
+
// program arguments (preset to defaults)
bool debugMode = false;
const char *bootstrapName = NULL;
+ const char* messagingName = SECURITY_MESSAGES_NAME;
bool doFork = false;
bool reExecute = false;
int workerTimeout = 0;
int maxThreads = 0;
+ bool waitForClients = true;
+ bool mdsIsInstalled = false;
const char *authorizationConfig = "/etc/authorization";
const char *tokenCacheDir = "/var/db/TokenCache";
const char *entropyFile = "/var/db/SystemEntropyCache";
const char *equivDbFile = EQUIVALENCEDBPATH;
const char *smartCardOptions = getenv("SMARTCARDS");
+ uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
+ unsigned int verbose = 0;
+
+ // check for the Installation-DVD environment and modify some default arguments if found
+ if (access("/etc/rc.cdrom", F_OK) == 0) { // /etc/rc.cdrom exists
+ SECURITYD_INSTALLMODE();
+ smartCardOptions = "off"; // needs writable directories that aren't
+ }
// parse command line arguments
extern char *optarg;
extern int optind;
int arg;
- while ((arg = getopt(argc, argv, "a:c:de:E:fN:s:t:T:X")) != -1) {
+ while ((arg = getopt(argc, argv, "a:c:de:E:imN:s:t:T:uvWX")) != -1) {
switch (arg) {
case 'a':
authorizationConfig = optarg;
case 'E':
entropyFile = optarg;
break;
- case 'f':
- fprintf(stderr, "%s: the -f option is obsolete\n", argv[0]);
+ case 'i':
+ keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID;
+ break;
+ case 'm':
+ mdsIsInstalled = true;
break;
case 'N':
bootstrapName = optarg;
if ((workerTimeout = atoi(optarg)) < 0)
workerTimeout = 0;
break;
+ case 'W':
+ waitForClients = false;
+ break;
+ case 'u':
+ keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
+ break;
+ case 'v':
+ verbose++;
+ break;
case 'X':
doFork = true;
reExecute = true;
if (!bootstrapName) {
bootstrapName = getenv(SECURITYSERVER_BOOTSTRAP_ENV);
if (!bootstrapName)
+ {
bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME;
+ }
+ else
+ {
+ messagingName = bootstrapName;
+ }
}
-
+ else
+ {
+ messagingName = bootstrapName;
+ }
+
// configure logging first
if (debugMode) {
Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR);
fprintf(stderr, "You are not allowed to run securityd\n");
exit(1);
#else
- fprintf(stderr, "securityd is unprivileged; some features may not work.\n");
- secdebug("SS", "Running as user %d (you have been warned)", uid);
+ fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid);
#endif //NDEBUG
}
}
// arm signal handlers; code below may generate signals we want to see
- if (signal(SIGCHLD, handleSignals) == SIG_ERR)
- secdebug("SS", "Cannot handle SIGCHLD: errno=%d", errno);
- if (signal(SIGINT, handleSignals) == SIG_ERR)
- secdebug("SS", "Cannot handle SIGINT: errno=%d", errno);
- if (signal(SIGTERM, handleSignals) == SIG_ERR)
- secdebug("SS", "Cannot handle SIGTERM: errno=%d", errno);
+ if (signal(SIGCHLD, handleSignals) == SIG_ERR
+ || signal(SIGINT, handleSignals) == SIG_ERR
+ || signal(SIGTERM, handleSignals) == SIG_ERR
+ || signal(SIGPIPE, handleSignals) == SIG_ERR
#if !defined(NDEBUG)
- if (signal(SIGUSR1, handleSignals) == SIG_ERR)
- secdebug("SS", "Cannot handle SIGHUP: errno=%d", errno);
+ || signal(SIGUSR1, handleSignals) == SIG_ERR
#endif //NDEBUG
-
- // create a code signing engine
- CodeSigning::OSXSigner signer;
-
+ || signal(SIGUSR2, handleSignals) == SIG_ERR) {
+ perror("signal");
+ exit(1);
+ }
+
// create an Authorization engine
Authority authority(authorizationConfig);
- // establish the ACL machinery
+ // introduce all supported ACL subject types
new AnyAclSubject::Maker();
new PasswordAclSubject::Maker();
new ProtectedPasswordAclSubject::Maker();
new ThresholdAclSubject::Maker();
new CommentAclSubject::Maker();
new ProcessAclSubject::Maker();
- new CodeSignatureAclSubject::Maker(signer);
- new KeychainPromptAclSubject::Maker();
+ new CodeSignatureAclSubject::Maker();
+ new KeychainPromptAclSubject::Maker(keychainAclDefault);
new PreAuthorizationAcls::OriginMaker();
new PreAuthorizationAcls::SourceMaker();
server.timeout(workerTimeout);
if (maxThreads)
server.maxThreads(maxThreads);
+ server.floatingThread(true);
+ server.waitForClients(waitForClients);
+ server.verbosity(verbose);
// add the RNG seed timer
# if defined(NDEBUG)
# else
if (getuid() == 0) new EntropyManager(server, entropyFile);
# endif
-
- // create a token-cache interface
-#if !defined(NDEBUG)
- if (const char *s = getenv("TOKENCACHE"))
- tokenCacheDir = s;
-#endif //NDEBUG
- TokenCache tokenCache(tokenCacheDir);
// create a smartcard monitor to manage external token devices
- PCSCMonitor secureCards(server, tokenCache, scOptions(smartCardOptions));
+ gPCSC = new PCSCMonitor(server, tokenCacheDir, scOptions(smartCardOptions));
// create the RootSession object (if -d, give it graphics and tty attributes)
- RootSession rootSession(server,
- debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0);
+ RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server);
+
+ // create a monitor thread to watch for audit session events
+ AuditMonitor audits(gMainServerPort);
+ audits.run();
- // install MDS and initialize the local CSSM
- server.loadCssm();
+ // install MDS (if needed) and initialize the local CSSM
+ server.loadCssm(mdsIsInstalled);
+ // create the shared memory notification hub
+ new SharedMemoryListener(messagingName, kSharedMemoryPoolSize);
+
// okay, we're ready to roll
+ SECURITYD_INITIALIZED((char*)bootstrapName);
Syslog::notice("Entering service");
- secdebug("SS", "%s initialized", bootstrapName);
- Debug::trace (kSecTraceSecurityServerInitialized);
- #ifdef PERFORMANCE_MEASUREMENT
- // needed for automated timing of securityd startup
- uint64_t endTime = mach_absolute_time ();
-
- // compute how long it took to initialize
- uint64_t elapsedTime = endTime - startTime;
- mach_timebase_info_data_t multiplier;
- mach_timebase_info (&multiplier);
-
- elapsedTime = elapsedTime * multiplier.numer / multiplier.denom;
-
- FILE* f = fopen ("/var/log/startuptime.txt", "a");
- if (f == NULL)
- {
- // probably not running as root.
- f = fopen ("/tmp/startuptime.txt", "a");
- }
-
- fprintf (f, "%lld\n", elapsedTime);
- fclose (f);
- #endif
-
// go
server.run();
//
static void usage(const char *me)
{
- fprintf(stderr, "Usage: %s [-dX]"
+ fprintf(stderr, "Usage: %s [-dwX]"
"\n\t[-a authConfigFile] Authorization configuration file"
"\n\t[-c tokencache] smartcard token cache directory"
"\n\t[-e equivDatabase] path to code equivalence database"
//
static void handleSignals(int sig)
{
+ SECURITYD_SIGNAL_RECEIVED(sig);
if (kern_return_t rc = self_client_handleSignal(gMainServerPort, mach_task_self(), sig))
Syslog::error("self-send failed (mach error %d)", rc);
}