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 /* Define ${cimshutdown} */
157
158 kumpf 1.2 DefineMacro("cimshutdown", CIMSHUTDOWN);
159
160 /* Define ${cimservera} */
161
162 DefineMacro("cimservera", CIMSERVERA);
163
164 /* Define ${cimservermainPath} */
165 {
166 char path[EXECUTOR_BUFFER_SIZE];
167
168 if (ExpandMacros("${internalBinDir}/${cimservermain}", path) != 0)
169 Fatal(FL, "failed to resolve cimservermainPath");
170
171 DefineMacro("cimservermainPath", path);
172 }
173
174 /* Define ${cimprovagtPath} */
175 {
176 char path[EXECUTOR_BUFFER_SIZE];
177
178 if (ExpandMacros("${internalBinDir}/${cimprovagt}", path) != 0)
179 kumpf 1.2 Fatal(FL, "failed to resolve cimprovagtPath");
180
181 DefineMacro("cimprovagtPath", path);
182 }
183
184 /* Define ${cimshutdownPath} */
185 {
186 char path[EXECUTOR_BUFFER_SIZE];
187
188 if (ExpandMacros("${internalBinDir}/${cimshutdown}", path) != 0)
189 Fatal(FL, "failed to resolve cimshutdownPath");
190
191 DefineMacro("cimshutdownPath", path);
192 }
193
194 /* Define ${cimserveraPath} */
195 {
196 char path[EXECUTOR_BUFFER_SIZE];
197
198 if (ExpandMacros("${internalBinDir}/${cimservera}", path) != 0)
199 Fatal(FL, "failed to resolve cimserveraPath");
200 kumpf 1.2
201 DefineMacro("cimserveraPath", path);
202 }
203
204 /* Define ${shutdownTimeout} */
205
206 {
207 char buffer[EXECUTOR_BUFFER_SIZE];
208
209 if (GetConfigParam("shutdownTimeout", buffer) != 0)
|
210 kumpf 1.7 {
211 Strlcpy(
212 buffer,
213 PEGASUS_DEFAULT_SHUTDOWN_TIMEOUT_SECONDS_STRING,
214 sizeof(buffer));
215 }
|
216 kumpf 1.2
217 DefineMacro("shutdownTimeout", buffer);
218 }
219
220 /* Define ${currentConfigFilePath} */
221 {
222 char path[EXECUTOR_BUFFER_SIZE];
223
224 if (GetHomedPath(PEGASUS_CURRENT_CONFIG_FILE_PATH, path) != 0)
225 {
226 Fatal(FL, "GetHomedPath() failed on \"%s\"",
227 PEGASUS_CURRENT_CONFIG_FILE_PATH);
228 }
229
230 DefineMacro("currentConfigFilePath", path);
231 }
232
233 /* Define ${plannedConfigFilePath} */
234 {
235 char path[EXECUTOR_BUFFER_SIZE];
236
237 kumpf 1.2 if (GetHomedPath(PEGASUS_PLANNED_CONFIG_FILE_PATH, path) != 0)
238 {
239 Fatal(FL, "GetHomedPath() failed on \"%s\"",
240 PEGASUS_PLANNED_CONFIG_FILE_PATH);
241 }
242
243 DefineMacro("plannedConfigFilePath", path);
244 }
245
246 /* Define ${passwordFilePath} */
247
248 if (DefineConfigPathMacro("passwordFilePath", "cimserver.passwd") != 0)
249 Fatal(FL, "missing \"passwordFilePath\" configuration parameter.");
250
251 /* Define ${sslKeyFilePath} */
252
253 if (DefineConfigPathMacro("sslKeyFilePath", "file.pem") != 0)
254 Fatal(FL, "missing \"sslKeyFilePath\" configuration parameter.");
255
256 /* Define ${sslTrustStore} */
257
258 kumpf 1.2 if (DefineConfigPathMacro("sslTrustStore", "cimserver_trust") != 0)
259 Fatal(FL, "missing \"sslTrustStore\" configuration parameter.");
260
261 /* Define ${crlStore} */
262
263 if (DefineConfigPathMacro("crlStore", "crl") != 0)
264 Fatal(FL, "missing \"crlStore\" configuration parameter.");
|
265 sahana.prabhakar 1.18
266 /* Define ${localAuthDir} */
267 if(DefineMacro("localAuthDir",PEGASUS_LOCAL_AUTH_DIR) != 0)
268 Fatal(FL, "missing \"localAuthDir\" configuration parameter.");
|
269 kumpf 1.2 }
270
271 /*
272 **==============================================================================
273 **
274 ** main()
275 **
276 **==============================================================================
277 */
278
|
279 s.kodali 1.17
|
280 kumpf 1.2 int main(int argc, char** argv)
281 {
282 const char* cimservermainPath;
|
283 kumpf 1.11 const char* workingDirectory;
|
284 kumpf 1.2 int pair[2];
|
285 kumpf 1.10 int initCompletePipe[2];
286 int pid;
|
287 kumpf 1.2 char username[EXECUTOR_BUFFER_SIZE];
|
288 kumpf 1.6 const char* childUserName;
289 int childUid;
290 int childGid;
|
291 kumpf 1.2 int childPid;
292 struct Options options;
293
294 /* Get options. */
295
296 GetOptions(&argc, &argv, &options);
297
298 /* Save argc-argv as globals. */
299
300 globals.argc = argc;
301 globals.argv = argv;
302
|
303 kumpf 1.6 /* Open the log. */
304
|
305 s.kodali 1.17 OpenLog(CIMSERVER_LOG_IDENTITY);
|
306 kumpf 1.6
|
307 kumpf 1.2 /* Define macros needed by the executor. */
308
309 DefineExecutorMacros();
310
|
311 kumpf 1.6 /* If shutting down, then run CIMSHUTDOWN client. */
|
312 kumpf 1.2
313 if (options.shutdown)
314 ExecShutdown();
315
316 /* Process --policy and --macros options. */
317
318 if (options.dump)
319 {
|
320 kumpf 1.4 DumpPolicy(stdout, 1);
321 DumpMacros(stdout);
|
322 kumpf 1.2 exit(0);
323 }
324
325 /* Get absolute CIMSERVERMAIN program name. */
326
327 if ((cimservermainPath = FindMacro("cimservermainPath")) == NULL)
328 Fatal(FL, "Failed to locate %s program", CIMSERVERMAIN);
329
330 /* If CIMSERVERMAIN is already running, warn and exit now, unless one of
331 * the following options are given: -v, --version, -h, --help (these are
332 * passed through to CIMSERVERMAIN).
333 */
334
|
335 denise.eckstein 1.16 if (!options.version && !options.help)
336 {
337 int isRunning = (TestProcessRunning(
338 PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN) == 0);
339 if (options.status)
340 {
341 if (isRunning)
342 {
343 fprintf(stderr, "CIM Server is running.\n");
344 exit(0);
345 }
346 else
347 {
348 fprintf(stderr, "CIM Server is not running.\n");
349 exit(2);
350 }
351 }
352 else if (isRunning)
353 {
354 fprintf(stderr,
355 "%s: cimserver is already running (the PID found in the file "
356 denise.eckstein 1.16 "\"%s\" corresponds to an existing process named \"%s\").\n\n",
357 globals.argv[0], PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN);
358 exit(1);
359 }
360 }
|
361 kumpf 1.2
362 /* Get enableAuthentication configuration option. */
363
364 {
365 char buffer[EXECUTOR_BUFFER_SIZE];
366
367 if (GetConfigParam("enableAuthentication", buffer) == 0 &&
368 strcasecmp(buffer, "true") == 0)
369 {
370 globals.enableAuthentication = 1;
371 }
372 }
373
|
374 kumpf 1.4 /* Initialize the log-level from the configuration parameter. */
|
375 kumpf 1.2
|
376 kumpf 1.4 InitLogLevel();
|
377 kumpf 1.2
|
378 denise.eckstein 1.13 Log(LL_TRACE, "starting");
|
379 kumpf 1.2
380 /* Be sure this process is running as root (otherwise fail). */
381
382 if (setuid(0) != 0 || setgid(0) != 0)
383 Fatal(FL, "attempted to run program as non-root user");
384
385 /* Warn if authentication not enabled (suspicious use of executor). */
386
387 if (!globals.enableAuthentication)
388 Log(LL_WARNING, "authentication is NOT enabled");
389 else
390 Log(LL_TRACE, "authentication is enabled");
391
392 /* Print user info. */
393
394 if (GetUserName(getuid(), username) != 0)
395 Fatal(FL, "cannot resolve user from uid=%d", getuid());
396
397 Log(LL_TRACE, "running as %s (uid=%d, gid=%d)",
398 username, (int)getuid(), (int)getgid());
399
|
400 mateus.baur 1.9 /* Change the current directory */
401
|
402 kumpf 1.11 #if defined(PEGASUS_USE_RELEASE_DIRS) && defined(PEGASUS_CORE_DIR)
403 workingDirectory = PEGASUS_CORE_DIR;
|
404 denise.eckstein 1.12 #elif defined(PEGASUS_DEBUG)
405 workingDirectory = getenv("PEGASUS_TMP");
|
406 mateus.baur 1.9 #endif
|
407 denise.eckstein 1.12 if (workingDirectory == NULL)
408 {
409 workingDirectory = "/";
410 }
|
411 kumpf 1.11 if (chdir(workingDirectory) != 0)
412 {
413 Log(LL_WARNING, "Failed to change working directory to %s",
414 workingDirectory);
415 }
416
|
417 kumpf 1.10 /* Create a pipe for communicating with cimserver daemon process. */
418
419 if (pipe(initCompletePipe) != 0)
420 Fatal(FL, "Failed to create pipe");
421
422 CloseOnExec(initCompletePipe[0]);
423 CloseOnExec(initCompletePipe[1]);
424
425 /* Fork to ensure we are not a session leader so setsid() will succeed. */
426
427 pid = fork();
428
429 if (pid < 0)
430 {
431 Fatal(FL, "fork() failed");
432 }
433
434 if (pid > 0)
435 {
436 /* Wait until daemon writes an exit code or closes the pipe. */
437
438 kumpf 1.10 char exitRC;
439 ssize_t result;
440 time_t startTime;
441 time_t now;
442
443 close(initCompletePipe[1]);
444 SetNonBlocking(initCompletePipe[0]);
445 time(&startTime);
446
447 do
448 {
449 time(&now);
450 result = WaitForReadEnable(
451 initCompletePipe[0],
452 (CIMSERVER_COMMAND_TIMEOUT_SECONDS - (now - startTime)) * 1000);
453 } while (result == -1 && errno == EINTR);
454
455 if (result == 0)
456 {
457 fprintf(stderr,
458 "The cimserver command timed out waiting for the CIM server "
459 kumpf 1.10 "to start.");
460 _exit(0);
461 }
462
463 EXECUTOR_RESTART(read(initCompletePipe[0], &exitRC, 1), result);
464 if (result <= 0)
465 {
466 exitRC = 1;
467 }
468 _exit(exitRC);
469 }
470
471 close(initCompletePipe[0]);
472
473 /* Become session leader (so that our child process will not be one) */
474
475 if (setsid() < 0)
476 {
477 Fatal(FL, "setsid() failed");
478 }
479
480 kumpf 1.10 /* Ignore SIGHUP: */
481
482 signal(SIGHUP, SIG_IGN);
483
484 /* Ignore SIGCHLD: */
485
486 signal(SIGCHLD, SIG_IGN);
487
488 /* Ignore SIGPIPE: */
489
490 signal(SIGPIPE, SIG_IGN);
491
492 /* Fork cimserver daemon process (not a session leader since parent is). */
493
494 pid = fork();
495
496 if (pid < 0)
497 {
498 Fatal(FL, "fork() failed");
499 }
500
501 kumpf 1.10 if (pid > 0)
502 {
503 _exit(0);
504 }
505
|
506 kumpf 1.2 /* Determine user for running CIMSERVERMAIN. */
507
|
508 kumpf 1.6 GetServerUser(&childUserName, &childUid, &childGid);
|
509 kumpf 1.2
|
510 kumpf 1.10 /* Create a socket pair for communicating with the child process. */
511
512 if (CreateSocketPair(pair) != 0)
513 Fatal(FL, "Failed to create socket pair");
514
515 CloseOnExec(pair[1]);
516
|
517 kumpf 1.2 /* Fork child process. */
518
519 childPid = fork();
520
521 if (childPid == 0)
522 {
523 /* Child. */
524 close(pair[1]);
|
525 kumpf 1.3 Child(
526 argc,
527 argv,
528 cimservermainPath,
|
529 kumpf 1.6 childUserName,
530 childUid,
531 childGid,
|
532 kumpf 1.3 pair[0]);
|
533 kumpf 1.2 }
534 else if (childPid > 0)
535 {
536 /* Parent. */
537 close(pair[0]);
|
538 kumpf 1.10 Parent(pair[1], initCompletePipe[1], childPid, options.bindVerbose);
|
539 kumpf 1.2 }
540 else
541 {
542 Fatal(FL, "fork() failed");
543 }
544
545 return 0;
546 }
|