1 kumpf 1.2 /*
2 //%2006////////////////////////////////////////////////////////////////////////
3 //
4 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
5 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
6 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
7 // IBM Corp.; EMC Corporation, The Open Group.
8 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
9 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
10 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
11 // EMC Corporation; VERITAS Software Corporation; The Open Group.
12 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
13 // EMC Corporation; Symantec Corporation; The Open Group.
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining a copy
16 // of this software and associated documentation files (the "Software"), to
17 // deal in the Software without restriction, including without limitation the
18 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
19 // sell copies of the Software, and to permit persons to whom the Software is
20 // furnished to do so, subject to the following conditions:
21 //
22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
23 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
24 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
25 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 //%/////////////////////////////////////////////////////////////////////////////
32 */
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <string.h>
|
38 kumpf 1.10 #include <signal.h>
39 #include <time.h>
|
40 kumpf 1.2 #include "Config.h"
41 #include "Child.h"
42 #include "Parent.h"
43 #include "User.h"
44 #include "Fatal.h"
45 #include "Process.h"
46 #include "Path.h"
47 #include "Globals.h"
48 #include "Socket.h"
49 #include "Strlcpy.h"
50 #include "Strlcat.h"
51 #include "Log.h"
52 #include "Policy.h"
53 #include "Macro.h"
54 #include "Assert.h"
55 #include "Options.h"
|
56 kumpf 1.8 #include <Pegasus/Common/PegasusVersion.h>
|
57 kumpf 1.2
|
58 kumpf 1.10 #define CIMSERVER_COMMAND_TIMEOUT_SECONDS 240
59
|
60 kumpf 1.2 /*
61 **==============================================================================
62 **
63 ** GetServerUser
64 **
65 ** Determine which user to run CIMSERVERMAIN as.
66 **
67 **==============================================================================
68 */
69
|
70 kumpf 1.3 int GetServerUser(const char** userName, int* uid, int* gid)
|
71 kumpf 1.2 {
|
72 kumpf 1.3 *userName = PEGASUS_CIMSERVERMAIN_USER;
|
73 kumpf 1.2
|
74 kumpf 1.3 if (GetUserInfo(*userName, uid, gid) != 0)
|
75 kumpf 1.2 {
76 Fatal(FL,
77 "The %s user \"%s\" does not exist.",
|
78 kumpf 1.3 CIMSERVERMAIN, *userName);
|
79 kumpf 1.2 }
80
81 return 0;
82 }
83
84 /*
85 **==============================================================================
86 **
87 ** ExecShutdown()
88 **
89 **==============================================================================
90 */
91
|
92 kumpf 1.5 void ExecShutdown(void)
|
93 kumpf 1.2 {
94 char* tmpArgv[3];
95 const char* cimshutdownPath;
96 const char* shutdownTimeout;
97
98 /* Get shutdownTimeout configuration parameter. */
99
100 if ((shutdownTimeout = FindMacro("shutdownTimeout")) == NULL)
101 Fatal(FL, "failed to resolve shutdownTimeout");
102
103 /* Get absolute CIMSHUTDOWN program name. */
104
105 if ((cimshutdownPath = FindMacro("cimshutdownPath")) == NULL)
106 Fatal(FL, "failed to resolve cimshutdownPath");
107
108 /* Create argument list. */
109
110 tmpArgv[0] = CIMSHUTDOWN;
111 tmpArgv[1] = (char*)shutdownTimeout;
112 tmpArgv[2] = 0;
113
114 kumpf 1.2 /* Exec CIMSHUTDOWN program. */
115
116 /* Flawfinder: ignore */
117 execv(cimshutdownPath, tmpArgv);
118 Fatal(FL, "failed to exec %s", cimshutdownPath);
119 }
120
121 /*
122 **==============================================================================
123 **
124 ** DefineExecutorMacros()
125 **
126 ** Define macros used by the executor.
127 **
128 **==============================================================================
129 */
130
|
131 kumpf 1.5 void DefineExecutorMacros(void)
|
132 kumpf 1.2 {
133 /* Define ${internalBinDir} */
134 {
135 char path[EXECUTOR_BUFFER_SIZE];
136
137 if (GetPegasusInternalBinDir(path) != 0)
138 Fatal(FL, "failed to resolve internal pegasus bin directory");
139
140 DefineMacro("internalBinDir", path);
141 }
142
143 /* Define ${cimservermain} */
144
145 DefineMacro("cimservermain", CIMSERVERMAIN);
146
147 /* Define ${cimprovagt} */
148
149 DefineMacro("cimprovagt", CIMPROVAGT);
150
151 /* Define ${cimshutdown} */
152
153 kumpf 1.2 DefineMacro("cimshutdown", CIMSHUTDOWN);
154
155 /* Define ${cimservera} */
156
157 DefineMacro("cimservera", CIMSERVERA);
158
159 /* Define ${cimservermainPath} */
160 {
161 char path[EXECUTOR_BUFFER_SIZE];
162
163 if (ExpandMacros("${internalBinDir}/${cimservermain}", path) != 0)
164 Fatal(FL, "failed to resolve cimservermainPath");
165
166 DefineMacro("cimservermainPath", path);
167 }
168
169 /* Define ${cimprovagtPath} */
170 {
171 char path[EXECUTOR_BUFFER_SIZE];
172
173 if (ExpandMacros("${internalBinDir}/${cimprovagt}", path) != 0)
174 kumpf 1.2 Fatal(FL, "failed to resolve cimprovagtPath");
175
176 DefineMacro("cimprovagtPath", path);
177 }
178
179 /* Define ${cimshutdownPath} */
180 {
181 char path[EXECUTOR_BUFFER_SIZE];
182
183 if (ExpandMacros("${internalBinDir}/${cimshutdown}", path) != 0)
184 Fatal(FL, "failed to resolve cimshutdownPath");
185
186 DefineMacro("cimshutdownPath", path);
187 }
188
189 /* Define ${cimserveraPath} */
190 {
191 char path[EXECUTOR_BUFFER_SIZE];
192
193 if (ExpandMacros("${internalBinDir}/${cimservera}", path) != 0)
194 Fatal(FL, "failed to resolve cimserveraPath");
195 kumpf 1.2
196 DefineMacro("cimserveraPath", path);
197 }
198
199 /* Define ${shutdownTimeout} */
200
201 {
202 char buffer[EXECUTOR_BUFFER_SIZE];
203
204 if (GetConfigParam("shutdownTimeout", buffer) != 0)
|
205 kumpf 1.7 {
206 Strlcpy(
207 buffer,
208 PEGASUS_DEFAULT_SHUTDOWN_TIMEOUT_SECONDS_STRING,
209 sizeof(buffer));
210 }
|
211 kumpf 1.2
212 DefineMacro("shutdownTimeout", buffer);
213 }
214
215 /* Define ${currentConfigFilePath} */
216 {
217 char path[EXECUTOR_BUFFER_SIZE];
218
219 if (GetHomedPath(PEGASUS_CURRENT_CONFIG_FILE_PATH, path) != 0)
220 {
221 Fatal(FL, "GetHomedPath() failed on \"%s\"",
222 PEGASUS_CURRENT_CONFIG_FILE_PATH);
223 }
224
225 DefineMacro("currentConfigFilePath", path);
226 }
227
228 /* Define ${plannedConfigFilePath} */
229 {
230 char path[EXECUTOR_BUFFER_SIZE];
231
232 kumpf 1.2 if (GetHomedPath(PEGASUS_PLANNED_CONFIG_FILE_PATH, path) != 0)
233 {
234 Fatal(FL, "GetHomedPath() failed on \"%s\"",
235 PEGASUS_PLANNED_CONFIG_FILE_PATH);
236 }
237
238 DefineMacro("plannedConfigFilePath", path);
239 }
240
241 /* Define ${passwordFilePath} */
242
243 if (DefineConfigPathMacro("passwordFilePath", "cimserver.passwd") != 0)
244 Fatal(FL, "missing \"passwordFilePath\" configuration parameter.");
245
246 /* Define ${sslKeyFilePath} */
247
248 if (DefineConfigPathMacro("sslKeyFilePath", "file.pem") != 0)
249 Fatal(FL, "missing \"sslKeyFilePath\" configuration parameter.");
250
251 /* Define ${sslTrustStore} */
252
253 kumpf 1.2 if (DefineConfigPathMacro("sslTrustStore", "cimserver_trust") != 0)
254 Fatal(FL, "missing \"sslTrustStore\" configuration parameter.");
255
256 /* Define ${crlStore} */
257
258 if (DefineConfigPathMacro("crlStore", "crl") != 0)
259 Fatal(FL, "missing \"crlStore\" configuration parameter.");
260 }
261
262 /*
263 **==============================================================================
264 **
265 ** main()
266 **
267 **==============================================================================
268 */
269
270 int main(int argc, char** argv)
271 {
272 const char* cimservermainPath;
|
273 kumpf 1.11 const char* workingDirectory;
|
274 kumpf 1.2 int pair[2];
|
275 kumpf 1.10 int initCompletePipe[2];
276 int pid;
|
277 kumpf 1.2 char username[EXECUTOR_BUFFER_SIZE];
|
278 kumpf 1.6 const char* childUserName;
279 int childUid;
280 int childGid;
|
281 kumpf 1.2 int childPid;
282 struct Options options;
283
284 /* Get options. */
285
286 GetOptions(&argc, &argv, &options);
287
288 /* Save argc-argv as globals. */
289
290 globals.argc = argc;
291 globals.argv = argv;
292
|
293 kumpf 1.6 /* Open the log. */
294
295 OpenLog("cimserver");
296
|
297 kumpf 1.2 /* Define macros needed by the executor. */
298
299 DefineExecutorMacros();
300
|
301 kumpf 1.6 /* If shutting down, then run CIMSHUTDOWN client. */
|
302 kumpf 1.2
303 if (options.shutdown)
304 ExecShutdown();
305
306 /* Process --policy and --macros options. */
307
308 if (options.dump)
309 {
|
310 kumpf 1.4 DumpPolicy(stdout, 1);
311 DumpMacros(stdout);
|
312 kumpf 1.2 exit(0);
313 }
314
315 /* Get absolute CIMSERVERMAIN program name. */
316
317 if ((cimservermainPath = FindMacro("cimservermainPath")) == NULL)
318 Fatal(FL, "Failed to locate %s program", CIMSERVERMAIN);
319
320 /* If CIMSERVERMAIN is already running, warn and exit now, unless one of
321 * the following options are given: -v, --version, -h, --help (these are
322 * passed through to CIMSERVERMAIN).
323 */
324
|
325 kumpf 1.4 if (!options.version &&
326 !options.help &&
327 TestProcessRunning(PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN) == 0)
|
328 kumpf 1.2 {
329 fprintf(stderr,
330 "%s: cimserver is already running (the PID found in the file "
331 "\"%s\" corresponds to an existing process named \"%s\").\n\n",
332 globals.argv[0], PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN);
333
334 exit(1);
335 }
336
337 /* Get enableAuthentication configuration option. */
338
339 {
340 char buffer[EXECUTOR_BUFFER_SIZE];
341
342 if (GetConfigParam("enableAuthentication", buffer) == 0 &&
343 strcasecmp(buffer, "true") == 0)
344 {
345 globals.enableAuthentication = 1;
346 }
347 }
348
|
349 kumpf 1.4 /* Initialize the log-level from the configuration parameter. */
|
350 kumpf 1.2
|
351 kumpf 1.4 InitLogLevel();
|
352 kumpf 1.2
353 Log(LL_INFORMATION, "starting");
354
355 /* Be sure this process is running as root (otherwise fail). */
356
357 if (setuid(0) != 0 || setgid(0) != 0)
358 Fatal(FL, "attempted to run program as non-root user");
359
360 /* Warn if authentication not enabled (suspicious use of executor). */
361
362 if (!globals.enableAuthentication)
363 Log(LL_WARNING, "authentication is NOT enabled");
364 else
365 Log(LL_TRACE, "authentication is enabled");
366
367 /* Print user info. */
368
369 if (GetUserName(getuid(), username) != 0)
370 Fatal(FL, "cannot resolve user from uid=%d", getuid());
371
372 Log(LL_TRACE, "running as %s (uid=%d, gid=%d)",
373 kumpf 1.2 username, (int)getuid(), (int)getgid());
374
|
375 mateus.baur 1.9 /* Change the current directory */
376
|
377 kumpf 1.11 #if defined(PEGASUS_USE_RELEASE_DIRS) && defined(PEGASUS_CORE_DIR)
378 workingDirectory = PEGASUS_CORE_DIR;
|
379 denise.eckstein 1.12 #elif defined(PEGASUS_DEBUG)
380 workingDirectory = getenv("PEGASUS_TMP");
|
381 mateus.baur 1.9 #endif
|
382 denise.eckstein 1.12 if (workingDirectory == NULL)
383 {
384 workingDirectory = "/";
385 }
|
386 kumpf 1.11 if (chdir(workingDirectory) != 0)
387 {
388 Log(LL_WARNING, "Failed to change working directory to %s",
389 workingDirectory);
390 }
391
|
392 kumpf 1.10 /* Create a pipe for communicating with cimserver daemon process. */
393
394 if (pipe(initCompletePipe) != 0)
395 Fatal(FL, "Failed to create pipe");
396
397 CloseOnExec(initCompletePipe[0]);
398 CloseOnExec(initCompletePipe[1]);
399
400 /* Fork to ensure we are not a session leader so setsid() will succeed. */
401
402 pid = fork();
403
404 if (pid < 0)
405 {
406 Fatal(FL, "fork() failed");
407 }
408
409 if (pid > 0)
410 {
411 /* Wait until daemon writes an exit code or closes the pipe. */
412
413 kumpf 1.10 char exitRC;
414 ssize_t result;
415 time_t startTime;
416 time_t now;
417
418 close(initCompletePipe[1]);
419 SetNonBlocking(initCompletePipe[0]);
420 time(&startTime);
421
422 do
423 {
424 time(&now);
425 result = WaitForReadEnable(
426 initCompletePipe[0],
427 (CIMSERVER_COMMAND_TIMEOUT_SECONDS - (now - startTime)) * 1000);
428 } while (result == -1 && errno == EINTR);
429
430 if (result == 0)
431 {
432 fprintf(stderr,
433 "The cimserver command timed out waiting for the CIM server "
434 kumpf 1.10 "to start.");
435 _exit(0);
436 }
437
438 EXECUTOR_RESTART(read(initCompletePipe[0], &exitRC, 1), result);
439 if (result <= 0)
440 {
441 exitRC = 1;
442 }
443 _exit(exitRC);
444 }
445
446 close(initCompletePipe[0]);
447
448 /* Become session leader (so that our child process will not be one) */
449
450 if (setsid() < 0)
451 {
452 Fatal(FL, "setsid() failed");
453 }
454
455 kumpf 1.10 /* Ignore SIGHUP: */
456
457 signal(SIGHUP, SIG_IGN);
458
459 /* Ignore SIGCHLD: */
460
461 signal(SIGCHLD, SIG_IGN);
462
463 /* Ignore SIGPIPE: */
464
465 signal(SIGPIPE, SIG_IGN);
466
467 /* Fork cimserver daemon process (not a session leader since parent is). */
468
469 pid = fork();
470
471 if (pid < 0)
472 {
473 Fatal(FL, "fork() failed");
474 }
475
476 kumpf 1.10 if (pid > 0)
477 {
478 _exit(0);
479 }
480
|
481 kumpf 1.2 /* Determine user for running CIMSERVERMAIN. */
482
|
483 kumpf 1.6 GetServerUser(&childUserName, &childUid, &childGid);
|
484 kumpf 1.2
|
485 kumpf 1.10 /* Create a socket pair for communicating with the child process. */
486
487 if (CreateSocketPair(pair) != 0)
488 Fatal(FL, "Failed to create socket pair");
489
490 CloseOnExec(pair[1]);
491
|
492 kumpf 1.2 /* Fork child process. */
493
494 childPid = fork();
495
496 if (childPid == 0)
497 {
498 /* Child. */
499 close(pair[1]);
|
500 kumpf 1.3 Child(
501 argc,
502 argv,
503 cimservermainPath,
|
504 kumpf 1.6 childUserName,
505 childUid,
506 childGid,
|
507 kumpf 1.3 pair[0]);
|
508 kumpf 1.2 }
509 else if (childPid > 0)
510 {
511 /* Parent. */
512 close(pair[0]);
|
513 kumpf 1.10 Parent(pair[1], initCompletePipe[1], childPid, options.bindVerbose);
|
514 kumpf 1.2 }
515 else
516 {
517 Fatal(FL, "fork() failed");
518 }
519
520 return 0;
521 }
|