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