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