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.6 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
218 kumpf 1.2
|
219 kumpf 1.6 # if defined(PEGASUS_OS_TYPE_WINDOWS)
|
220 kumpf 1.2
221 AutoMutex autoMutex(_mutex);
222
223 // Set output parameters in case of failure.
224
225 pid = 0;
226 readPipe = 0;
227 writePipe = 0;
228
229 // Create pipes. Export handles to string.
230
231 AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe());
232 AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe());
233
234 char readHandle[32];
235 char writeHandle[32];
236 pipeToAgent->exportReadHandle(readHandle);
237 pipeFromAgent->exportWriteHandle(writeHandle);
238
239 // Initialize PROCESS_INFORMATION.
240
241 kumpf 1.2 PROCESS_INFORMATION piProcInfo;
242 ZeroMemory(&piProcInfo, sizeof (PROCESS_INFORMATION));
243
244 // Initialize STARTUPINFO.
245
246 STARTUPINFO siStartInfo;
247 ZeroMemory(&siStartInfo, sizeof (STARTUPINFO));
248 siStartInfo.cb = sizeof (STARTUPINFO);
249
250 // Build full path of "cimprovagt" program.
251
252 String path = FileSystem::getAbsolutePath(
253 pegasusHome.getCString(), PEGASUS_PROVIDER_AGENT_PROC_NAME);
254
255 // Format command line.
256
257 char cmdLine[2048];
258
259 sprintf(cmdLine, "\"%s\" %s %s \"%s\"",
260 (const char*)path.getCString(),
261 readHandle,
262 kumpf 1.2 writeHandle,
263 module);
264
265 // Create provider agent proess.
266
267 if (!CreateProcess (
268 NULL, //
269 cmdLine, // command line
270 NULL, // process security attributes
271 NULL, // primary thread security attributes
272 TRUE, // handles are inherited
273 0, // creation flags
274 NULL, // use parent's environment
275 NULL, // use parent's current directory
276 &siStartInfo, // STARTUPINFO
277 &piProcInfo)) // PROCESS_INFORMATION
278 {
|
279 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
280 kumpf 1.2 return -1;
281 }
282
283 CloseHandle(piProcInfo.hProcess);
284 CloseHandle(piProcInfo.hThread);
285
286 // Close our copies of the agent's ends of the pipes
287
288 pipeToAgent->closeReadHandle();
289 pipeFromAgent->closeWriteHandle();
290
291 readPipe = pipeFromAgent.release();
292 writePipe = pipeToAgent.release();
293
|
294 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
295 kumpf 1.2 return 0;
296
|
297 kumpf 1.6 # else /* POSIX CASE FOLLOWS */
|
298 thilo.boehm 1.16
|
299 kumpf 1.2 AutoMutex autoMutex(_mutex);
300
301 // Initialize output parameters in case of error.
302
303 pid = -1;
304 readPipe = 0;
305 writePipe = 0;
306
307 // Pipes:
308
309 int to[2];
310 int from[2];
311
|
312 thilo.boehm 1.16 # if defined(PEGASUS_OS_ZOS)
313 // zOS is using __spawn2() instead of frok()
314 struct __inheritance inherit;
315 const char *c_argv[5];
316 char arg1[32];
317 char arg2[32];
318
319 # endif
320
|
321 kumpf 1.2 do
322 {
323 // Resolve full path of "cimprovagt".
324
325 String path = FileSystem::getAbsolutePath(
326 pegasusHome.getCString(), PEGASUS_PROVIDER_AGENT_PROC_NAME);
327
|
328 r.kieninger 1.13 # if !defined(PEGASUS_DISABLE_PROV_USERCTXT) && !defined(PEGASUS_OS_ZOS)
|
329 kumpf 1.3
330 PEGASUS_UID_T newUid = (PEGASUS_UID_T)-1;
331 PEGASUS_GID_T newGid = (PEGASUS_GID_T)-1;
332
333 if (userName != System::getEffectiveUserName())
334 {
335 if (!System::lookupUserId(
336 userName.getCString(), newUid, newGid))
337 {
|
338 thilo.boehm 1.16 PEG_TRACE((TRC_SERVER, Tracer::LEVEL2,
339 "System::lookupUserId(%s) for provider user "
340 "context failed.",
|
341 kumpf 1.3 (const char*)userName.getCString()));
|
342 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
343 kumpf 1.3 return -1;
344 }
345 }
346
|
347 kumpf 1.6 # endif /* !defined(PEGASUS_DISABLE_PROV_USERCTXT) */
|
348 kumpf 1.3
|
349 kumpf 1.2 // Create "to-agent" pipe:
350
351 if (pipe(to) != 0)
|
352 thilo.boehm 1.16 {
353 PEG_METHOD_EXIT();
|
354 kumpf 1.2 return -1;
|
355 thilo.boehm 1.16 }
356
|
357 kumpf 1.2
358 // Create "from-agent" pipe:
359
360 if (pipe(from) != 0)
|
361 thilo.boehm 1.16 {
362 PEG_METHOD_EXIT();
|
363 kumpf 1.2 return -1;
|
364 thilo.boehm 1.16 }
365
366 // Start provider agent:
367
368 # if defined(PEGASUS_OS_ZOS)
369 // zOS is using __spawn2() to start provider agent
370 sprintf(arg1, "%d", to[0]);
371 sprintf(arg2, "%d", from[1]);
372
373 CString program_name = path.getCString();
374
375 c_argv[0] = program_name;
376 c_argv[1] = arg1;
377 c_argv[2] = arg2;
378 c_argv[3] = module;
379 c_argv[4] = NULL;
380
381 // reset the inherit structure
382 memset(&inherit,0,sizeof(inherit));
383
384 // The provider agent should get a defined JobName.
385 thilo.boehm 1.16 inherit.flags=SPAWN_SETJOBNAME;
386 memcpy( inherit.jobname,"CFZOOPA ",
387 sizeof(inherit.jobname));
388
389 CString program = path.getCString();
390
391 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
392 "Starting provider agent: %s %s %s %s %s",
393 program,program_name,arg1,arg2,module));
|
394 kumpf 1.2
|
395 thilo.boehm 1.16 pid = __spawn2(program,0,NULL,&inherit,
396 c_argv,(const char **)environ);
|
397 kumpf 1.2
|
398 thilo.boehm 1.16 if (pid < 0)
399 {
400 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
401 "Spawn of provider agent fails:%s "
402 "( errno %d , reason code %08X )",
403 strerror(errno) ,errno,__errno2()));
404 PEG_METHOD_EXIT();
405 return -1;
406 }
407
408 # elif defined(PEGASUS_OS_VMS)
|
409 kumpf 1.2 pid = (int)vfork();
|
410 thilo.boehm 1.16 # elif defined(PEGASUS_OS_PASE)
|
411 ouyang.jian 1.11 pid = (int)fork400("QUMEPRVAGT",0);
|
412 kumpf 1.6 # else
|
413 kumpf 1.2 pid = (int)fork();
|
414 kumpf 1.6 # endif
|
415 kumpf 1.2
|
416 thilo.boehm 1.16 # if !defined(PEGASUS_OS_ZOS)
417
|
418 kumpf 1.2 if (pid < 0)
|
419 thilo.boehm 1.16 {
420 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
421 "Fork for provider agent fails: errno = %d",errno));
422 PEG_METHOD_EXIT();
|
423 kumpf 1.2 return -1;
|
424 thilo.boehm 1.16 }
425
|
426 kumpf 1.2 // If child proceses.
427 if (pid == 0)
428 {
|
429 thilo.boehm 1.16 # if !defined(PEGASUS_OS_VMS)
|
430 kumpf 1.2 // Close unused pipe descriptors:
431
432 close(to[1]);
433 close(from[0]);
434
435
436 // Close unused descriptors. Leave stdin, stdout, stderr,
437 // and the child's pipe descriptors open.
438
439 struct rlimit rlim;
440
441 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
442 {
443 for (int i = 3; i < int(rlim.rlim_cur); i++)
444 {
445 if (i != to[0] && i != from[1])
446 close(i);
447 }
448 }
449
|
450 thilo.boehm 1.16 # endif /* !defined(PEGASUS_OS_VMS) */
|
451 kumpf 1.3
|
452 thilo.boehm 1.16 # if !defined(PEGASUS_DISABLE_PROV_USERCTXT)
|
453 kumpf 1.2
454 // Set uid and gid for the new provider agent process.
455
|
456 kumpf 1.3 if (newUid != (PEGASUS_UID_T)-1 && newGid != (PEGASUS_GID_T)-1)
|
457 kumpf 1.2 {
|
458 kumpf 1.3 if (!System::changeUserContext_SingleThreaded(
459 userName.getCString(), newUid, newGid))
|
460 kumpf 1.2 {
461 return -1;
462 }
463 }
464
|
465 thilo.boehm 1.16 # endif /* !defined(PEGASUS_DISABLE_PROV_USERCTXT) */
|
466 kumpf 1.2
467 // Exec the cimprovagt program.
468
469 char arg1[32];
470 char arg2[32];
471 sprintf(arg1, "%d", to[0]);
472 sprintf(arg2, "%d", from[1]);
473
474 {
475 CString cstr = path.getCString();
476 if (execl(cstr, cstr, arg1, arg2, module, (char*)0) == -1)
477 {
|
478 thilo.boehm 1.16 PEG_TRACE((TRC_SERVER, Tracer::LEVEL2,
|
479 kumpf 1.2 "execl() failed. errno = %d.", errno));
480 _exit(1);
481 }
482 }
483 }
|
484 thilo.boehm 1.16 # else /* PEGASUS_OS_ZOS */
485 if (pid > 0)
486 {
487 PEG_TRACE((TRC_SERVER, Tracer::LEVEL4,
488 "Provider agent started suggessfully: Pid(%d).",pid));
489 break;
490 }
491 #endif /* PEGASUS_OS_ZOS */
492
|
493 kumpf 1.2 }
494 while (0);
495
496 // Close unused pipe descriptors.
497
498 close(to[0]);
499 close(from[1]);
500
501 // Set output parameters.
502
503 int readFd = from[0];
504 int writeFd = to[1];
505
506 // Create to and from AnonymousPipe instances to correspond to the pipe
507 // descriptors created above.
508
509 char readFdStr[32];
510 char writeFdStr[32];
511 sprintf(readFdStr, "%d", readFd);
512 sprintf(writeFdStr, "%d", writeFd);
513
514 kumpf 1.2 readPipe = new AnonymousPipe(readFdStr, 0);
515 writePipe = new AnonymousPipe(0, writeFdStr);
516
|
517 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
518 kumpf 1.2 return 0;
519
|
520 kumpf 1.6 # endif /* POSIX CASE */
521
522 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is defined */
523
524 // Out-of-Process providers are never started by the cimserver process
525 // when Privilege Separation is enabled.
526 return -1;
527
528 #endif
|
529 kumpf 1.2 }
530
531 virtual int daemonizeExecutor()
532 {
533 return -1;
534 }
535
536 virtual int reapProviderAgent(
537 int pid)
538 {
|
539 kumpf 1.6 #if !defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
540
|
541 kumpf 1.2 int status = 0;
542
|
543 kumpf 1.6 # if defined(PEGASUS_HAS_SIGNALS)
|
544 kumpf 1.2 while ((status = waitpid(pid, 0, 0)) == -1 && errno == EINTR)
545 ;
|
546 kumpf 1.6 # endif
|
547 kumpf 1.2
548 return status;
|
549 kumpf 1.6
550 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is defined */
551
552 // Out-of-Process providers are never started by the cimserver process
553 // when Privilege Separation is enabled.
554 return -1;
555
556 #endif
|
557 kumpf 1.2 }
558
559 virtual int authenticatePassword(
560 const char* username,
561 const char* password)
562 {
563 #if defined(PEGASUS_PAM_AUTHENTICATION)
564 return PAMAuthenticate(username, password);
565 #else
566 // ATTN: not handled so don't call in this case.
567 return -1;
568 #endif
569 }
570
571 virtual int validateUser(
572 const char* username)
573 {
|
574 kumpf 1.12 #if defined(PEGASUS_PAM_AUTHENTICATION)
|
575 kumpf 1.2 return PAMValidateUser(username);
|
576 kumpf 1.12 #else
|
577 kumpf 1.2 // ATTN: not handled so don't call in this case.
578 return -1;
|
579 kumpf 1.12 #endif
|
580 kumpf 1.2 }
581
582 virtual int challengeLocal(
583 const char* username,
584 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
585 {
586 // ATTN: not handled so don't call in this case.
587 return -1;
588 }
589
590 virtual int authenticateLocal(
591 const char* challengeFilePath,
592 const char* response)
593 {
594 // ATTN: not handled so don't call in this case.
595 return -1;
596 }
597
|
598 kumpf 1.8 virtual int updateLogLevel(
599 const char* logLevel)
600 {
601 // If Privilege Separation is not enabled, we don't need to update
602 // the log level in the Executor.
603 return 0;
604 }
605
|
606 kumpf 1.2 private:
607
608 Mutex _mutex;
609 };
610
611 ////////////////////////////////////////////////////////////////////////////////
612 //
613 //
614 // class ExecutorSocketImpl : public ExecutorImpl
615 //
616 //
617 ////////////////////////////////////////////////////////////////////////////////
618
619 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
620
621 class ExecutorSocketImpl : public ExecutorImpl
622 {
623 public:
624
625 ExecutorSocketImpl(int sock) : _sock(sock)
626 {
627 kumpf 1.2 }
628
629 virtual ~ExecutorSocketImpl()
630 {
631 }
632
633 virtual int detectExecutor()
634 {
635 return 0;
636 }
637
638 virtual int ping()
639 {
640 AutoMutex autoMutex(_mutex);
641
|
642 kumpf 1.9 // Send request header:
|
643 kumpf 1.2
644 ExecutorRequestHeader header;
645 header.code = EXECUTOR_PING_MESSAGE;
646
|
647 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
648 kumpf 1.2 return -1;
649
650 ExecutorPingResponse response;
651
|
652 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
653 kumpf 1.2 return -1;
654
655 if (response.magic == EXECUTOR_PING_MAGIC)
656 return 0;
657
658 return -1;
659 }
660
661 virtual FILE* openFile(
662 const char* path,
663 int mode)
664 {
665 AutoMutex autoMutex(_mutex);
666
667 if (mode != 'r' && mode != 'w' && mode != 'a')
668 return NULL;
669
|
670 kumpf 1.9 // Send request header:
|
671 kumpf 1.2
672 ExecutorRequestHeader header;
673 header.code = EXECUTOR_OPEN_FILE_MESSAGE;
674
|
675 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
676 kumpf 1.2 return NULL;
677
|
678 kumpf 1.9 // Send request body.
|
679 kumpf 1.2
680 ExecutorOpenFileRequest request;
681 memset(&request, 0, sizeof(request));
682 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
683 request.mode = mode;
684
|
685 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
686 kumpf 1.2 return NULL;
687
688 // Receive the response
689
690 ExecutorOpenFileResponse response;
691
|
692 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
693 kumpf 1.2 return NULL;
694
695 // Receive descriptor (if response successful).
696
697 if (response.status == 0)
698 {
699 int fds[1];
700
701 if (RecvDescriptorArray(_sock, fds, 1) != 0)
702 return NULL;
703
704 if (fds[0] == -1)
705 return NULL;
706 else
707 {
708 if (mode == 'r')
709 return fdopen(fds[0], "rb");
710 else
711 return fdopen(fds[0], "wb");
712 }
713 }
714 kumpf 1.2
715 return NULL;
716 }
717
718 virtual int renameFile(
719 const char* oldPath,
720 const char* newPath)
721 {
722 AutoMutex autoMutex(_mutex);
723
|
724 kumpf 1.9 // Send request header:
|
725 kumpf 1.2
726 ExecutorRequestHeader header;
727 header.code = EXECUTOR_RENAME_FILE_MESSAGE;
728
|
729 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
730 kumpf 1.2 return -1;
731
|
732 kumpf 1.9 // Send request body.
|
733 kumpf 1.2
734 ExecutorRenameFileRequest request;
735 memset(&request, 0, sizeof(request));
736 Strlcpy(request.oldPath, oldPath, EXECUTOR_BUFFER_SIZE);
737 Strlcpy(request.newPath, newPath, EXECUTOR_BUFFER_SIZE);
738
|
739 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
740 kumpf 1.2 return -1;
741
742 // Receive the response
743
744 ExecutorRenameFileResponse response;
745
|
746 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
747 kumpf 1.2 return -1;
748
749 return response.status;
750 }
751
752 virtual int removeFile(
753 const char* path)
754 {
755 AutoMutex autoMutex(_mutex);
756
|
757 kumpf 1.9 // Send request header:
|
758 kumpf 1.2
759 ExecutorRequestHeader header;
760 header.code = EXECUTOR_REMOVE_FILE_MESSAGE;
761
|
762 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
763 kumpf 1.2 return -1;
764
|
765 kumpf 1.9 // Send request body.
|
766 kumpf 1.2
767 ExecutorRemoveFileRequest request;
768 memset(&request, 0, sizeof(request));
769 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
770
|
771 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
772 kumpf 1.2 return -1;
773
774 // Receive the response
775
776 ExecutorRemoveFileResponse response;
777
|
778 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
779 kumpf 1.2 return -1;
780
781 return response.status;
782 }
783
784 virtual int startProviderAgent(
785 const char* module,
786 const String& pegasusHome,
787 const String& userName,
788 int& pid,
789 AnonymousPipe*& readPipe,
790 AnonymousPipe*& writePipe)
791 {
792 AutoMutex autoMutex(_mutex);
793
794 readPipe = 0;
795 writePipe = 0;
796
797 // Reject strings longer than EXECUTOR_BUFFER_SIZE.
798
|
799 kumpf 1.3 size_t moduleNameLength = strlen(module);
800
801 if (moduleNameLength >= EXECUTOR_BUFFER_SIZE)
802 return -1;
803
804 CString userNameCString = userName.getCString();
805 size_t userNameLength = strlen(userNameCString);
|
806 kumpf 1.2
|
807 kumpf 1.3 if (userNameLength >= EXECUTOR_BUFFER_SIZE)
|
808 kumpf 1.2 return -1;
809
|
810 kumpf 1.9 // Send request header:
|
811 kumpf 1.2
812 ExecutorRequestHeader header;
813 header.code = EXECUTOR_START_PROVIDER_AGENT_MESSAGE;
814
|
815 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
816 kumpf 1.2 return -1;
817
|
818 kumpf 1.9 // Send request body.
|
819 kumpf 1.2
820 ExecutorStartProviderAgentRequest request;
821 memset(&request, 0, sizeof(request));
|
822 kumpf 1.3 memcpy(request.module, module, moduleNameLength);
823 memcpy(request.userName, userNameCString, userNameLength);
|
824 kumpf 1.2
|
825 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
826 kumpf 1.2 return -1;
827
828 // Receive the response
829
830 ExecutorStartProviderAgentResponse response;
831
|
832 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
833 kumpf 1.2 return -1;
834
835 // Check response status and pid.
836
837 if (response.status != 0)
838 return -1;
839
840 // Get pid:
841
842 pid = response.pid;
843
844 // Receive descriptors.
845
846 int descriptors[2];
847 int result = RecvDescriptorArray(_sock, descriptors, 2);
848
849 if (result == 0)
850 {
851 int readFd = descriptors[0];
852 int writeFd = descriptors[1];
853
854 kumpf 1.2 // Create to and from AnonymousPipe instances to correspond to
855 // the pipe descriptors created above.
856
857 char readFdStr[32];
858 char writeFdStr[32];
859 sprintf(readFdStr, "%d", readFd);
860 sprintf(writeFdStr, "%d", writeFd);
861
862 readPipe = new AnonymousPipe(readFdStr, 0);
863 writePipe = new AnonymousPipe(0, writeFdStr);
864 }
865
866 return result;
867 }
868
869 virtual int daemonizeExecutor()
870 {
871 AutoMutex autoMutex(_mutex);
872
|
873 kumpf 1.9 // Send request header:
|
874 kumpf 1.2
875 ExecutorRequestHeader header;
876 header.code = EXECUTOR_DAEMONIZE_EXECUTOR_MESSAGE;
877
|
878 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
879 kumpf 1.2 return -1;
880
881 // Receive the response
882
883 ExecutorDaemonizeExecutorResponse response;
884
|
885 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
886 kumpf 1.2 return -1;
887
888 return response.status;
889 }
890
891 virtual int reapProviderAgent(
892 int pid)
893 {
|
894 kumpf 1.10 // The Executor process automatically cleans up all its child
895 // processes, so it does not need to explicitly harvest the
896 // exit status of the cimprovagt processes it starts.
|
897 kumpf 1.2
|
898 kumpf 1.10 return 0;
|
899 kumpf 1.2 }
900
901 virtual int authenticatePassword(
902 const char* username,
903 const char* password)
904 {
905 AutoMutex autoMutex(_mutex);
906
|
907 kumpf 1.9 // Send request header:
|
908 kumpf 1.2
909 ExecutorRequestHeader header;
910 header.code = EXECUTOR_AUTHENTICATE_PASSWORD_MESSAGE;
911
|
912 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
913 kumpf 1.2 return -1;
914
|
915 kumpf 1.9 // Send request body.
|
916 kumpf 1.2
917 ExecutorAuthenticatePasswordRequest request;
918 memset(&request, 0, sizeof(request));
919 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
920 Strlcpy(request.password, password, EXECUTOR_BUFFER_SIZE);
921
|
922 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
923 kumpf 1.2 return -1;
924
925 // Receive the response
926
927 ExecutorAuthenticatePasswordResponse response;
928
|
929 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
930 kumpf 1.2 return -1;
931
932 return response.status;
933 }
934
935 virtual int validateUser(
936 const char* username)
937 {
938 AutoMutex autoMutex(_mutex);
939
|
940 kumpf 1.9 // Send request header:
|
941 kumpf 1.2
942 ExecutorRequestHeader header;
943 header.code = EXECUTOR_VALIDATE_USER_MESSAGE;
944
|
945 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
946 kumpf 1.2 return -1;
947
|
948 kumpf 1.9 // Send request body.
|
949 kumpf 1.2
950 ExecutorValidateUserRequest request;
951 memset(&request, 0, sizeof(request));
952 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
953
|
954 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
955 kumpf 1.2 return -1;
956
957 // Receive the response
958
959 ExecutorValidateUserResponse response;
960
|
961 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
962 kumpf 1.2 return -1;
963
964 return response.status;
965 }
966
967 virtual int challengeLocal(
968 const char* username,
969 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
970 {
971 AutoMutex autoMutex(_mutex);
972
|
973 kumpf 1.9 // Send request header:
|
974 kumpf 1.2
975 ExecutorRequestHeader header;
976 header.code = EXECUTOR_CHALLENGE_LOCAL_MESSAGE;
977
|
978 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
979 kumpf 1.2 return -1;
980
|
981 kumpf 1.9 // Send request body.
|
982 kumpf 1.2
983 ExecutorChallengeLocalRequest request;
984 memset(&request, 0, sizeof(request));
985 Strlcpy(request.user, username, EXECUTOR_BUFFER_SIZE);
986
|
987 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
988 kumpf 1.2 return -1;
989
990 // Receive the response
991
992 ExecutorChallengeLocalResponse response;
993
|
994 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
995 kumpf 1.2 return -1;
996
997 Strlcpy(challengeFilePath, response.challenge, EXECUTOR_BUFFER_SIZE);
998
999 return response.status;
1000 }
1001
1002 virtual int authenticateLocal(
1003 const char* challengeFilePath,
1004 const char* response)
1005 {
1006 AutoMutex autoMutex(_mutex);
1007
|
1008 kumpf 1.9 // Send request header:
|
1009 kumpf 1.2
1010 ExecutorRequestHeader header;
1011 header.code = EXECUTOR_AUTHENTICATE_LOCAL_MESSAGE;
1012
|
1013 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1014 kumpf 1.2 return -1;
1015
|
1016 kumpf 1.9 // Send request body.
|
1017 kumpf 1.2
1018 ExecutorAuthenticateLocalRequest request;
1019 memset(&request, 0, sizeof(request));
1020 Strlcpy(request.challenge, challengeFilePath, EXECUTOR_BUFFER_SIZE);
1021 Strlcpy(request.response, response, EXECUTOR_BUFFER_SIZE);
1022
|
1023 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1024 kumpf 1.2 return -1;
1025
1026 // Receive the response
1027
1028 ExecutorAuthenticateLocalResponse response_;
1029
|
1030 kumpf 1.9 if (RecvBlock(_sock, &response_, sizeof(response_)) !=
1031 sizeof(response_))
1032 {
|
1033 kumpf 1.2 return -1;
|
1034 kumpf 1.9 }
|
1035 kumpf 1.2
1036 return response_.status;
1037 }
1038
|
1039 kumpf 1.8 virtual int updateLogLevel(
1040 const char* logLevel)
1041 {
1042 AutoMutex autoMutex(_mutex);
1043
|
1044 kumpf 1.9 // Send request header:
|
1045 kumpf 1.8
1046 ExecutorRequestHeader header;
1047 header.code = EXECUTOR_UPDATE_LOG_LEVEL_MESSAGE;
1048
|
1049 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1050 kumpf 1.8 return -1;
1051
|
1052 kumpf 1.9 // Send request body:
|
1053 kumpf 1.8
1054 ExecutorUpdateLogLevelRequest request;
1055 memset(&request, 0, sizeof(request));
1056 Strlcpy(request.logLevel, logLevel, EXECUTOR_BUFFER_SIZE);
1057
|
1058 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1059 kumpf 1.8 return -1;
1060
1061 // Receive the response
1062
1063 ExecutorUpdateLogLevelResponse response;
1064
|
1065 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
1066 kumpf 1.8 return -1;
1067
1068 return response.status;
1069 }
1070
|
1071 kumpf 1.2 private:
1072
1073 int _sock;
1074 Mutex _mutex;
1075 };
1076
1077 #endif /* defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION) */
1078
1079 ////////////////////////////////////////////////////////////////////////////////
1080 //
1081 //
1082 // class Executor
1083 //
1084 //
1085 ////////////////////////////////////////////////////////////////////////////////
1086
1087 static int _executorSock = -1;
|
1088 kumpf 1.5 static AutoPtr<ExecutorImpl> _executorImpl;
|
1089 kumpf 1.7 static Once _executorImplOnce = PEGASUS_ONCE_INITIALIZER;
|
1090 kumpf 1.2
|
1091 kumpf 1.7 static void _initExecutorImpl()
|
1092 kumpf 1.2 {
1093 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
1094 kumpf 1.7 if (_executorSock == -1)
1095 _executorImpl.reset(new ExecutorLoopbackImpl());
1096 else
1097 _executorImpl.reset(new ExecutorSocketImpl(_executorSock));
|
1098 kumpf 1.2 #else
|
1099 kumpf 1.7 _executorImpl.reset(new ExecutorLoopbackImpl());
|
1100 kumpf 1.2 #endif
1101 }
1102
1103 void Executor::setSock(int sock)
1104 {
1105 _executorSock = sock;
1106 }
1107
1108 int Executor::detectExecutor()
1109 {
|
1110 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1111 return _executorImpl->detectExecutor();
|
1112 kumpf 1.2 }
1113
1114 int Executor::ping()
1115 {
|
1116 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1117 return _executorImpl->ping();
|
1118 kumpf 1.2 }
1119
1120 FILE* Executor::openFile(
1121 const char* path,
1122 int mode)
1123 {
|
1124 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1125 return _executorImpl->openFile(path, mode);
|
1126 kumpf 1.2 }
1127
1128 int Executor::renameFile(
1129 const char* oldPath,
1130 const char* newPath)
1131 {
|
1132 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1133 return _executorImpl->renameFile(oldPath, newPath);
|
1134 kumpf 1.2 }
1135
1136 int Executor::removeFile(
1137 const char* path)
1138 {
|
1139 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1140 return _executorImpl->removeFile(path);
|
1141 kumpf 1.2 }
1142
1143 int Executor::startProviderAgent(
1144 const char* module,
1145 const String& pegasusHome,
1146 const String& userName,
1147 int& pid,
1148 AnonymousPipe*& readPipe,
1149 AnonymousPipe*& writePipe)
1150 {
|
1151 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1152 return _executorImpl->startProviderAgent(
|
1153 kumpf 1.3 module, pegasusHome, userName, pid, readPipe, writePipe);
|
1154 kumpf 1.2 }
1155
1156 int Executor::daemonizeExecutor()
1157 {
|
1158 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1159 return _executorImpl->daemonizeExecutor();
|
1160 kumpf 1.2 }
1161
1162 int Executor::reapProviderAgent(
1163 int pid)
1164 {
|
1165 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1166 return _executorImpl->reapProviderAgent(pid);
|
1167 kumpf 1.2 }
1168
1169 int Executor::authenticatePassword(
1170 const char* username,
1171 const char* password)
1172 {
|
1173 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1174 return _executorImpl->authenticatePassword(username, password);
|
1175 kumpf 1.2 }
1176
1177 int Executor::validateUser(
1178 const char* username)
1179 {
|
1180 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1181 return _executorImpl->validateUser(username);
|
1182 kumpf 1.2 }
1183
1184 int Executor::challengeLocal(
1185 const char* user,
1186 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
1187 {
|
1188 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1189 return _executorImpl->challengeLocal(user, challengeFilePath);
|
1190 kumpf 1.2 }
1191
1192 int Executor::authenticateLocal(
1193 const char* challengeFilePath,
1194 const char* response)
1195 {
|
1196 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1197 return _executorImpl->authenticateLocal(challengeFilePath, response);
|
1198 kumpf 1.2 }
1199
|
1200 kumpf 1.8 int Executor::updateLogLevel(
1201 const char* logLevel)
1202 {
1203 once(&_executorImplOnce, _initExecutorImpl);
1204 return _executorImpl->updateLogLevel(logLevel);
1205 }
1206
|
1207 kumpf 1.2 PEGASUS_NAMESPACE_END
|