1 /* $NetBSD: privsep.c,v 1.18 2008/12/08 06:00:53 tteras 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/types.h>
46 #include <sys/socket.h>
47 #include <sys/param.h>
49 #include <netinet/in.h>
57 #include "crypto_openssl.h"
58 #include "isakmp_var.h"
62 #include "isakmp_xauth.h"
63 #include "isakmp_cfg.h"
65 #include "localconf.h"
66 #include "remoteconf.h"
71 static int privsep_sock
[2] = { -1, -1 };
73 static int privsep_recv(int, struct privsep_com_msg
**, size_t *);
74 static int privsep_send(int, struct privsep_com_msg
*, size_t);
75 static int safety_check(struct privsep_com_msg
*, int i
);
76 static int port_check(int);
77 static int unsafe_env(char *const *);
78 static int unknown_name(int);
79 static int unsafe_path(char *, int);
80 static int rec_fd(int);
81 static int send_fd(int, int);
99 const struct sockaddr
*addr
;
104 privsep_send(sock
, buf
, len
)
106 struct privsep_com_msg
*buf
;
112 if (sendto(sock
, (char *)buf
, len
, 0, NULL
, 0) == -1) {
113 plog(LLV_ERROR
, LOCATION
, NULL
,
114 "privsep_send failed: %s\n",
119 racoon_free((char *)buf
);
126 privsep_recv(sock
, bufp
, lenp
)
128 struct privsep_com_msg
**bufp
;
131 struct admin_com com
;
132 struct admin_com
*combuf
;
139 while ((len
= recvfrom(sock
, (char *)&com
,
140 sizeof(com
), MSG_PEEK
, NULL
, NULL
)) == -1) {
143 if (errno
== ECONNRESET
)
146 plog(LLV_ERROR
, LOCATION
, NULL
,
147 "privsep_recv failed: %s\n",
152 /* EOF, other side has closed. */
156 /* Check for short packets */
157 if (len
< sizeof(com
)) {
158 plog(LLV_ERROR
, LOCATION
, NULL
,
159 "corrupted privsep message (short header)\n");
163 /* Allocate buffer for the whole message */
164 if ((combuf
= (struct admin_com
*)racoon_malloc(com
.ac_len
)) == NULL
) {
165 plog(LLV_ERROR
, LOCATION
, NULL
,
166 "failed to allocate memory: %s\n", strerror(errno
));
170 /* Get the whole buffer */
171 while ((len
= recvfrom(sock
, (char *)combuf
,
172 com
.ac_len
, 0, NULL
, NULL
)) == -1) {
175 if (errno
== ECONNRESET
)
177 plog(LLV_ERROR
, LOCATION
, NULL
,
178 "failed to recv privsep command: %s\n",
183 /* We expect len to match */
184 if (len
!= com
.ac_len
) {
185 plog(LLV_ERROR
, LOCATION
, NULL
,
186 "corrupted privsep message (short packet)\n");
190 *bufp
= (struct privsep_com_msg
*)combuf
;
202 /* If running as root, we don't use the privsep code path */
203 if (lcconf
->uid
== 0)
207 * When running privsep, certificate and script paths
208 * are mandatory, as they enable us to check path safety
209 * in the privileged instance
211 if ((lcconf
->pathinfo
[LC_PATHTYPE_CERT
] == NULL
) ||
212 (lcconf
->pathinfo
[LC_PATHTYPE_SCRIPT
] == NULL
)) {
213 plog(LLV_ERROR
, LOCATION
, NULL
, "privilege separation "
214 "require path cert and path script in the config file\n");
218 if (socketpair(PF_LOCAL
, SOCK_STREAM
, 0, privsep_sock
) != 0) {
219 plog(LLV_ERROR
, LOCATION
, NULL
,
220 "Cannot allocate privsep_sock: %s\n", strerror(errno
));
224 switch (child_pid
= fork()) {
226 plog(LLV_ERROR
, LOCATION
, NULL
, "Cannot fork privsep: %s\n",
231 case 0: /* Child: drop privileges */
232 (void)close(privsep_sock
[0]);
234 if (lcconf
->chroot
!= NULL
) {
235 if (chdir(lcconf
->chroot
) != 0) {
236 plog(LLV_ERROR
, LOCATION
, NULL
,
237 "Cannot chdir(%s): %s\n", lcconf
->chroot
,
241 if (chroot(lcconf
->chroot
) != 0) {
242 plog(LLV_ERROR
, LOCATION
, NULL
,
243 "Cannot chroot(%s): %s\n", lcconf
->chroot
,
249 if (setgid(lcconf
->gid
) != 0) {
250 plog(LLV_ERROR
, LOCATION
, NULL
,
251 "Cannot setgid(%d): %s\n", lcconf
->gid
,
256 if (setegid(lcconf
->gid
) != 0) {
257 plog(LLV_ERROR
, LOCATION
, NULL
,
258 "Cannot setegid(%d): %s\n", lcconf
->gid
,
263 if (setuid(lcconf
->uid
) != 0) {
264 plog(LLV_ERROR
, LOCATION
, NULL
,
265 "Cannot setuid(%d): %s\n", lcconf
->uid
,
270 if (seteuid(lcconf
->uid
) != 0) {
271 plog(LLV_ERROR
, LOCATION
, NULL
,
272 "Cannot seteuid(%d): %s\n", lcconf
->uid
,
280 default: /* Parent: privileged process */
285 * Close everything except the socketpair,
286 * and stdout if running in the forground.
288 for (i
= sysconf(_SC_OPEN_MAX
); i
> 0; i
--) {
289 if (i
== privsep_sock
[0])
291 if ((f_foreground
) && (i
== 1))
296 /* Above trickery closed the log file, reopen it */
299 plog(LLV_INFO
, LOCATION
, NULL
,
300 "racoon privileged process running with PID %d\n", getpid());
302 plog(LLV_INFO
, LOCATION
, NULL
,
303 "racoon unprivileged process running with PID %d\n", child_pid
);
305 #if defined(__NetBSD__) || defined(__FreeBSD__)
306 setproctitle("[priv]");
310 * Don't catch any signal
311 * This duplicate session:signals[], which is static...
313 signal(SIGPIPE
, SIG_IGN
);
314 signal(SIGHUP
, SIG_DFL
);
315 signal(SIGINT
, SIG_DFL
);
316 signal(SIGTERM
, SIG_DFL
);
317 signal(SIGUSR1
, SIG_DFL
);
318 signal(SIGUSR2
, SIG_DFL
);
319 signal(SIGCHLD
, SIG_DFL
);
323 struct privsep_com_msg
*combuf
;
324 struct privsep_com_msg
*reply
;
328 char *bufs
[PRIVSEP_NBUF_MAX
];
331 if (privsep_recv(privsep_sock
[0], &combuf
, &len
) != 0)
334 /* Safety checks and gather the data */
335 if (len
< sizeof(*combuf
)) {
336 plog(LLV_ERROR
, LOCATION
, NULL
,
337 "corrupted privsep message (short buflen)\n");
341 data
= (char *)(combuf
+ 1);
342 totallen
= sizeof(*combuf
);
343 for (i
= 0; i
< PRIVSEP_NBUF_MAX
; i
++) {
344 bufs
[i
] = (char *)data
;
345 data
+= combuf
->bufs
.buflen
[i
];
346 totallen
+= combuf
->bufs
.buflen
[i
];
349 if (totallen
> len
) {
350 plog(LLV_ERROR
, LOCATION
, NULL
,
351 "corrupted privsep message (bufs too big)\n");
355 /* Prepare the reply buffer */
356 if ((reply
= racoon_malloc(sizeof(*reply
))) == NULL
) {
357 plog(LLV_ERROR
, LOCATION
, NULL
,
358 "Cannot allocate reply buffer: %s\n",
362 bzero(reply
, sizeof(*reply
));
363 reply
->hdr
.ac_cmd
= combuf
->hdr
.ac_cmd
;
364 reply
->hdr
.ac_len
= sizeof(*reply
);
366 switch(combuf
->hdr
.ac_cmd
) {
368 * XXX Improvement: instead of returning the key,
369 * stuff eay_get_pkcs1privkey and eay_get_x509sign
370 * together and sign the hash in the privileged
372 * pro: the key remains inaccessible to unpriv
373 * con: a compromised unpriv racoon can still sign anything
375 case PRIVSEP_EAY_GET_PKCS1PRIVKEY
: {
378 /* Make sure the string is NULL terminated */
379 if (safety_check(combuf
, 0) != 0)
381 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
383 if (unsafe_path(bufs
[0], LC_PATHTYPE_CERT
) != 0) {
384 plog(LLV_ERROR
, LOCATION
, NULL
,
385 "privsep_eay_get_pkcs1privkey: "
386 "unsafe cert \"%s\"\n", bufs
[0]);
389 plog(LLV_DEBUG
, LOCATION
, NULL
,
390 "eay_get_pkcs1privkey(\"%s\")\n", bufs
[0]);
392 if ((privkey
= eay_get_pkcs1privkey(bufs
[0])) == NULL
){
393 reply
->hdr
.ac_errno
= errno
;
397 reply
->bufs
.buflen
[0] = privkey
->l
;
398 reply
->hdr
.ac_len
= sizeof(*reply
) + privkey
->l
;
399 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
401 plog(LLV_ERROR
, LOCATION
, NULL
,
402 "Cannot allocate reply buffer: %s\n",
407 memcpy(reply
+ 1, privkey
->v
, privkey
->l
);
412 case PRIVSEP_SCRIPT_EXEC
: {
421 * First count the bufs, and make sure strings
422 * are NULL terminated.
424 * We expect: script, name, envp[], void
426 if (safety_check(combuf
, 0) != 0)
428 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
429 count
++; /* script */
433 for (; count
< PRIVSEP_NBUF_MAX
; count
++) {
434 if (combuf
->bufs
.buflen
[count
] == 0)
437 [combuf
->bufs
.buflen
[count
] - 1] = '\0';
441 /* count a void buf and perform safety check */
443 if (count
>= PRIVSEP_NBUF_MAX
) {
444 plog(LLV_ERROR
, LOCATION
, NULL
,
445 "privsep_script_exec: too many args\n");
451 * Allocate the arrays for envp
453 envp
= racoon_malloc((envc
+ 1) * sizeof(char *));
455 plog(LLV_ERROR
, LOCATION
, NULL
,
456 "cannot allocate memory: %s\n",
460 bzero(envp
, (envc
+ 1) * sizeof(char *));
464 * Populate script, name and envp
467 script
= bufs
[count
++];
469 if (combuf
->bufs
.buflen
[count
] != sizeof(name
)) {
470 plog(LLV_ERROR
, LOCATION
, NULL
,
471 "privsep_script_exec: corrupted message\n");
474 memcpy((char *)&name
, bufs
[count
++], sizeof(name
));
476 for (i
= 0; combuf
->bufs
.buflen
[count
]; count
++)
477 envp
[i
++] = bufs
[count
];
481 plog(LLV_DEBUG
, LOCATION
, NULL
,
482 "script_exec(\"%s\", %d, %p)\n",
486 * Check env for dangerous variables
487 * Check script path and name
488 * Perform fork and execve
490 if ((unsafe_env(envp
) == 0) &&
491 (unknown_name(name
) == 0) &&
492 (unsafe_path(script
, LC_PATHTYPE_SCRIPT
) == 0))
493 (void)script_exec(script
, name
, envp
);
495 plog(LLV_ERROR
, LOCATION
, NULL
,
496 "privsep_script_exec: "
497 "unsafe script \"%s\"\n", script
);
503 case PRIVSEP_GETPSK
: {
507 /* Make sure the string is NULL terminated */
508 if (safety_check(combuf
, 0) != 0)
510 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
512 if (combuf
->bufs
.buflen
[1] != sizeof(keylen
)) {
513 plog(LLV_ERROR
, LOCATION
, NULL
,
514 "privsep_getpsk: corrupted message\n");
517 memcpy(&keylen
, bufs
[1], sizeof(keylen
));
519 plog(LLV_DEBUG
, LOCATION
, NULL
,
520 "getpsk(\"%s\", %d)\n", bufs
[0], keylen
);
522 if ((psk
= getpsk(bufs
[0], keylen
)) == NULL
) {
523 reply
->hdr
.ac_errno
= errno
;
527 reply
->bufs
.buflen
[0] = psk
->l
;
528 reply
->hdr
.ac_len
= sizeof(*reply
) + psk
->l
;
529 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
531 plog(LLV_ERROR
, LOCATION
, NULL
,
532 "Cannot allocate reply buffer: %s\n",
537 memcpy(reply
+ 1, psk
->v
, psk
->l
);
542 case PRIVSEP_SOCKET
: {
543 struct socket_args socket_args
;
546 /* Make sure the string is NULL terminated */
547 if (safety_check(combuf
, 0) != 0)
550 if (combuf
->bufs
.buflen
[0] !=
551 sizeof(struct socket_args
)) {
552 plog(LLV_ERROR
, LOCATION
, NULL
,
553 "privsep_socket: corrupted message\n");
556 memcpy(&socket_args
, bufs
[0],
557 sizeof(struct socket_args
));
559 if (socket_args
.domain
!= PF_INET
&&
560 socket_args
.domain
!= PF_INET6
) {
561 plog(LLV_ERROR
, LOCATION
, NULL
,
563 "unauthorized domain (%d)\n",
568 if ((s
= socket(socket_args
.domain
, socket_args
.type
,
569 socket_args
.protocol
)) == -1) {
570 reply
->hdr
.ac_errno
= errno
;
574 if (send_fd(privsep_sock
[0], s
) < 0) {
575 plog(LLV_ERROR
, LOCATION
, NULL
,
576 "privsep_socket: send_fd failed\n");
586 struct bind_args bind_args
;
589 /* Make sure the string is NULL terminated */
590 if (safety_check(combuf
, 0) != 0)
593 if (combuf
->bufs
.buflen
[0] !=
594 sizeof(struct bind_args
)) {
595 plog(LLV_ERROR
, LOCATION
, NULL
,
596 "privsep_bind: corrupted message\n");
599 memcpy(&bind_args
, bufs
[0], sizeof(struct bind_args
));
601 if (combuf
->bufs
.buflen
[1] != bind_args
.addrlen
) {
602 plog(LLV_ERROR
, LOCATION
, NULL
,
603 "privsep_bind: corrupted message\n");
606 bind_args
.addr
= (const struct sockaddr
*)bufs
[1];
608 if ((bind_args
.s
= rec_fd(privsep_sock
[0])) < 0) {
609 plog(LLV_ERROR
, LOCATION
, NULL
,
610 "privsep_bind: rec_fd failed\n");
614 port
= extract_port(bind_args
.addr
);
615 if (port
!= PORT_ISAKMP
&& port
!= PORT_ISAKMP_NATT
&&
616 port
!= lcconf
->port_isakmp
&&
617 port
!= lcconf
->port_isakmp_natt
) {
618 plog(LLV_ERROR
, LOCATION
, NULL
,
620 "unauthorized port (%d)\n",
626 err
= bind(bind_args
.s
, bind_args
.addr
,
630 reply
->hdr
.ac_errno
= errno
;
636 case PRIVSEP_SETSOCKOPTS
: {
637 struct sockopt_args sockopt_args
;
640 /* Make sure the string is NULL terminated */
641 if (safety_check(combuf
, 0) != 0)
644 if (combuf
->bufs
.buflen
[0] !=
645 sizeof(struct sockopt_args
)) {
646 plog(LLV_ERROR
, LOCATION
, NULL
,
647 "privsep_setsockopt: "
648 "corrupted message\n");
651 memcpy(&sockopt_args
, bufs
[0],
652 sizeof(struct sockopt_args
));
654 if (combuf
->bufs
.buflen
[1] != sockopt_args
.optlen
) {
655 plog(LLV_ERROR
, LOCATION
, NULL
,
656 "privsep_setsockopt: corrupted message\n");
659 sockopt_args
.optval
= bufs
[1];
661 if (sockopt_args
.optname
!=
662 (sockopt_args
.level
==
663 IPPROTO_IP
? IP_IPSEC_POLICY
:
664 IPV6_IPSEC_POLICY
)) {
665 plog(LLV_ERROR
, LOCATION
, NULL
,
666 "privsep_setsockopt: "
667 "unauthorized option (%d)\n",
668 sockopt_args
.optname
);
672 if ((sockopt_args
.s
= rec_fd(privsep_sock
[0])) < 0) {
673 plog(LLV_ERROR
, LOCATION
, NULL
,
674 "privsep_setsockopt: rec_fd failed\n");
678 err
= setsockopt(sockopt_args
.s
,
680 sockopt_args
.optname
,
682 sockopt_args
.optlen
);
684 reply
->hdr
.ac_errno
= errno
;
686 close(sockopt_args
.s
);
691 case PRIVSEP_ACCOUNTING_SYSTEM
: {
695 struct sockaddr
*raddr
;
697 if (safety_check(combuf
, 0) != 0)
699 if (safety_check(combuf
, 1) != 0)
701 if (safety_check(combuf
, 2) != 0)
703 if (safety_check(combuf
, 3) != 0)
706 memcpy(&port
, bufs
[0], sizeof(port
));
707 raddr
= (struct sockaddr
*)bufs
[1];
709 bufs
[2][combuf
->bufs
.buflen
[2] - 1] = '\0';
710 memcpy(&inout
, bufs
[3], sizeof(port
));
712 if (port_check(port
) != 0)
715 plog(LLV_DEBUG
, LOCATION
, NULL
,
716 "accounting_system(%d, %s, %s)\n",
717 port
, saddr2str(raddr
), bufs
[2]);
720 if (isakmp_cfg_accounting_system(port
,
721 raddr
, bufs
[2], inout
) != 0) {
723 reply
->hdr
.ac_errno
= EINVAL
;
725 reply
->hdr
.ac_errno
= errno
;
729 case PRIVSEP_XAUTH_LOGIN_SYSTEM
: {
730 if (safety_check(combuf
, 0) != 0)
732 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
734 if (safety_check(combuf
, 1) != 0)
736 bufs
[1][combuf
->bufs
.buflen
[1] - 1] = '\0';
738 plog(LLV_DEBUG
, LOCATION
, NULL
,
739 "xauth_login_system(\"%s\", <password>)\n",
743 if (xauth_login_system(bufs
[0], bufs
[1]) != 0) {
745 reply
->hdr
.ac_errno
= EINVAL
;
747 reply
->hdr
.ac_errno
= errno
;
752 case PRIVSEP_ACCOUNTING_PAM
: {
757 if (safety_check(combuf
, 0) != 0)
759 if (safety_check(combuf
, 1) != 0)
761 if (safety_check(combuf
, 2) != 0)
764 memcpy(&port
, bufs
[0], sizeof(port
));
765 memcpy(&inout
, bufs
[1], sizeof(inout
));
766 memcpy(&pool_size
, bufs
[2], sizeof(pool_size
));
768 if (pool_size
!= isakmp_cfg_config
.pool_size
)
769 if (isakmp_cfg_resize_pool(pool_size
) != 0)
772 if (port_check(port
) != 0)
775 plog(LLV_DEBUG
, LOCATION
, NULL
,
776 "isakmp_cfg_accounting_pam(%d, %d)\n",
780 if (isakmp_cfg_accounting_pam(port
, inout
) != 0) {
782 reply
->hdr
.ac_errno
= EINVAL
;
784 reply
->hdr
.ac_errno
= errno
;
789 case PRIVSEP_XAUTH_LOGIN_PAM
: {
792 struct sockaddr
*raddr
;
794 if (safety_check(combuf
, 0) != 0)
796 if (safety_check(combuf
, 1) != 0)
798 if (safety_check(combuf
, 2) != 0)
800 if (safety_check(combuf
, 3) != 0)
802 if (safety_check(combuf
, 4) != 0)
805 memcpy(&port
, bufs
[0], sizeof(port
));
806 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
807 raddr
= (struct sockaddr
*)bufs
[2];
809 bufs
[3][combuf
->bufs
.buflen
[3] - 1] = '\0';
810 bufs
[4][combuf
->bufs
.buflen
[4] - 1] = '\0';
812 if (pool_size
!= isakmp_cfg_config
.pool_size
)
813 if (isakmp_cfg_resize_pool(pool_size
) != 0)
816 if (port_check(port
) != 0)
819 plog(LLV_DEBUG
, LOCATION
, NULL
,
820 "xauth_login_pam(%d, %s, \"%s\", <password>)\n",
821 port
, saddr2str(raddr
), bufs
[3]);
824 if (xauth_login_pam(port
,
825 raddr
, bufs
[3], bufs
[4]) != 0) {
827 reply
->hdr
.ac_errno
= EINVAL
;
829 reply
->hdr
.ac_errno
= errno
;
834 case PRIVSEP_CLEANUP_PAM
: {
838 if (safety_check(combuf
, 0) != 0)
840 if (safety_check(combuf
, 1) != 0)
843 memcpy(&port
, bufs
[0], sizeof(port
));
844 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
846 if (pool_size
!= isakmp_cfg_config
.pool_size
)
847 if (isakmp_cfg_resize_pool(pool_size
) != 0)
850 if (port_check(port
) != 0)
853 plog(LLV_DEBUG
, LOCATION
, NULL
,
854 "cleanup_pam(%d)\n", port
);
857 reply
->hdr
.ac_errno
= 0;
861 #endif /* HAVE_LIBPAM */
862 #endif /* ENABLE_HYBRID */
865 plog(LLV_ERROR
, LOCATION
, NULL
,
866 "unexpected privsep command %d\n",
872 /* This frees reply */
873 if (privsep_send(privsep_sock
[0],
874 reply
, reply
->hdr
.ac_len
) != 0) {
883 plog(LLV_INFO
, LOCATION
, NULL
,
884 "racoon privileged process %d terminated\n", getpid());
890 privsep_eay_get_pkcs1privkey(path
)
894 struct privsep_com_msg
*msg
;
898 return eay_get_pkcs1privkey(path
);
900 len
= sizeof(*msg
) + strlen(path
) + 1;
901 if ((msg
= racoon_malloc(len
)) == NULL
) {
902 plog(LLV_ERROR
, LOCATION
, NULL
,
903 "Cannot allocate memory: %s\n", strerror(errno
));
907 msg
->hdr
.ac_cmd
= PRIVSEP_EAY_GET_PKCS1PRIVKEY
;
908 msg
->hdr
.ac_len
= len
;
909 msg
->bufs
.buflen
[0] = len
- sizeof(*msg
);
910 memcpy(msg
+ 1, path
, msg
->bufs
.buflen
[0]);
912 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
915 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
918 if (msg
->hdr
.ac_errno
!= 0) {
919 errno
= msg
->hdr
.ac_errno
;
923 if ((privkey
= vmalloc(len
- sizeof(*msg
))) == NULL
)
926 memcpy(privkey
->v
, msg
+ 1, privkey
->l
);
936 privsep_script_exec(script
, name
, envp
)
945 struct privsep_com_msg
*msg
;
948 return script_exec(script
, name
, envp
);
950 if ((msg
= racoon_malloc(sizeof(*msg
))) == NULL
) {
951 plog(LLV_ERROR
, LOCATION
, NULL
,
952 "Cannot allocate memory: %s\n", strerror(errno
));
956 bzero(msg
, sizeof(*msg
));
957 msg
->hdr
.ac_cmd
= PRIVSEP_SCRIPT_EXEC
;
958 msg
->hdr
.ac_len
= sizeof(*msg
);
962 * script, name, envp[0], ... envp[N], void
966 * Safety check on the counts: PRIVSEP_NBUF_MAX max
969 count
++; /* script */
971 for (c
= envp
; *c
; c
++) /* envp */
975 if (count
> PRIVSEP_NBUF_MAX
) {
976 plog(LLV_ERROR
, LOCATION
, NULL
, "Unexpected error: "
977 "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
987 msg
->bufs
.buflen
[count
] = strlen(script
) + 1; /* script */
988 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
990 msg
->bufs
.buflen
[count
] = sizeof(name
); /* name */
991 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
993 for (c
= envp
; *c
; c
++) { /* envp */
994 msg
->bufs
.buflen
[count
] = strlen(*c
) + 1;
995 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
998 msg
->bufs
.buflen
[count
] = 0; /* void */
999 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
1001 if ((msg
= racoon_realloc(msg
, msg
->hdr
.ac_len
)) == NULL
) {
1002 plog(LLV_ERROR
, LOCATION
, NULL
,
1003 "Cannot allocate memory: %s\n", strerror(errno
));
1010 data
= (char *)(msg
+ 1);
1013 memcpy(data
, (char *)script
, msg
->bufs
.buflen
[count
]); /* script */
1014 data
+= msg
->bufs
.buflen
[count
++];
1016 memcpy(data
, (char *)&name
, msg
->bufs
.buflen
[count
]); /* name */
1017 data
+= msg
->bufs
.buflen
[count
++];
1019 for (c
= envp
; *c
; c
++) { /* envp */
1020 memcpy(data
, *c
, msg
->bufs
.buflen
[count
]);
1021 data
+= msg
->bufs
.buflen
[count
++];
1029 if (privsep_send(privsep_sock
[1], msg
, msg
->hdr
.ac_len
) != 0)
1032 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1035 if (msg
->hdr
.ac_errno
!= 0) {
1036 errno
= msg
->hdr
.ac_errno
;
1046 privsep_getpsk(str
, keylen
)
1051 struct privsep_com_msg
*msg
;
1057 return getpsk(str
, keylen
);
1059 len
= sizeof(*msg
) + strlen(str
) + 1 + sizeof(keylen
);
1060 if ((msg
= racoon_malloc(len
)) == NULL
) {
1061 plog(LLV_ERROR
, LOCATION
, NULL
,
1062 "Cannot allocate memory: %s\n", strerror(errno
));
1066 msg
->hdr
.ac_cmd
= PRIVSEP_GETPSK
;
1067 msg
->hdr
.ac_len
= len
;
1069 data
= (char *)(msg
+ 1);
1070 msg
->bufs
.buflen
[0] = strlen(str
) + 1;
1071 memcpy(data
, str
, msg
->bufs
.buflen
[0]);
1073 data
+= msg
->bufs
.buflen
[0];
1074 msg
->bufs
.buflen
[1] = sizeof(keylen
);
1075 memcpy(data
, &keylen
, sizeof(keylen
));
1077 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1080 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1083 if (msg
->hdr
.ac_errno
!= 0) {
1084 errno
= msg
->hdr
.ac_errno
;
1088 if ((psk
= vmalloc(len
- sizeof(*msg
))) == NULL
)
1091 memcpy(psk
->v
, msg
+ 1, psk
->l
);
1101 * Create a privileged socket. On BSD systems a socket obtains special
1102 * capabilities if it is created by root; setsockopt(IP_IPSEC_POLICY) will
1103 * succeed but will be ineffective if performed on an unprivileged socket.
1106 privsep_socket(domain
, type
, protocol
)
1111 struct privsep_com_msg
*msg
;
1114 struct socket_args socket_args
;
1115 int s
, saved_errno
= 0;
1118 return socket(domain
, type
, protocol
);
1120 len
= sizeof(*msg
) + sizeof(socket_args
);
1122 if ((msg
= racoon_malloc(len
)) == NULL
) {
1123 plog(LLV_ERROR
, LOCATION
, NULL
,
1124 "Cannot allocate memory: %s\n", strerror(errno
));
1128 msg
->hdr
.ac_cmd
= PRIVSEP_SOCKET
;
1129 msg
->hdr
.ac_len
= len
;
1131 socket_args
.domain
= domain
;
1132 socket_args
.type
= type
;
1133 socket_args
.protocol
= protocol
;
1135 data
= (char *)(msg
+ 1);
1136 msg
->bufs
.buflen
[0] = sizeof(socket_args
);
1137 memcpy(data
, &socket_args
, msg
->bufs
.buflen
[0]);
1140 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1143 /* Get the privileged socket descriptor from the privileged process. */
1144 if ((s
= rec_fd(privsep_sock
[1])) == -1)
1147 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1150 if (msg
->hdr
.ac_errno
!= 0) {
1151 errno
= msg
->hdr
.ac_errno
;
1164 * Bind() a socket to a port. This works just like regular bind(), except that
1165 * if you want to bind to the designated isakmp ports and you don't have the
1166 * privilege to do so, it will ask a privileged process to do it.
1169 privsep_bind(s
, addr
, addrlen
)
1171 const struct sockaddr
*addr
;
1174 struct privsep_com_msg
*msg
;
1177 struct bind_args bind_args
;
1178 int err
, saved_errno
= 0;
1180 err
= bind(s
, addr
, addrlen
);
1181 if ((err
== 0) || (saved_errno
= errno
) != EACCES
|| geteuid() == 0) {
1183 plog(LLV_ERROR
, LOCATION
, NULL
,
1184 "privsep_bind (%s) = %d\n", strerror(saved_errno
), err
);
1185 errno
= saved_errno
;
1189 len
= sizeof(*msg
) + sizeof(bind_args
) + addrlen
;
1191 if ((msg
= racoon_malloc(len
)) == NULL
) {
1192 plog(LLV_ERROR
, LOCATION
, NULL
,
1193 "Cannot allocate memory: %s\n", strerror(errno
));
1197 msg
->hdr
.ac_cmd
= PRIVSEP_BIND
;
1198 msg
->hdr
.ac_len
= len
;
1201 bind_args
.addr
= NULL
;
1202 bind_args
.addrlen
= addrlen
;
1204 data
= (char *)(msg
+ 1);
1205 msg
->bufs
.buflen
[0] = sizeof(bind_args
);
1206 memcpy(data
, &bind_args
, msg
->bufs
.buflen
[0]);
1208 data
+= msg
->bufs
.buflen
[0];
1209 msg
->bufs
.buflen
[1] = addrlen
;
1210 memcpy(data
, addr
, addrlen
);
1213 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1216 /* Send the socket descriptor to the privileged process. */
1217 if (send_fd(privsep_sock
[1], s
) < 0)
1220 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1223 if (msg
->hdr
.ac_errno
!= 0) {
1224 errno
= msg
->hdr
.ac_errno
;
1237 * Set socket options. This works just like regular setsockopt(), except that
1238 * if you want to change IP_IPSEC_POLICY or IPV6_IPSEC_POLICY and you don't
1239 * have the privilege to do so, it will ask a privileged process to do it.
1242 privsep_setsockopt(s
, level
, optname
, optval
, optlen
)
1249 struct privsep_com_msg
*msg
;
1252 struct sockopt_args sockopt_args
;
1253 int err
, saved_errno
= 0;
1255 if ((err
= setsockopt(s
, level
, optname
, optval
, optlen
) == 0) ||
1256 (saved_errno
= errno
) != EACCES
||
1259 plog(LLV_ERROR
, LOCATION
, NULL
,
1260 "privsep_setsockopt (%s)\n",
1261 strerror(saved_errno
));
1263 errno
= saved_errno
;
1267 len
= sizeof(*msg
) + sizeof(sockopt_args
) + optlen
;
1269 if ((msg
= racoon_malloc(len
)) == NULL
) {
1270 plog(LLV_ERROR
, LOCATION
, NULL
,
1271 "Cannot allocate memory: %s\n", strerror(errno
));
1275 msg
->hdr
.ac_cmd
= PRIVSEP_SETSOCKOPTS
;
1276 msg
->hdr
.ac_len
= len
;
1278 sockopt_args
.s
= -1;
1279 sockopt_args
.level
= level
;
1280 sockopt_args
.optname
= optname
;
1281 sockopt_args
.optval
= NULL
;
1282 sockopt_args
.optlen
= optlen
;
1284 data
= (char *)(msg
+ 1);
1285 msg
->bufs
.buflen
[0] = sizeof(sockopt_args
);
1286 memcpy(data
, &sockopt_args
, msg
->bufs
.buflen
[0]);
1288 data
+= msg
->bufs
.buflen
[0];
1289 msg
->bufs
.buflen
[1] = optlen
;
1290 memcpy(data
, optval
, optlen
);
1293 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1296 if (send_fd(privsep_sock
[1], s
) < 0)
1299 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0) {
1300 plog(LLV_ERROR
, LOCATION
, NULL
,
1301 "privsep_recv failed\n");
1305 if (msg
->hdr
.ac_errno
!= 0) {
1306 errno
= msg
->hdr
.ac_errno
;
1318 #ifdef ENABLE_HYBRID
1320 privsep_xauth_login_system(usr
, pwd
)
1324 struct privsep_com_msg
*msg
;
1329 return xauth_login_system(usr
, pwd
);
1331 len
= sizeof(*msg
) + strlen(usr
) + 1 + strlen(pwd
) + 1;
1332 if ((msg
= racoon_malloc(len
)) == NULL
) {
1333 plog(LLV_ERROR
, LOCATION
, NULL
,
1334 "Cannot allocate memory: %s\n", strerror(errno
));
1338 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_SYSTEM
;
1339 msg
->hdr
.ac_len
= len
;
1341 data
= (char *)(msg
+ 1);
1342 msg
->bufs
.buflen
[0] = strlen(usr
) + 1;
1343 memcpy(data
, usr
, msg
->bufs
.buflen
[0]);
1344 data
+= msg
->bufs
.buflen
[0];
1346 msg
->bufs
.buflen
[1] = strlen(pwd
) + 1;
1347 memcpy(data
, pwd
, msg
->bufs
.buflen
[1]);
1350 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1353 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1356 if (msg
->hdr
.ac_errno
!= 0) {
1366 privsep_accounting_system(port
, raddr
, usr
, inout
)
1368 struct sockaddr
*raddr
;
1372 struct privsep_com_msg
*msg
;
1378 return isakmp_cfg_accounting_system(port
, raddr
,
1383 + sysdep_sa_len(raddr
)
1387 if ((msg
= racoon_malloc(len
)) == NULL
) {
1388 plog(LLV_ERROR
, LOCATION
, NULL
,
1389 "Cannot allocate memory: %s\n", strerror(errno
));
1393 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_SYSTEM
;
1394 msg
->hdr
.ac_len
= len
;
1395 msg
->bufs
.buflen
[0] = sizeof(port
);
1396 msg
->bufs
.buflen
[1] = sysdep_sa_len(raddr
);
1397 msg
->bufs
.buflen
[2] = strlen(usr
) + 1;
1398 msg
->bufs
.buflen
[3] = sizeof(inout
);
1400 data
= (char *)(msg
+ 1);
1401 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1403 data
+= msg
->bufs
.buflen
[0];
1404 memcpy(data
, raddr
, msg
->bufs
.buflen
[1]);
1406 data
+= msg
->bufs
.buflen
[1];
1407 memcpy(data
, usr
, msg
->bufs
.buflen
[2]);
1409 data
+= msg
->bufs
.buflen
[2];
1410 memcpy(data
, &inout
, msg
->bufs
.buflen
[3]);
1413 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1416 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1419 if (msg
->hdr
.ac_errno
!= 0) {
1420 errno
= msg
->hdr
.ac_errno
;
1436 if ((port
< 0) || (port
>= isakmp_cfg_config
.pool_size
)) {
1437 plog(LLV_ERROR
, LOCATION
, NULL
,
1438 "privsep: port %d outside of allowed range [0,%zu]\n",
1439 port
, isakmp_cfg_config
.pool_size
- 1);
1448 safety_check(msg
, index
)
1449 struct privsep_com_msg
*msg
;
1452 if (index
>= PRIVSEP_NBUF_MAX
) {
1453 plog(LLV_ERROR
, LOCATION
, NULL
,
1454 "privsep: Corrupted message, too many buffers\n");
1458 if (msg
->bufs
.buflen
[index
] == 0) {
1459 plog(LLV_ERROR
, LOCATION
, NULL
,
1460 "privsep: Corrupted message, unexpected void buffer\n");
1468 * Filter unsafe environement variables
1476 char *const bad_env
[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL
};
1478 for (e
= envp
; *e
; e
++) {
1479 for (be
= bad_env
; *be
; be
++) {
1480 if (strncmp(*e
, *be
, strlen(*be
)) == 0) {
1488 plog(LLV_ERROR
, LOCATION
, NULL
,
1489 "privsep_script_exec: unsafe environement variable\n");
1497 unsafe_path(script
, pathtype
)
1502 char rpath
[MAXPATHLEN
+ 1];
1508 path
= lcconf
->pathinfo
[pathtype
];
1510 /* No path was given for scripts: skip the check */
1514 if (realpath(script
, rpath
) == NULL
) {
1515 plog(LLV_ERROR
, LOCATION
, NULL
,
1516 "script path \"%s\" is invalid\n", script
);
1521 if (strncmp(path
, rpath
, len
) != 0)
1531 if ((name
< 0) || (name
> SCRIPT_MAX
)) {
1532 plog(LLV_ERROR
, LOCATION
, NULL
,
1533 "privsep_script_exec: unsafe name index\n");
1540 /* Receive a file descriptor through the argument socket */
1546 struct cmsghdr
*cmsg
;
1552 iov
.iov_base
= iobuf
;
1555 if (sizeof(cmsbuf
) < CMSG_SPACE(sizeof(fd
))) {
1556 plog(LLV_ERROR
, LOCATION
, NULL
,
1557 "send_fd: buffer size too small\n");
1560 bzero(&msg
, sizeof(msg
));
1561 msg
.msg_name
= NULL
;
1562 msg
.msg_namelen
= 0;
1565 msg
.msg_control
= cmsbuf
;
1566 msg
.msg_controllen
= CMSG_SPACE(sizeof(fd
));
1568 if (recvmsg(s
, &msg
, MSG_WAITALL
) == -1)
1571 cmsg
= CMSG_FIRSTHDR(&msg
);
1572 return *(int *)CMSG_DATA(cmsg
);
1575 /* Send the file descriptor fd through the argument socket s */
1582 struct cmsghdr
*cmsg
;
1589 if (sizeof(cmsbuf
) < CMSG_SPACE(sizeof(fd
))) {
1590 plog(LLV_ERROR
, LOCATION
, NULL
,
1591 "send_fd: buffer size too small\n");
1594 bzero(&msg
, sizeof(msg
));
1595 msg
.msg_name
= NULL
;
1596 msg
.msg_namelen
= 0;
1599 msg
.msg_control
= cmsbuf
;
1600 msg
.msg_controllen
= CMSG_SPACE(sizeof(fd
));
1603 cmsg
= CMSG_FIRSTHDR(&msg
);
1604 cmsg
->cmsg_level
= SOL_SOCKET
;
1605 cmsg
->cmsg_type
= SCM_RIGHTS
;
1606 cmsg
->cmsg_len
= CMSG_LEN(sizeof(fd
));
1607 *(int *)CMSG_DATA(cmsg
) = fd
;
1608 msg
.msg_controllen
= cmsg
->cmsg_len
;
1610 if (sendmsg(s
, &msg
, 0) == -1)
1618 privsep_accounting_pam(port
, inout
)
1622 struct privsep_com_msg
*msg
;
1626 int *pool_size_data
;
1630 return isakmp_cfg_accounting_pam(port
, inout
);
1635 + sizeof(isakmp_cfg_config
.pool_size
);
1637 if ((msg
= racoon_malloc(len
)) == NULL
) {
1638 plog(LLV_ERROR
, LOCATION
, NULL
,
1639 "Cannot allocate memory: %s\n", strerror(errno
));
1643 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_PAM
;
1644 msg
->hdr
.ac_len
= len
;
1645 msg
->bufs
.buflen
[0] = sizeof(port
);
1646 msg
->bufs
.buflen
[1] = sizeof(inout
);
1647 msg
->bufs
.buflen
[2] = sizeof(isakmp_cfg_config
.pool_size
);
1649 port_data
= (int *)(msg
+ 1);
1650 inout_data
= (int *)(port_data
+ 1);
1651 pool_size_data
= (int *)(inout_data
+ 1);
1654 *inout_data
= inout
;
1655 *pool_size_data
= isakmp_cfg_config
.pool_size
;
1658 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1661 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1664 if (msg
->hdr
.ac_errno
!= 0) {
1665 errno
= msg
->hdr
.ac_errno
;
1678 privsep_xauth_login_pam(port
, raddr
, usr
, pwd
)
1680 struct sockaddr
*raddr
;
1684 struct privsep_com_msg
*msg
;
1690 return xauth_login_pam(port
, raddr
, usr
, pwd
);
1694 + sizeof(isakmp_cfg_config
.pool_size
)
1695 + sysdep_sa_len(raddr
)
1699 if ((msg
= racoon_malloc(len
)) == NULL
) {
1700 plog(LLV_ERROR
, LOCATION
, NULL
,
1701 "Cannot allocate memory: %s\n", strerror(errno
));
1705 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_PAM
;
1706 msg
->hdr
.ac_len
= len
;
1707 msg
->bufs
.buflen
[0] = sizeof(port
);
1708 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1709 msg
->bufs
.buflen
[2] = sysdep_sa_len(raddr
);
1710 msg
->bufs
.buflen
[3] = strlen(usr
) + 1;
1711 msg
->bufs
.buflen
[4] = strlen(pwd
) + 1;
1713 data
= (char *)(msg
+ 1);
1714 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1716 data
+= msg
->bufs
.buflen
[0];
1717 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1719 data
+= msg
->bufs
.buflen
[1];
1720 memcpy(data
, raddr
, msg
->bufs
.buflen
[2]);
1722 data
+= msg
->bufs
.buflen
[2];
1723 memcpy(data
, usr
, msg
->bufs
.buflen
[3]);
1725 data
+= msg
->bufs
.buflen
[3];
1726 memcpy(data
, pwd
, msg
->bufs
.buflen
[4]);
1729 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1732 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1735 if (msg
->hdr
.ac_errno
!= 0) {
1736 errno
= msg
->hdr
.ac_errno
;
1749 privsep_cleanup_pam(port
)
1752 struct privsep_com_msg
*msg
;
1758 return cleanup_pam(port
);
1762 + sizeof(isakmp_cfg_config
.pool_size
);
1764 if ((msg
= racoon_malloc(len
)) == NULL
) {
1765 plog(LLV_ERROR
, LOCATION
, NULL
,
1766 "Cannot allocate memory: %s\n", strerror(errno
));
1770 msg
->hdr
.ac_cmd
= PRIVSEP_CLEANUP_PAM
;
1771 msg
->hdr
.ac_len
= len
;
1772 msg
->bufs
.buflen
[0] = sizeof(port
);
1773 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1775 data
= (char *)(msg
+ 1);
1776 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1778 data
+= msg
->bufs
.buflen
[0];
1779 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1782 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1785 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1788 if (msg
->hdr
.ac_errno
!= 0)
1789 errno
= msg
->hdr
.ac_errno
;