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