1 /* $NetBSD: privsep.c,v 1.6 2006/09/09 16:22:10 manu Exp $ */
3 /* Id: privsep.c,v 1.15 2005/08/08 11:23:44 vanhu Exp */
6 * Copyright (C) 2004 Emmanuel Dreyfus
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <stdlib.h> /* for setproctitle */
45 #include <sys/socket.h>
46 #include <sys/param.h>
55 #include "crypto_openssl.h"
56 #include "isakmp_var.h"
60 #include "isakmp_xauth.h"
61 #include "isakmp_cfg.h"
63 #include "localconf.h"
64 #include "remoteconf.h"
70 static int privsep_sock
[2] = { -1, -1 };
72 static int privsep_recv(int, struct privsep_com_msg
**, size_t *);
73 static int privsep_send(int, struct privsep_com_msg
*, size_t);
74 static int safety_check(struct privsep_com_msg
*, int i
);
75 static int port_check(int);
76 static int unsafe_env(char *const *);
77 static int unknown_name(int);
78 static int unsafe_path(char *, int);
83 privsep_send(sock
, buf
, len
)
85 struct privsep_com_msg
*buf
;
91 if (sendto(sock
, (char *)buf
, len
, 0, NULL
, 0) == -1) {
92 plog(LLV_ERROR
, LOCATION
, NULL
,
93 "privsep_send failed: %s\n",
98 racoon_free((char *)buf
);
105 privsep_recv(sock
, bufp
, lenp
)
107 struct privsep_com_msg
**bufp
;
110 struct admin_com com
;
111 struct admin_com
*combuf
;
118 while ((len
= recvfrom(sock
, (char *)&com
,
119 sizeof(com
), MSG_PEEK
, NULL
, NULL
)) == -1) {
123 plog(LLV_ERROR
, LOCATION
, NULL
,
124 "privsep_recv failed: %s\n",
129 /* Check for short packets */
130 if (len
< sizeof(com
)) {
131 plog(LLV_ERROR
, LOCATION
, NULL
,
132 "corrupted privsep message (short header)\n");
136 /* Allocate buffer for the whole message */
137 if ((combuf
= (struct admin_com
*)racoon_malloc(com
.ac_len
)) == NULL
) {
138 plog(LLV_ERROR
, LOCATION
, NULL
,
139 "failed to allocate memory: %s\n", strerror(errno
));
143 /* Get the whole buffer */
144 while ((len
= recvfrom(sock
, (char *)combuf
,
145 com
.ac_len
, 0, NULL
, NULL
)) == -1) {
148 plog(LLV_ERROR
, LOCATION
, NULL
,
149 "failed to recv privsep command: %s\n",
154 /* We expect len to match */
155 if (len
!= com
.ac_len
) {
156 plog(LLV_ERROR
, LOCATION
, NULL
,
157 "corrupted privsep message (short packet)\n");
161 *bufp
= (struct privsep_com_msg
*)combuf
;
166 #endif /* HAVE_OPENSSL */
175 /* If running as root, we don't use the privsep code path */
176 if (lcconf
->uid
== 0)
180 * When running privsep, certificate and script paths
181 * are mandatory, as they enable us to check path safety
182 * in the privilegied instance
184 if ((lcconf
->pathinfo
[LC_PATHTYPE_CERT
] == NULL
) ||
185 (lcconf
->pathinfo
[LC_PATHTYPE_SCRIPT
] == NULL
)) {
186 plog(LLV_ERROR
, LOCATION
, NULL
, "privilege separation "
187 "require path cert and path script in the config file\n");
191 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, privsep_sock
) != 0) {
192 plog(LLV_ERROR
, LOCATION
, NULL
,
193 "Cannot allocate privsep_sock: %s\n", strerror(errno
));
197 switch (child_pid
= fork()) {
199 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot fork privsep: %s\n",
204 case 0: /* Child: drop privileges */
205 if (lcconf
->chroot
!= NULL
) {
206 if (chdir(lcconf
->chroot
) != 0) {
207 plog(LLV_ERROR
, LOCATION
, NULL
,
208 "Cannot chdir(%s): %s\n", lcconf
->chroot
,
212 if (chroot(lcconf
->chroot
) != 0) {
213 plog(LLV_ERROR
, LOCATION
, NULL
,
214 "Cannot chroot(%s): %s\n", lcconf
->chroot
,
220 if (setgid(lcconf
->gid
) != 0) {
221 plog(LLV_ERROR
, LOCATION
, NULL
,
222 "Cannot setgid(%d): %s\n", lcconf
->gid
,
227 if (setegid(lcconf
->gid
) != 0) {
228 plog(LLV_ERROR
, LOCATION
, NULL
,
229 "Cannot setegid(%d): %s\n", lcconf
->gid
,
234 if (setuid(lcconf
->uid
) != 0) {
235 plog(LLV_ERROR
, LOCATION
, NULL
,
236 "Cannot setuid(%d): %s\n", lcconf
->uid
,
241 if (seteuid(lcconf
->uid
) != 0) {
242 plog(LLV_ERROR
, LOCATION
, NULL
,
243 "Cannot seteuid(%d): %s\n", lcconf
->uid
,
251 default: /* Parent: privilegied process */
256 * Close everything except the socketpair,
257 * and stdout if running in the forground.
259 for (i
= sysconf(_SC_OPEN_MAX
); i
> 0; i
--) {
260 if (i
== privsep_sock
[0])
262 if (i
== privsep_sock
[1])
264 if ((f_foreground
) && (i
== 1))
269 /* Above trickery closed the log file, reopen it */
272 plog(LLV_INFO
, LOCATION
, NULL
,
273 "racoon privilegied process running with PID %d\n", getpid());
276 setproctitle("[priv]");
280 * Don't catch any signal
281 * This duplicate session:signals[], which is static...
283 signal(SIGHUP
, SIG_DFL
);
284 signal(SIGINT
, SIG_DFL
);
285 signal(SIGTERM
, SIG_DFL
);
286 signal(SIGUSR1
, SIG_DFL
);
287 signal(SIGUSR2
, SIG_DFL
);
288 signal(SIGCHLD
, SIG_DFL
);
292 struct privsep_com_msg
*combuf
;
293 struct privsep_com_msg
*reply
;
297 char *bufs
[PRIVSEP_NBUF_MAX
];
300 if (privsep_recv(privsep_sock
[0], &combuf
, &len
) != 0)
303 /* Safety checks and gather the data */
304 if (len
< sizeof(*combuf
)) {
305 plog(LLV_ERROR
, LOCATION
, NULL
,
306 "corrupted privsep message (short buflen)\n");
310 data
= (char *)(combuf
+ 1);
311 totallen
= sizeof(*combuf
);
312 for (i
= 0; i
< PRIVSEP_NBUF_MAX
; i
++) {
313 bufs
[i
] = (char *)data
;
314 data
+= combuf
->bufs
.buflen
[i
];
315 totallen
+= combuf
->bufs
.buflen
[i
];
318 if (totallen
> len
) {
319 plog(LLV_ERROR
, LOCATION
, NULL
,
320 "corrupted privsep message (bufs too big)\n");
324 /* Prepare the reply buffer */
325 if ((reply
= racoon_malloc(sizeof(*reply
))) == NULL
) {
326 plog(LLV_ERROR
, LOCATION
, NULL
,
327 "Cannot allocate reply buffer: %s\n",
331 bzero(reply
, sizeof(*reply
));
332 reply
->hdr
.ac_cmd
= combuf
->hdr
.ac_cmd
;
333 reply
->hdr
.ac_len
= sizeof(*reply
);
335 switch(combuf
->hdr
.ac_cmd
) {
337 * XXX Improvement: instead of returning the key,
338 * stuff eay_get_pkcs1privkey and eay_get_x509sign
339 * together and sign the hash in the privilegied
341 * pro: the key remains inaccessible to unpriv
342 * con: a compromised unpriv racoon can still sign anything
344 case PRIVSEP_EAY_GET_PKCS1PRIVKEY
: {
347 /* Make sure the string is NULL terminated */
348 if (safety_check(combuf
, 0) != 0)
350 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
352 if (unsafe_path(bufs
[0], LC_PATHTYPE_CERT
) != 0) {
353 plog(LLV_ERROR
, LOCATION
, NULL
,
354 "privsep_eay_get_pkcs1privkey: "
355 "unsafe cert \"%s\"\n", bufs
[0]);
358 plog(LLV_DEBUG
, LOCATION
, NULL
,
359 "eay_get_pkcs1privkey(\"%s\")\n", bufs
[0]);
361 if ((privkey
= eay_get_pkcs1privkey(bufs
[0])) == NULL
){
362 reply
->hdr
.ac_errno
= errno
;
366 reply
->bufs
.buflen
[0] = privkey
->l
;
367 reply
->hdr
.ac_len
= sizeof(*reply
) + privkey
->l
;
368 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
370 plog(LLV_ERROR
, LOCATION
, NULL
,
371 "Cannot allocate reply buffer: %s\n",
376 memcpy(reply
+ 1, privkey
->v
, privkey
->l
);
381 case PRIVSEP_SCRIPT_EXEC
: {
390 * First count the bufs, and make sure strings
391 * are NULL terminated.
393 * We expect: script, name, envp[], void
395 if (safety_check(combuf
, 0) != 0)
397 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
398 count
++; /* script */
401 for (; count
< PRIVSEP_NBUF_MAX
; count
++) {
402 if (combuf
->bufs
.buflen
[count
] == 0)
405 [combuf
->bufs
.buflen
[count
] - 1] = '\0';
409 /* count a void buf and perform safety check */
411 if (count
>= PRIVSEP_NBUF_MAX
) {
412 plog(LLV_ERROR
, LOCATION
, NULL
,
413 "privsep_script_exec: too many args\n");
419 * Allocate the arrays for envp
421 envp
= racoon_malloc((envc
+ 1) * sizeof(char *));
423 plog(LLV_ERROR
, LOCATION
, NULL
,
424 "cannot allocate memory: %s\n",
428 bzero(envp
, (envc
+ 1) * sizeof(char *));
432 * Populate script, name and envp
435 script
= bufs
[count
++];
437 if (combuf
->bufs
.buflen
[count
] != sizeof(name
)) {
438 plog(LLV_ERROR
, LOCATION
, NULL
,
439 "privsep_script_exec: corrupted message\n");
442 memcpy((char *)&name
, bufs
[count
++], sizeof(name
));
444 for (i
= 0; combuf
->bufs
.buflen
[count
]; count
++)
445 envp
[i
++] = bufs
[count
];
449 plog(LLV_DEBUG
, LOCATION
, NULL
,
450 "script_exec(\"%s\", %d, %p)\n",
454 * Check env for dangerous variables
455 * Check script path and name
456 * Perform fork and execve
458 if ((unsafe_env(envp
) == 0) &&
459 (unknown_name(name
) == 0) &&
460 (unsafe_path(script
, LC_PATHTYPE_SCRIPT
) == 0))
461 (void)script_exec(script
, name
, envp
);
463 plog(LLV_ERROR
, LOCATION
, NULL
,
464 "privsep_script_exec: "
465 "unsafe script \"%s\"\n", script
);
471 case PRIVSEP_GETPSK
: {
475 /* Make sure the string is NULL terminated */
476 if (safety_check(combuf
, 0) != 0)
478 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
480 if (combuf
->bufs
.buflen
[1] != sizeof(keylen
)) {
481 plog(LLV_ERROR
, LOCATION
, NULL
,
482 "privsep_getpsk: corrupted message\n");
485 memcpy(&keylen
, bufs
[1], sizeof(keylen
));
487 plog(LLV_DEBUG
, LOCATION
, NULL
,
488 "getpsk(\"%s\", %d)\n", bufs
[0], keylen
);
490 if ((psk
= getpsk(bufs
[0], keylen
)) == NULL
) {
491 reply
->hdr
.ac_errno
= errno
;
495 reply
->bufs
.buflen
[0] = psk
->l
;
496 reply
->hdr
.ac_len
= sizeof(*reply
) + psk
->l
;
497 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
499 plog(LLV_ERROR
, LOCATION
, NULL
,
500 "Cannot allocate reply buffer: %s\n",
505 memcpy(reply
+ 1, psk
->v
, psk
->l
);
511 case PRIVSEP_ACCOUNTING_SYSTEM
: {
515 struct sockaddr
*raddr
;
517 if (safety_check(combuf
, 0) != 0)
519 if (safety_check(combuf
, 1) != 0)
521 if (safety_check(combuf
, 2) != 0)
523 if (safety_check(combuf
, 3) != 0)
526 memcpy(&port
, bufs
[0], sizeof(port
));
527 raddr
= (struct sockaddr
*)bufs
[1];
529 bufs
[2][combuf
->bufs
.buflen
[2] - 1] = '\0';
530 memcpy(&inout
, bufs
[3], sizeof(port
));
532 if (port_check(port
) != 0)
535 plog(LLV_DEBUG
, LOCATION
, NULL
,
536 "accounting_system(%d, %s, %s)\n",
537 port
, saddr2str(raddr
), bufs
[2]);
540 if (isakmp_cfg_accounting_system(port
,
541 raddr
, bufs
[2], inout
) != 0) {
543 reply
->hdr
.ac_errno
= EINVAL
;
545 reply
->hdr
.ac_errno
= errno
;
549 case PRIVSEP_XAUTH_LOGIN_SYSTEM
: {
550 if (safety_check(combuf
, 0) != 0)
552 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
554 if (safety_check(combuf
, 1) != 0)
556 bufs
[1][combuf
->bufs
.buflen
[1] - 1] = '\0';
558 plog(LLV_DEBUG
, LOCATION
, NULL
,
559 "xauth_login_system(\"%s\", <password>)\n",
563 if (xauth_login_system(bufs
[0], bufs
[1]) != 0) {
565 reply
->hdr
.ac_errno
= EINVAL
;
567 reply
->hdr
.ac_errno
= errno
;
572 case PRIVSEP_ACCOUNTING_PAM
: {
577 if (safety_check(combuf
, 0) != 0)
579 if (safety_check(combuf
, 1) != 0)
581 if (safety_check(combuf
, 2) != 0)
584 memcpy(&port
, bufs
[0], sizeof(port
));
585 memcpy(&inout
, bufs
[1], sizeof(inout
));
586 memcpy(&pool_size
, bufs
[2], sizeof(pool_size
));
588 if (pool_size
!= isakmp_cfg_config
.pool_size
)
589 if (isakmp_cfg_resize_pool(pool_size
) != 0)
592 if (port_check(port
) != 0)
595 plog(LLV_DEBUG
, LOCATION
, NULL
,
596 "isakmp_cfg_accounting_pam(%d, %d)\n",
600 if (isakmp_cfg_accounting_pam(port
, inout
) != 0) {
602 reply
->hdr
.ac_errno
= EINVAL
;
604 reply
->hdr
.ac_errno
= errno
;
609 case PRIVSEP_XAUTH_LOGIN_PAM
: {
612 struct sockaddr
*raddr
;
614 if (safety_check(combuf
, 0) != 0)
616 if (safety_check(combuf
, 1) != 0)
618 if (safety_check(combuf
, 2) != 0)
620 if (safety_check(combuf
, 3) != 0)
622 if (safety_check(combuf
, 4) != 0)
625 memcpy(&port
, bufs
[0], sizeof(port
));
626 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
627 raddr
= (struct sockaddr
*)bufs
[2];
629 bufs
[3][combuf
->bufs
.buflen
[3] - 1] = '\0';
630 bufs
[4][combuf
->bufs
.buflen
[4] - 1] = '\0';
632 if (pool_size
!= isakmp_cfg_config
.pool_size
)
633 if (isakmp_cfg_resize_pool(pool_size
) != 0)
636 if (port_check(port
) != 0)
639 plog(LLV_DEBUG
, LOCATION
, NULL
,
640 "xauth_login_pam(%d, %s, \"%s\", <password>)\n",
641 port
, saddr2str(raddr
), bufs
[3]);
644 if (xauth_login_pam(port
,
645 raddr
, bufs
[3], bufs
[4]) != 0) {
647 reply
->hdr
.ac_errno
= EINVAL
;
649 reply
->hdr
.ac_errno
= errno
;
654 case PRIVSEP_CLEANUP_PAM
: {
658 if (safety_check(combuf
, 0) != 0)
660 if (safety_check(combuf
, 1) != 0)
663 memcpy(&port
, bufs
[0], sizeof(port
));
664 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
666 if (pool_size
!= isakmp_cfg_config
.pool_size
)
667 if (isakmp_cfg_resize_pool(pool_size
) != 0)
670 if (port_check(port
) != 0)
673 plog(LLV_DEBUG
, LOCATION
, NULL
,
674 "cleanup_pam(%d)\n", port
);
677 reply
->hdr
.ac_errno
= 0;
681 #endif /* HAVE_LIBPAM */
682 #endif /* ENABLE_HYBRID */
685 plog(LLV_ERROR
, LOCATION
, NULL
,
686 "unexpected privsep command %d\n",
692 /* This frees reply */
693 if (privsep_send(privsep_sock
[0],
694 reply
, reply
->hdr
.ac_len
) != 0)
701 plog(LLV_INFO
, LOCATION
, NULL
, "privsep exit\n");
704 #endif /* HAVE_OPENSSL */
708 privsep_eay_get_pkcs1privkey(path
)
712 struct privsep_com_msg
*msg
;
716 return eay_get_pkcs1privkey(path
);
718 len
= sizeof(*msg
) + strlen(path
) + 1;
719 if ((msg
= racoon_malloc(len
)) == NULL
) {
720 plog(LLV_ERROR
, LOCATION
, NULL
,
721 "Cannot allocate memory: %s\n", strerror(errno
));
725 msg
->hdr
.ac_cmd
= PRIVSEP_EAY_GET_PKCS1PRIVKEY
;
726 msg
->hdr
.ac_len
= len
;
727 msg
->bufs
.buflen
[0] = len
- sizeof(*msg
);
728 memcpy(msg
+ 1, path
, msg
->bufs
.buflen
[0]);
730 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
733 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
736 if (msg
->hdr
.ac_errno
!= 0) {
737 errno
= msg
->hdr
.ac_errno
;
741 if ((privkey
= vmalloc(len
- sizeof(*msg
))) == NULL
)
744 memcpy(privkey
->v
, msg
+ 1, privkey
->l
);
755 * No prigilege separation trick here, we just open PFKEY before
756 * dropping root privs and we remember it later.
758 static int pfkey_socket
= -1;
760 privsep_pfkey_open(void)
764 if (pfkey_socket
!= -1)
775 * Consequence of the above trickery: don't
776 * really close PFKEY as we never re-open it.
779 privsep_pfkey_close(ps
)
787 privsep_script_exec(script
, name
, envp
)
796 struct privsep_com_msg
*msg
;
799 return script_exec(script
, name
, envp
);
801 if ((msg
= racoon_malloc(sizeof(*msg
))) == NULL
) {
802 plog(LLV_ERROR
, LOCATION
, NULL
,
803 "Cannot allocate memory: %s\n", strerror(errno
));
807 bzero(msg
, sizeof(*msg
));
808 msg
->hdr
.ac_cmd
= PRIVSEP_SCRIPT_EXEC
;
809 msg
->hdr
.ac_len
= sizeof(*msg
);
813 * script, name, envp[0], ... envp[N], void
817 * Safety check on the counts: PRIVSEP_NBUF_MAX max
820 count
++; /* script */
822 for (c
= envp
; *c
; c
++) /* envp */
826 if (count
> PRIVSEP_NBUF_MAX
) {
827 plog(LLV_ERROR
, LOCATION
, NULL
, "Unexpected error: "
828 "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
838 msg
->bufs
.buflen
[count
] = strlen(script
) + 1; /* script */
839 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
841 msg
->bufs
.buflen
[count
] = sizeof(name
); /* name */
842 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
844 for (c
= envp
; *c
; c
++) { /* envp */
845 msg
->bufs
.buflen
[count
] = strlen(*c
) + 1;
846 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
849 msg
->bufs
.buflen
[count
] = 0; /* void */
850 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
852 if ((msg
= racoon_realloc(msg
, msg
->hdr
.ac_len
)) == NULL
) {
853 plog(LLV_ERROR
, LOCATION
, NULL
,
854 "Cannot allocate memory: %s\n", strerror(errno
));
861 data
= (char *)(msg
+ 1);
864 memcpy(data
, (char *)script
, msg
->bufs
.buflen
[count
]); /* script */
865 data
+= msg
->bufs
.buflen
[count
++];
867 memcpy(data
, (char *)&name
, msg
->bufs
.buflen
[count
]); /* name */
868 data
+= msg
->bufs
.buflen
[count
++];
870 for (c
= envp
; *c
; c
++) { /* envp */
871 memcpy(data
, *c
, msg
->bufs
.buflen
[count
]);
872 data
+= msg
->bufs
.buflen
[count
++];
880 if (privsep_send(privsep_sock
[1], msg
, msg
->hdr
.ac_len
) != 0)
883 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
886 if (msg
->hdr
.ac_errno
!= 0) {
887 errno
= msg
->hdr
.ac_errno
;
899 privsep_getpsk(str
, keylen
)
904 struct privsep_com_msg
*msg
;
910 return getpsk(str
, keylen
);
912 len
= sizeof(*msg
) + strlen(str
) + 1 + sizeof(keylen
);
913 if ((msg
= racoon_malloc(len
)) == NULL
) {
914 plog(LLV_ERROR
, LOCATION
, NULL
,
915 "Cannot allocate memory: %s\n", strerror(errno
));
919 msg
->hdr
.ac_cmd
= PRIVSEP_GETPSK
;
920 msg
->hdr
.ac_len
= len
;
922 data
= (char *)(msg
+ 1);
923 msg
->bufs
.buflen
[0] = strlen(str
) + 1;
924 memcpy(data
, str
, msg
->bufs
.buflen
[0]);
926 data
+= msg
->bufs
.buflen
[0];
927 msg
->bufs
.buflen
[1] = sizeof(keylen
);
928 memcpy(data
, &keylen
, sizeof(keylen
));
930 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
933 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
936 if (msg
->hdr
.ac_errno
!= 0) {
937 errno
= msg
->hdr
.ac_errno
;
941 if ((psk
= vmalloc(len
- sizeof(*msg
))) == NULL
)
944 memcpy(psk
->v
, msg
+ 1, psk
->l
);
957 privsep_xauth_login_system(usr
, pwd
)
961 struct privsep_com_msg
*msg
;
966 return xauth_login_system(usr
, pwd
);
968 len
= sizeof(*msg
) + strlen(usr
) + 1 + strlen(pwd
) + 1;
969 if ((msg
= racoon_malloc(len
)) == NULL
) {
970 plog(LLV_ERROR
, LOCATION
, NULL
,
971 "Cannot allocate memory: %s\n", strerror(errno
));
975 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_SYSTEM
;
976 msg
->hdr
.ac_len
= len
;
978 data
= (char *)(msg
+ 1);
979 msg
->bufs
.buflen
[0] = strlen(usr
) + 1;
980 memcpy(data
, usr
, msg
->bufs
.buflen
[0]);
981 data
+= msg
->bufs
.buflen
[0];
983 msg
->bufs
.buflen
[1] = strlen(pwd
) + 1;
984 memcpy(data
, pwd
, msg
->bufs
.buflen
[1]);
986 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
989 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
992 if (msg
->hdr
.ac_errno
!= 0) {
1002 privsep_accounting_system(port
, raddr
, usr
, inout
)
1004 struct sockaddr
*raddr
;
1008 struct privsep_com_msg
*msg
;
1014 return isakmp_cfg_accounting_system(port
, raddr
,
1019 + sysdep_sa_len(raddr
)
1023 if ((msg
= racoon_malloc(len
)) == NULL
) {
1024 plog(LLV_ERROR
, LOCATION
, NULL
,
1025 "Cannot allocate memory: %s\n", strerror(errno
));
1029 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_SYSTEM
;
1030 msg
->hdr
.ac_len
= len
;
1031 msg
->bufs
.buflen
[0] = sizeof(port
);
1032 msg
->bufs
.buflen
[1] = sysdep_sa_len(raddr
);
1033 msg
->bufs
.buflen
[2] = strlen(usr
) + 1;
1034 msg
->bufs
.buflen
[3] = sizeof(inout
);
1036 data
= (char *)(msg
+ 1);
1037 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1039 data
+= msg
->bufs
.buflen
[0];
1040 memcpy(data
, raddr
, msg
->bufs
.buflen
[1]);
1042 data
+= msg
->bufs
.buflen
[1];
1043 memcpy(data
, usr
, msg
->bufs
.buflen
[2]);
1045 data
+= msg
->bufs
.buflen
[2];
1046 memcpy(data
, &inout
, msg
->bufs
.buflen
[3]);
1048 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1051 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1054 if (msg
->hdr
.ac_errno
!= 0) {
1055 errno
= msg
->hdr
.ac_errno
;
1072 if ((port
< 0) || (port
>= isakmp_cfg_config
.pool_size
)) {
1073 plog(LLV_ERROR
, LOCATION
, NULL
,
1074 "privsep: port %d outside of allowed range [0,%zu]\n",
1075 port
, isakmp_cfg_config
.pool_size
- 1);
1081 #endif /* HAVE_OPENSSL */
1085 safety_check(msg
, index
)
1086 struct privsep_com_msg
*msg
;
1089 if (index
>= PRIVSEP_NBUF_MAX
) {
1090 plog(LLV_ERROR
, LOCATION
, NULL
,
1091 "privsep: Corrupted message, too many buffers\n");
1095 if (msg
->bufs
.buflen
[index
] == 0) {
1096 plog(LLV_ERROR
, LOCATION
, NULL
,
1097 "privsep: Corrupted message, unexpected void buffer\n");
1105 * Filter unsafe environement variables
1113 char *const bad_env
[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL
};
1115 for (e
= envp
; *e
; e
++) {
1116 for (be
= bad_env
; *be
; be
++) {
1117 if (strncmp(*e
, *be
, strlen(*be
)) == 0) {
1125 plog(LLV_ERROR
, LOCATION
, NULL
,
1126 "privsep_script_exec: unsafe environement variable\n");
1134 unsafe_path(script
, pathtype
)
1139 char rpath
[MAXPATHLEN
+ 1];
1145 path
= lcconf
->pathinfo
[pathtype
];
1147 /* No path was given for scripts: skip the check */
1151 if (realpath(script
, rpath
) == NULL
) {
1152 plog(LLV_ERROR
, LOCATION
, NULL
,
1153 "script path \"%s\" is invalid\n", script
);
1158 if (strncmp(path
, rpath
, len
) != 0)
1168 if ((name
< 0) || (name
> SCRIPT_MAX
)) {
1169 plog(LLV_ERROR
, LOCATION
, NULL
,
1170 "privsep_script_exec: unsafe name index\n");
1176 #endif /* HAVE_OPENSSL */
1180 privsep_accounting_pam(port
, inout
)
1184 struct privsep_com_msg
*msg
;
1188 int *pool_size_data
;
1192 return isakmp_cfg_accounting_pam(port
, inout
);
1197 + sizeof(isakmp_cfg_config
.pool_size
);
1199 if ((msg
= racoon_malloc(len
)) == NULL
) {
1200 plog(LLV_ERROR
, LOCATION
, NULL
,
1201 "Cannot allocate memory: %s\n", strerror(errno
));
1205 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_PAM
;
1206 msg
->hdr
.ac_len
= len
;
1207 msg
->bufs
.buflen
[0] = sizeof(port
);
1208 msg
->bufs
.buflen
[1] = sizeof(inout
);
1209 msg
->bufs
.buflen
[2] = sizeof(isakmp_cfg_config
.pool_size
);
1211 port_data
= (int *)(msg
+ 1);
1212 inout_data
= (int *)(port_data
+ 1);
1213 pool_size_data
= (int *)(inout_data
+ 1);
1216 *inout_data
= inout
;
1217 *pool_size_data
= isakmp_cfg_config
.pool_size
;
1219 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1222 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1225 if (msg
->hdr
.ac_errno
!= 0) {
1226 errno
= msg
->hdr
.ac_errno
;
1239 privsep_xauth_login_pam(port
, raddr
, usr
, pwd
)
1241 struct sockaddr
*raddr
;
1245 struct privsep_com_msg
*msg
;
1251 return xauth_login_pam(port
, raddr
, usr
, pwd
);
1255 + sizeof(isakmp_cfg_config
.pool_size
)
1256 + sysdep_sa_len(raddr
)
1260 if ((msg
= racoon_malloc(len
)) == NULL
) {
1261 plog(LLV_ERROR
, LOCATION
, NULL
,
1262 "Cannot allocate memory: %s\n", strerror(errno
));
1266 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_PAM
;
1267 msg
->hdr
.ac_len
= len
;
1268 msg
->bufs
.buflen
[0] = sizeof(port
);
1269 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1270 msg
->bufs
.buflen
[2] = sysdep_sa_len(raddr
);
1271 msg
->bufs
.buflen
[3] = strlen(usr
) + 1;
1272 msg
->bufs
.buflen
[4] = strlen(pwd
) + 1;
1274 data
= (char *)(msg
+ 1);
1275 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1277 data
+= msg
->bufs
.buflen
[0];
1278 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1280 data
+= msg
->bufs
.buflen
[1];
1281 memcpy(data
, raddr
, msg
->bufs
.buflen
[2]);
1283 data
+= msg
->bufs
.buflen
[2];
1284 memcpy(data
, usr
, msg
->bufs
.buflen
[3]);
1286 data
+= msg
->bufs
.buflen
[3];
1287 memcpy(data
, pwd
, msg
->bufs
.buflen
[4]);
1289 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1292 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1295 if (msg
->hdr
.ac_errno
!= 0) {
1296 errno
= msg
->hdr
.ac_errno
;
1309 privsep_cleanup_pam(port
)
1312 struct privsep_com_msg
*msg
;
1318 return cleanup_pam(port
);
1322 + sizeof(isakmp_cfg_config
.pool_size
);
1324 if ((msg
= racoon_malloc(len
)) == NULL
) {
1325 plog(LLV_ERROR
, LOCATION
, NULL
,
1326 "Cannot allocate memory: %s\n", strerror(errno
));
1330 msg
->hdr
.ac_cmd
= PRIVSEP_CLEANUP_PAM
;
1331 msg
->hdr
.ac_len
= len
;
1332 msg
->bufs
.buflen
[0] = sizeof(port
);
1333 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1335 data
= (char *)(msg
+ 1);
1336 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1338 data
+= msg
->bufs
.buflen
[0];
1339 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1341 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1344 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1347 if (msg
->hdr
.ac_errno
!= 0)
1348 errno
= msg
->hdr
.ac_errno
;