1 mike 1.1.2.1 /*
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 mike 1.1.2.1 // 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 #include "Config.h"
39 #include "Child.h"
40 #include "Parent.h"
41 #include "User.h"
42 #include "Fatal.h"
43 mike 1.1.2.1 #include "Process.h"
44 #include "Path.h"
45 #include "Globals.h"
46 #include "Socket.h"
|
47 mike 1.1.2.6 #include "Strlcpy.h"
|
48 mike 1.1.2.1 #include "Log.h"
|
49 mike 1.1.2.7 #include "Policy.h"
|
50 mike 1.1.2.8 #include "Macro.h"
|
51 mike 1.1.2.1
52 /*
53 **==============================================================================
54 **
55 ** GetServerUser
56 **
57 ** Determine which user to run cimservermain as.
58 **
|
59 mike 1.1.2.4 ** Note: this algorithm is no longer in use.
60 **
|
61 mike 1.1.2.1 **==============================================================================
62 */
63
|
64 mike 1.1.2.4 int GetServerUser(int* uid, int* gid)
|
65 mike 1.1.2.1 {
|
66 mike 1.1.2.4 const char* username = PEGASUS_CIMSERVERMAIN_USER;
|
67 mike 1.1.2.1
|
68 mike 1.1.2.4 if (GetUserInfo(username, uid, gid) != 0)
|
69 mike 1.1.2.1 {
|
70 mike 1.1.2.4 Fatal(FL,
71 "The cimservermain user does not exist: \"%s\". Please create "
72 "a system user with that name or use an OpenPegasus build that "
73 "disables privilege separation.", username);
|
74 mike 1.1.2.1 }
75
76 return -1;
77 }
78
79 /*
80 **==============================================================================
81 **
82 ** ReadPidFile()
83 **
84 **==============================================================================
85 */
86
87 static int ReadPidFile(const char* path, int* pid)
88 {
89 FILE* is = fopen(path, "r");
90
91 if (!is)
92 return -1;
93
94 *pid = 0;
95 mike 1.1.2.1
96 fscanf(is, "%d\n", pid);
97 fclose(is);
98
99 if (*pid == 0)
100 return -1;
101
102 return 0;
103 }
104
105 /*
106 **==============================================================================
107 **
108 ** TestCimServerProcess()
109 **
110 ** Returns 0 if cimserver process is running.
111 **
112 **==============================================================================
113 */
114
115 int TestCimServerProcess()
116 mike 1.1.2.1 {
117 int pid;
118 char name[EXECUTOR_BUFFER_SIZE];
119
120 if (ReadPidFile(PEGASUS_CIMSERVER_START_FILE, &pid) != 0)
121 return -1;
122
123 if (GetProcessName(pid, name) != 0 || strcmp(name, CIMSERVERMAIN) != 0)
124 return -1;
125
126 return 0;
127 }
128
129 /*
130 **==============================================================================
131 **
132 ** ExecShutdown()
133 **
134 **==============================================================================
135 */
136
|
137 mike 1.1.2.6 void ExecShutdown(int argc, char** argv)
|
138 mike 1.1.2.1 {
139 char* tmpArgv[3];
|
140 mike 1.1.2.6 char cimshutdownPath[EXECUTOR_BUFFER_SIZE];
141 char shutdownTimeout[EXECUTOR_BUFFER_SIZE];
|
142 mike 1.1.2.1
|
143 mike 1.1.2.6 /* Get shutdownTimeout configuration parameter. */
|
144 mike 1.1.2.1
|
145 mike 1.1.2.6 if (GetConfigParam(argc, argv, "shutdownTimeout", shutdownTimeout) != 0)
146 Strlcpy(shutdownTimeout, "5", sizeof(shutdownTimeout));
147
148 /* Get absolute cimshutdown program name. */
|
149 mike 1.1.2.1
150 if (GetInternalPegasusProgramPath(CIMSHUTDOWN, cimshutdownPath) != 0)
151 Fatal(FL, "Failed to locate Pegasus program: %s", CIMSHUTDOWN);
152
153 /* Create argument list. */
154
155 tmpArgv[0] = CIMSHUTDOWN;
|
156 mike 1.1.2.6 tmpArgv[1] = shutdownTimeout;
|
157 mike 1.1.2.1 tmpArgv[2] = 0;
158
159 /* Exec CIMSHUTDOWN program. */
160
161 /* Flawfinder: ignore */
162 execv(cimshutdownPath, tmpArgv);
163 Fatal(FL, "failed to exec %s", cimshutdownPath);
164 }
165
166 /*
167 **==============================================================================
168 **
|
169 mike 1.1.2.8 ** DefineExecutorMacros()
170 **
171 ** Define macros used by the executor.
172 **
173 **==============================================================================
174 */
175
176 void DefineExecutorMacros()
177 {
178 /* Define ${internalBinDir} */
179 {
180 char path[EXECUTOR_BUFFER_SIZE];
181
182 if (GetPegasusInternalBinDir(path) != 0)
183 Fatal(FL, "failed to resolve internal pegasus bin directory");
184
185 DefineMacro("internalBinDir", path);
186 }
187
188 /* Define ${cimservermainPath} */
189 {
190 mike 1.1.2.8 char path[EXECUTOR_BUFFER_SIZE];
191
192 if (ExpandMacros("${internalBinDir}/cimservermain", path) != 0)
193 Fatal(FL, "failed to resolve cimserver main path");
194
195 DefineMacro("cimservermainPath", path);
196 }
197
198 /* Define ${cimprovagtPath} */
199 {
200 char path[EXECUTOR_BUFFER_SIZE];
201
202 if (ExpandMacros("${internalBinDir}/cimprovagt", path) != 0)
203 Fatal(FL, "failed to resolve cimserver main path");
204
205 DefineMacro("cimprovagtPath", path);
206 }
207
208 /* Define ${cimserveraPath} */
209 {
210 char path[EXECUTOR_BUFFER_SIZE];
211 mike 1.1.2.8
212 if (ExpandMacros("${internalBinDir}/cimservera", path) != 0)
213 Fatal(FL, "failed to resolve cimserver main path");
214
215 DefineMacro("cimserveraPath", path);
216 }
217
218 /* Define ${currentConfigFilePath} */
219 {
220 char path[EXECUTOR_BUFFER_SIZE];
221
222 if (GetHomedPath(PEGASUS_CURRENT_CONFIG_FILE_PATH, path) != 0)
223 {
224 Fatal(FL, "GetHomedPath() failed on \"%s\"",
225 PEGASUS_CURRENT_CONFIG_FILE_PATH);
226 }
227
228 DefineMacro("currentConfigFilePath", path);
229 }
230
231 /* Define ${repositoryDir} */
232 mike 1.1.2.8
233 if (DefineConfigPathMacro("repositoryDir", PEGASUS_REPOSITORY_DIR) != 0)
234 Fatal(FL, "missing \"repositoryDir\" configuration parameter.");
235
236 /* Define ${passwordFilePath} */
237
238 if (DefineConfigPathMacro("passwordFilePath", "cimserver.passwd") != 0)
239 Fatal(FL, "missing \"passwordFilePath\" configuration parameter.");
240
241 /* Define ${traceFilePath} */
242
243 if (DefineConfigPathMacro("traceFilePath", NULL) != 0)
244 Fatal(FL, "missing \"traceFilePath\" 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 mike 1.1.2.8 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 ** TestFlagOption()
266 **
267 ** Check whether argv contains the given option. Return 0 if so. Else
268 ** return -1. Remove the argument from the list if the *remove* argument
269 ** is non-zero.
270 **
271 ** if (TestFlagOption(&argc, &argv, "--help", 0) == 0)
272 ** {
273 ** }
274 mike 1.1.2.8 **
275 **==============================================================================
276 */
277
278 int TestFlagOption(int* argc_, char*** argv_, const char* option, int remove)
279 {
280 int argc = *argc_;
281 char** argv = *argv_;
282 int i;
283
284 for (i = 0; i < argc; i++)
285 {
286 if (strcmp(argv[i], option) == 0)
287 {
288 if (remove)
289 {
290 memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));
291 argc--;
292 }
293
294 *argc_ = argc;
295 mike 1.1.2.8 *argv_ = argv;
296 return 0;
297 }
298 }
299
300 /* Not found */
301 return -1;
302 }
303
304 /*
305 **==============================================================================
306 **
|
307 mike 1.1.2.1 ** main()
308 **
309 **==============================================================================
310 */
311
312 void doit();
313
314 int main(int argc, char** argv)
315 {
316 int i;
317 char cimservermainPath[EXECUTOR_BUFFER_SIZE];
318 int pair[2];
319 char username[EXECUTOR_BUFFER_SIZE];
320 int childPid;
321 int perror;
|
322 mike 1.1.2.6 long shutdownTimeout;
|
323 mike 1.1.2.8 const char* repositoryDir;
|
324 mike 1.1.2.1
325 /* Save as global so it can be used in error and log messages. */
326
|
327 mike 1.1.2.8 globals.argc = argc;
328 globals.argv = argv;
|
329 mike 1.1.2.1
330 /* If shuting down, then run "cimshutdown" client. */
331
|
332 mike 1.1.2.8 if (TestFlagOption(&argc, &argv, "-s", 0) == 0)
333 ExecShutdown(argc, argv);
334
335 /* Define macros needed by the executor. */
336
337 DefineExecutorMacros();
338
339 /* Check for --dump-policy option. */
340
341 if (TestFlagOption(&argc, &argv, "--dump-policy", 0) == 0)
|
342 mike 1.1.2.1 {
|
343 mike 1.1.2.8 DumpPolicy(1);
344 putchar('\n');
345 exit(0);
346 }
347
348 /* Check for --dump-macros option. */
349
350 if (TestFlagOption(&argc, &argv, "--dump-macros", 0) == 0)
351 {
352 DumpMacros();
353 putchar('\n');
354 exit(0);
|
355 mike 1.1.2.1 }
356
|
357 mike 1.1.2.6 /* Get absolute cimservermain program name. */
358
359 if (GetInternalPegasusProgramPath(CIMSERVERMAIN, cimservermainPath) != 0)
360 Fatal(FL, "Failed to locate Pegasus program: %s", CIMSERVERMAIN);
361
|
362 mike 1.1.2.1 /* If CIMSERVERMAIN is already running, warn and exit now. */
363
364 if (TestCimServerProcess() == 0)
365 {
366 fprintf(stderr,
367 "%s: cimserver is already running (the PID found in the file "
368 "\"%s\" corresponds to an existing process named \"%s\").\n\n",
|
369 mike 1.1.2.8 globals.argv[0], PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN);
|
370 mike 1.1.2.1
371 exit(1);
372 }
373
|
374 mike 1.1.2.2 /* Get enableAuthentication configuration option. */
375
376 {
377 char buffer[EXECUTOR_BUFFER_SIZE];
378
379 if (GetConfigParam(argc, argv, "enableAuthentication", buffer) == 0 &&
380 strcasecmp(buffer, "true") == 0)
381 {
382 globals.enableAuthentication = 1;
383 }
384 }
385
|
386 mike 1.1.2.1 /* Create a socket pair for communicating with the child process. */
387
388 if (CreateSocketPair(pair) != 0)
|
389 mike 1.1.2.5 Fatal(FL, "Failed to create socket pair");
|
390 mike 1.1.2.1
391 CloseOnExec(pair[1]);
392
393 /* Get the log-level from the configuration parameter. */
394
395 GetLogLevel(argc, argv);
396
|
397 mike 1.1.2.8 /* Extract --perror option (directs syslog output to stderr). */
|
398 mike 1.1.2.1
399 perror = 0;
400
|
401 mike 1.1.2.8 if (TestFlagOption(&argc, &argv, "--perror", 1) == 0)
402 perror = 1;
|
403 mike 1.1.2.1
404 /* Open the log. */
405
406 OpenLog("cimexecutor", perror);
407
408 Log(LL_INFORMATION, "starting");
409
410 /* Be sure this process is running as root (otherwise fail). */
411
412 if (setuid(0) != 0 || setgid(0) != 0)
413 {
414 Log(LL_FATAL, "attempted to run program as non-root user");
|
415 mike 1.1.2.8 fprintf(stderr,
416 "%s: this program must be run as root\n", globals.argv[0]);
|
417 mike 1.1.2.1 exit(0);
418 }
419
|
420 mike 1.1.2.2 /* Warn if authentication not enabled (strange use of executor if not). */
421
422 if (!globals.enableAuthentication)
423 Log(LL_WARNING, "authentication is NOT enabled");
424 else
|
425 mike 1.1.2.3 Log(LL_TRACE, "authentication is enabled");
|
426 mike 1.1.2.2
|
427 mike 1.1.2.1 /* Print user info. */
428
429 if (GetUserName(getuid(), username) != 0)
430 Fatal(FL, "cannot resolve user from uid=%d", getuid());
431
432 Log(LL_TRACE, "running as %s (uid=%d, gid=%d)",
433 username, (int)getuid(), (int)getgid());
434
435 /* Determine user for running cimservermain. */
436
|
437 mike 1.1.2.4 GetServerUser(&globals.childUid, &globals.childGid);
|
438 mike 1.1.2.1
|
439 mike 1.1.2.8 /* Get repositoryDir for child. */
440
441 if ((repositoryDir = FindMacro("repositoryDir")) == NULL)
442 Fatal(FL, "failed to find repositoryDir macro");
443
|
444 mike 1.1.2.1 /* Fork child process. */
445
446 childPid = fork();
447
448 if (childPid == 0)
449 {
450 /* Child. */
451 close(pair[1]);
|
452 mike 1.1.2.8 Child(argc, argv, cimservermainPath, globals.childUid,
453 globals.childGid, pair[0], repositoryDir);
|
454 mike 1.1.2.1 }
455 else if (childPid > 0)
456 {
457 /* Parent. */
458 close(pair[0]);
459 Parent(pair[1], childPid);
460 }
461 else
462 {
463 Fatal(FL, "fork() failed");
464 }
465
466 return 0;
467 }
|