/ securityd / src / main.cpp
main.cpp
  1  /*
  2   * Copyright (c) 2000-2009,2014 Apple Inc. All Rights Reserved.
  3   * 
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   * 
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  
 25  //
 26  // securityd - Apple security services daemon.
 27  //
 28  #include <securityd_client/ucsp.h>
 29  
 30  #include "server.h"
 31  #include "session.h"
 32  #include "notifications.h"
 33  #include "auditevents.h"
 34  #include "self.h"
 35  #include "util.h"
 36  
 37  #include <security_utilities/daemon.h>
 38  #include <security_utilities/machserver.h>
 39  #include <security_utilities/logging.h>
 40  
 41  #include <Security/SecKeychainPriv.h>
 42  
 43  #include <unistd.h>
 44  #include <sys/types.h>
 45  #include <signal.h>
 46  #include <syslog.h>
 47  
 48  // ACL subject types (their makers are instantiated here)
 49  #include <security_cdsa_utilities/acl_any.h>
 50  #include <security_cdsa_utilities/acl_password.h>
 51  #include <security_cdsa_utilities/acl_prompted.h>
 52  #include <security_cdsa_utilities/acl_protectedpw.h>
 53  #include <security_cdsa_utilities/acl_threshold.h>
 54  #include <security_cdsa_utilities/acl_codesigning.h>
 55  #include <security_cdsa_utilities/acl_process.h>
 56  #include <security_cdsa_utilities/acl_comment.h>
 57  #include <security_cdsa_utilities/acl_preauth.h>
 58  #include "acl_keychain.h"
 59  #include "acl_partition.h"
 60  
 61  #include <sandbox.h>
 62  
 63  //
 64  // Local functions of the main program driver
 65  //
 66  static void usage(const char *me) __attribute__((noreturn));
 67  static void handleSignals(int sig);
 68  
 69  static Port gMainServerPort;
 70  
 71  
 72  //
 73  // Main driver
 74  //
 75  int main(int argc, char *argv[])
 76  {
 77  	DisableLocalization();
 78  
 79  	// clear the umask - we know what we're doing
 80  	secnotice("SecServer", "starting umask was 0%o", ::umask(0));
 81  	::umask(0);
 82  
 83  	// tell the keychain (client) layer to turn off the server interface
 84  	SecKeychainSetServerMode();
 85  
 86      const char *params[] = {"LEGACY_TOKENS_ENABLED", "NO", NULL};
 87      char* errorbuf = NULL;
 88      if (sandbox_init_with_parameters("com.apple.securityd", SANDBOX_NAMED, params, &errorbuf)) {
 89          seccritical("SecServer: unable to enter sandbox: %{public}s", errorbuf);
 90          if (errorbuf) {
 91              sandbox_free_error(errorbuf);
 92          }
 93          exit(1);
 94      } else {
 95          secnotice("SecServer", "entered sandbox");
 96      }
 97  
 98  	// program arguments (preset to defaults)
 99  	bool debugMode = false;
100  	int workerTimeout = 0;
101  	int maxThreads = 0;
102  	bool waitForClients = true;
103      bool mdsIsInstalled = false;
104  	uint32_t keychainAclDefault = CSSM_ACL_KEYCHAIN_PROMPT_INVALID | CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
105  	unsigned int verbose = 0;
106  	
107  	// check for the Installation-DVD environment and modify some default arguments if found
108  	if (access("/etc/rc.cdrom", F_OK) == 0) {	// /etc/rc.cdrom exists
109          secnotice("SecServer", "starting in installmode");
110  	}
111  
112  	// parse command line arguments
113  	extern char *optarg;
114  	extern int optind;
115  	int arg;
116  	while ((arg = getopt(argc, argv, ":dE:im:t:T:uvW")) != -1) {
117  		switch (arg) {
118  		case 'd':
119  			debugMode = true;
120  			break;
121          case 'E':
122              /* was entropyFile, kept to preserve ABI */
123              break;
124  		case 'i':
125  			keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_INVALID;
126  			break;
127          case 'm':
128              mdsIsInstalled = true;
129              break;
130  		case 't':
131  			if ((maxThreads = atoi(optarg)) < 0)
132  				maxThreads = 0;
133  			break;
134  		case 'T':
135  			if ((workerTimeout = atoi(optarg)) < 0)
136  				workerTimeout = 0;
137  			break;
138  		case 'W':
139  			waitForClients = false;
140  			break;
141  		case 'u':
142  			keychainAclDefault &= ~CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED;
143  			break;
144  		case 'v':
145  			verbose++;
146  			break;
147  		default:
148  			usage(argv[0]);
149  		}
150  	}
151  	
152  	// take no non-option arguments
153  	if (optind < argc) {
154  		usage(argv[0]);
155  	}
156  
157  	const char *bootstrapName = SECURITYSERVER_BOOTSTRAP_NAME;
158  	const char* messagingName = SharedMemoryCommon::kDefaultSecurityMessagesName;
159  
160  	// configure logging first
161  	if (debugMode) {
162  		Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_PERROR);
163  		Syslog::notice("%s started in debug mode", argv[0]);
164  	} else {
165  		Syslog::open(bootstrapName, LOG_AUTHPRIV, LOG_CONS);
166  	}
167      
168      // if we're not running as root in production mode, fail
169      // in debug mode, issue a warning
170      if (uid_t uid = getuid()) {
171  #if defined(NDEBUG)
172          Syslog::alert("Tried to run securityd as user %d: aborted", uid);
173          fprintf(stderr, "You are not allowed to run securityd\n");
174          exit(1);
175  #else
176          fprintf(stderr, "securityd is unprivileged (uid=%d); some features may not work.\n", uid);
177  #endif //NDEBUG
178      }
179      
180      // turn into a properly diabolical daemon unless debugMode is on
181      if (!debugMode && getppid() != 1 && !Daemon::incarnate(false)) {
182  		exit(1);	// can't daemonize
183  	}
184          
185      // arm signal handlers; code below may generate signals we want to see
186      if (signal(SIGCHLD, handleSignals) == SIG_ERR
187  		|| signal(SIGINT, handleSignals) == SIG_ERR
188  		|| signal(SIGTERM, handleSignals) == SIG_ERR
189  		|| signal(SIGPIPE, handleSignals) == SIG_ERR
190  #if !defined(NDEBUG)
191  		|| signal(SIGUSR1, handleSignals) == SIG_ERR
192  #endif //NDEBUG
193  		|| signal(SIGUSR2, handleSignals) == SIG_ERR) {
194  		perror("signal");
195  		exit(1);
196  	}
197  
198  // The clang static analyzer isn't a big fan of our "object creation hooks object into global pointer graph" model.
199  // Tell it not to worry.
200  #ifndef __clang_analyzer__
201  	// introduce all supported ACL subject types
202  	new AnyAclSubject::Maker();
203  	new PasswordAclSubject::Maker();
204      new ProtectedPasswordAclSubject::Maker();
205      new PromptedAclSubject::Maker();
206  	new ThresholdAclSubject::Maker();
207  	new CommentAclSubject::Maker();
208   	new ProcessAclSubject::Maker();
209  	new CodeSignatureAclSubject::Maker();
210  	new KeychainPromptAclSubject::Maker(keychainAclDefault);
211  	new PartitionAclSubject::Maker();
212  	new PreAuthorizationAcls::OriginMaker();
213      new PreAuthorizationAcls::SourceMaker();
214  #endif
215      // establish the code equivalents database
216      CodeSignatures codeSignatures;
217  
218  
219      // create the main server object and register it
220   	Server server(codeSignatures, bootstrapName);
221  
222      // Remember the primary service port to send signal events to
223      gMainServerPort = server.primaryServicePort();
224  
225      // set server configuration from arguments, if specified
226  	if (workerTimeout)
227  		server.timeout(workerTimeout);
228  	if (maxThreads)
229  		server.maxThreads(maxThreads);
230  	server.floatingThread(true);
231  	server.waitForClients(waitForClients);
232  	server.verbosity(verbose);
233  
234      // create the RootSession object (if -d, give it graphics and tty attributes)
235      RootSession rootSession(debugMode ? (sessionHasGraphicAccess | sessionHasTTY) : 0, server);
236  	
237  	// create a monitor thread to watch for audit session events
238  	AuditMonitor audits(gMainServerPort);
239  	audits.threadRun();
240      
241      // install MDS (if needed) and initialize the local CSSM
242      server.loadCssm(mdsIsInstalled);
243  
244  #ifndef __clang_analyzer__
245  	// create the shared memory notification hub
246  	new SharedMemoryListener(messagingName, kSharedMemoryPoolSize);
247  #endif
248  	
249  
250  	// okay, we're ready to roll
251      secnotice("SecServer", "Entering service as %s", (char*)bootstrapName);
252  	Syslog::notice("Entering service");
253      
254  	// go
255  	server.run();
256  	
257  	// fell out of runloop (should not happen)
258  	Syslog::alert("Aborting");
259      return 1;
260  }
261  
262  
263  //
264  // Issue usage message and die
265  //
266  static void usage(const char *me)
267  {
268  	fprintf(stderr, "Usage: %s [-dwX]"
269  		"\n\t[-e equivDatabase] 					path to code equivalence database"
270  		"\n\t[-t maxthreads] [-T threadTimeout]     server thread control"
271  		"\n", me);
272  	exit(2);
273  }
274  
275  const CFStringRef kTKSmartCardPreferencesDomain = CFSTR("com.apple.security.smartcard");
276  const CFStringRef kTKLegacyTokendPreferencesKey  = CFSTR("Legacy");
277  
278  //
279  // Handle signals.
280  // We send ourselves a message (through the "self" service), so actual
281  // actions happen on the normal event loop path. Note that another thread
282  // may be picking up the message immediately.
283  //
284  static void handleSignals(int sig)
285  {
286  	(void)self_client_handleSignal(gMainServerPort, sig);
287  }