1 kumpf 1.2 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 kumpf 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <cstdio>
35 #include <cstdlib>
36 #include <cstring>
37
38 #include <Pegasus/Common/Config.h>
39
40 #if defined(PEGASUS_OS_TYPE_WINDOWS)
41 # include <windows.h>
42 #else
43 kumpf 1.2 # include <unistd.h>
|
44 thilo.boehm 1.16 # include <errno.h>
|
45 kumpf 1.2 # include <sys/types.h>
46 # include <sys/time.h>
47 # include <sys/resource.h>
48 #endif
49
50 #if defined(PEGASUS_HAS_SIGNALS)
51 # include <sys/wait.h>
52 #endif
53
54 #include <Pegasus/Common/Constants.h>
55 #include <Pegasus/Common/Mutex.h>
|
56 kumpf 1.7 #include <Pegasus/Common/Once.h>
|
57 kumpf 1.2 #include <Pegasus/Common/FileSystem.h>
58 #include <Pegasus/Common/String.h>
59 #include <Pegasus/Common/Tracer.h>
|
60 kumpf 1.3 #include <Pegasus/Common/System.h>
|
61 kumpf 1.2 #include <Pegasus/Common/Executor.h>
62
63 #include <Executor/Strlcpy.h>
64
65 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
66 # include <Executor/Socket.h>
67 # include <Executor/Messages.h>
68 #endif
69
70 #if defined(PEGASUS_PAM_AUTHENTICATION)
71 # include <Executor/PAMAuth.h>
72 #endif
73
|
74 ouyang.jian 1.11 #ifdef PEGASUS_OS_PASE
75 # include <as400_protos.h> // For fork400()
76 #endif
77
|
78 kumpf 1.17 #ifdef PEGASUS_OS_ZOS
79 # include <spawn.h>
80 #endif
81
|
82 kumpf 1.2 PEGASUS_NAMESPACE_BEGIN
83
84 ////////////////////////////////////////////////////////////////////////////////
85 //
86 //
87 // class ExecutorImpl
88 //
89 //
90 ////////////////////////////////////////////////////////////////////////////////
91
92 class ExecutorImpl
93 {
94 public:
95
96 virtual ~ExecutorImpl()
97 {
98 }
99
100 virtual int detectExecutor() = 0;
101
102 virtual int ping() = 0;
103 kumpf 1.2
104 virtual FILE* openFile(
105 const char* path,
106 int mode) = 0;
107
108 virtual int renameFile(
109 const char* oldPath,
110 const char* newPath) = 0;
111
112 virtual int removeFile(
113 const char* path) = 0;
114
115 virtual int startProviderAgent(
116 const char* module,
117 const String& pegasusHome,
118 const String& userName,
119 int& pid,
120 AnonymousPipe*& readPipe,
121 AnonymousPipe*& writePipe) = 0;
122
123 virtual int daemonizeExecutor() = 0;
124 kumpf 1.2
125 virtual int reapProviderAgent(
126 int pid) = 0;
127
128 virtual int authenticatePassword(
129 const char* username,
130 const char* password) = 0;
131
132 virtual int validateUser(
133 const char* username) = 0;
134
135 virtual int challengeLocal(
136 const char* username,
137 char challengeFilePath[EXECUTOR_BUFFER_SIZE]) = 0;
138
139 virtual int authenticateLocal(
140 const char* challengeFilePath,
141 const char* response) = 0;
|
142 kumpf 1.8
143 virtual int updateLogLevel(
144 const char* logLevel) = 0;
|
145 kumpf 1.2 };
146
147 ////////////////////////////////////////////////////////////////////////////////
148 //
149 //
150 // class ExecutorLoopbackImpl
151 //
152 //
153 ////////////////////////////////////////////////////////////////////////////////
154
155 class ExecutorLoopbackImpl : public ExecutorImpl
156 {
157 public:
158
159 virtual ~ExecutorLoopbackImpl()
160 {
161 }
162
163 virtual int detectExecutor()
164 {
165 return -1;
166 kumpf 1.2 }
167
168 virtual int ping()
169 {
170 return -1;
171 }
172
173 virtual FILE* openFile(
174 const char* path,
175 int mode)
176 {
177 switch (mode)
178 {
179 case 'r':
|
180 carson.hovey 1.15 return fopen(path, "r");
|
181 kumpf 1.2
182 case 'w':
|
183 carson.hovey 1.15 return fopen(path, "w");
|
184 kumpf 1.2
185 case 'a':
|
186 carson.hovey 1.15 return fopen(path, "a+");
|
187 kumpf 1.2
188 default:
189 return NULL;
190 }
191 }
192
193 virtual int renameFile(
194 const char* oldPath,
195 const char* newPath)
196 {
197 return FileSystem::renameFile(oldPath, newPath) ? 0 : -1;
198 }
199
200
201 virtual int removeFile(
202 const char* path)
203 {
204 return FileSystem::removeFile(path) ? 0 : -1;
205 }
206
207
208 kumpf 1.2 virtual int startProviderAgent(
209 const char* module,
210 const String& pegasusHome,
211 const String& userName,
212 int& pid,
213 AnonymousPipe*& readPipe,
214 AnonymousPipe*& writePipe)
215 {
|
216 thilo.boehm 1.16 PEG_METHOD_ENTER(TRC_SERVER,"ExecutorLoopbackImpl::startProviderAgent");
|
217 kumpf 1.18
|
218 kumpf 1.6 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
219 kumpf 1.2
|
220 kumpf 1.18 // Resolve full path of "cimprovagt" program.
221
222 String path = FileSystem::getAbsolutePath(
223 pegasusHome.getCString(), PEGASUS_PROVIDER_AGENT_PROC_NAME);
224
225 // Create CString handles for cimprovagt arguments
226
227 CString agentProgramPath = path.getCString();
228 CString userNameCString = userName.getCString();
229
230 # if defined(PEGASUS_DISABLE_PROV_USERCTXT)
231 const char* setUserContextFlag = "0"; // False
232 # else
233 const char* setUserContextFlag = "1"; // True
234 # endif
235
|
236 kumpf 1.6 # if defined(PEGASUS_OS_TYPE_WINDOWS)
|
237 kumpf 1.2
238 AutoMutex autoMutex(_mutex);
239
240 // Set output parameters in case of failure.
241
242 pid = 0;
243 readPipe = 0;
244 writePipe = 0;
245
246 // Create pipes. Export handles to string.
247
248 AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe());
249 AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe());
250
251 char readHandle[32];
252 char writeHandle[32];
253 pipeToAgent->exportReadHandle(readHandle);
254 pipeFromAgent->exportWriteHandle(writeHandle);
255
256 // Initialize PROCESS_INFORMATION.
257
258 kumpf 1.2 PROCESS_INFORMATION piProcInfo;
259 ZeroMemory(&piProcInfo, sizeof (PROCESS_INFORMATION));
260
261 // Initialize STARTUPINFO.
262
263 STARTUPINFO siStartInfo;
264 ZeroMemory(&siStartInfo, sizeof (STARTUPINFO));
265 siStartInfo.cb = sizeof (STARTUPINFO);
266
267 // Format command line.
268
269 char cmdLine[2048];
270
|
271 kumpf 1.18 sprintf(cmdLine, "\"%s\" %s %s %s \"%s\" \"%s\"",
272 (const char*)agentProgramPath,
273 setUserContextFlag,
|
274 kumpf 1.2 readHandle,
275 writeHandle,
|
276 kumpf 1.18 (const char*)userNameCString,
|
277 kumpf 1.2 module);
278
279 // Create provider agent proess.
280
281 if (!CreateProcess (
282 NULL, //
283 cmdLine, // command line
284 NULL, // process security attributes
285 NULL, // primary thread security attributes
286 TRUE, // handles are inherited
287 0, // creation flags
288 NULL, // use parent's environment
289 NULL, // use parent's current directory
290 &siStartInfo, // STARTUPINFO
291 &piProcInfo)) // PROCESS_INFORMATION
292 {
|
293 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
294 kumpf 1.2 return -1;
295 }
296
297 CloseHandle(piProcInfo.hProcess);
298 CloseHandle(piProcInfo.hThread);
299
300 // Close our copies of the agent's ends of the pipes
301
302 pipeToAgent->closeReadHandle();
303 pipeFromAgent->closeWriteHandle();
304
305 readPipe = pipeFromAgent.release();
306 writePipe = pipeToAgent.release();
307
|
308 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
309 kumpf 1.2 return 0;
310
|
311 kumpf 1.6 # else /* POSIX CASE FOLLOWS */
|
312 thilo.boehm 1.16
|
313 kumpf 1.2 AutoMutex autoMutex(_mutex);
314
315 // Initialize output parameters in case of error.
316
317 pid = -1;
318 readPipe = 0;
319 writePipe = 0;
320
321 // Pipes:
322
323 int to[2];
324 int from[2];
|
325 kumpf 1.18 char toPipeArg[32];
326 char fromPipeArg[32];
|
327 thilo.boehm 1.16
|
328 kumpf 1.2 do
329 {
330 // Create "to-agent" pipe:
331
332 if (pipe(to) != 0)
|
333 thilo.boehm 1.16 {
334 PEG_METHOD_EXIT();
|
335 kumpf 1.2 return -1;
|
336 thilo.boehm 1.16 }
337
|
338 kumpf 1.2 // Create "from-agent" pipe:
339
340 if (pipe(from) != 0)
|
341 thilo.boehm 1.16 {
342 PEG_METHOD_EXIT();
|
343 kumpf 1.2 return -1;
|
344 thilo.boehm 1.16 }
345
|
346 kumpf 1.18 // Initialize the cimprovagt pipe arguments:
347
348 sprintf(toPipeArg, "%d", to[0]);
349 sprintf(fromPipeArg, "%d", from[1]);
350
|
351 thilo.boehm 1.16 // Start provider agent:
352
353 # if defined(PEGASUS_OS_ZOS)
|
354 kumpf 1.18 // zOS uses __spawn2() instead of fork() to start provider agent
355
356 struct __inheritance inherit;
357 const char *c_argv[7];
358
359 c_argv[0] = agentProgramPath;
360 c_argv[1] = setUserContextFlag;
361 c_argv[2] = toPipeArg;
362 c_argv[3] = fromPipeArg;
363 c_argv[4] = userNameCString;
364 c_argv[5] = module;
365 c_argv[6] = NULL;
|
366 thilo.boehm 1.16
367 // reset the inherit structure
368 memset(&inherit,0,sizeof(inherit));
369
370 // The provider agent should get a defined JobName.
371 inherit.flags=SPAWN_SETJOBNAME;
372 memcpy( inherit.jobname,"CFZOOPA ",
373 sizeof(inherit.jobname));
374
375 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
|
376 kumpf 1.18 "Starting provider agent: %s %s %s %s %s %s %s",
377 (const char*)agentProgramPath,
378 c_argv[0],
379 c_argv[1],
380 c_argv[2],
381 c_argv[3],
382 c_argv[4],
383 c_argv[5]));
|
384 kumpf 1.2
|
385 kumpf 1.18 pid = __spawn2(agentProgramPath,0,NULL,&inherit,
|
386 thilo.boehm 1.16 c_argv,(const char **)environ);
|
387 kumpf 1.2
|
388 thilo.boehm 1.16 if (pid < 0)
389 {
|
390 marek 1.19 PEG_TRACE((TRC_SERVER, Tracer::LEVEL1,
|
391 thilo.boehm 1.16 "Spawn of provider agent fails:%s "
392 "( errno %d , reason code %08X )",
393 strerror(errno) ,errno,__errno2()));
394 PEG_METHOD_EXIT();
395 return -1;
396 }
397
|
398 kumpf 1.18 # else // !defined(PEGASUS_OS_ZOS)
399
400 # if defined(PEGASUS_OS_VMS)
|
401 kumpf 1.2 pid = (int)vfork();
|
402 kumpf 1.18 # elif defined(PEGASUS_OS_PASE)
|
403 ouyang.jian 1.11 pid = (int)fork400("QUMEPRVAGT",0);
|
404 kumpf 1.18 # else
|
405 kumpf 1.2 pid = (int)fork();
|
406 kumpf 1.18 # endif
|
407 thilo.boehm 1.16
|
408 kumpf 1.2 if (pid < 0)
|
409 thilo.boehm 1.16 {
|
410 marek 1.19 PEG_TRACE((TRC_SERVER, Tracer::LEVEL1,
|
411 thilo.boehm 1.16 "Fork for provider agent fails: errno = %d",errno));
412 PEG_METHOD_EXIT();
|
413 kumpf 1.2 return -1;
|
414 thilo.boehm 1.16 }
415
|
416 kumpf 1.2 if (pid == 0)
417 {
|
418 kumpf 1.18 // Child process
419
|
420 thilo.boehm 1.16 # if !defined(PEGASUS_OS_VMS)
|
421 kumpf 1.2 // Close unused pipe descriptors:
422
423 close(to[1]);
424 close(from[0]);
425
426 // Close unused descriptors. Leave stdin, stdout, stderr,
427 // and the child's pipe descriptors open.
428
429 struct rlimit rlim;
430
431 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
432 {
433 for (int i = 3; i < int(rlim.rlim_cur); i++)
434 {
435 if (i != to[0] && i != from[1])
436 close(i);
437 }
438 }
439
|
440 thilo.boehm 1.16 # endif /* !defined(PEGASUS_OS_VMS) */
|
441 kumpf 1.3
|
442 kumpf 1.2 // Exec the cimprovagt program.
443
444 {
|
445 kumpf 1.18 if (execl(
446 agentProgramPath,
447 agentProgramPath,
448 setUserContextFlag,
449 toPipeArg,
450 fromPipeArg,
451 (const char*)userNameCString,
452 module,
453 (char*)0) == -1)
|
454 kumpf 1.2 {
|
455 marek 1.19 PEG_TRACE((TRC_SERVER, Tracer::LEVEL1,
|
456 kumpf 1.2 "execl() failed. errno = %d.", errno));
457 _exit(1);
458 }
459 }
460 }
|
461 kumpf 1.18 # endif /* PEGASUS_OS_ZOS */
|
462 kumpf 1.2 }
463 while (0);
464
|
465 kumpf 1.18 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
466 "Provider agent started: pid(%d).", pid));
467
|
468 kumpf 1.2 // Close unused pipe descriptors.
469
470 close(to[0]);
471 close(from[1]);
472
473 // Set output parameters.
474
475 int readFd = from[0];
476 int writeFd = to[1];
477
478 // Create to and from AnonymousPipe instances to correspond to the pipe
479 // descriptors created above.
480
481 char readFdStr[32];
482 char writeFdStr[32];
483 sprintf(readFdStr, "%d", readFd);
484 sprintf(writeFdStr, "%d", writeFd);
485
486 readPipe = new AnonymousPipe(readFdStr, 0);
487 writePipe = new AnonymousPipe(0, writeFdStr);
488
|
489 kumpf 1.18 # if defined(PEGASUS_HAS_SIGNALS)
490 # if !defined(PEGASUS_DISABLE_PROV_USERCTXT) && !defined(PEGASUS_OS_ZOS)
491 // The cimprovagt forks and returns right away. Clean up the zombie
492 // process now instead of in reapProviderAgent().
493 int status = 0;
494 while ((status = waitpid(pid, 0, 0)) == -1 && errno == EINTR)
495 ;
496 # endif
497 # endif
498
|
499 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
500 kumpf 1.2 return 0;
501
|
502 kumpf 1.6 # endif /* POSIX CASE */
503
504 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is defined */
505
506 // Out-of-Process providers are never started by the cimserver process
507 // when Privilege Separation is enabled.
508 return -1;
509
510 #endif
|
511 kumpf 1.2 }
512
513 virtual int daemonizeExecutor()
514 {
515 return -1;
516 }
517
518 virtual int reapProviderAgent(
519 int pid)
520 {
|
521 kumpf 1.6 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
522
|
523 kumpf 1.2 int status = 0;
524
|
525 kumpf 1.6 # if defined(PEGASUS_HAS_SIGNALS)
|
526 kumpf 1.18 # if defined(PEGASUS_DISABLE_PROV_USERCTXT) || defined(PEGASUS_OS_ZOS)
527 // When provider user context is enabled, this is done in
528 // startProviderAgent().
|
529 kumpf 1.2 while ((status = waitpid(pid, 0, 0)) == -1 && errno == EINTR)
530 ;
|
531 kumpf 1.18 # endif
|
532 kumpf 1.6 # endif
|
533 kumpf 1.2
534 return status;
|
535 kumpf 1.6
536 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is defined */
537
538 // Out-of-Process providers are never started by the cimserver process
539 // when Privilege Separation is enabled.
540 return -1;
541
542 #endif
|
543 kumpf 1.2 }
544
545 virtual int authenticatePassword(
546 const char* username,
547 const char* password)
548 {
549 #if defined(PEGASUS_PAM_AUTHENTICATION)
550 return PAMAuthenticate(username, password);
551 #else
552 // ATTN: not handled so don't call in this case.
553 return -1;
554 #endif
555 }
556
557 virtual int validateUser(
558 const char* username)
559 {
|
560 kumpf 1.12 #if defined(PEGASUS_PAM_AUTHENTICATION)
|
561 kumpf 1.2 return PAMValidateUser(username);
|
562 kumpf 1.12 #else
|
563 kumpf 1.2 // ATTN: not handled so don't call in this case.
564 return -1;
|
565 kumpf 1.12 #endif
|
566 kumpf 1.2 }
567
568 virtual int challengeLocal(
569 const char* username,
570 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
571 {
572 // ATTN: not handled so don't call in this case.
573 return -1;
574 }
575
576 virtual int authenticateLocal(
577 const char* challengeFilePath,
578 const char* response)
579 {
580 // ATTN: not handled so don't call in this case.
581 return -1;
582 }
583
|
584 kumpf 1.8 virtual int updateLogLevel(
585 const char* logLevel)
586 {
587 // If Privilege Separation is not enabled, we don't need to update
588 // the log level in the Executor.
589 return 0;
590 }
591
|
592 kumpf 1.2 private:
593
594 Mutex _mutex;
595 };
596
597 ////////////////////////////////////////////////////////////////////////////////
598 //
599 //
600 // class ExecutorSocketImpl : public ExecutorImpl
601 //
602 //
603 ////////////////////////////////////////////////////////////////////////////////
604
605 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
606
607 class ExecutorSocketImpl : public ExecutorImpl
608 {
609 public:
610
611 ExecutorSocketImpl(int sock) : _sock(sock)
612 {
613 kumpf 1.2 }
614
615 virtual ~ExecutorSocketImpl()
616 {
617 }
618
619 virtual int detectExecutor()
620 {
621 return 0;
622 }
623
624 virtual int ping()
625 {
626 AutoMutex autoMutex(_mutex);
627
|
628 kumpf 1.9 // Send request header:
|
629 kumpf 1.2
630 ExecutorRequestHeader header;
631 header.code = EXECUTOR_PING_MESSAGE;
632
|
633 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
634 kumpf 1.2 return -1;
635
636 ExecutorPingResponse response;
637
|
638 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
639 kumpf 1.2 return -1;
640
641 if (response.magic == EXECUTOR_PING_MAGIC)
642 return 0;
643
644 return -1;
645 }
646
647 virtual FILE* openFile(
648 const char* path,
649 int mode)
650 {
651 AutoMutex autoMutex(_mutex);
652
653 if (mode != 'r' && mode != 'w' && mode != 'a')
654 return NULL;
655
|
656 kumpf 1.9 // Send request header:
|
657 kumpf 1.2
658 ExecutorRequestHeader header;
659 header.code = EXECUTOR_OPEN_FILE_MESSAGE;
660
|
661 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
662 kumpf 1.2 return NULL;
663
|
664 kumpf 1.9 // Send request body.
|
665 kumpf 1.2
666 ExecutorOpenFileRequest request;
667 memset(&request, 0, sizeof(request));
668 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
669 request.mode = mode;
670
|
671 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
672 kumpf 1.2 return NULL;
673
674 // Receive the response
675
676 ExecutorOpenFileResponse response;
677
|
678 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
679 kumpf 1.2 return NULL;
680
681 // Receive descriptor (if response successful).
682
683 if (response.status == 0)
684 {
685 int fds[1];
686
687 if (RecvDescriptorArray(_sock, fds, 1) != 0)
688 return NULL;
689
690 if (fds[0] == -1)
691 return NULL;
692 else
693 {
694 if (mode == 'r')
695 return fdopen(fds[0], "rb");
696 else
697 return fdopen(fds[0], "wb");
698 }
699 }
700 kumpf 1.2
701 return NULL;
702 }
703
704 virtual int renameFile(
705 const char* oldPath,
706 const char* newPath)
707 {
708 AutoMutex autoMutex(_mutex);
709
|
710 kumpf 1.9 // Send request header:
|
711 kumpf 1.2
712 ExecutorRequestHeader header;
713 header.code = EXECUTOR_RENAME_FILE_MESSAGE;
714
|
715 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
716 kumpf 1.2 return -1;
717
|
718 kumpf 1.9 // Send request body.
|
719 kumpf 1.2
720 ExecutorRenameFileRequest request;
721 memset(&request, 0, sizeof(request));
722 Strlcpy(request.oldPath, oldPath, EXECUTOR_BUFFER_SIZE);
723 Strlcpy(request.newPath, newPath, EXECUTOR_BUFFER_SIZE);
724
|
725 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
726 kumpf 1.2 return -1;
727
728 // Receive the response
729
730 ExecutorRenameFileResponse response;
731
|
732 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
733 kumpf 1.2 return -1;
734
735 return response.status;
736 }
737
738 virtual int removeFile(
739 const char* path)
740 {
741 AutoMutex autoMutex(_mutex);
742
|
743 kumpf 1.9 // Send request header:
|
744 kumpf 1.2
745 ExecutorRequestHeader header;
746 header.code = EXECUTOR_REMOVE_FILE_MESSAGE;
747
|
748 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
749 kumpf 1.2 return -1;
750
|
751 kumpf 1.9 // Send request body.
|
752 kumpf 1.2
753 ExecutorRemoveFileRequest request;
754 memset(&request, 0, sizeof(request));
755 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
756
|
757 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
758 kumpf 1.2 return -1;
759
760 // Receive the response
761
762 ExecutorRemoveFileResponse response;
763
|
764 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
765 kumpf 1.2 return -1;
766
767 return response.status;
768 }
769
770 virtual int startProviderAgent(
771 const char* module,
772 const String& pegasusHome,
773 const String& userName,
774 int& pid,
775 AnonymousPipe*& readPipe,
776 AnonymousPipe*& writePipe)
777 {
778 AutoMutex autoMutex(_mutex);
779
780 readPipe = 0;
781 writePipe = 0;
782
783 // Reject strings longer than EXECUTOR_BUFFER_SIZE.
784
|
785 kumpf 1.3 size_t moduleNameLength = strlen(module);
786
787 if (moduleNameLength >= EXECUTOR_BUFFER_SIZE)
788 return -1;
789
790 CString userNameCString = userName.getCString();
791 size_t userNameLength = strlen(userNameCString);
|
792 kumpf 1.2
|
793 kumpf 1.3 if (userNameLength >= EXECUTOR_BUFFER_SIZE)
|
794 kumpf 1.2 return -1;
795
|
796 kumpf 1.9 // Send request header:
|
797 kumpf 1.2
798 ExecutorRequestHeader header;
799 header.code = EXECUTOR_START_PROVIDER_AGENT_MESSAGE;
800
|
801 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
802 kumpf 1.2 return -1;
803
|
804 kumpf 1.9 // Send request body.
|
805 kumpf 1.2
806 ExecutorStartProviderAgentRequest request;
807 memset(&request, 0, sizeof(request));
|
808 kumpf 1.3 memcpy(request.module, module, moduleNameLength);
809 memcpy(request.userName, userNameCString, userNameLength);
|
810 kumpf 1.2
|
811 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
812 kumpf 1.2 return -1;
813
814 // Receive the response
815
816 ExecutorStartProviderAgentResponse response;
817
|
818 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
819 kumpf 1.2 return -1;
820
821 // Check response status and pid.
822
823 if (response.status != 0)
824 return -1;
825
826 // Get pid:
827
828 pid = response.pid;
829
830 // Receive descriptors.
831
832 int descriptors[2];
833 int result = RecvDescriptorArray(_sock, descriptors, 2);
834
835 if (result == 0)
836 {
837 int readFd = descriptors[0];
838 int writeFd = descriptors[1];
839
840 kumpf 1.2 // Create to and from AnonymousPipe instances to correspond to
841 // the pipe descriptors created above.
842
843 char readFdStr[32];
844 char writeFdStr[32];
845 sprintf(readFdStr, "%d", readFd);
846 sprintf(writeFdStr, "%d", writeFd);
847
848 readPipe = new AnonymousPipe(readFdStr, 0);
849 writePipe = new AnonymousPipe(0, writeFdStr);
850 }
851
852 return result;
853 }
854
855 virtual int daemonizeExecutor()
856 {
857 AutoMutex autoMutex(_mutex);
858
|
859 kumpf 1.9 // Send request header:
|
860 kumpf 1.2
861 ExecutorRequestHeader header;
862 header.code = EXECUTOR_DAEMONIZE_EXECUTOR_MESSAGE;
863
|
864 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
865 kumpf 1.2 return -1;
866
867 // Receive the response
868
869 ExecutorDaemonizeExecutorResponse response;
870
|
871 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
872 kumpf 1.2 return -1;
873
874 return response.status;
875 }
876
877 virtual int reapProviderAgent(
878 int pid)
879 {
|
880 kumpf 1.10 // The Executor process automatically cleans up all its child
881 // processes, so it does not need to explicitly harvest the
882 // exit status of the cimprovagt processes it starts.
|
883 kumpf 1.2
|
884 kumpf 1.10 return 0;
|
885 kumpf 1.2 }
886
887 virtual int authenticatePassword(
888 const char* username,
889 const char* password)
890 {
891 AutoMutex autoMutex(_mutex);
892
|
893 kumpf 1.9 // Send request header:
|
894 kumpf 1.2
895 ExecutorRequestHeader header;
896 header.code = EXECUTOR_AUTHENTICATE_PASSWORD_MESSAGE;
897
|
898 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
899 kumpf 1.2 return -1;
900
|
901 kumpf 1.9 // Send request body.
|
902 kumpf 1.2
903 ExecutorAuthenticatePasswordRequest request;
904 memset(&request, 0, sizeof(request));
905 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
906 Strlcpy(request.password, password, EXECUTOR_BUFFER_SIZE);
907
|
908 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
909 kumpf 1.2 return -1;
910
911 // Receive the response
912
913 ExecutorAuthenticatePasswordResponse response;
914
|
915 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
916 kumpf 1.2 return -1;
917
918 return response.status;
919 }
920
921 virtual int validateUser(
922 const char* username)
923 {
924 AutoMutex autoMutex(_mutex);
925
|
926 kumpf 1.9 // Send request header:
|
927 kumpf 1.2
928 ExecutorRequestHeader header;
929 header.code = EXECUTOR_VALIDATE_USER_MESSAGE;
930
|
931 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
932 kumpf 1.2 return -1;
933
|
934 kumpf 1.9 // Send request body.
|
935 kumpf 1.2
936 ExecutorValidateUserRequest request;
937 memset(&request, 0, sizeof(request));
938 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
939
|
940 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
941 kumpf 1.2 return -1;
942
943 // Receive the response
944
945 ExecutorValidateUserResponse response;
946
|
947 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
948 kumpf 1.2 return -1;
949
950 return response.status;
951 }
952
953 virtual int challengeLocal(
954 const char* username,
955 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
956 {
957 AutoMutex autoMutex(_mutex);
958
|
959 kumpf 1.9 // Send request header:
|
960 kumpf 1.2
961 ExecutorRequestHeader header;
962 header.code = EXECUTOR_CHALLENGE_LOCAL_MESSAGE;
963
|
964 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
965 kumpf 1.2 return -1;
966
|
967 kumpf 1.9 // Send request body.
|
968 kumpf 1.2
969 ExecutorChallengeLocalRequest request;
970 memset(&request, 0, sizeof(request));
971 Strlcpy(request.user, username, EXECUTOR_BUFFER_SIZE);
972
|
973 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
974 kumpf 1.2 return -1;
975
976 // Receive the response
977
978 ExecutorChallengeLocalResponse response;
979
|
980 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
981 kumpf 1.2 return -1;
982
983 Strlcpy(challengeFilePath, response.challenge, EXECUTOR_BUFFER_SIZE);
984
985 return response.status;
986 }
987
988 virtual int authenticateLocal(
989 const char* challengeFilePath,
990 const char* response)
991 {
992 AutoMutex autoMutex(_mutex);
993
|
994 kumpf 1.9 // Send request header:
|
995 kumpf 1.2
996 ExecutorRequestHeader header;
997 header.code = EXECUTOR_AUTHENTICATE_LOCAL_MESSAGE;
998
|
999 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1000 kumpf 1.2 return -1;
1001
|
1002 kumpf 1.9 // Send request body.
|
1003 kumpf 1.2
1004 ExecutorAuthenticateLocalRequest request;
1005 memset(&request, 0, sizeof(request));
1006 Strlcpy(request.challenge, challengeFilePath, EXECUTOR_BUFFER_SIZE);
1007 Strlcpy(request.response, response, EXECUTOR_BUFFER_SIZE);
1008
|
1009 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1010 kumpf 1.2 return -1;
1011
1012 // Receive the response
1013
1014 ExecutorAuthenticateLocalResponse response_;
1015
|
1016 kumpf 1.9 if (RecvBlock(_sock, &response_, sizeof(response_)) !=
1017 sizeof(response_))
1018 {
|
1019 kumpf 1.2 return -1;
|
1020 kumpf 1.9 }
|
1021 kumpf 1.2
1022 return response_.status;
1023 }
1024
|
1025 kumpf 1.8 virtual int updateLogLevel(
1026 const char* logLevel)
1027 {
1028 AutoMutex autoMutex(_mutex);
1029
|
1030 kumpf 1.9 // Send request header:
|
1031 kumpf 1.8
1032 ExecutorRequestHeader header;
1033 header.code = EXECUTOR_UPDATE_LOG_LEVEL_MESSAGE;
1034
|
1035 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1036 kumpf 1.8 return -1;
1037
|
1038 kumpf 1.9 // Send request body:
|
1039 kumpf 1.8
1040 ExecutorUpdateLogLevelRequest request;
1041 memset(&request, 0, sizeof(request));
1042 Strlcpy(request.logLevel, logLevel, EXECUTOR_BUFFER_SIZE);
1043
|
1044 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1045 kumpf 1.8 return -1;
1046
1047 // Receive the response
1048
1049 ExecutorUpdateLogLevelResponse response;
1050
|
1051 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
1052 kumpf 1.8 return -1;
1053
1054 return response.status;
1055 }
1056
|
1057 kumpf 1.2 private:
1058
1059 int _sock;
1060 Mutex _mutex;
1061 };
1062
1063 #endif /* defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION) */
1064
1065 ////////////////////////////////////////////////////////////////////////////////
1066 //
1067 //
1068 // class Executor
1069 //
1070 //
1071 ////////////////////////////////////////////////////////////////////////////////
1072
1073 static int _executorSock = -1;
|
1074 kumpf 1.5 static AutoPtr<ExecutorImpl> _executorImpl;
|
1075 kumpf 1.7 static Once _executorImplOnce = PEGASUS_ONCE_INITIALIZER;
|
1076 kumpf 1.2
|
1077 kumpf 1.7 static void _initExecutorImpl()
|
1078 kumpf 1.2 {
1079 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
1080 kumpf 1.7 if (_executorSock == -1)
1081 _executorImpl.reset(new ExecutorLoopbackImpl());
1082 else
1083 _executorImpl.reset(new ExecutorSocketImpl(_executorSock));
|
1084 kumpf 1.2 #else
|
1085 kumpf 1.7 _executorImpl.reset(new ExecutorLoopbackImpl());
|
1086 kumpf 1.2 #endif
1087 }
1088
1089 void Executor::setSock(int sock)
1090 {
1091 _executorSock = sock;
1092 }
1093
1094 int Executor::detectExecutor()
1095 {
|
1096 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1097 return _executorImpl->detectExecutor();
|
1098 kumpf 1.2 }
1099
1100 int Executor::ping()
1101 {
|
1102 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1103 return _executorImpl->ping();
|
1104 kumpf 1.2 }
1105
1106 FILE* Executor::openFile(
1107 const char* path,
1108 int mode)
1109 {
|
1110 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1111 return _executorImpl->openFile(path, mode);
|
1112 kumpf 1.2 }
1113
1114 int Executor::renameFile(
1115 const char* oldPath,
1116 const char* newPath)
1117 {
|
1118 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1119 return _executorImpl->renameFile(oldPath, newPath);
|
1120 kumpf 1.2 }
1121
1122 int Executor::removeFile(
1123 const char* path)
1124 {
|
1125 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1126 return _executorImpl->removeFile(path);
|
1127 kumpf 1.2 }
1128
1129 int Executor::startProviderAgent(
1130 const char* module,
1131 const String& pegasusHome,
1132 const String& userName,
1133 int& pid,
1134 AnonymousPipe*& readPipe,
1135 AnonymousPipe*& writePipe)
1136 {
|
1137 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1138 return _executorImpl->startProviderAgent(
|
1139 kumpf 1.3 module, pegasusHome, userName, pid, readPipe, writePipe);
|
1140 kumpf 1.2 }
1141
1142 int Executor::daemonizeExecutor()
1143 {
|
1144 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1145 return _executorImpl->daemonizeExecutor();
|
1146 kumpf 1.2 }
1147
1148 int Executor::reapProviderAgent(
1149 int pid)
1150 {
|
1151 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1152 return _executorImpl->reapProviderAgent(pid);
|
1153 kumpf 1.2 }
1154
1155 int Executor::authenticatePassword(
1156 const char* username,
1157 const char* password)
1158 {
|
1159 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1160 return _executorImpl->authenticatePassword(username, password);
|
1161 kumpf 1.2 }
1162
1163 int Executor::validateUser(
1164 const char* username)
1165 {
|
1166 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1167 return _executorImpl->validateUser(username);
|
1168 kumpf 1.2 }
1169
1170 int Executor::challengeLocal(
1171 const char* user,
1172 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
1173 {
|
1174 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1175 return _executorImpl->challengeLocal(user, challengeFilePath);
|
1176 kumpf 1.2 }
1177
1178 int Executor::authenticateLocal(
1179 const char* challengeFilePath,
1180 const char* response)
1181 {
|
1182 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1183 return _executorImpl->authenticateLocal(challengeFilePath, response);
|
1184 kumpf 1.2 }
1185
|
1186 kumpf 1.8 int Executor::updateLogLevel(
1187 const char* logLevel)
1188 {
1189 once(&_executorImplOnce, _initExecutorImpl);
1190 return _executorImpl->updateLogLevel(logLevel);
1191 }
1192
|
1193 kumpf 1.2 PEGASUS_NAMESPACE_END
|