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