1 kumpf 1.1.4.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.1.4.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 <cstdlib>
37 #include <cstring>
38
39 #if defined(PEGASUS_OS_TYPE_WINDOWS)
40 # include <windows.h>
41 #else
42 # include <Executor/Socket.h>
43 kumpf 1.1.4.2 # include <sys/types.h>
44 # include <sys/socket.h>
45 # include <unistd.h>
46 # include <fcntl.h>
47 # include <sys/wait.h>
48 # include <unistd.h>
49 # include <sys/time.h>
50 # include <sys/resource.h>
51 #endif
52
53 #include "Constants.h"
54 #include "Executor.h"
55 #include "Mutex.h"
56 #include "FileSystem.h"
57 #include "String.h"
58 #include <Executor/Strlcpy.h>
59 #include <Executor/Strlcat.h>
60
61 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
62 # include <Executor/Messages.h>
63 #endif
64 kumpf 1.1.4.2
65 #if defined(PEGASUS_PAM_AUTHENTICATION)
66 # include <Executor/PAMAuth.h>
67 #endif
68
69 PEGASUS_NAMESPACE_BEGIN
70
71 ////////////////////////////////////////////////////////////////////////////////
72 //
73 //
74 // class ExecutorImpl
75 //
76 //
77 ////////////////////////////////////////////////////////////////////////////////
78
79 class ExecutorImpl
80 {
81 public:
82
83 virtual ~ExecutorImpl()
84 {
85 kumpf 1.1.4.2 }
86
87 virtual int detectExecutor() = 0;
88
89 virtual int ping() = 0;
90
91 virtual FILE* openFile(
92 const char* path,
93 int mode) = 0;
94
95 virtual int renameFile(
96 const char* oldPath,
97 const char* newPath) = 0;
98
99 virtual int removeFile(
100 const char* path) = 0;
101
102 virtual int startProviderAgent(
103 const SessionKey& sessionKey,
104 const char* module,
105 int uid,
106 kumpf 1.1.4.2 int gid,
107 int& pid,
108 SessionKey& providerAgentSessionKey,
109 AnonymousPipe*& readPipe,
110 AnonymousPipe*& writePipe) = 0;
111
112 virtual int daemonizeExecutor() = 0;
113
114 virtual int reapProviderAgent(
115 const SessionKey& sessionKey,
116 int pid) = 0;
117
118 virtual int authenticatePassword(
119 const char* username,
120 const char* password,
121 SessionKey& sessionKey) = 0;
122
123 virtual int validateUser(
124 const char* username) = 0;
125
126 virtual int challengeLocal(
127 kumpf 1.1.4.2 const char* username,
128 char challenge[EXECUTOR_BUFFER_SIZE],
129 SessionKey& sessionKey) = 0;
130
131 virtual int authenticateLocal(
132 const SessionKey& sessionKey,
133 const char* challengeResponse) = 0;
134
135 virtual int newSessionKey(
136 const char username[EXECUTOR_BUFFER_SIZE],
137 SessionKey& sessionKey) = 0;
138
139 virtual int deleteSessionKey(
140 const SessionKey& sessionKey) = 0;
141 };
142
143 ////////////////////////////////////////////////////////////////////////////////
144 //
145 //
146 // class ExecutorLoopbackImpl
147 //
148 kumpf 1.1.4.2 //
149 ////////////////////////////////////////////////////////////////////////////////
150
151 class ExecutorLoopbackImpl : public ExecutorImpl
152 {
153 public:
154
155 virtual ~ExecutorLoopbackImpl()
156 {
157 }
158
159 virtual int detectExecutor()
160 {
161 return -1;
162 }
163
164 virtual int ping()
165 {
166 return -1;
167 }
168
169 kumpf 1.1.4.2 virtual FILE* openFile(
170 const char* path,
171 int mode)
172 {
173 switch (mode)
174 {
175 case 'r':
176 return fopen(path, "rb");
177
178 case 'w':
179 return fopen(path, "wb");
180
181 case 'a':
182 return fopen(path, "a+");
183
184 default:
185 return NULL;
186 }
187 }
188
189 virtual int renameFile(
190 kumpf 1.1.4.2 const char* oldPath,
191 const char* newPath)
192 {
193 return FileSystem::renameFile(oldPath, newPath) ? 0 : -1;
194 }
195
196
197 virtual int removeFile(
198 const char* path)
199 {
200 return FileSystem::removeFile(path) ? 0 : -1;
201 }
202
203
204 virtual int startProviderAgent(
205 const SessionKey& sessionKey,
206 const char* module,
207 int uid,
208 int gid,
209 int& pid,
210 SessionKey& providerAgentSessionKey,
211 kumpf 1.1.4.2 AnonymousPipe*& readPipe,
212 AnonymousPipe*& writePipe)
213 {
214 #if defined(PEGASUS_OS_TYPE_WINDOWS)
215
216 AutoMutex autoMutex(_mutex);
217
218 // Set output parameters in case of failure.
219
220 pid = 0;
221 readPipe = 0;
222 writePipe = 0;
223
224 // Create pipes. Export handles to string.
225
226 AnonymousPipe* pipeFromAgent = new AnonymousPipe();
227 AnonymousPipe* pipeToAgent = new AnonymousPipe();
228
229 char readHandle[32];
230 char writeHandle[32];
231 pipeToAgent->exportReadHandle(readHandle);
232 kumpf 1.1.4.2 pipeFromAgent->exportWriteHandle(writeHandle);
233
234 // Initialize PROCESS_INFORMATION.
235
236 PROCESS_INFORMATION piProcInfo;
237 ZeroMemory(&piProcInfo, sizeof (PROCESS_INFORMATION));
238
239 // Initialize STARTUPINFO.
240
241 STARTUPINFO siStartInfo;
242 ZeroMemory(&siStartInfo, sizeof (STARTUPINFO));
243 siStartInfo.cb = sizeof (STARTUPINFO);
244
245 // Build full path of "cimprovagt" program.
246
247 String path;
248
249 if (_getProviderAgentPath(path) != 0)
250 {
251 delete pipeToAgent;
252 delete pipeFromAgent;
253 kumpf 1.1.4.2 return -1;
254 }
255
256 // Format command line.
257
258 char cmdLine[2048];
259
260 sprintf(cmdLine, "\"%s\" %s %s \"%s\"",
261 (const char*)path.getCString(),
262 readHandle,
263 writeHandle,
264 module);
265
266 // Create provider agent proess.
267
268 if (!CreateProcess (
269 NULL, //
270 cmdLine, // command line
271 NULL, // process security attributes
272 NULL, // primary thread security attributes
273 TRUE, // handles are inherited
274 kumpf 1.1.4.2 0, // creation flags
275 NULL, // use parent's environment
276 NULL, // use parent's current directory
277 &siStartInfo, // STARTUPINFO
278 &piProcInfo)) // PROCESS_INFORMATION
279 {
280 delete pipeToAgent;
281 delete pipeFromAgent;
282 return -1;
283 }
284
285 CloseHandle(piProcInfo.hProcess);
286 CloseHandle(piProcInfo.hThread);
287
288 // Close our copies of the agent's ends of the pipes
289
290 pipeToAgent->closeReadHandle();
291 pipeFromAgent->closeWriteHandle();
292
293 readPipe = pipeFromAgent;
294 writePipe = pipeToAgent;
295 kumpf 1.1.4.2
296 return 0;
297
298 #elif defined(PEGASUS_OS_OS400)
299
300 // ATTN: no implementation for OS400.
301 return -1;
302
303 #else /* POSIX CASE FOLLOWS */
304
305 AutoMutex autoMutex(_mutex);
306
307 // Initialize output parameters in case of error.
308
309 providerAgentSessionKey.clear();
310 pid = -1;
311 readPipe = 0;
312 writePipe = 0;
313
314 // Pipes:
315
316 kumpf 1.1.4.2 int to[2];
317 int from[2];
318
319 do
320 {
321 // Resolve full path of "cimprovagt".
322
323 String path;
324
325 if (_getProviderAgentPath(path) != 0)
326 return -1;
327
328 // Create "to-agent" pipe:
329
330 if (pipe(to) != 0)
331 return -1;
332
333 // Create "from-agent" pipe:
334
335 if (pipe(from) != 0)
336 return -1;
337 kumpf 1.1.4.2
338 // Fork process:
339
|
341 kumpf 1.1.4.2 pid = (int)vfork();
342 #else
343 pid = (int)fork();
344 #endif
345
346 if (pid < 0)
347 return -1;
348
349 // If child proceses.
350
351 if (pid == 0)
352 {
353 // Close unused pipe descriptors:
354
355 close(to[1]);
356 close(from[0]);
357
358 #if !defined(PEGASUS_OS_VMS)
359
360 // Close unused descriptors. Leave stdin, stdout, stderr,
361 // and the child's pipe descriptors open.
362 kumpf 1.1.4.2
363 struct rlimit rlim;
364
365 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
366 {
367 for (int i = 3; i < int(rlim.rlim_cur); i++)
368 {
369 if (i != to[0] && i != from[1])
370 close(i);
371 }
372 }
373
374 #endif /* !defined(PEGASUS_OS_VMS) */
375
376 // Set uid and gid for the new provider agent process.
377
378 # if !defined(PEGASUS_DISABLE_PROV_USERCTXT)
379
380 if (uid != -1 && gid != -1)
381 {
382 if ((int)getgid() != gid)
383 kumpf 1.1.4.2 {
384 // ATTN: log failure!
385 setgid(gid);
386 }
387
388 if ((int)getuid() != uid)
389 {
390 // ATTN: log failure!
391 setuid(uid);
392 }
393 }
394
395 # endif /* !defined(PEGASUS_DISABLE_PROV_USERCTXT) */
396
397 // Exec the cimprovagt program.
398
399 char arg1[32];
400 char arg2[32];
401 sprintf(arg1, "%d", to[0]);
402 sprintf(arg2, "%d", from[1]);
403
404 kumpf 1.1.4.2 {
405 CString cstr = path.getCString();
406 execl(cstr, cstr, arg1, arg2, module, (char*)0);
407 _exit(1);
408 }
409
410 // ATTN: log failure!
411 }
412 }
413 while (0);
414
415 // Close unused pipe descriptors.
416
417 close(to[0]);
418 close(from[1]);
419
420 // Set output parameters.
421
422 int readFd = from[0];
423 int writeFd = to[1];
424
425 kumpf 1.1.4.2 // Create to and from AnonymousPipe instances to correspond to the pipe
426 // descriptors created above.
427
428 char readFdStr[32];
429 char writeFdStr[32];
430 sprintf(readFdStr, "%d", readFd);
431 sprintf(writeFdStr, "%d", writeFd);
432
433 readPipe = new AnonymousPipe(readFdStr, 0);
434 writePipe = new AnonymousPipe(0, writeFdStr);
435
436 return 0;
437
438 #endif /* !defined(START_PROVIDER_AGENT) */
439 }
440
441 virtual int daemonizeExecutor()
442 {
443 return -1;
444 }
445
446 kumpf 1.1.4.2 virtual int reapProviderAgent(
447 const SessionKey& sessionKey,
448 int pid)
449 {
450 int status;
451
452 while ((status = waitpid(pid, 0, 0)) == -1 && errno == EINTR)
453 ;
454
455 return status;
456 }
457
458 virtual int authenticatePassword(
459 const char* username,
460 const char* password,
461 SessionKey& sessionKey)
462 {
463 sessionKey.clear();
464
465 #if defined(PEGASUS_PAM_AUTHENTICATION)
466 return PAMAuthenticate(username, password);
467 kumpf 1.1.4.2 #else
468 // ATTN: not handled so don't call in this case.
469 sessionKey.clear();
470 return -1;
471 #endif
472 }
473
474 virtual int validateUser(
475 const char* username)
476 {
477 #if defined(PEGASUS_PAM_AUTHENTICATION)
478 return PAMValidateUser(username);
479 #else
480 // ATTN: not handled so don't call in this case.
481 return -1;
482 #endif
483 }
484
485 virtual int challengeLocal(
486 const char* username,
487 char challenge[EXECUTOR_BUFFER_SIZE],
488 kumpf 1.1.4.2 SessionKey& sessionKey)
489 {
490 // ATTN: not handled so don't call in this case.
491 sessionKey.clear();
492 return -1;
493 }
494
495 virtual int authenticateLocal(
496 const SessionKey& sessionKey,
497 const char* challengeResponse)
498 {
499 // ATTN: not handled so don't call in this case.
500 return -1;
501 }
502
503 virtual int newSessionKey(
504 const char username[EXECUTOR_BUFFER_SIZE],
505 SessionKey& sessionKey)
506 {
507 sessionKey.clear();
508 return -1;
509 kumpf 1.1.4.2 }
510
511 virtual int deleteSessionKey(
512 const SessionKey& sessionKey)
513 {
514 return -1;
515 }
516
517 private:
518
519 static int _getProviderAgentPath(String& path)
520 {
521 path = PEGASUS_PROVIDER_AGENT_PROC_NAME;
522
523 if (path[0] != '/')
524 {
525 const char* env = getenv("PEGASUS_HOME");
526
527 if (!env)
528 return -1;
529
530 kumpf 1.1.4.2 path = String(env) + String("/") + path;
531 }
532
533 return 0;
534 }
535
536 Mutex _mutex;
537 };
538
539 ////////////////////////////////////////////////////////////////////////////////
540 //
541 //
542 // class ExecutorSocketImpl : public ExecutorImpl
543 //
544 //
545 ////////////////////////////////////////////////////////////////////////////////
546
547 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
548
549 class ExecutorSocketImpl : public ExecutorImpl
550 {
551 kumpf 1.1.4.2 public:
552
553 ExecutorSocketImpl(int sock) : _sock(sock)
554 {
555 }
556
557 virtual ~ExecutorSocketImpl()
558 {
559 }
560
561 virtual int detectExecutor()
562 {
563 return 0;
564 }
565
566 virtual int ping()
567 {
568 AutoMutex autoMutex(_mutex);
569
570 // _send request header:
571
572 kumpf 1.1.4.2 ExecutorRequestHeader header;
573 header.code = EXECUTOR_PING_MESSAGE;
574
575 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
576 return -1;
577
578 ExecutorPingResponse response;
579
580 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
581 return -1;
582
583 if (response.magic == EXECUTOR_PING_MAGIC)
584 return 0;
585
586 return -1;
587 }
588
589 virtual FILE* openFile(
590 const char* path,
591 int mode)
592 {
593 kumpf 1.1.4.2 AutoMutex autoMutex(_mutex);
594
595 if (mode != 'r' && mode != 'w' && mode != 'a')
596 return NULL;
597
598 // _send request header:
599
600 ExecutorRequestHeader header;
601 header.code = EXECUTOR_OPEN_FILE_MESSAGE;
602
603 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
604 return NULL;
605
606 // _send request body.
607
608 ExecutorOpenFileRequest request;
609 memset(&request, 0, sizeof(request));
610 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
611 request.mode = mode;
612
613 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
614 kumpf 1.1.4.2 return NULL;
615
616 // Receive the response
617
618 ExecutorOpenFileResponse response;
619
620 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
621 return NULL;
622
623 // Receive descriptor (if response successful).
624
625 if (response.status == 0)
626 {
627 int fds[1];
628
629 if (RecvDescriptorArray(_sock, fds, 1) != 0)
630 return NULL;
631
632 if (fds[0] == -1)
633 return NULL;
634 else
635 kumpf 1.1.4.2 {
636 if (mode == 'r')
637 return fdopen(fds[0], "rb");
638 else
639 return fdopen(fds[0], "wb");
640 }
641 }
642
643 return NULL;
644 }
645
646 virtual int renameFile(
647 const char* oldPath,
648 const char* newPath)
649 {
650 AutoMutex autoMutex(_mutex);
651
652 // _send request header:
653
654 ExecutorRequestHeader header;
655 header.code = EXECUTOR_RENAME_FILE_MESSAGE;
656 kumpf 1.1.4.2
657 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
658 return -1;
659
660 // _send request body.
661
662 ExecutorRenameFileRequest request;
663 memset(&request, 0, sizeof(request));
664 Strlcpy(request.oldPath, oldPath, EXECUTOR_BUFFER_SIZE);
665 Strlcpy(request.newPath, newPath, EXECUTOR_BUFFER_SIZE);
666
667 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
668 return -1;
669
670 // Receive the response
671
672 ExecutorRenameFileResponse response;
673
674 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
675 return -1;
676
677 kumpf 1.1.4.2 return response.status;
678 }
679
680 virtual int removeFile(
681 const char* path)
682 {
683 AutoMutex autoMutex(_mutex);
684
685 // _send request header:
686
687 ExecutorRequestHeader header;
688 header.code = EXECUTOR_REMOVE_FILE_MESSAGE;
689
690 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
691 return -1;
692
693 // _send request body.
694
695 ExecutorRemoveFileRequest request;
696 memset(&request, 0, sizeof(request));
697 Strlcpy(request.path, path, EXECUTOR_BUFFER_SIZE);
698 kumpf 1.1.4.2
699 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
700 return -1;
701
702 // Receive the response
703
704 ExecutorRemoveFileResponse response;
705
706 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
707 return -1;
708
709 return response.status;
710 }
711
712 virtual int startProviderAgent(
713 const SessionKey& sessionKey,
714 const char* module,
715 int uid,
716 int gid,
717 int& pid,
718 SessionKey& providerAgentSessionKey,
719 kumpf 1.1.4.2 AnonymousPipe*& readPipe,
720 AnonymousPipe*& writePipe)
721 {
722 AutoMutex autoMutex(_mutex);
723
724 providerAgentSessionKey.clear();
725 readPipe = 0;
726 writePipe = 0;
727
728 // Reject strings longer than EXECUTOR_BUFFER_SIZE.
729
730 size_t n = strlen(module);
731
732 if (n >= EXECUTOR_BUFFER_SIZE)
733 return -1;
734
735 // _send request header:
736
737 ExecutorRequestHeader header;
738 header.code = EXECUTOR_START_PROVIDER_AGENT_MESSAGE;
739
740 kumpf 1.1.4.2 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
741 return -1;
742
743 // _send request body.
744
745 ExecutorStartProviderAgentRequest request;
746 memset(&request, 0, sizeof(request));
747 Strlcpy(request.key, sessionKey.data(), sizeof(request.key));
748 memcpy(request.module, module, n);
749 request.uid = uid;
750 request.gid = gid;
751
752 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
753 return -1;
754
755 // Receive the response
756
757 ExecutorStartProviderAgentResponse response;
758
759 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
760 return -1;
761 kumpf 1.1.4.2
762 // Get the session key.
763
764 Strlcpy((char*)providerAgentSessionKey.data(),
765 response.key, providerAgentSessionKey.size());
766
767 // Check response status and pid.
768
769 if (response.status != 0)
770 return -1;
771
772 // Get pid:
773
774 pid = response.pid;
775
776 // Receive descriptors.
777
778 int descriptors[2];
779 int result = RecvDescriptorArray(_sock, descriptors, 2);
780
781 if (result == 0)
782 kumpf 1.1.4.2 {
783 int readFd = descriptors[0];
784 int writeFd = descriptors[1];
785
786 // Create to and from AnonymousPipe instances to correspond to
787 // the pipe descriptors created above.
788
789 char readFdStr[32];
790 char writeFdStr[32];
791 sprintf(readFdStr, "%d", readFd);
792 sprintf(writeFdStr, "%d", writeFd);
793
794 readPipe = new AnonymousPipe(readFdStr, 0);
795 writePipe = new AnonymousPipe(0, writeFdStr);
796 }
797
798 return result;
799 }
800
801 virtual int daemonizeExecutor()
802 {
803 kumpf 1.1.4.2 AutoMutex autoMutex(_mutex);
804
805 // _send request header:
806
807 ExecutorRequestHeader header;
808 header.code = EXECUTOR_DAEMONIZE_EXECUTOR_MESSAGE;
809
810 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
811 return -1;
812
813 // Receive the response
814
815 ExecutorDaemonizeExecutorResponse response;
816
817 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
818 return -1;
819
820 return response.status;
821 }
822
823 virtual int reapProviderAgent(
824 kumpf 1.1.4.2 const SessionKey& sessionKey,
825 int pid)
826 {
827 AutoMutex autoMutex(_mutex);
828
829 // _send request header:
830
831 ExecutorRequestHeader header;
832 header.code = EXECUTOR_REAP_PROVIDER_AGENT;
833
834 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
835 return -1;
836
837 // _send request body:
838
839 ExecutorReapProviderAgentRequest request;
840 memset(&request, 0, sizeof(request));
841 Strlcpy(request.key, sessionKey.data(), sizeof(request.key));
842 request.pid = pid;
843
844 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
845 kumpf 1.1.4.2 return -1;
846
847 // Receive the response
848
849 ExecutorReapProviderAgentResponse response;
850
851 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
852 return -1;
853
854 return response.status;
855 }
856
857 virtual int authenticatePassword(
858 const char* username,
859 const char* password,
860 SessionKey& sessionKey)
861 {
862 AutoMutex autoMutex(_mutex);
863
864 sessionKey.clear();
865
866 kumpf 1.1.4.2 // _send request header:
867
868 ExecutorRequestHeader header;
869 header.code = EXECUTOR_AUTHENTICATE_PASSWORD_MESSAGE;
870
871 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
872 return -1;
873
874 // _send request body.
875
876 ExecutorAuthenticatePasswordRequest request;
877 memset(&request, 0, sizeof(request));
878 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
879 Strlcpy(request.password, password, EXECUTOR_BUFFER_SIZE);
880
881 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
882 return -1;
883
884 // Receive the response
885
886 ExecutorAuthenticatePasswordResponse response;
887 kumpf 1.1.4.2
888 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
889 return -1;
890
891 Strlcpy((char*)sessionKey.data(), response.key, sessionKey.size());
892
893 return response.status;
894 }
895
896 virtual int validateUser(
897 const char* username)
898 {
899 AutoMutex autoMutex(_mutex);
900
901 // _send request header:
902
903 ExecutorRequestHeader header;
904 header.code = EXECUTOR_VALIDATE_USER_MESSAGE;
905
906 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
907 return -1;
908 kumpf 1.1.4.2
909 // _send request body.
910
911 ExecutorValidateUserRequest request;
912 memset(&request, 0, sizeof(request));
913 Strlcpy(request.username, username, EXECUTOR_BUFFER_SIZE);
914
915 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
916 return -1;
917
918 // Receive the response
919
920 ExecutorValidateUserResponse response;
921
922 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
923 return -1;
924
925 return response.status;
926 }
927
928 virtual int challengeLocal(
929 kumpf 1.1.4.2 const char* username,
930 char challenge[EXECUTOR_BUFFER_SIZE],
931 SessionKey& sessionKey)
932 {
933 AutoMutex autoMutex(_mutex);
934
935 sessionKey.clear();
936
937 // _send request header:
938
939 ExecutorRequestHeader header;
940 header.code = EXECUTOR_CHALLENGE_LOCAL_MESSAGE;
941
942 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
943 return -1;
944
945 // _send request body.
946
947 ExecutorChallengeLocalRequest request;
948 memset(&request, 0, sizeof(request));
949 Strlcpy(request.user, username, EXECUTOR_BUFFER_SIZE);
950 kumpf 1.1.4.2
951 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
952 return -1;
953
954 // Receive the response
955
956 ExecutorChallengeLocalResponse response;
957
958 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
959 return -1;
960
961 Strlcpy((char*)sessionKey.data(), response.key, sessionKey.size());
962 Strlcpy(challenge, response.challenge, EXECUTOR_BUFFER_SIZE);
963
964 return response.status;
965 }
966
967 virtual int authenticateLocal(
968 const SessionKey& sessionKey,
969 const char* challengeResponse)
970 {
971 kumpf 1.1.4.2 AutoMutex autoMutex(_mutex);
972
973 // _send request header:
974
975 ExecutorRequestHeader header;
976 header.code = EXECUTOR_AUTHENTICATE_LOCAL_MESSAGE;
977
978 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
979 return -1;
980
981 // _send request body.
982
983 ExecutorAuthenticateLocalRequest request;
984 memset(&request, 0, sizeof(request));
985 Strlcpy(request.key, (char*)sessionKey.data(), EXECUTOR_BUFFER_SIZE);
986 Strlcpy(request.token, challengeResponse, EXECUTOR_BUFFER_SIZE);
987
988 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
989 return -1;
990
991 // Receive the response
992 kumpf 1.1.4.2
993 ExecutorAuthenticateLocalResponse response;
994
995 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
996 return -1;
997
998 return response.status;
999 }
1000
1001 virtual int newSessionKey(
1002 const char username[EXECUTOR_BUFFER_SIZE],
1003 SessionKey& sessionKey)
1004 {
1005 AutoMutex autoMutex(_mutex);
1006
1007 sessionKey.clear();
1008
1009 // _send request header:
1010
1011 ExecutorRequestHeader header;
1012 header.code = EXECUTOR_NEW_SESSION_KEY_MESSAGE;
1013 kumpf 1.1.4.2
1014 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
1015 return -1;
1016
1017 // _send request body.
1018
1019 ExecutorNewSessionKeyRequest request;
1020 memset(&request, 0, sizeof(request));
1021 Strlcpy(request.username, username, sizeof(request.username));
1022
1023 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
1024 return -1;
1025
1026 // Receive the response
1027
1028 ExecutorNewSessionKeyResponse response;
1029
1030 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
1031 return -1;
1032
1033 Strlcpy((char*)sessionKey.data(), response.key, sessionKey.size());
1034 kumpf 1.1.4.2
1035 return response.status;
1036 }
1037
1038 virtual int deleteSessionKey(
1039 const SessionKey& sessionKey)
1040 {
1041 AutoMutex autoMutex(_mutex);
1042
1043 // Send request header:
1044
1045 ExecutorRequestHeader header;
1046 header.code = EXECUTOR_DELETE_SESSION_KEY_MESSAGE;
1047
1048 if (_send(_sock, &header, sizeof(header)) != sizeof(header))
1049 return -1;
1050
1051 // Send request body.
1052
1053 ExecutorDeleteSessionKeyRequest request;
1054 memset(&request, 0, sizeof(request));
1055 kumpf 1.1.4.2 Strlcpy(request.key, sessionKey.data(), sizeof(request.key));
1056
1057 if (_send(_sock, &request, sizeof(request)) != sizeof(request))
1058 return -1;
1059
1060 // Receive the response
1061
1062 ExecutorDeleteSessionKeyResponse response;
1063
1064 if (_recv(_sock, &response, sizeof(response)) != sizeof(response))
1065 return -1;
1066
1067 return response.status;
1068 }
1069
1070 private:
1071
1072 static ssize_t _recv(int sock, void* buffer, size_t size)
1073 {
1074 size_t r = size;
1075 char* p = (char*)buffer;
1076 kumpf 1.1.4.2
1077 if (size == 0)
1078 return -1;
1079
1080 while (r)
1081 {
1082 ssize_t n;
1083
1084 EXECUTOR_RESTART(read(sock, p, r), n);
1085
1086 if (n == -1)
1087 return -1;
1088 else if (n == 0)
1089 return size - r;
1090
1091 r -= n;
1092 p += n;
1093 }
1094
1095 return size - r;
1096 }
1097 kumpf 1.1.4.2
1098 static ssize_t _send(int sock, void* buffer, size_t size)
1099 {
1100 size_t r = size;
1101 char* p = (char*)buffer;
1102
1103 while (r)
1104 {
1105 ssize_t n;
1106 EXECUTOR_RESTART(write(sock, p, r), n);
1107
1108 if (n == -1)
1109 return -1;
1110 else if (n == 0)
1111 return size - r;
1112
1113 r -= n;
1114 p += n;
1115 }
1116
1117 return size - r;
1118 kumpf 1.1.4.2 }
1119
1120 int _sock;
1121 Mutex _mutex;
1122 };
1123
1124 #endif /* defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION) */
1125
1126 ////////////////////////////////////////////////////////////////////////////////
1127 //
1128 //
1129 // class Executor
1130 //
1131 //
1132 ////////////////////////////////////////////////////////////////////////////////
1133
1134 static int _sock = -1;
1135 static ExecutorImpl* _impl = 0;
1136 static Mutex _mutex;
1137
1138 static ExecutorImpl* _getImpl()
1139 kumpf 1.1.4.2 {
1140 // Use the double-checked locking technique to avoid the overhead of a lock
1141 // on every call.
1142
1143 if (_impl == 0)
1144 {
1145 _mutex.lock();
1146
1147 if (_impl == 0)
1148 {
1149 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
1150 if (_sock == -1)
1151 _impl = new ExecutorLoopbackImpl();
1152 else
1153 _impl = new ExecutorSocketImpl(_sock);
1154 #else
1155 _impl = new ExecutorLoopbackImpl();
1156 #endif
1157 }
1158
1159 _mutex.unlock();
1160 kumpf 1.1.4.2 }
1161
1162 return _impl;
1163 }
1164
1165 void Executor::setSock(int sock)
1166 {
1167 _mutex.lock();
1168 _sock = sock;
1169 _mutex.unlock();
1170 }
1171
1172 int Executor::detectExecutor()
1173 {
1174 return _getImpl()->detectExecutor();
1175 }
1176
1177 int Executor::ping()
1178 {
1179 return _getImpl()->ping();
1180 }
1181 kumpf 1.1.4.2
1182 FILE* Executor::openFile(
1183 const char* path,
1184 int mode)
1185 {
1186 return _getImpl()->openFile(path, mode);
1187 }
1188
1189 int Executor::renameFile(
1190 const char* oldPath,
1191 const char* newPath)
1192 {
1193 return _getImpl()->renameFile(oldPath, newPath);
1194 }
1195
1196 int Executor::removeFile(
1197 const char* path)
1198 {
1199 return _getImpl()->removeFile(path);
1200 }
1201
1202 kumpf 1.1.4.2 int Executor::startProviderAgent(
1203 const SessionKey& sessionKey,
1204 const char* module,
1205 int uid,
1206 int gid,
1207 int& pid,
1208 SessionKey& providerAgentSessionKey,
1209 AnonymousPipe*& readPipe,
1210 AnonymousPipe*& writePipe)
1211 {
1212 return _getImpl()->startProviderAgent(sessionKey, module,
1213 uid, gid, pid, providerAgentSessionKey, readPipe, writePipe);
1214 }
1215
1216 int Executor::daemonizeExecutor()
1217 {
1218 return _getImpl()->daemonizeExecutor();
1219 }
1220
1221 int Executor::reapProviderAgent(
1222 const SessionKey& sessionKey,
1223 kumpf 1.1.4.2 int pid)
1224 {
1225 return _getImpl()->reapProviderAgent(sessionKey, pid);
1226 }
1227
1228 int Executor::authenticatePassword(
1229 const char* username,
1230 const char* password,
1231 SessionKey& sessionKey)
1232 {
1233 return _getImpl()->authenticatePassword(username, password, sessionKey);
1234 }
1235
1236 int Executor::validateUser(
1237 const char* username)
1238 {
1239 return _getImpl()->validateUser(username);
1240 }
1241
1242 int Executor::challengeLocal(
1243 const char* user,
1244 kumpf 1.1.4.2 char path[EXECUTOR_BUFFER_SIZE],
1245 SessionKey& sessionKey)
1246 {
1247 return _getImpl()->challengeLocal(user, path, sessionKey);
1248 }
1249
1250 int Executor::authenticateLocal(
1251 const SessionKey& sessionKey,
1252 const char* challengeResponse)
1253 {
1254 return _getImpl()->authenticateLocal(sessionKey, challengeResponse);
1255 }
1256
1257 int Executor::newSessionKey(
1258 const char username[EXECUTOR_BUFFER_SIZE],
1259 SessionKey& sessionKey)
1260 {
1261 return _getImpl()->newSessionKey(username, sessionKey);
1262 }
1263
1264 int Executor::deleteSessionKey(
1265 kumpf 1.1.4.2 const SessionKey& sessionKey)
1266 {
1267 return _getImpl()->deleteSessionKey(sessionKey);
1268 }
1269
1270 PEGASUS_NAMESPACE_END
|