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