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