2 * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * 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.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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
38 static pid_t wait_on_pid
= -1;
42 * Signal handler that justs waits for the children when they die.
46 childhandler (int sig
)
52 pid
= waitpid (-1, &status
, WNOHANG
|WUNTRACED
);
53 if (pid
> 0 && pid
== wait_on_pid
)
56 signal (SIGCHLD
, childhandler
);
61 * Print the error message `format' and `...' on fd and die.
65 fatal (kx_context
*kc
, int fd
, char *format
, ...)
72 va_start(args
, format
);
75 vsnprintf ((char *)p
+ 4, sizeof(msg
) - 5, format
, args
);
76 syslog (LOG_ERR
, "%s", (char *)p
+ 4);
77 len
= strlen ((char *)p
+ 4);
78 p
+= kx_put_int (len
, p
, 4, 4);
80 kx_write (kc
, fd
, msg
, p
- msg
);
86 * Remove all sockets and cookie files.
90 cleanup(int nsockets
, struct x_socket
*sockets
)
96 for (i
= 0; i
< nsockets
; ++i
) {
97 if (sockets
[i
].pathname
!= NULL
) {
98 unlink (sockets
[i
].pathname
);
99 free (sockets
[i
].pathname
);
106 * Prepare to receive a connection on `sock'.
110 recv_conn (int sock
, kx_context
*kc
,
111 int *dispnr
, int *nsockets
, struct x_socket
**sockets
,
114 u_char msg
[1024], *p
;
117 struct passwd
*passwd
;
118 char remotehost
[MaxHostNameLen
];
119 char remoteaddr
[INET6_ADDRSTRLEN
];
125 memset(kc
, 0, sizeof(*kc
));
130 addrlen
= sizeof(kc
->__ss_this
);
131 kc
->thisaddr
= (struct sockaddr
*)&kc
->__ss_this
;
132 if (getsockname (sock
, kc
->thisaddr
, &addrlen
) < 0) {
133 syslog (LOG_ERR
, "getsockname: %m");
136 kc
->thisaddr_len
= addrlen
;
137 addrlen
= sizeof(kc
->__ss_that
);
138 kc
->thataddr
= (struct sockaddr
*)&kc
->__ss_that
;
139 if (getpeername (sock
, kc
->thataddr
, &addrlen
) < 0) {
140 syslog (LOG_ERR
, "getpeername: %m");
143 kc
->thataddr_len
= addrlen
;
145 getnameinfo_verified (kc
->thataddr
,
147 remotehost
, sizeof(remotehost
),
150 if (net_read (sock
, msg
, 4) != 4) {
151 syslog (LOG_ERR
, "read: %m");
156 if (ret
&& recv_v5_auth (kc
, sock
, msg
) == 0)
160 syslog (LOG_ERR
, "unrecognized auth protocol: %x %x %x %x",
161 msg
[0], msg
[1], msg
[2], msg
[3]);
165 len
= kx_read (kc
, sock
, msg
, sizeof(msg
));
167 syslog (LOG_ERR
, "kx_read failed");
172 fatal(kc
, sock
, "Bad message");
174 if ((p
- msg
) < sizeof(msg
))
175 fatal(kc
, sock
, "user");
177 p
+= kx_get_int (p
, &tmp32
, 4, 0);
178 if (tmp32
>= sizeof(user
) - 1)
179 fatal(kc
, sock
, "user name too long");
180 if ((p
- msg
) + tmp32
>= sizeof(msg
))
181 fatal(kc
, sock
, "user too long");
182 memcpy (user
, p
, tmp32
);
186 passwd
= k_getpwnam (user
);
188 fatal (kc
, sock
, "cannot find uid for %s", user
);
190 if (context_userok (kc
, user
) != 0)
191 fatal (kc
, sock
, "%s not allowed to login as %s",
194 if ((p
- msg
) >= sizeof(msg
))
195 fatal(kc
, sock
, "user too long");
199 if (flags
& PASSIVE
) {
203 tmp
= get_xsockets (nsockets
, sockets
, tcp_flag
);
205 fatal (kc
, sock
, "Cannot create X socket(s): %s",
210 if (chown_xsockets (*nsockets
, *sockets
,
211 passwd
->pw_uid
, passwd
->pw_gid
)) {
212 cleanup (*nsockets
, *sockets
);
213 fatal (kc
, sock
, "Cannot chown sockets: %s",
219 cleanup (*nsockets
, *sockets
);
220 fatal (kc
, sock
, "fork: %s", strerror(errno
));
221 } else if (pid
!= 0) {
225 cleanup (*nsockets
, *sockets
);
230 if (setgid (passwd
->pw_gid
) ||
231 initgroups(passwd
->pw_name
, passwd
->pw_gid
) ||
232 #ifdef HAVE_GETUDBNAM /* XXX this happens on crays */
233 setjob(passwd
->pw_uid
, 0) == -1 ||
235 setuid(passwd
->pw_uid
)) {
236 syslog(LOG_ERR
, "setting uid/groups: %m");
237 fatal (kc
, sock
, "cannot set uid");
240 ret
= getnameinfo(kc
->thataddr
, kc
->thataddr_len
,
241 remoteaddr
, sizeof(remoteaddr
),
242 NULL
, 0, NI_NUMERICHOST
);
244 fatal (kc
, sock
, "getnameinfo failed: %s", gai_strerror(ret
));
246 syslog (LOG_INFO
, "from %s(%s): %s -> %s",
247 remotehost
, remoteaddr
,
250 if (!(flags
& PASSIVE
)) {
251 p
+= kx_get_int (p
, &tmp32
, 4, 0);
252 if (tmp32
> display_size
)
253 fatal(kc
, sock
, "display too large");
254 if ((p
- msg
) + tmp32
+ 8 >= sizeof(msg
))
255 fatal(kc
, sock
, "user too long");
256 memcpy (display
, p
, tmp32
);
257 display
[tmp32
] = '\0';
259 p
+= kx_get_int (p
, &tmp32
, 4, 0);
260 len
= min(tmp32
, xauthfile_size
);
261 memcpy (xauthfile
, p
, len
);
262 xauthfile
[len
] = '\0';
264 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
265 if (flags
& KEEP_ALIVE
) {
268 setsockopt (sock
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&one
,
280 passive_session (kx_context
*kc
, int fd
, int sock
, int cookiesp
)
282 if (verify_and_remove_cookies (fd
, sock
, cookiesp
))
285 return copy_encrypted (kc
, fd
, sock
);
293 active_session (kx_context
*kc
, int fd
, int sock
, int cookiesp
)
295 fd
= connect_local_xsocket(0);
297 if (replace_cookie (fd
, sock
, xauthfile
, cookiesp
))
300 return copy_encrypted (kc
, fd
, sock
);
304 * Handle a new connection.
308 doit_conn (kx_context
*kc
,
309 int fd
, int meta_sock
, int flags
, int cookiesp
)
311 int sock
, sock2
, port
;
312 struct sockaddr_storage __ss_addr
;
313 struct sockaddr
*addr
= (struct sockaddr
*)&__ss_addr
;
314 struct sockaddr_storage __ss_thisaddr
;
315 struct sockaddr
*thisaddr
= (struct sockaddr
*)&__ss_thisaddr
;
317 u_char msg
[1024], *p
;
319 sock
= socket (kc
->thisaddr
->sa_family
, SOCK_STREAM
, 0);
321 syslog (LOG_ERR
, "socket: %m");
324 #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
327 setsockopt (sock
, IPPROTO_TCP
, TCP_NODELAY
, (void *)&one
, sizeof(one
));
330 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
331 if (flags
& KEEP_ALIVE
) {
334 setsockopt (sock
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&one
,
338 memset (&__ss_addr
, 0, sizeof(__ss_addr
));
339 addr
->sa_family
= kc
->thisaddr
->sa_family
;
340 if (kc
->thisaddr_len
> sizeof(__ss_addr
)) {
341 syslog(LOG_ERR
, "error in af");
344 if (bind (sock
, addr
, kc
->thisaddr_len
) < 0) {
345 syslog (LOG_ERR
, "bind: %m");
348 addrlen
= sizeof(__ss_addr
);
349 if (getsockname (sock
, addr
, &addrlen
) < 0) {
350 syslog (LOG_ERR
, "getsockname: %m");
353 if (listen (sock
, SOMAXCONN
) < 0) {
354 syslog (LOG_ERR
, "listen: %m");
357 port
= socket_get_port(addr
);
361 p
+= kx_put_int (ntohs(port
), p
, 4, 4);
363 if (kx_write (kc
, meta_sock
, msg
, p
- msg
) < 0) {
364 syslog (LOG_ERR
, "write: %m");
368 addrlen
= sizeof(__ss_thisaddr
);
369 sock2
= accept (sock
, thisaddr
, &addrlen
);
371 syslog (LOG_ERR
, "accept: %m");
378 return passive_session (kc
, fd
, sock2
, cookiesp
);
380 return active_session (kc
, fd
, sock2
, cookiesp
);
384 * Is the current user the owner of the console?
388 check_user_console (kx_context
*kc
, int fd
)
392 if (stat ("/dev/console", &sb
) < 0)
393 fatal (kc
, fd
, "Cannot stat /dev/console: %s", strerror(errno
));
394 if (getuid() != sb
.st_uid
)
395 fatal (kc
, fd
, "Permission denied");
398 /* close down the new connection with a reasonable error message */
400 close_connection(int fd
, const char *message
)
402 char buf
[264]; /* max message */
407 mlen
= strlen(message
);
411 /* read first part of connection packet, to get byte order */
412 if(read(fd
, buf
, 6) != 6) {
419 *p
++ = 0; /* failed */
420 *p
++ = mlen
; /* length of message */
421 p
+= 4; /* skip protocol version */
422 p
+= 2; /* skip additional length */
423 memcpy(p
, message
, mlen
); /* copy message */
425 while((p
- buf
) % 4) /* pad to multiple of 4 bytes */
428 /* now fill in length of additional data */
430 buf
[6] = (p
- buf
- 8) / 4;
434 buf
[7] = (p
- buf
- 8) / 4;
436 write(fd
, buf
, p
- buf
);
442 * Handle a passive session on `sock'
446 doit_passive (kx_context
*kc
,
451 struct x_socket
*sockets
,
457 u_char msg
[1024], *p
;
460 display_num
= dispnr
;
462 snprintf (display
, display_size
, "localhost:%u", display_num
);
464 snprintf (display
, display_size
, ":%u", display_num
);
465 error
= create_and_write_cookie (xauthfile
, xauthfile_size
,
468 cleanup(nsockets
, sockets
);
469 fatal (kc
, sock
, "Cookie-creation failed: %s", strerror(error
));
478 len
= strlen (display
);
479 tmp
= kx_put_int (len
, p
, rem
, 4);
480 if (tmp
< 0 || rem
< len
+ 4) {
481 syslog (LOG_ERR
, "doit: buffer too small");
482 cleanup(nsockets
, sockets
);
488 memcpy (p
, display
, len
);
492 len
= strlen (xauthfile
);
493 tmp
= kx_put_int (len
, p
, rem
, 4);
494 if (tmp
< 0 || rem
< len
+ 4) {
495 syslog (LOG_ERR
, "doit: buffer too small");
496 cleanup(nsockets
, sockets
);
502 memcpy (p
, xauthfile
, len
);
506 if(kx_write (kc
, sock
, msg
, p
- msg
) < 0) {
507 syslog (LOG_ERR
, "write: %m");
508 cleanup(nsockets
, sockets
);
520 if (sock
>= FD_SETSIZE
) {
521 syslog (LOG_ERR
, "fd too large");
522 cleanup(nsockets
, sockets
);
527 for (i
= 0; i
< nsockets
; ++i
) {
528 if (sockets
[i
].fd
>= FD_SETSIZE
) {
529 syslog (LOG_ERR
, "fd too large");
530 cleanup(nsockets
, sockets
);
533 FD_SET(sockets
[i
].fd
, &fds
);
535 ret
= select(FD_SETSIZE
, &fds
, NULL
, NULL
, NULL
);
538 if(FD_ISSET(sock
, &fds
)){
539 /* there are no processes left on the remote side
541 cleanup(nsockets
, sockets
);
544 for (i
= 0; i
< nsockets
; ++i
) {
545 if (FD_ISSET(sockets
[i
].fd
, &fds
)) {
546 if (sockets
[i
].flags
== TCP
) {
547 struct sockaddr_storage __ss_peer
;
548 struct sockaddr
*peer
= (struct sockaddr
*)&__ss_peer
;
549 socklen_t slen
= sizeof(__ss_peer
);
551 fd
= accept (sockets
[i
].fd
,
554 if (fd
< 0 && errno
!= EINTR
)
555 syslog (LOG_ERR
, "accept: %m");
558 if (fd
>= 0 && suspicious_address (fd
, peer
)) {
563 } else if(sockets
[i
].flags
== UNIX_SOCKET
) {
566 fd
= accept (sockets
[i
].fd
, NULL
, &zero
);
568 if (fd
< 0 && errno
!= EINTR
)
569 syslog (LOG_ERR
, "accept: %m");
570 #ifdef MAY_HAVE_X11_PIPES
571 } else if(sockets
[i
].flags
== STREAM_PIPE
) {
573 * this code tries to handle the
574 * send fd-over-pipe stuff for
578 struct strrecvfd strrecvfd
;
580 ret
= ioctl (sockets
[i
].fd
,
581 I_RECVFD
, &strrecvfd
);
582 if (ret
< 0 && errno
!= EINTR
) {
583 syslog (LOG_ERR
, "ioctl I_RECVFD: %m");
588 if (strrecvfd
.uid
!= getuid()) {
589 close (strrecvfd
.fd
);
597 #endif /* MAY_HAVE_X11_PIPES */
613 syslog (LOG_ERR
, "fork: %m");
616 close_connection(fd
, strerror(errno
));
617 } else if (child
== 0) {
618 for (i
= 0; i
< nsockets
; ++i
)
619 close (sockets
[i
].fd
);
620 return doit_conn (kc
, fd
, sock
, flags
, cookiesp
);
628 * Handle an active session on `sock'
632 doit_active (kx_context
*kc
,
637 u_char msg
[1024], *p
;
639 check_user_console (kc
, sock
);
644 if(kx_write (kc
, sock
, msg
, p
- msg
) < 0) {
645 syslog (LOG_ERR
, "write: %m");
652 len
= kx_read (kc
, sock
, msg
, sizeof(msg
));
654 syslog (LOG_ERR
, "read: %m");
658 if (*p
!= NEW_CONN
) {
659 syslog (LOG_ERR
, "bad_message: %d", *p
);
665 syslog (LOG_ERR
, "fork: %m");
668 } else if (child
== 0) {
669 return doit_conn (kc
, sock
, sock
, flags
, 1);
676 * Receive a connection on `sock' and process it.
680 doit(int sock
, int tcp_flag
)
686 struct x_socket
*sockets
;
689 flags
= recv_conn (sock
, &context
, &dispnr
, &nsockets
, &sockets
, tcp_flag
);
691 if (flags
& PASSIVE
) {
692 ret
= doit_passive (&context
, sock
, flags
, dispnr
,
693 nsockets
, sockets
, tcp_flag
);
695 ret
= doit_active (&context
, sock
, flags
, tcp_flag
);
696 cleanup(nsockets
, sockets
);
698 context_destroy (&context
);
702 static char *port_str
= NULL
;
703 static int inetd_flag
= 1;
704 static int tcp_flag
= 0;
705 static int version_flag
= 0;
706 static int help_flag
= 0;
708 struct getargs args
[] = {
709 { "inetd", 'i', arg_negative_flag
, &inetd_flag
,
710 "Not started from inetd" },
711 { "tcp", 't', arg_flag
, &tcp_flag
, "Use TCP" },
712 { "port", 'p', arg_string
, &port_str
, "Use this port",
714 { "version", 0, arg_flag
, &version_flag
},
715 { "help", 0, arg_flag
, &help_flag
}
721 arg_printusage (args
,
722 sizeof(args
) / sizeof(args
[0]),
729 * kxd - receive a forwarded X conncection
733 main (int argc
, char **argv
)
738 setprogname (argv
[0]);
739 roken_openlog ("kxd", LOG_ODELAY
| LOG_PID
, LOG_DAEMON
);
741 if (getarg (args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
,
749 print_version (NULL
);
754 struct servent
*s
= roken_getservbyname (port_str
, "tcp");
761 port
= strtol (port_str
, &ptr
, 10);
762 if (port
== 0 && ptr
== port_str
)
763 errx (1, "bad port `%s'", port_str
);
768 port
= krb5_getportbyname(NULL
, "kx", "tcp", KX_PORT
);
777 signal (SIGCHLD
, childhandler
);
778 return doit(STDIN_FILENO
, tcp_flag
);