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