]> git.saurik.com Git - apple/security.git/blob - SecurityServer/main.cpp
Security-29.tar.gz
[apple/security.git] / SecurityServer / main.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // SecurityServer - Apple security services daemon.
21 //
22 #include "securityserver.h"
23 #include "server.h"
24 #include <MacYarrow/yarrowseed.h>
25
26 #include <Security/daemon.h>
27 #include <Security/osxsigner.h>
28 #include "authority.h"
29 #include "session.h"
30
31 #include <unistd.h>
32 #include <Security/machserver.h>
33
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <signal.h>
37
38 // ACL subject types (their makers are instantiated here)
39 #include <Security/acl_any.h>
40 #include <Security/acl_password.h>
41 #include <Security/acl_threshold.h>
42 #include <Security/acl_codesigning.h>
43 #include <Security/acl_comment.h>
44 #include "acl_keychain.h"
45
46
47 namespace Security
48 {
49
50 //
51 // Program options (set by argument scan and environment)
52 //
53 uint32 debugMode = 0;
54
55 } // end namespace Security
56
57
58 //
59 // Local functions of the main program driver
60 //
61 static void usage(const char *me);
62 static void handleSIGCHLD(int);
63 static void handleSIGOther(int);
64
65
66 //
67 // Main driver
68 //
69 int main(int argc, char *argv[])
70 {
71 // program arguments (preset to defaults)
72 bool forceCssmInit = false;
73 int workerTimeout = 0;
74 int maxThreads = 0;
75 const char *authorizationConfig = "/etc/authorization";
76 const char *bootstrapName = "SecurityServer";
77
78 // parse command line arguments
79 extern char *optarg;
80 extern int optind;
81 int arg;
82 while ((arg = getopt(argc, argv, "a:dfN:t:T:")) != -1) {
83 switch (arg) {
84 case 'a':
85 authorizationConfig = optarg;
86 break;
87 case 'd':
88 debugMode++;
89 break;
90 case 'f':
91 forceCssmInit = true;
92 break;
93 case 'N':
94 bootstrapName = optarg;
95 break;
96 case 't':
97 if ((maxThreads = atoi(optarg)) < 0)
98 maxThreads = 0;
99 break;
100 case 'T':
101 if ((workerTimeout = atoi(optarg)) < 0)
102 workerTimeout = 0;
103 break;
104 default:
105 usage(argv[0]);
106 }
107 }
108
109 // take no non-option arguments
110 if (optind < argc)
111 usage(argv[0]);
112
113 // configure logging
114 if (debugMode) {
115 Syslog::open(argv[0], LOG_AUTHPRIV, LOG_PERROR);
116 Syslog::notice("SecurityServer started in debug mode");
117 } else {
118 Syslog::open(argv[0], LOG_AUTHPRIV, LOG_CONS);
119 }
120
121 // if we're not running as root in production mode, fail
122 // in debug mode, issue a warning
123 if (uid_t uid = getuid()) {
124 #if defined(NDEBUG)
125 Syslog::alert("Unprivileged SecurityServer aborted (uid=%d)", uid);
126 fprintf(stderr, "You are not allowed to run SecurityServer\n");
127 exit(1);
128 #else
129 debug("SS", "Running unprivileged (uid=%d); some features may not work", uid);
130 #endif //NDEBUG
131 }
132
133 // turn into a properly diabolical daemon unless debugMode is on
134 if (!debugMode && !Daemon::incarnate())
135 exit(1);
136
137 // create a code signing engine
138 CodeSigning::OSXSigner signer;
139
140 // create an Authorization engine
141 Authority authority(authorizationConfig);
142
143 // establish the ACL machinery
144 new AnyAclSubject::Maker();
145 new PasswordAclSubject::Maker();
146 new ThresholdAclSubject::Maker();
147 new KeychainPromptAclSubject::Maker();
148 new CommentAclSubject::Maker();
149 new CodeSignatureAclSubject::Maker(signer);
150
151 // create the RootSession object
152 RootSession rootSession;
153
154 // create the main server object and register it
155 Server server(authority, bootstrapName);
156
157 // set server configuration from arguments, if specified
158 if (workerTimeout)
159 server.timeout(workerTimeout);
160 if (maxThreads)
161 server.maxThreads(maxThreads);
162
163 // add the RNG seed timer to it
164 YarrowTimer yarrow(server);
165
166 // set up signal handlers
167 if (signal(SIGCHLD, handleSIGCHLD) == SIG_ERR)
168 debug("SS", "Cannot ignore SIGCHLD: errno=%d", errno);
169 if (signal(SIGINT, handleSIGOther) == SIG_ERR)
170 debug("SS", "Cannot handle SIGINT: errno=%d", errno);
171 if (signal(SIGTERM, handleSIGOther) == SIG_ERR)
172 debug("SS", "Cannot handle SIGTERM: errno=%d", errno);
173
174 // initialize CSSM now if requested
175 if (forceCssmInit)
176 server.loadCssm();
177
178 Syslog::notice("Entering service");
179 debug("SS", "Entering service run loop");
180 server.run();
181
182 // fell out of runloop (should not happen)
183 Syslog::alert("Aborting");
184 return 1;
185 }
186
187
188 //
189 // Issue usage message and die
190 //
191 static void usage(const char *me)
192 {
193 fprintf(stderr, "Usage: %s [-df] [-t maxthreads] [-T threadTimeout]"
194 "\t[-N bootstrapName] [-a authConfigFile]\n", me);
195 exit(2);
196 }
197
198
199 //
200 // Handle SIGCHLD signals to reap our children (zombie cleanup)
201 //
202 static void handleSIGCHLD(int)
203 {
204 int status;
205 switch (pid_t pid = waitpid(-1, &status, WNOHANG)) {
206 case 0:
207 debug("SS", "Spurious SIGCHLD ignored");
208 return;
209 case -1:
210 debug("SS", "waitpid after SIGCHLD failed: errno=%d", errno);
211 return;
212 default:
213 debug("SS", "Reaping child pid=%d", pid);
214 return;
215 }
216 }
217
218
219 //
220 // Handle some other signals to shut down cleanly (and with logging)
221 //
222 static void handleSIGOther(int sig)
223 {
224 switch (sig) {
225 case SIGINT:
226 debug("SS", "Interrupt signal; terminating");
227 exit(0);
228 case SIGTERM:
229 debug("SS", "Termination signal; terminating");
230 exit(0);
231 }
232 }