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