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"
69 static int privsep_sock
[2] = { -1, -1 };
71 static int privsep_recv(int, struct privsep_com_msg
**, size_t *);
72 static int privsep_send(int, struct privsep_com_msg
*, size_t);
73 static int safety_check(struct privsep_com_msg
*, int i
);
74 static int port_check(int);
75 static int unsafe_env(char *const *);
76 static int unknown_name(int);
77 static int unsafe_path(char *, 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 inaccessible to unpriv
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 cert \"%s\"\n", bufs
[0]);
353 plog(LLV_DEBUG
, LOCATION
, NULL
,
354 "eay_get_pkcs1privkey(\"%s\")\n", bufs
[0]);
356 if ((privkey
= eay_get_pkcs1privkey(bufs
[0])) == NULL
){
357 reply
->hdr
.ac_errno
= errno
;
361 reply
->bufs
.buflen
[0] = privkey
->l
;
362 reply
->hdr
.ac_len
= sizeof(*reply
) + privkey
->l
;
363 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
365 plog(LLV_ERROR
, LOCATION
, NULL
,
366 "Cannot allocate reply buffer: %s\n",
371 memcpy(reply
+ 1, privkey
->v
, privkey
->l
);
376 case PRIVSEP_SCRIPT_EXEC
: {
385 * First count the bufs, and make sure strings
386 * are NULL terminated.
388 * We expect: script, name, envp[], void
390 if (safety_check(combuf
, 0) != 0)
392 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
393 count
++; /* script */
396 for (; count
< PRIVSEP_NBUF_MAX
; count
++) {
397 if (combuf
->bufs
.buflen
[count
] == 0)
400 [combuf
->bufs
.buflen
[count
] - 1] = '\0';
404 /* count a void buf and perform safety check */
406 if (count
>= PRIVSEP_NBUF_MAX
) {
407 plog(LLV_ERROR
, LOCATION
, NULL
,
408 "privsep_script_exec: too many args\n");
414 * Allocate the arrays for envp
416 envp
= racoon_malloc((envc
+ 1) * sizeof(char *));
418 plog(LLV_ERROR
, LOCATION
, NULL
,
419 "cannot allocate memory: %s\n",
423 bzero(envp
, (envc
+ 1) * sizeof(char *));
427 * Populate script, name and envp
430 script
= bufs
[count
++];
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
];
444 plog(LLV_DEBUG
, LOCATION
, NULL
,
445 "script_exec(\"%s\", %d, %p)\n",
449 * Check env for dangerous variables
450 * Check script path and name
451 * Perform fork and execve
453 if ((unsafe_env(envp
) == 0) &&
454 (unknown_name(name
) == 0) &&
455 (unsafe_path(script
, LC_PATHTYPE_SCRIPT
) == 0))
456 (void)script_exec(script
, name
, envp
);
458 plog(LLV_ERROR
, LOCATION
, NULL
,
459 "privsep_script_exec: "
460 "unsafe script \"%s\"\n", script
);
466 case PRIVSEP_GETPSK
: {
470 /* Make sure the string is NULL terminated */
471 if (safety_check(combuf
, 0) != 0)
473 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
475 if (combuf
->bufs
.buflen
[1] != sizeof(keylen
)) {
476 plog(LLV_ERROR
, LOCATION
, NULL
,
477 "privsep_getpsk: corrupted message\n");
480 memcpy(&keylen
, bufs
[1], sizeof(keylen
));
482 plog(LLV_DEBUG
, LOCATION
, NULL
,
483 "getpsk(\"%s\", %d)\n", bufs
[0], keylen
);
485 if ((psk
= getpsk(bufs
[0], keylen
)) == NULL
) {
486 reply
->hdr
.ac_errno
= errno
;
490 reply
->bufs
.buflen
[0] = psk
->l
;
491 reply
->hdr
.ac_len
= sizeof(*reply
) + psk
->l
;
492 reply
= racoon_realloc(reply
, reply
->hdr
.ac_len
);
494 plog(LLV_ERROR
, LOCATION
, NULL
,
495 "Cannot allocate reply buffer: %s\n",
500 memcpy(reply
+ 1, psk
->v
, psk
->l
);
506 case PRIVSEP_ACCOUNTING_SYSTEM
: {
510 struct sockaddr
*raddr
;
512 if (safety_check(combuf
, 0) != 0)
514 if (safety_check(combuf
, 1) != 0)
516 if (safety_check(combuf
, 2) != 0)
518 if (safety_check(combuf
, 3) != 0)
521 memcpy(&port
, bufs
[0], sizeof(port
));
522 raddr
= (struct sockaddr
*)bufs
[1];
524 bufs
[2][combuf
->bufs
.buflen
[2] - 1] = '\0';
525 memcpy(&inout
, bufs
[3], sizeof(port
));
527 if (port_check(port
) != 0)
530 plog(LLV_DEBUG
, LOCATION
, NULL
,
531 "accounting_system(%d, %s, %s)\n",
532 port
, saddr2str(raddr
), bufs
[2]);
535 if (isakmp_cfg_accounting_system(port
,
536 raddr
, bufs
[2], inout
) != 0) {
538 reply
->hdr
.ac_errno
= EINVAL
;
540 reply
->hdr
.ac_errno
= errno
;
544 case PRIVSEP_XAUTH_LOGIN_SYSTEM
: {
545 if (safety_check(combuf
, 0) != 0)
547 bufs
[0][combuf
->bufs
.buflen
[0] - 1] = '\0';
549 if (safety_check(combuf
, 1) != 0)
551 bufs
[1][combuf
->bufs
.buflen
[1] - 1] = '\0';
553 plog(LLV_DEBUG
, LOCATION
, NULL
,
554 "xauth_login_system(\"%s\", <password>)\n",
558 if (xauth_login_system(bufs
[0], bufs
[1]) != 0) {
560 reply
->hdr
.ac_errno
= EINVAL
;
562 reply
->hdr
.ac_errno
= errno
;
567 case PRIVSEP_ACCOUNTING_PAM
: {
572 if (safety_check(combuf
, 0) != 0)
574 if (safety_check(combuf
, 1) != 0)
576 if (safety_check(combuf
, 2) != 0)
579 memcpy(&port
, bufs
[0], sizeof(port
));
580 memcpy(&inout
, bufs
[1], sizeof(inout
));
581 memcpy(&pool_size
, bufs
[2], sizeof(pool_size
));
583 if (pool_size
!= isakmp_cfg_config
.pool_size
)
584 if (isakmp_cfg_resize_pool(pool_size
) != 0)
587 if (port_check(port
) != 0)
590 plog(LLV_DEBUG
, LOCATION
, NULL
,
591 "isakmp_cfg_accounting_pam(%d, %d)\n",
595 if (isakmp_cfg_accounting_pam(port
, inout
) != 0) {
597 reply
->hdr
.ac_errno
= EINVAL
;
599 reply
->hdr
.ac_errno
= errno
;
604 case PRIVSEP_XAUTH_LOGIN_PAM
: {
607 struct sockaddr
*raddr
;
609 if (safety_check(combuf
, 0) != 0)
611 if (safety_check(combuf
, 1) != 0)
613 if (safety_check(combuf
, 2) != 0)
615 if (safety_check(combuf
, 3) != 0)
617 if (safety_check(combuf
, 4) != 0)
620 memcpy(&port
, bufs
[0], sizeof(port
));
621 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
622 raddr
= (struct sockaddr
*)bufs
[2];
624 bufs
[3][combuf
->bufs
.buflen
[3] - 1] = '\0';
625 bufs
[4][combuf
->bufs
.buflen
[4] - 1] = '\0';
627 if (pool_size
!= isakmp_cfg_config
.pool_size
)
628 if (isakmp_cfg_resize_pool(pool_size
) != 0)
631 if (port_check(port
) != 0)
634 plog(LLV_DEBUG
, LOCATION
, NULL
,
635 "xauth_login_pam(%d, %s, \"%s\", <password>)\n",
636 port
, saddr2str(raddr
), bufs
[3]);
639 if (xauth_login_pam(port
,
640 raddr
, bufs
[3], bufs
[4]) != 0) {
642 reply
->hdr
.ac_errno
= EINVAL
;
644 reply
->hdr
.ac_errno
= errno
;
649 case PRIVSEP_CLEANUP_PAM
: {
653 if (safety_check(combuf
, 0) != 0)
655 if (safety_check(combuf
, 1) != 0)
658 memcpy(&port
, bufs
[0], sizeof(port
));
659 memcpy(&pool_size
, bufs
[1], sizeof(pool_size
));
661 if (pool_size
!= isakmp_cfg_config
.pool_size
)
662 if (isakmp_cfg_resize_pool(pool_size
) != 0)
665 if (port_check(port
) != 0)
668 plog(LLV_DEBUG
, LOCATION
, NULL
,
669 "cleanup_pam(%d)\n", port
);
672 reply
->hdr
.ac_errno
= 0;
676 #endif /* HAVE_LIBPAM */
677 #endif /* ENABLE_HYBRID */
680 plog(LLV_ERROR
, LOCATION
, NULL
,
681 "unexpected privsep command %d\n",
687 /* This frees reply */
688 if (privsep_send(privsep_sock
[0],
689 reply
, reply
->hdr
.ac_len
) != 0)
696 plog(LLV_INFO
, LOCATION
, NULL
, "privsep exit\n");
702 privsep_eay_get_pkcs1privkey(path
)
706 struct privsep_com_msg
*msg
;
710 return eay_get_pkcs1privkey(path
);
712 len
= sizeof(*msg
) + strlen(path
) + 1;
713 if ((msg
= racoon_malloc(len
)) == NULL
) {
714 plog(LLV_ERROR
, LOCATION
, NULL
,
715 "Cannot allocate memory: %s\n", strerror(errno
));
719 msg
->hdr
.ac_cmd
= PRIVSEP_EAY_GET_PKCS1PRIVKEY
;
720 msg
->hdr
.ac_len
= len
;
721 msg
->bufs
.buflen
[0] = len
- sizeof(*msg
);
722 memcpy(msg
+ 1, path
, msg
->bufs
.buflen
[0]);
724 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
727 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
730 if (msg
->hdr
.ac_errno
!= 0) {
731 errno
= msg
->hdr
.ac_errno
;
735 if ((privkey
= vmalloc(len
- sizeof(*msg
))) == NULL
)
738 memcpy(privkey
->v
, msg
+ 1, privkey
->l
);
748 * No prigilege separation trick here, we just open PFKEY before
749 * dropping root privs and we remember it later.
751 static int pfkey_socket
= -1;
753 privsep_pfkey_open(void)
757 if (pfkey_socket
!= -1)
768 * Consequence of the above trickery: don't
769 * really close PFKEY as we never re-open it.
772 privsep_pfkey_close(ps
)
779 privsep_script_exec(script
, name
, envp
)
788 struct privsep_com_msg
*msg
;
791 return script_exec(script
, name
, envp
);
793 if ((msg
= racoon_malloc(sizeof(*msg
))) == NULL
) {
794 plog(LLV_ERROR
, LOCATION
, NULL
,
795 "Cannot allocate memory: %s\n", strerror(errno
));
799 bzero(msg
, sizeof(*msg
));
800 msg
->hdr
.ac_cmd
= PRIVSEP_SCRIPT_EXEC
;
801 msg
->hdr
.ac_len
= sizeof(*msg
);
805 * script, name, envp[0], ... envp[N], void
809 * Safety check on the counts: PRIVSEP_NBUF_MAX max
812 count
++; /* script */
814 for (c
= envp
; *c
; c
++) /* envp */
818 if (count
> PRIVSEP_NBUF_MAX
) {
819 plog(LLV_ERROR
, LOCATION
, NULL
, "Unexpected error: "
820 "privsep_script_exec count > PRIVSEP_NBUF_MAX\n");
830 msg
->bufs
.buflen
[count
] = strlen(script
) + 1; /* script */
831 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
833 msg
->bufs
.buflen
[count
] = sizeof(name
); /* name */
834 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
836 for (c
= envp
; *c
; c
++) { /* envp */
837 msg
->bufs
.buflen
[count
] = strlen(*c
) + 1;
838 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
841 msg
->bufs
.buflen
[count
] = 0; /* void */
842 msg
->hdr
.ac_len
+= msg
->bufs
.buflen
[count
++];
844 if ((msg
= racoon_realloc(msg
, msg
->hdr
.ac_len
)) == NULL
) {
845 plog(LLV_ERROR
, LOCATION
, NULL
,
846 "Cannot allocate memory: %s\n", strerror(errno
));
853 data
= (char *)(msg
+ 1);
856 memcpy(data
, (char *)script
, msg
->bufs
.buflen
[count
]); /* script */
857 data
+= msg
->bufs
.buflen
[count
++];
859 memcpy(data
, (char *)&name
, msg
->bufs
.buflen
[count
]); /* name */
860 data
+= msg
->bufs
.buflen
[count
++];
862 for (c
= envp
; *c
; c
++) { /* envp */
863 memcpy(data
, *c
, msg
->bufs
.buflen
[count
]);
864 data
+= msg
->bufs
.buflen
[count
++];
872 if (privsep_send(privsep_sock
[1], msg
, msg
->hdr
.ac_len
) != 0)
875 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
878 if (msg
->hdr
.ac_errno
!= 0) {
879 errno
= msg
->hdr
.ac_errno
;
889 privsep_getpsk(str
, keylen
)
894 struct privsep_com_msg
*msg
;
900 return getpsk(str
, keylen
);
902 len
= sizeof(*msg
) + strlen(str
) + 1 + sizeof(keylen
);
903 if ((msg
= racoon_malloc(len
)) == NULL
) {
904 plog(LLV_ERROR
, LOCATION
, NULL
,
905 "Cannot allocate memory: %s\n", strerror(errno
));
909 msg
->hdr
.ac_cmd
= PRIVSEP_GETPSK
;
910 msg
->hdr
.ac_len
= len
;
912 data
= (char *)(msg
+ 1);
913 msg
->bufs
.buflen
[0] = strlen(str
) + 1;
914 memcpy(data
, str
, msg
->bufs
.buflen
[0]);
916 data
+= msg
->bufs
.buflen
[0];
917 msg
->bufs
.buflen
[1] = sizeof(keylen
);
918 memcpy(data
, &keylen
, sizeof(keylen
));
920 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
923 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
926 if (msg
->hdr
.ac_errno
!= 0) {
927 errno
= msg
->hdr
.ac_errno
;
931 if ((psk
= vmalloc(len
- sizeof(*msg
))) == NULL
)
934 memcpy(psk
->v
, msg
+ 1, psk
->l
);
945 privsep_xauth_login_system(usr
, pwd
)
949 struct privsep_com_msg
*msg
;
954 return xauth_login_system(usr
, pwd
);
956 len
= sizeof(*msg
) + strlen(usr
) + 1 + strlen(pwd
) + 1;
957 if ((msg
= racoon_malloc(len
)) == NULL
) {
958 plog(LLV_ERROR
, LOCATION
, NULL
,
959 "Cannot allocate memory: %s\n", strerror(errno
));
963 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_SYSTEM
;
964 msg
->hdr
.ac_len
= len
;
966 data
= (char *)(msg
+ 1);
967 msg
->bufs
.buflen
[0] = strlen(usr
) + 1;
968 memcpy(data
, usr
, msg
->bufs
.buflen
[0]);
969 data
+= msg
->bufs
.buflen
[0];
971 msg
->bufs
.buflen
[1] = strlen(pwd
) + 1;
972 memcpy(data
, pwd
, msg
->bufs
.buflen
[1]);
974 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
977 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
980 if (msg
->hdr
.ac_errno
!= 0) {
990 privsep_accounting_system(port
, raddr
, usr
, inout
)
992 struct sockaddr
*raddr
;
996 struct privsep_com_msg
*msg
;
1002 return isakmp_cfg_accounting_system(port
, raddr
,
1007 + sysdep_sa_len(raddr
)
1011 if ((msg
= racoon_malloc(len
)) == NULL
) {
1012 plog(LLV_ERROR
, LOCATION
, NULL
,
1013 "Cannot allocate memory: %s\n", strerror(errno
));
1017 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_SYSTEM
;
1018 msg
->hdr
.ac_len
= len
;
1019 msg
->bufs
.buflen
[0] = sizeof(port
);
1020 msg
->bufs
.buflen
[1] = sysdep_sa_len(raddr
);
1021 msg
->bufs
.buflen
[2] = strlen(usr
) + 1;
1022 msg
->bufs
.buflen
[3] = sizeof(inout
);
1024 data
= (char *)(msg
+ 1);
1025 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1027 data
+= msg
->bufs
.buflen
[0];
1028 memcpy(data
, raddr
, msg
->bufs
.buflen
[1]);
1030 data
+= msg
->bufs
.buflen
[1];
1031 memcpy(data
, usr
, msg
->bufs
.buflen
[2]);
1033 data
+= msg
->bufs
.buflen
[2];
1034 memcpy(data
, &inout
, msg
->bufs
.buflen
[3]);
1036 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1039 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1042 if (msg
->hdr
.ac_errno
!= 0) {
1043 errno
= msg
->hdr
.ac_errno
;
1059 if ((port
< 0) || (port
>= isakmp_cfg_config
.pool_size
)) {
1060 plog(LLV_ERROR
, LOCATION
, NULL
,
1061 "privsep: port %d outside of allowed range [0,%zu]\n",
1062 port
, isakmp_cfg_config
.pool_size
- 1);
1071 safety_check(msg
, index
)
1072 struct privsep_com_msg
*msg
;
1075 if (index
>= PRIVSEP_NBUF_MAX
) {
1076 plog(LLV_ERROR
, LOCATION
, NULL
,
1077 "privsep: Corrupted message, too many buffers\n");
1081 if (msg
->bufs
.buflen
[index
] == 0) {
1082 plog(LLV_ERROR
, LOCATION
, NULL
,
1083 "privsep: Corrupted message, unexpected void buffer\n");
1091 * Filter unsafe environement variables
1099 char *const bad_env
[] = { "PATH=", "LD_LIBRARY_PATH=", "IFS=", NULL
};
1101 for (e
= envp
; *e
; e
++) {
1102 for (be
= bad_env
; *be
; be
++) {
1103 if (strncmp(*e
, *be
, strlen(*be
)) == 0) {
1111 plog(LLV_ERROR
, LOCATION
, NULL
,
1112 "privsep_script_exec: unsafe environement variable\n");
1120 unsafe_path(script
, pathtype
)
1125 char rpath
[MAXPATHLEN
+ 1];
1131 path
= lcconf
->pathinfo
[pathtype
];
1133 /* No path was given for scripts: skip the check */
1137 if (realpath(script
, rpath
) == NULL
) {
1138 plog(LLV_ERROR
, LOCATION
, NULL
,
1139 "script path \"%s\" is invalid\n", script
);
1144 if (strncmp(path
, rpath
, len
) != 0)
1154 if ((name
< 0) || (name
> SCRIPT_MAX
)) {
1155 plog(LLV_ERROR
, LOCATION
, NULL
,
1156 "privsep_script_exec: unsafe name index\n");
1165 privsep_accounting_pam(port
, inout
)
1169 struct privsep_com_msg
*msg
;
1173 int *pool_size_data
;
1177 return isakmp_cfg_accounting_pam(port
, inout
);
1182 + sizeof(isakmp_cfg_config
.pool_size
);
1184 if ((msg
= racoon_malloc(len
)) == NULL
) {
1185 plog(LLV_ERROR
, LOCATION
, NULL
,
1186 "Cannot allocate memory: %s\n", strerror(errno
));
1190 msg
->hdr
.ac_cmd
= PRIVSEP_ACCOUNTING_PAM
;
1191 msg
->hdr
.ac_len
= len
;
1192 msg
->bufs
.buflen
[0] = sizeof(port
);
1193 msg
->bufs
.buflen
[1] = sizeof(inout
);
1194 msg
->bufs
.buflen
[2] = sizeof(isakmp_cfg_config
.pool_size
);
1196 port_data
= (int *)(msg
+ 1);
1197 inout_data
= (int *)(port_data
+ 1);
1198 pool_size_data
= (int *)(inout_data
+ 1);
1201 *inout_data
= inout
;
1202 *pool_size_data
= isakmp_cfg_config
.pool_size
;
1204 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1207 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1210 if (msg
->hdr
.ac_errno
!= 0) {
1211 errno
= msg
->hdr
.ac_errno
;
1224 privsep_xauth_login_pam(port
, raddr
, usr
, pwd
)
1226 struct sockaddr
*raddr
;
1230 struct privsep_com_msg
*msg
;
1236 return xauth_login_pam(port
, raddr
, usr
, pwd
);
1240 + sizeof(isakmp_cfg_config
.pool_size
)
1241 + sysdep_sa_len(raddr
)
1245 if ((msg
= racoon_malloc(len
)) == NULL
) {
1246 plog(LLV_ERROR
, LOCATION
, NULL
,
1247 "Cannot allocate memory: %s\n", strerror(errno
));
1251 msg
->hdr
.ac_cmd
= PRIVSEP_XAUTH_LOGIN_PAM
;
1252 msg
->hdr
.ac_len
= len
;
1253 msg
->bufs
.buflen
[0] = sizeof(port
);
1254 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1255 msg
->bufs
.buflen
[2] = sysdep_sa_len(raddr
);
1256 msg
->bufs
.buflen
[3] = strlen(usr
) + 1;
1257 msg
->bufs
.buflen
[4] = strlen(pwd
) + 1;
1259 data
= (char *)(msg
+ 1);
1260 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1262 data
+= msg
->bufs
.buflen
[0];
1263 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1265 data
+= msg
->bufs
.buflen
[1];
1266 memcpy(data
, raddr
, msg
->bufs
.buflen
[2]);
1268 data
+= msg
->bufs
.buflen
[2];
1269 memcpy(data
, usr
, msg
->bufs
.buflen
[3]);
1271 data
+= msg
->bufs
.buflen
[3];
1272 memcpy(data
, pwd
, msg
->bufs
.buflen
[4]);
1274 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1277 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1280 if (msg
->hdr
.ac_errno
!= 0) {
1281 errno
= msg
->hdr
.ac_errno
;
1294 privsep_cleanup_pam(port
)
1297 struct privsep_com_msg
*msg
;
1303 return cleanup_pam(port
);
1307 + sizeof(isakmp_cfg_config
.pool_size
);
1309 if ((msg
= racoon_malloc(len
)) == NULL
) {
1310 plog(LLV_ERROR
, LOCATION
, NULL
,
1311 "Cannot allocate memory: %s\n", strerror(errno
));
1315 msg
->hdr
.ac_cmd
= PRIVSEP_CLEANUP_PAM
;
1316 msg
->hdr
.ac_len
= len
;
1317 msg
->bufs
.buflen
[0] = sizeof(port
);
1318 msg
->bufs
.buflen
[1] = sizeof(isakmp_cfg_config
.pool_size
);
1320 data
= (char *)(msg
+ 1);
1321 memcpy(data
, &port
, msg
->bufs
.buflen
[0]);
1323 data
+= msg
->bufs
.buflen
[0];
1324 memcpy(data
, &isakmp_cfg_config
.pool_size
, msg
->bufs
.buflen
[1]);
1326 if (privsep_send(privsep_sock
[1], msg
, len
) != 0)
1329 if (privsep_recv(privsep_sock
[1], &msg
, &len
) != 0)
1332 if (msg
->hdr
.ac_errno
!= 0)
1333 errno
= msg
->hdr
.ac_errno
;