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
62 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
63 dl.meetei 1.28 #include <Executor/Strlcpy.h>
|
64 kumpf 1.2 # 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 karl 1.27 # if defined(PEGASUS_HAS_SIGNALS) && \
506 !(defined(PEGASUS_DISABLE_PROV_USERCTXT) || defined(PEGASUS_OS_ZOS))
|
507 kumpf 1.18 // 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
|
514 thilo.boehm 1.16 PEG_METHOD_EXIT();
|
515 kumpf 1.2 return 0;
516
|
517 kumpf 1.6 # endif /* POSIX CASE */
518
519 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is defined */
520
521 // Out-of-Process providers are never started by the cimserver process
522 // when Privilege Separation is enabled.
523 return -1;
524
525 #endif
|
526 kumpf 1.2 }
527
528 virtual int daemonizeExecutor()
529 {
530 return -1;
531 }
532
|
533 marek 1.26 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
534 virtual int reapProviderAgent(int)
|
535 kumpf 1.2 {
|
536 marek 1.26 // Out-of-Process providers are never started by the cimserver process
537 // when Privilege Separation is enabled.
538 return -1;
539 }
540 #else /* PEGASUS_ENABLE_PRIVILEGE_SEPARATION is NOT defined */
|
541 karl 1.27 # if defined(PEGASUS_HAS_SIGNALS) && \
542 (defined(PEGASUS_DISABLE_PROV_USERCTXT) || defined(PEGASUS_OS_ZOS))
|
543 marek 1.26 virtual int reapProviderAgent(int pid)
544 {
545 int status = 0;
|
546 kumpf 1.18 // When provider user context is enabled, this is done in
547 // startProviderAgent().
|
548 kumpf 1.2 while ((status = waitpid(pid, 0, 0)) == -1 && errno == EINTR)
|
549 marek 1.26 {
550 };
551 return status;
552 }
|
553 karl 1.27 # else
|
554 marek 1.26 virtual int reapProviderAgent(int)
555 {
556 return 0;
557 }
|
558 kumpf 1.6 # endif
|
559 marek 1.26 #endif
|
560 kumpf 1.2
561
|
562 marek 1.26 #if defined(PEGASUS_PAM_AUTHENTICATION)
|
563 kumpf 1.2 virtual int authenticatePassword(
564 const char* username,
565 const char* password)
566 {
567 return PAMAuthenticate(username, password);
|
568 marek 1.26 }
569
570 virtual int validateUser(
571 const char* username)
572 {
573 return PAMValidateUser(username);
574 }
575 #else
576 virtual int authenticatePassword(
577 const char*,
578 const char*)
579 {
|
580 kumpf 1.2 // ATTN: not handled so don't call in this case.
581 return -1;
582 }
|
583 marek 1.26
|
584 kumpf 1.2 virtual int validateUser(
|
585 marek 1.26 const char*)
|
586 kumpf 1.2 {
587 // ATTN: not handled so don't call in this case.
588 return -1;
|
589 marek 1.26 }
|
590 kumpf 1.12 #endif
|
591 kumpf 1.2
592 virtual int challengeLocal(
|
593 marek 1.26 const char*,
594 char[EXECUTOR_BUFFER_SIZE])
|
595 kumpf 1.2 {
596 // ATTN: not handled so don't call in this case.
597 return -1;
598 }
599
600 virtual int authenticateLocal(
|
601 marek 1.26 const char*,
602 const char*)
|
603 kumpf 1.2 {
604 // ATTN: not handled so don't call in this case.
605 return -1;
606 }
607
|
608 kumpf 1.8 virtual int updateLogLevel(
|
609 marek 1.26 const char*)
|
610 kumpf 1.8 {
611 // If Privilege Separation is not enabled, we don't need to update
612 // the log level in the Executor.
613 return 0;
614 }
615
|
616 kumpf 1.2 private:
617
618 Mutex _mutex;
619 };
620
621 ////////////////////////////////////////////////////////////////////////////////
622 //
623 //
624 // class ExecutorSocketImpl : public ExecutorImpl
625 //
626 //
627 ////////////////////////////////////////////////////////////////////////////////
628
629 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
630
631 class ExecutorSocketImpl : public ExecutorImpl
632 {
633 public:
634
635 ExecutorSocketImpl(int sock) : _sock(sock)
636 {
637 kumpf 1.2 }
638
639 virtual ~ExecutorSocketImpl()
640 {
641 }
642
643 virtual int detectExecutor()
644 {
645 return 0;
646 }
647
648 virtual int ping()
649 {
650 AutoMutex autoMutex(_mutex);
651
|
652 kumpf 1.9 // Send request header:
|
653 kumpf 1.2
654 ExecutorRequestHeader header;
655 header.code = EXECUTOR_PING_MESSAGE;
656
|
657 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
658 kumpf 1.2 return -1;
659
660 ExecutorPingResponse response;
661
|
662 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
663 kumpf 1.2 return -1;
664
665 if (response.magic == EXECUTOR_PING_MAGIC)
666 return 0;
667
668 return -1;
669 }
670
671 virtual FILE* openFile(
672 const char* path,
673 int mode)
674 {
675 AutoMutex autoMutex(_mutex);
676
677 if (mode != 'r' && mode != 'w' && mode != 'a')
678 return NULL;
679
|
680 kumpf 1.9 // Send request header:
|
681 kumpf 1.2
682 ExecutorRequestHeader header;
683 header.code = EXECUTOR_OPEN_FILE_MESSAGE;
684
|
685 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
686 kumpf 1.2 return NULL;
687
|
688 kumpf 1.9 // Send request body.
|
689 kumpf 1.2
690 ExecutorOpenFileRequest request;
691 memset(&request, 0, sizeof(request));
692 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
693 request.mode = mode;
694
|
695 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
696 kumpf 1.2 return NULL;
697
698 // Receive the response
699
700 ExecutorOpenFileResponse response;
701
|
702 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
703 kumpf 1.2 return NULL;
704
705 // Receive descriptor (if response successful).
706
707 if (response.status == 0)
708 {
709 int fds[1];
710
711 if (RecvDescriptorArray(_sock, fds, 1) != 0)
712 return NULL;
713
714 if (fds[0] == -1)
715 return NULL;
716 else
717 {
718 if (mode == 'r')
719 return fdopen(fds[0], "rb");
720 else
721 return fdopen(fds[0], "wb");
722 }
723 }
724 kumpf 1.2
725 return NULL;
726 }
727
728 virtual int renameFile(
729 const char* oldPath,
730 const char* newPath)
731 {
732 AutoMutex autoMutex(_mutex);
733
|
734 kumpf 1.9 // Send request header:
|
735 kumpf 1.2
736 ExecutorRequestHeader header;
737 header.code = EXECUTOR_RENAME_FILE_MESSAGE;
738
|
739 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
740 kumpf 1.2 return -1;
741
|
742 kumpf 1.9 // Send request body.
|
743 kumpf 1.2
744 ExecutorRenameFileRequest request;
745 memset(&request, 0, sizeof(request));
746 Strlcpy(request.oldPath, oldPath, EXECUTOR_BUFFER_SIZE);
747 Strlcpy(request.newPath, newPath, EXECUTOR_BUFFER_SIZE);
748
|
749 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
750 kumpf 1.2 return -1;
751
752 // Receive the response
753
754 ExecutorRenameFileResponse response;
755
|
756 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
757 kumpf 1.2 return -1;
758
759 return response.status;
760 }
761
762 virtual int removeFile(
763 const char* path)
764 {
765 AutoMutex autoMutex(_mutex);
766
|
767 kumpf 1.9 // Send request header:
|
768 kumpf 1.2
769 ExecutorRequestHeader header;
770 header.code = EXECUTOR_REMOVE_FILE_MESSAGE;
771
|
772 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
773 kumpf 1.2 return -1;
774
|
775 kumpf 1.9 // Send request body.
|
776 kumpf 1.2
777 ExecutorRemoveFileRequest request;
778 memset(&request, 0, sizeof(request));
779 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
780
|
781 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
782 kumpf 1.2 return -1;
783
784 // Receive the response
785
786 ExecutorRemoveFileResponse response;
787
|
788 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
789 kumpf 1.2 return -1;
790
791 return response.status;
792 }
793
794 virtual int startProviderAgent(
|
795 s.kodali 1.25 unsigned short bitness,
|
796 kumpf 1.2 const char* module,
797 const String& pegasusHome,
798 const String& userName,
799 int& pid,
800 AnonymousPipe*& readPipe,
801 AnonymousPipe*& writePipe)
802 {
803 AutoMutex autoMutex(_mutex);
804
805 readPipe = 0;
806 writePipe = 0;
807
808 // Reject strings longer than EXECUTOR_BUFFER_SIZE.
809
|
810 kumpf 1.3 size_t moduleNameLength = strlen(module);
811
812 if (moduleNameLength >= EXECUTOR_BUFFER_SIZE)
813 return -1;
814
815 CString userNameCString = userName.getCString();
816 size_t userNameLength = strlen(userNameCString);
|
817 kumpf 1.2
|
818 kumpf 1.3 if (userNameLength >= EXECUTOR_BUFFER_SIZE)
|
819 kumpf 1.2 return -1;
820
|
821 kumpf 1.9 // Send request header:
|
822 kumpf 1.2
823 ExecutorRequestHeader header;
824 header.code = EXECUTOR_START_PROVIDER_AGENT_MESSAGE;
825
|
826 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
827 kumpf 1.2 return -1;
828
|
829 kumpf 1.9 // Send request body.
|
830 kumpf 1.2
831 ExecutorStartProviderAgentRequest request;
832 memset(&request, 0, sizeof(request));
|
833 kumpf 1.3 memcpy(request.module, module, moduleNameLength);
834 memcpy(request.userName, userNameCString, userNameLength);
|
835 s.kodali 1.25 request.moduleBitness = bitness;
|
836 kumpf 1.2
|
837 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
838 kumpf 1.2 return -1;
839
840 // Receive the response
841
842 ExecutorStartProviderAgentResponse response;
843
|
844 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
845 kumpf 1.2 return -1;
846
847 // Check response status and pid.
848
849 if (response.status != 0)
850 return -1;
851
852 // Get pid:
853
854 pid = response.pid;
855
856 // Receive descriptors.
857
858 int descriptors[2];
859 int result = RecvDescriptorArray(_sock, descriptors, 2);
860
861 if (result == 0)
862 {
863 int readFd = descriptors[0];
864 int writeFd = descriptors[1];
865
866 kumpf 1.2 // Create to and from AnonymousPipe instances to correspond to
867 // the pipe descriptors created above.
868
869 char readFdStr[32];
870 char writeFdStr[32];
871 sprintf(readFdStr, "%d", readFd);
872 sprintf(writeFdStr, "%d", writeFd);
873
874 readPipe = new AnonymousPipe(readFdStr, 0);
875 writePipe = new AnonymousPipe(0, writeFdStr);
876 }
877
878 return result;
879 }
880
881 virtual int daemonizeExecutor()
882 {
883 AutoMutex autoMutex(_mutex);
884
|
885 kumpf 1.9 // Send request header:
|
886 kumpf 1.2
887 ExecutorRequestHeader header;
888 header.code = EXECUTOR_DAEMONIZE_EXECUTOR_MESSAGE;
889
|
890 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
891 kumpf 1.2 return -1;
892
893 // Receive the response
894
895 ExecutorDaemonizeExecutorResponse response;
896
|
897 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
898 kumpf 1.2 return -1;
899
900 return response.status;
901 }
902
903 virtual int reapProviderAgent(
904 int pid)
905 {
|
906 kumpf 1.10 // The Executor process automatically cleans up all its child
907 // processes, so it does not need to explicitly harvest the
908 // exit status of the cimprovagt processes it starts.
|
909 kumpf 1.2
|
910 kumpf 1.10 return 0;
|
911 kumpf 1.2 }
912
913 virtual int authenticatePassword(
914 const char* username,
915 const char* password)
916 {
917 AutoMutex autoMutex(_mutex);
918
|
919 kumpf 1.9 // Send request header:
|
920 kumpf 1.2
921 ExecutorRequestHeader header;
922 header.code = EXECUTOR_AUTHENTICATE_PASSWORD_MESSAGE;
923
|
924 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
925 kumpf 1.2 return -1;
926
|
927 kumpf 1.9 // Send request body.
|
928 kumpf 1.2
929 ExecutorAuthenticatePasswordRequest request;
930 memset(&request, 0, sizeof(request));
931 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
932 Strlcpy(request.password, password, EXECUTOR_BUFFER_SIZE);
933
|
934 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
935 kumpf 1.2 return -1;
936
937 // Receive the response
938
939 ExecutorAuthenticatePasswordResponse response;
940
|
941 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
942 kumpf 1.2 return -1;
943
944 return response.status;
945 }
946
947 virtual int validateUser(
948 const char* username)
949 {
950 AutoMutex autoMutex(_mutex);
951
|
952 kumpf 1.9 // Send request header:
|
953 kumpf 1.2
954 ExecutorRequestHeader header;
955 header.code = EXECUTOR_VALIDATE_USER_MESSAGE;
956
|
957 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
958 kumpf 1.2 return -1;
959
|
960 kumpf 1.9 // Send request body.
|
961 kumpf 1.2
962 ExecutorValidateUserRequest request;
963 memset(&request, 0, sizeof(request));
964 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
965
|
966 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
967 kumpf 1.2 return -1;
968
969 // Receive the response
970
971 ExecutorValidateUserResponse response;
972
|
973 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
974 kumpf 1.2 return -1;
975
976 return response.status;
977 }
978
979 virtual int challengeLocal(
980 const char* username,
981 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
982 {
983 AutoMutex autoMutex(_mutex);
984
|
985 kumpf 1.9 // Send request header:
|
986 kumpf 1.2
987 ExecutorRequestHeader header;
988 header.code = EXECUTOR_CHALLENGE_LOCAL_MESSAGE;
989
|
990 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
991 kumpf 1.2 return -1;
992
|
993 kumpf 1.9 // Send request body.
|
994 kumpf 1.2
995 ExecutorChallengeLocalRequest request;
996 memset(&request, 0, sizeof(request));
997 Strlcpy(request.user, username, EXECUTOR_BUFFER_SIZE);
998
|
999 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1000 kumpf 1.2 return -1;
1001
1002 // Receive the response
1003
1004 ExecutorChallengeLocalResponse response;
1005
|
1006 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
1007 kumpf 1.2 return -1;
1008
1009 Strlcpy(challengeFilePath, response.challenge, EXECUTOR_BUFFER_SIZE);
1010
1011 return response.status;
1012 }
1013
1014 virtual int authenticateLocal(
1015 const char* challengeFilePath,
1016 const char* response)
1017 {
1018 AutoMutex autoMutex(_mutex);
1019
|
1020 kumpf 1.9 // Send request header:
|
1021 kumpf 1.2
1022 ExecutorRequestHeader header;
1023 header.code = EXECUTOR_AUTHENTICATE_LOCAL_MESSAGE;
1024
|
1025 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1026 kumpf 1.2 return -1;
1027
|
1028 kumpf 1.9 // Send request body.
|
1029 kumpf 1.2
1030 ExecutorAuthenticateLocalRequest request;
1031 memset(&request, 0, sizeof(request));
1032 Strlcpy(request.challenge, challengeFilePath, EXECUTOR_BUFFER_SIZE);
1033 Strlcpy(request.response, response, EXECUTOR_BUFFER_SIZE);
1034
|
1035 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1036 kumpf 1.2 return -1;
1037
1038 // Receive the response
1039
1040 ExecutorAuthenticateLocalResponse response_;
1041
|
1042 kumpf 1.9 if (RecvBlock(_sock, &response_, sizeof(response_)) !=
1043 sizeof(response_))
1044 {
|
1045 kumpf 1.2 return -1;
|
1046 kumpf 1.9 }
|
1047 kumpf 1.2
1048 return response_.status;
1049 }
1050
|
1051 kumpf 1.8 virtual int updateLogLevel(
1052 const char* logLevel)
1053 {
1054 AutoMutex autoMutex(_mutex);
1055
|
1056 kumpf 1.9 // Send request header:
|
1057 kumpf 1.8
1058 ExecutorRequestHeader header;
1059 header.code = EXECUTOR_UPDATE_LOG_LEVEL_MESSAGE;
1060
|
1061 kumpf 1.9 if (SendBlock(_sock, &header, sizeof(header)) != sizeof(header))
|
1062 kumpf 1.8 return -1;
1063
|
1064 kumpf 1.9 // Send request body:
|
1065 kumpf 1.8
1066 ExecutorUpdateLogLevelRequest request;
1067 memset(&request, 0, sizeof(request));
1068 Strlcpy(request.logLevel, logLevel, EXECUTOR_BUFFER_SIZE);
1069
|
1070 kumpf 1.9 if (SendBlock(_sock, &request, sizeof(request)) != sizeof(request))
|
1071 kumpf 1.8 return -1;
1072
1073 // Receive the response
1074
1075 ExecutorUpdateLogLevelResponse response;
1076
|
1077 kumpf 1.9 if (RecvBlock(_sock, &response, sizeof(response)) != sizeof(response))
|
1078 kumpf 1.8 return -1;
1079
1080 return response.status;
1081 }
1082
|
1083 kumpf 1.2 private:
1084
1085 int _sock;
1086 Mutex _mutex;
1087 };
1088
1089 #endif /* defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION) */
1090
1091 ////////////////////////////////////////////////////////////////////////////////
1092 //
1093 //
1094 // class Executor
1095 //
1096 //
1097 ////////////////////////////////////////////////////////////////////////////////
1098
1099 static int _executorSock = -1;
|
1100 kumpf 1.5 static AutoPtr<ExecutorImpl> _executorImpl;
|
1101 kumpf 1.7 static Once _executorImplOnce = PEGASUS_ONCE_INITIALIZER;
|
1102 kumpf 1.2
|
1103 kumpf 1.7 static void _initExecutorImpl()
|
1104 kumpf 1.2 {
1105 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
1106 kumpf 1.7 if (_executorSock == -1)
1107 _executorImpl.reset(new ExecutorLoopbackImpl());
1108 else
1109 _executorImpl.reset(new ExecutorSocketImpl(_executorSock));
|
1110 kumpf 1.2 #else
|
1111 kumpf 1.7 _executorImpl.reset(new ExecutorLoopbackImpl());
|
1112 kumpf 1.2 #endif
1113 }
1114
1115 void Executor::setSock(int sock)
1116 {
1117 _executorSock = sock;
1118 }
1119
1120 int Executor::detectExecutor()
1121 {
|
1122 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1123 return _executorImpl->detectExecutor();
|
1124 kumpf 1.2 }
1125
1126 int Executor::ping()
1127 {
|
1128 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1129 return _executorImpl->ping();
|
1130 kumpf 1.2 }
1131
1132 FILE* Executor::openFile(
1133 const char* path,
1134 int mode)
1135 {
|
1136 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1137 return _executorImpl->openFile(path, mode);
|
1138 kumpf 1.2 }
1139
1140 int Executor::renameFile(
1141 const char* oldPath,
1142 const char* newPath)
1143 {
|
1144 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1145 return _executorImpl->renameFile(oldPath, newPath);
|
1146 kumpf 1.2 }
1147
1148 int Executor::removeFile(
1149 const char* path)
1150 {
|
1151 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1152 return _executorImpl->removeFile(path);
|
1153 kumpf 1.2 }
1154
1155 int Executor::startProviderAgent(
|
1156 s.kodali 1.25 unsigned short bitness,
|
1157 kumpf 1.2 const char* module,
1158 const String& pegasusHome,
1159 const String& userName,
1160 int& pid,
1161 AnonymousPipe*& readPipe,
1162 AnonymousPipe*& writePipe)
1163 {
|
1164 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
|
1165 s.kodali 1.25 return _executorImpl->startProviderAgent(bitness,
|
1166 kumpf 1.3 module, pegasusHome, userName, pid, readPipe, writePipe);
|
1167 kumpf 1.2 }
1168
1169 int Executor::daemonizeExecutor()
1170 {
|
1171 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1172 return _executorImpl->daemonizeExecutor();
|
1173 kumpf 1.2 }
1174
1175 int Executor::reapProviderAgent(
1176 int pid)
1177 {
|
1178 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1179 return _executorImpl->reapProviderAgent(pid);
|
1180 kumpf 1.2 }
1181
1182 int Executor::authenticatePassword(
1183 const char* username,
1184 const char* password)
1185 {
|
1186 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1187 return _executorImpl->authenticatePassword(username, password);
|
1188 kumpf 1.2 }
1189
1190 int Executor::validateUser(
1191 const char* username)
1192 {
|
1193 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1194 return _executorImpl->validateUser(username);
|
1195 kumpf 1.2 }
1196
1197 int Executor::challengeLocal(
1198 const char* user,
1199 char challengeFilePath[EXECUTOR_BUFFER_SIZE])
1200 {
|
1201 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1202 return _executorImpl->challengeLocal(user, challengeFilePath);
|
1203 kumpf 1.2 }
1204
1205 int Executor::authenticateLocal(
1206 const char* challengeFilePath,
1207 const char* response)
1208 {
|
1209 kumpf 1.7 once(&_executorImplOnce, _initExecutorImpl);
1210 return _executorImpl->authenticateLocal(challengeFilePath, response);
|
1211 kumpf 1.2 }
1212
|
1213 kumpf 1.8 int Executor::updateLogLevel(
1214 const char* logLevel)
1215 {
1216 once(&_executorImplOnce, _initExecutorImpl);
1217 return _executorImpl->updateLogLevel(logLevel);
1218 }
1219
|
1220 kumpf 1.2 PEGASUS_NAMESPACE_END
|