1 /* $Id: privsep.c,v 1.6.2.7 2005/08/08 11:25:01 vanhu Exp $ */
4 * Copyright (C) 2004 Emmanuel Dreyfus
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <stdlib.h> /* for setproctitle */
43 #include <sys/socket.h>
44 #include <sys/param.h>
53 #include "crypto_openssl.h"
54 #include "isakmp_var.h"
57 #include "isakmp_xauth.h"
58 #include "isakmp_cfg.h"
60 #include "localconf.h"
61 #include "remoteconf.h"
65 static int privsep_sock
[2] = { -1, -1 };
67 static int privsep_recv(int, struct privsep_com_msg
**, size_t *);
68 static int privsep_send(int, struct privsep_com_msg
*, size_t);
69 static int safety_check(struct privsep_com_msg
*, int i
);
71 static int port_check(int);
73 static int unsafe_env(char *const *);
74 static int unknown_name(int);
75 static int unknown_script(int);
76 static int unsafe_path(char *, int);
77 static char *script_name2path(int);
80 privsep_send(sock
, buf
, len
)
82 struct privsep_com_msg
*buf
;
88 if (sendto(sock
, (char *)buf
, len
, 0, NULL
, 0) == -1) {
89 plog(LLV_ERROR
, LOCATION
, NULL
,
90 "privsep_send failed: %s\n",
95 racoon_free((char *)buf
);
102 privsep_recv(sock
, bufp
, lenp
)
104 struct privsep_com_msg
**bufp
;
107 struct admin_com com
;
108 struct admin_com
*combuf
;
115 while ((len
= recvfrom(sock
, (char *)&com
,
116 sizeof(com
), MSG_PEEK
, NULL
, NULL
)) == -1) {
120 plog(LLV_ERROR
, LOCATION
, NULL
,
121 "privsep_recv failed: %s\n",
126 /* Check for short packets */
127 if (len
< sizeof(com
)) {
128 plog(LLV_ERROR
, LOCATION
, NULL
,
129 "corrupted privsep message (short header)\n");
133 /* Allocate buffer for the whole message */
134 if ((combuf
= (struct admin_com
*)racoon_malloc(com
.ac_len
)) == NULL
) {
135 plog(LLV_ERROR
, LOCATION
, NULL
,
136 "failed to allocate memory: %s\n", strerror(errno
));
140 /* Get the whole buffer */
141 while ((len
= recvfrom(sock
, (char *)combuf
,
142 com
.ac_len
, 0, NULL
, NULL
)) == -1) {
145 plog(LLV_ERROR
, LOCATION
, NULL
,
146 "failed to recv privsep command: %s\n",
151 /* We expect len to match */
152 if (len
!= com
.ac_len
) {
153 plog(LLV_ERROR
, LOCATION
, NULL
,
154 "corrupted privsep message (short packet)\n");
158 *bufp
= (struct privsep_com_msg
*)combuf
;
170 /* If running as root, we don't use the privsep code path */
171 if (lcconf
->uid
== 0)
175 * When running privsep, certificate and script paths
176 * are mandatory, as they enable us to check path safety
177 * in the privilegied instance
179 if ((lcconf
->pathinfo
[LC_PATHTYPE_CERT
] == NULL
) ||
180 (lcconf
->pathinfo
[LC_PATHTYPE_SCRIPT
] == NULL
)) {
181 plog(LLV_ERROR
, LOCATION
, NULL
, "privilege separation "
182 "require path cert and path script in the config file\n");
186 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, privsep_sock
) != 0) {
187 plog(LLV_ERROR
, LOCATION
, NULL
,
188 "Cannot allocate privsep_sock: %s\n", strerror(errno
));
192 switch (child_pid
= fork()) {
194 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot fork privsep: %s\n",
199 case 0: /* Child: drop privileges */
200 if (lcconf
->chroot
!= NULL
) {
201 if (chdir(lcconf
->chroot
) != 0) {
202 plog(LLV_ERROR
, LOCATION
, NULL
,
203 "Cannot chdir(%s): %s\n", lcconf
->chroot
,
207 if (chroot(lcconf
->chroot
) != 0) {
208 plog(LLV_ERROR
, LOCATION
, NULL
,
209 "Cannot chroot(%s): %s\n", lcconf
->chroot
,
215 if (setgid(lcconf
->gid
) != 0) {
216 plog(LLV_ERROR
, LOCATION
, NULL
,
217 "Cannot setgid(%d): %s\n", lcconf
->gid
,
222 if (setegid(lcconf
->gid
) != 0) {
223 plog(LLV_ERROR
, LOCATION
, NULL
,
224 "Cannot setegid(%d): %s\n", lcconf
->gid
,
229 if (setuid(lcconf
->uid
) != 0) {
230 plog(LLV_ERROR
, LOCATION
, NULL
,
231 "Cannot setuid(%d): %s\n", lcconf
->uid
,
236 if (seteuid(lcconf
->uid
) != 0) {
237 plog(LLV_ERROR
, LOCATION
, NULL
,
238 "Cannot seteuid(%d): %s\n", lcconf
->uid
,
246 default: /* Parent: privilegied process */
251 * Close everything except the socketpair,
252 * and stdout if running in the forground.
254 for (i
= sysconf(_SC_OPEN_MAX
); i
> 0; i
--) {
255 if (i
== privsep_sock
[0])
257 if (i
== privsep_sock
[1])
259 if ((f_foreground
) && (i
== 1))
264 /* Above trickery closed the log file, reopen it */
267 plog(LLV_INFO
, LOCATION
, NULL
,
268 "racoon privilegied process running with PID %d\n", getpid());
271 setproctitle("[priv]");
275 * Don't catch any signal
276 * This duplicate session:signals[], which is static...
278 signal(SIGHUP
, SIG_DFL
);
279 signal(SIGINT
, SIG_DFL
);
280 signal(SIGTERM
, SIG_DFL
);
281 signal(SIGUSR1
, SIG_DFL
);
282 signal(SIGUSR2
, SIG_DFL
);
283 signal(SIGCHLD
, SIG_DFL
);
287 struct privsep_com_msg
*combuf
;
288 struct privsep_com_msg
*reply
;
292 char *bufs
[PRIVSEP_NBUF_MAX
];
295 if (privsep_recv(privsep_sock
[0], &combuf
, &len
) != 0)
298 /* Safety checks and gather the data */
299 if (len
< sizeof(*combuf
)) {
300 plog(LLV_ERROR
, LOCATION
, NULL
,
301 "corrupted privsep message (short buflen)\n");
305 data
= (char *)(combuf
+ 1);
306 totallen
= sizeof(*combuf
);
307 for (i
= 0; i
< PRIVSEP_NBUF_MAX
; i
++) {
308 bufs
[i
] = (char *)data
;
309 data
+= combuf
->bufs
.buflen
[i
];
310 totallen
+= combuf
->bufs
.buflen
[i
];
313 if (totallen
> len
) {
314 plog(LLV_ERROR
, LOCATION
, NULL
,
315 "corrupted privsep message (bufs too big)\n");
319 /* Prepare the reply buffer */
320 if ((reply
= racoon_malloc(sizeof(*reply
))) == NULL
) {
321 plog(LLV_ERROR
, LOCATION
, NULL
,
322 "Cannot allocate reply buffer: %s\n",
326 bzero(reply
, sizeof(*reply
));
327 reply
->hdr
.ac_cmd
= combuf
->hdr
.ac_cmd
;
328 reply
->hdr
.ac_len
= sizeof(*reply
);
330 switch(combuf
->hdr
.ac_cmd
) {
332 * XXX Improvement: instead of returning the key,
333 * stuff eay_get_pkcs1privkey and eay_get_x509sign
334 * together and sign the hash in the privilegied
336 * pro: the key remains inaccessibleato
337 * con: a compromised unpriv racoon can still sign anything
339 case PRIVSEP_EAY_GET_PKCS1PRIVKEY
: {
342 /* Make sure the string is NULL terminated */
343 if (safety_check(combuf
, 0) != 0)
345 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
347 if (unsafe_path(bufs
[0], LC_PATHTYPE_CERT
) != 0) {
348 plog(LLV_ERROR
, LOCATION
, NULL
,
349 "privsep_eay_get_pkcs1privkey: "
350 "unsafe key \"%s\"\n", bufs
[0]);
353 if ((privkey
= eay_get_pkcs1privkey(bufs
[0])) == NULL
){
354 reply
->hdr
.ac_errno
= errno
;
358 reply
->bufs
.buflen
[0] = privkey
->l
;
359 reply
->hdr
.ac_len
= sizeof(*reply
) + privkey
->l
;
360 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
362 plog(LLV_ERROR
, LOCATION
, NULL
,
363 "Cannot allocate reply buffer: %s\n",
368 memcpy(reply
+ 1, privkey
->v
, privkey
->l
);
373 case PRIVSEP_SCRIPT_EXEC
: {
382 * First count the bufs, and make sure strings
383 * are NULL terminated.
385 * We expect: script, name, envp[], void
387 count
++; /* script */
390 for (; count
< PRIVSEP_NBUF_MAX
; count
++) {
391 if (combuf
->bufs
.buflen
[count
] == 0)
394 [combuf
->bufs
.buflen
[count
] - 1] = '\0';
398 /* count a void buf and perform safety check */
400 if (count
>= PRIVSEP_NBUF_MAX
) {
401 plog(LLV_ERROR
, LOCATION
, NULL
,
402 "privsep_script_exec: too many args\n");
408 * Allocate the arrays for envp
410 envp
= racoon_malloc((envc
+ 1) * sizeof(char *));
412 plog(LLV_ERROR
, LOCATION
, NULL
,
413 "cannot allocate memory: %s\n",
417 bzero(envp
, (envc
+ 1) * sizeof(char *));
421 * Populate script, name and envp
425 if (combuf
->bufs
.buflen
[count
] != sizeof(script
)) {
426 plog(LLV_ERROR
, LOCATION
, NULL
,
427 "privsep_script_exec: corrupted message\n");
430 memcpy((char *)&script
, bufs
[count
++], sizeof(script
));
432 if (combuf
->bufs
.buflen
[count
] != sizeof(name
)) {
433 plog(LLV_ERROR
, LOCATION
, NULL
,
434 "privsep_script_exec: corrupted message\n");
437 memcpy((char *)&name
, bufs
[count
++], sizeof(name
));
439 for (i
= 0; combuf
->bufs
.buflen
[count
]; count
++)
440 envp
[i
++] = bufs
[count
];
445 * Check env for dangerous variables
446 * Check script path and name
447 * Perform fork and execve
449 if ((unsafe_env(envp
) == 0) &&
450 (unknown_name(name
) == 0) &&
451 (unknown_script(script
) == 0) &&
452 (unsafe_path(script_name2path(script
),
453 LC_PATHTYPE_SCRIPT
) == 0))
454 (void)script_exec(script
, name
, envp
);
456 plog(LLV_ERROR
, LOCATION
, NULL
,
457 "privsep_script_exec: "
458 "unsafe script \"%s\"\n",
459 script_name2path(script
));
465 case PRIVSEP_GETPSK
: {
469 /* Make sure the string is NULL terminated */
470 if (safety_check(combuf
, 0) != 0)
472 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
474 if (combuf
->bufs
.buflen
[1] != sizeof(keylen
)) {
475 plog(LLV_ERROR
, LOCATION
, NULL
,
476 "privsep_getpsk: corrupted message\n");
479 memcpy(&keylen
, bufs
[1], sizeof(keylen
));
480 if ((psk
= getpsk(bufs
[0], keylen
)) == NULL
) {
481 reply
->hdr
.ac_errno
= errno
;
485 reply
->bufs
.buflen
[0] = psk
->l
;
486 reply
->hdr
.ac_len
= sizeof(*reply
) + psk
->l
;
487 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
489 plog(LLV_ERROR
, LOCATION
, NULL
,
490 "Cannot allocate reply buffer: %s\n",
495 memcpy(reply
+ 1, psk
->v
, psk
->l
);
501 case PRIVSEP_XAUTH_LOGIN_SYSTEM
: {
502 if (safety_check(combuf
, 0) != 0)
504 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
506 if (safety_check(combuf
, 1) != 0)
508 bufs
[1][combuf
->bufs
.buflen
[1] - 1] = '\0';
511 if (xauth_login_system(bufs
[0], bufs
[1]) != 0) {
513 reply
->hdr
.ac_errno
= EINVAL
;
515 reply
->hdr
.ac_errno
= errno
;
520 case PRIVSEP_ACCOUNTING_PAM
: {
524 if (safety_check(combuf
, 0) != 0)
526 if (safety_check(combuf
, 1) != 0)
529 memcpy(&port
, bufs
[0], sizeof(port
));
530 memcpy(&inout
, bufs
[1], sizeof(inout
));
532 if (port_check(port
) != 0)
536 if (isakmp_cfg_accounting_pam(port
, inout
) != 0) {
538 reply
->hdr
.ac_errno
= EINVAL
;
540 reply
->hdr
.ac_errno
= errno
;
545 case PRIVSEP_XAUTH_LOGIN_PAM
: {
547 struct sockaddr
*raddr
;
549 if (safety_check(combuf
, 0) != 0)
551 if (safety_check(combuf
, 1) != 0)
553 if (safety_check(combuf
, 2) != 0)
555 if (safety_check(combuf
, 3) != 0)
558 memcpy(&port
, bufs
[0], sizeof(port
));
559 raddr
= (struct sockaddr
*)bufs
[1];
561 bufs
[2][combuf
->bufs
.buflen
[2] - 1] = '\0';
562 bufs
[3][combuf
->bufs
.buflen
[3] - 1] = '\0';
564 if (port_check(port
) != 0)
568 if (xauth_login_pam(port
,
569 raddr
, bufs
[2], bufs
[3]) != 0) {
571 reply
->hdr
.ac_errno
= EINVAL
;
573 reply
->hdr
.ac_errno
= errno
;
578 case PRIVSEP_CLEANUP_PAM
: {
581 if (safety_check(combuf
, 0) != 0)
584 memcpy(&port
, bufs
[0], sizeof(port
));
586 if (port_check(port
) != 0)
590 reply
->hdr
.ac_errno
= 0;
594 #endif /* HAVE_LIBPAM */
595 #endif /* ENABLE_HYBRID */
598 plog(LLV_ERROR
, LOCATION
, NULL
,
599 "unexpected privsep command %d\n",
605 /* This frees reply */
606 if (privsep_send(privsep_sock
[0],
607 reply
, reply
->hdr
.ac_len
) != 0)
614 plog(LLV_INFO
, LOCATION
, NULL
, "privsep exit\n");
620 privsep_eay_get_pkcs1privkey(path
)
624 struct privsep_com_msg
*msg
;
628 return eay_get_pkcs1privkey(path
);
630 len
= sizeof(*msg
) + strlen(path
) + 1;
631 if ((msg
= racoon_malloc(len
)) == NULL
) {
632 plog(LLV_ERROR
, LOCATION
, NULL
,
633 "Cannot allocate memory: %s\n", strerror(errno
));
637 msg
->hdr
.ac_cmd
= PRIVSEP_EAY_GET_PKCS1PRIVKEY
;
638 msg
->hdr
.ac_len
= len
;
639 msg
->bufs
.buflen
[0] = len
- sizeof(*msg
);
640 memcpy(msg
+ 1, path
, msg
->bufs
.buflen
[0]);
642 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
645 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
648 if (msg
->hdr
.ac_errno
!= 0) {
649 errno
= msg
->hdr
.ac_errno
;
653 if ((privkey
= vmalloc(len
- sizeof(*msg
))) == NULL
)
656 memcpy(privkey
->v
, msg
+ 1, privkey
->l
);
666 * No prigilege separation trick here, we just open PFKEY before
667 * dropping root privs and we remember it later.
669 static int pfkey_socket
= -1;
671 privsep_pfkey_open(void)
675 if (pfkey_socket
!= -1)
686 * Consequence of the above trickery: don't
687 * really close PFKEY as we never re-open it.
690 privsep_pfkey_close(ps
)
697 privsep_script_exec(script
, name
, envp
)
706 struct privsep_com_msg
*msg
;
709 return script_exec(script
, name
, envp
);
711 if ((msg
= racoon_malloc(sizeof(*msg
))) == NULL
) {
712 plog(LLV_ERROR
, LOCATION
, NULL
,
713 "Cannot allocate memory: %s\n", strerror(errno
));
717 bzero(msg
, sizeof(*msg
));
718 msg
->hdr
.ac_cmd
= PRIVSEP_SCRIPT_EXEC
;
719 msg
->hdr
.ac_len
= sizeof(*msg
);
723 * script, name, envp[0], ... envp[N], void
727 * Safety check on the counts: PRIVSEP_NBUF_MAX max
730 count
++; /* script */
732 for (c
= envp
; *c
; c
++) /* envp */
736 if (count
> PRIVSEP_NBUF_MAX
) {
737 plog(LLV_ERROR
, LOCATION
, NULL
, "Unexpected error: "
738 "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
748 msg
->bufs
.buflen
[count
] = sizeof(script
); /* script */
749 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
751 msg
->bufs
.buflen
[count
] = sizeof(name
); /* name */
752 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
754 for (c
= envp
; *c
; c
++) { /* envp */
755 msg
->bufs
.buflen
[count
] = strlen(*c
) + 1;
756 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
759 msg
->bufs
.buflen
[count
] = 0; /* void */
760 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
762 if ((msg
= racoon_realloc(msg
, msg
->hdr
.ac_len
)) == NULL
) {
763 plog(LLV_ERROR
, LOCATION
, NULL
,
764 "Cannot allocate memory: %s\n", strerror(errno
));
771 data
= (char *)(msg
+ 1);
774 memcpy(data
, (char *)&script
, msg
->bufs
.buflen
[count
]); /* script */
775 data
+= msg
->bufs
.buflen
[count
++];
777 memcpy(data
, (char *)&name
, msg
->bufs
.buflen
[count
]); /* name */
778 data
+= msg
->bufs
.buflen
[count
++];
780 for (c
= envp
; *c
; c
++) { /* envp */
781 memcpy(data
, *c
, msg
->bufs
.buflen
[count
]);
782 data
+= msg
->bufs
.buflen
[count
++];
790 if (privsep_send(privsep_sock
[1], msg
, msg
->hdr
.ac_len
) != 0)
793 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
796 if (msg
->hdr
.ac_errno
!= 0) {
797 errno
= msg
->hdr
.ac_errno
;
807 privsep_getpsk(str
, keylen
)
812 struct privsep_com_msg
*msg
;
818 return getpsk(str
, keylen
);
820 len
= sizeof(*msg
) + strlen(str
) + 1 + sizeof(keylen
);
821 if ((msg
= racoon_malloc(len
)) == NULL
) {
822 plog(LLV_ERROR
, LOCATION
, NULL
,
823 "Cannot allocate memory: %s\n", strerror(errno
));
827 msg
->hdr
.ac_cmd
= PRIVSEP_GETPSK
;
828 msg
->hdr
.ac_len
= len
;
830 data
= (char *)(msg
+ 1);
831 msg
->bufs
.buflen
[0] = strlen(str
) + 1;
832 memcpy(data
, str
, msg
->bufs
.buflen
[0]);
834 data
+= msg
->bufs
.buflen
[0];
835 msg
->bufs
.buflen
[1] = sizeof(keylen
);
836 memcpy(data
, &keylen
, sizeof(keylen
));
838 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
841 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
844 if (msg
->hdr
.ac_errno
!= 0) {
845 errno
= msg
->hdr
.ac_errno
;
849 if ((psk
= vmalloc(len
- sizeof(*msg
))) == NULL
)
852 memcpy(psk
->v
, msg
+ 1, psk
->l
);
863 privsep_xauth_login_system(usr
, pwd
)
867 struct privsep_com_msg
*msg
;
872 return xauth_login_system(usr
, pwd
);
874 len
= sizeof(*msg
) + strlen(usr
) + 1 + strlen(pwd
) + 1;
875 if ((msg
= racoon_malloc(len
)) == NULL
) {
876 plog(LLV_ERROR
, LOCATION
, NULL
,
877 "Cannot allocate memory: %s\n", strerror(errno
));
881 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_SYSTEM
;
882 msg
->hdr
.ac_len
= len
;
884 data
= (char *)(msg
+ 1);
885 msg
->bufs
.buflen
[0] = strlen(usr
) + 1;
886 memcpy(data
, usr
, msg
->bufs
.buflen
[0]);
887 data
+= msg
->bufs
.buflen
[0];
889 msg
->bufs
.buflen
[1] = strlen(pwd
) + 1;
890 memcpy(data
, pwd
, msg
->bufs
.buflen
[1]);
892 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
895 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
898 if (msg
->hdr
.ac_errno
!= 0) {
906 #endif /* ENABLE_HYBRID */
913 if ((port
< 0) || (port
>= isakmp_cfg_config
.pool_size
)) {
914 plog(LLV_ERROR
, LOCATION
, NULL
,
915 "privsep: port %d outside of allowed range [0,%zu]\n",
916 port
, isakmp_cfg_config
.pool_size
- 1);
925 safety_check(msg
, index
)
926 struct privsep_com_msg
*msg
;
929 if (index
>= PRIVSEP_NBUF_MAX
) {
930 plog(LLV_ERROR
, LOCATION
, NULL
,
931 "privsep: Corrupted message, too many buffers\n");
935 if (msg
->bufs
.buflen
[index
] == 0) {
936 plog(LLV_ERROR
, LOCATION
, NULL
,
937 "privsep: Corrupted message, unexpected void buffer\n");
945 * Filter unsafe environement variables
953 char *const bad_env
[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL
};
955 for (e
= envp
; *e
; e
++) {
956 for (be
= bad_env
; *be
; be
++) {
957 if (strncmp(*e
, *be
, strlen(*be
)) == 0) {
965 plog(LLV_ERROR
, LOCATION
, NULL
,
966 "privsep_script_exec: unsafe environement variable\n");
974 unsafe_path(script
, pathtype
)
979 char rpath
[MAXPATHLEN
+ 1];
985 path
= lcconf
->pathinfo
[pathtype
];
987 /* No path was given for scripts: skip the check */
991 if (realpath(script
, rpath
) == NULL
) {
992 plog(LLV_ERROR
, LOCATION
, NULL
,
993 "script path \"%s\" is invalid\n", script
);
998 if (strncmp(path
, rpath
, len
) != 0)
1005 script_name2path(name
)
1010 if (script_paths
== NULL
) {
1011 plog(LLV_ERROR
, LOCATION
, NULL
,
1012 "script_name2path: script_paths was not initialized\n");
1016 sp
= (vchar_t
**)(script_paths
->v
);
1022 * Check the script path index is correct
1025 unknown_script(script
)
1028 if (script_paths
== NULL
) {
1029 plog(LLV_ERROR
, LOCATION
, NULL
,
1030 "privsep_script_exec: script_paths was not initialized\n");
1034 if ((script
< 0) || (script
> (script_paths
->l
/ sizeof(vchar_t
*)))) {
1035 plog(LLV_ERROR
, LOCATION
, NULL
,
1036 "privsep_script_exec: unsafe script index\n");
1047 if ((name
< 0) || (name
> SCRIPT_MAX
)) {
1048 plog(LLV_ERROR
, LOCATION
, NULL
,
1049 "privsep_script_exec: unsafe name index\n");
1058 privsep_accounting_pam(port
, inout
)
1062 struct privsep_com_msg
*msg
;
1069 return isakmp_cfg_accounting_pam(port
, inout
);
1071 len
= sizeof(*msg
) + sizeof(port
) + sizeof(inout
);
1072 if ((msg
= racoon_malloc(len
)) == NULL
) {
1073 plog(LLV_ERROR
, LOCATION
, NULL
,
1074 "Cannot allocate memory: %s\n", strerror(errno
));
1078 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_PAM
;
1079 msg
->hdr
.ac_len
= len
;
1080 msg
->bufs
.buflen
[0] = sizeof(port
);
1081 msg
->bufs
.buflen
[1] = sizeof(inout
);
1083 port_data
= (int *)(msg
+ 1);
1084 inout_data
= (int *)(port_data
+ 1);
1087 *inout_data
= inout
;
1089 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1092 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1095 if (msg
->hdr
.ac_errno
!= 0) {
1096 errno
= msg
->hdr
.ac_errno
;
1109 privsep_xauth_login_pam(port
, raddr
, usr
, pwd
)
1111 struct sockaddr
*raddr
;
1115 struct privsep_com_msg
*msg
;
1121 return xauth_login_pam(port
, raddr
, usr
, pwd
);
1125 + sysdep_sa_len(raddr
)
1128 if ((msg
= racoon_malloc(len
)) == NULL
) {
1129 plog(LLV_ERROR
, LOCATION
, NULL
,
1130 "Cannot allocate memory: %s\n", strerror(errno
));
1134 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_PAM
;
1135 msg
->hdr
.ac_len
= len
;
1136 msg
->bufs
.buflen
[0] = sizeof(port
);
1137 msg
->bufs
.buflen
[1] = sysdep_sa_len(raddr
);
1138 msg
->bufs
.buflen
[2] = strlen(usr
) + 1;
1139 msg
->bufs
.buflen
[3] = strlen(pwd
) + 1;
1141 data
= (char *)(msg
+ 1);
1142 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1144 data
+= sizeof(msg
->bufs
.buflen
[0]);
1145 memcpy(data
, raddr
, msg
->bufs
.buflen
[1]);
1147 data
+= msg
->bufs
.buflen
[1];
1148 memcpy(data
, usr
, msg
->bufs
.buflen
[2]);
1150 data
+= msg
->bufs
.buflen
[2];
1151 memcpy(data
, pwd
, msg
->bufs
.buflen
[3]);
1153 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1156 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1159 if (msg
->hdr
.ac_errno
!= 0) {
1160 errno
= msg
->hdr
.ac_errno
;
1173 privsep_cleanup_pam(port
)
1176 struct privsep_com_msg
*msg
;
1182 return cleanup_pam(port
);
1184 len
= sizeof(*msg
) + sizeof(port
);
1185 if ((msg
= racoon_malloc(len
)) == NULL
) {
1186 plog(LLV_ERROR
, LOCATION
, NULL
,
1187 "Cannot allocate memory: %s\n", strerror(errno
));
1191 msg
->hdr
.ac_cmd
= PRIVSEP_CLEANUP_PAM
;
1192 msg
->hdr
.ac_len
= len
;
1193 msg
->bufs
.buflen
[0] = sizeof(port
);
1195 data
= (char *)(msg
+ 1);
1196 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1198 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1201 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1204 if (msg
->hdr
.ac_errno
!= 0)
1205 errno
= msg
->hdr
.ac_errno
;