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