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
+= KRB_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
);
105 * Prepare to receive a connection on `sock'.
109 recv_conn (int sock
, kx_context
*kc
,
110 int *dispnr
, int *nsockets
, struct x_socket
**sockets
,
113 u_char msg
[1024], *p
;
116 struct passwd
*passwd
;
117 char remotehost
[MaxHostNameLen
];
118 char remoteaddr
[INET6_ADDRSTRLEN
];
124 addrlen
= sizeof(kc
->__ss_this
);
125 kc
->thisaddr
= (struct sockaddr
*)&kc
->__ss_this
;
126 if (getsockname (sock
, kc
->thisaddr
, &addrlen
) < 0) {
127 syslog (LOG_ERR
, "getsockname: %m");
130 kc
->thisaddr_len
= addrlen
;
131 addrlen
= sizeof(kc
->__ss_that
);
132 kc
->thataddr
= (struct sockaddr
*)&kc
->__ss_that
;
133 if (getpeername (sock
, kc
->thataddr
, &addrlen
) < 0) {
134 syslog (LOG_ERR
, "getpeername: %m");
137 kc
->thataddr_len
= addrlen
;
139 getnameinfo_verified (kc
->thataddr
,
141 remotehost
, sizeof(remotehost
),
144 if (net_read (sock
, msg
, 4) != 4) {
145 syslog (LOG_ERR
, "read: %m");
150 if (ret
&& recv_v5_auth (kc
, sock
, msg
) == 0)
154 if (ret
&& recv_v4_auth (kc
, sock
, msg
) == 0)
158 syslog (LOG_ERR
, "unrecognized auth protocol: %x %x %x %x",
159 msg
[0], msg
[1], msg
[2], msg
[3]);
163 len
= kx_read (kc
, sock
, msg
, sizeof(msg
));
165 syslog (LOG_ERR
, "kx_read failed");
170 fatal(kc
, sock
, "Bad message");
172 p
+= krb_get_int (p
, &tmp32
, 4, 0);
173 len
= min(sizeof(user
), tmp32
);
174 memcpy (user
, p
, len
);
178 passwd
= k_getpwnam (user
);
180 fatal (kc
, sock
, "cannot find uid for %s", user
);
182 if (context_userok (kc
, user
) != 0)
183 fatal (kc
, sock
, "%s not allowed to login as %s",
188 if (flags
& PASSIVE
) {
192 tmp
= get_xsockets (nsockets
, sockets
, tcp_flag
);
194 fatal (kc
, sock
, "Cannot create X socket(s): %s",
199 if (chown_xsockets (*nsockets
, *sockets
,
200 passwd
->pw_uid
, passwd
->pw_gid
)) {
201 cleanup (*nsockets
, *sockets
);
202 fatal (kc
, sock
, "Cannot chown sockets: %s",
208 cleanup (*nsockets
, *sockets
);
209 fatal (kc
, sock
, "fork: %s", strerror(errno
));
210 } else if (pid
!= 0) {
214 cleanup (*nsockets
, *sockets
);
219 if (setgid (passwd
->pw_gid
) ||
220 initgroups(passwd
->pw_name
, passwd
->pw_gid
) ||
221 #ifdef HAVE_GETUDBNAM /* XXX this happens on crays */
222 setjob(passwd
->pw_uid
, 0) == -1 ||
224 setuid(passwd
->pw_uid
)) {
225 syslog(LOG_ERR
, "setting uid/groups: %m");
226 fatal (kc
, sock
, "cannot set uid");
229 ret
= getnameinfo(kc
->thataddr
, kc
->thataddr_len
,
230 remoteaddr
, sizeof(remoteaddr
),
231 NULL
, 0, NI_NUMERICHOST
);
233 fatal (kc
, sock
, "getnameinfo failed: %s", gai_strerror(ret
));
235 syslog (LOG_INFO
, "from %s(%s): %s -> %s",
236 remotehost
, remoteaddr
,
239 if (!(flags
& PASSIVE
)) {
240 p
+= krb_get_int (p
, &tmp32
, 4, 0);
241 len
= min(tmp32
, display_size
);
242 memcpy (display
, p
, len
);
245 p
+= krb_get_int (p
, &tmp32
, 4, 0);
246 len
= min(tmp32
, xauthfile_size
);
247 memcpy (xauthfile
, p
, len
);
248 xauthfile
[len
] = '\0';
251 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
252 if (flags
& KEEP_ALIVE
) {
255 setsockopt (sock
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&one
,
267 passive_session (kx_context
*kc
, int fd
, int sock
, int cookiesp
)
269 if (verify_and_remove_cookies (fd
, sock
, cookiesp
))
272 return copy_encrypted (kc
, fd
, sock
);
280 active_session (kx_context
*kc
, int fd
, int sock
, int cookiesp
)
282 fd
= connect_local_xsocket(0);
284 if (replace_cookie (fd
, sock
, xauthfile
, cookiesp
))
287 return copy_encrypted (kc
, fd
, sock
);
291 * Handle a new connection.
295 doit_conn (kx_context
*kc
,
296 int fd
, int meta_sock
, int flags
, int cookiesp
)
298 int sock
, sock2
, port
;
299 struct sockaddr_storage __ss_addr
;
300 struct sockaddr
*addr
= (struct sockaddr
*)&__ss_addr
;
301 struct sockaddr_storage __ss_thisaddr
;
302 struct sockaddr
*thisaddr
= (struct sockaddr
*)&__ss_thisaddr
;
304 u_char msg
[1024], *p
;
306 sock
= socket (kc
->thisaddr
->sa_family
, SOCK_STREAM
, 0);
308 syslog (LOG_ERR
, "socket: %m");
311 #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
314 setsockopt (sock
, IPPROTO_TCP
, TCP_NODELAY
, (void *)&one
, sizeof(one
));
317 #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT)
318 if (flags
& KEEP_ALIVE
) {
321 setsockopt (sock
, SOL_SOCKET
, SO_KEEPALIVE
, (void *)&one
,
325 memset (&__ss_addr
, 0, sizeof(__ss_addr
));
326 addr
->sa_family
= kc
->thisaddr
->sa_family
;
327 if (kc
->thisaddr_len
> sizeof(__ss_addr
)) {
328 syslog(LOG_ERR
, "error in af");
331 if (bind (sock
, addr
, kc
->thisaddr_len
) < 0) {
332 syslog (LOG_ERR
, "bind: %m");
335 addrlen
= sizeof(__ss_addr
);
336 if (getsockname (sock
, addr
, &addrlen
) < 0) {
337 syslog (LOG_ERR
, "getsockname: %m");
340 if (listen (sock
, SOMAXCONN
) < 0) {
341 syslog (LOG_ERR
, "listen: %m");
344 port
= socket_get_port(addr
);
348 p
+= KRB_PUT_INT (ntohs(port
), p
, 4, 4);
350 if (kx_write (kc
, meta_sock
, msg
, p
- msg
) < 0) {
351 syslog (LOG_ERR
, "write: %m");
355 addrlen
= sizeof(__ss_thisaddr
);
356 sock2
= accept (sock
, thisaddr
, &addrlen
);
358 syslog (LOG_ERR
, "accept: %m");
365 return passive_session (kc
, fd
, sock2
, cookiesp
);
367 return active_session (kc
, fd
, sock2
, cookiesp
);
371 * Is the current user the owner of the console?
375 check_user_console (kx_context
*kc
, int fd
)
379 if (stat ("/dev/console", &sb
) < 0)
380 fatal (kc
, fd
, "Cannot stat /dev/console: %s", strerror(errno
));
381 if (getuid() != sb
.st_uid
)
382 fatal (kc
, fd
, "Permission denied");
385 /* close down the new connection with a reasonable error message */
387 close_connection(int fd
, const char *message
)
389 char buf
[264]; /* max message */
394 mlen
= strlen(message
);
398 /* read first part of connection packet, to get byte order */
399 if(read(fd
, buf
, 6) != 6) {
406 *p
++ = 0; /* failed */
407 *p
++ = mlen
; /* length of message */
408 p
+= 4; /* skip protocol version */
409 p
+= 2; /* skip additional length */
410 memcpy(p
, message
, mlen
); /* copy message */
412 while((p
- buf
) % 4) /* pad to multiple of 4 bytes */
415 /* now fill in length of additional data */
417 buf
[6] = (p
- buf
- 8) / 4;
421 buf
[7] = (p
- buf
- 8) / 4;
423 write(fd
, buf
, p
- buf
);
429 * Handle a passive session on `sock'
433 doit_passive (kx_context
*kc
,
438 struct x_socket
*sockets
,
444 u_char msg
[1024], *p
;
447 display_num
= dispnr
;
449 snprintf (display
, display_size
, "localhost:%u", display_num
);
451 snprintf (display
, display_size
, ":%u", display_num
);
452 error
= create_and_write_cookie (xauthfile
, xauthfile_size
,
455 cleanup(nsockets
, sockets
);
456 fatal (kc
, sock
, "Cookie-creation failed: %s", strerror(error
));
465 len
= strlen (display
);
466 tmp
= KRB_PUT_INT (len
, p
, rem
, 4);
467 if (tmp
< 0 || rem
< len
+ 4) {
468 syslog (LOG_ERR
, "doit: buffer too small");
469 cleanup(nsockets
, sockets
);
475 memcpy (p
, display
, len
);
479 len
= strlen (xauthfile
);
480 tmp
= KRB_PUT_INT (len
, p
, rem
, 4);
481 if (tmp
< 0 || rem
< len
+ 4) {
482 syslog (LOG_ERR
, "doit: buffer too small");
483 cleanup(nsockets
, sockets
);
489 memcpy (p
, xauthfile
, len
);
493 if(kx_write (kc
, sock
, msg
, p
- msg
) < 0) {
494 syslog (LOG_ERR
, "write: %m");
495 cleanup(nsockets
, sockets
);
507 if (sock
>= FD_SETSIZE
) {
508 syslog (LOG_ERR
, "fd too large");
509 cleanup(nsockets
, sockets
);
514 for (i
= 0; i
< nsockets
; ++i
) {
515 if (sockets
[i
].fd
>= FD_SETSIZE
) {
516 syslog (LOG_ERR
, "fd too large");
517 cleanup(nsockets
, sockets
);
520 FD_SET(sockets
[i
].fd
, &fds
);
522 ret
= select(FD_SETSIZE
, &fds
, NULL
, NULL
, NULL
);
525 if(FD_ISSET(sock
, &fds
)){
526 /* there are no processes left on the remote side
528 cleanup(nsockets
, sockets
);
531 for (i
= 0; i
< nsockets
; ++i
) {
532 if (FD_ISSET(sockets
[i
].fd
, &fds
)) {
533 if (sockets
[i
].flags
== TCP
) {
534 struct sockaddr_storage __ss_peer
;
535 struct sockaddr
*peer
= (struct sockaddr
*)&__ss_peer
;
536 socklen_t len
= sizeof(__ss_peer
);
538 fd
= accept (sockets
[i
].fd
,
541 if (fd
< 0 && errno
!= EINTR
)
542 syslog (LOG_ERR
, "accept: %m");
545 if (fd
>= 0 && suspicious_address (fd
, peer
)) {
550 } else if(sockets
[i
].flags
== UNIX_SOCKET
) {
553 fd
= accept (sockets
[i
].fd
, NULL
, &zero
);
555 if (fd
< 0 && errno
!= EINTR
)
556 syslog (LOG_ERR
, "accept: %m");
557 #ifdef MAY_HAVE_X11_PIPES
558 } else if(sockets
[i
].flags
== STREAM_PIPE
) {
560 * this code tries to handle the
561 * send fd-over-pipe stuff for
565 struct strrecvfd strrecvfd
;
567 ret
= ioctl (sockets
[i
].fd
,
568 I_RECVFD
, &strrecvfd
);
569 if (ret
< 0 && errno
!= EINTR
) {
570 syslog (LOG_ERR
, "ioctl I_RECVFD: %m");
575 if (strrecvfd
.uid
!= getuid()) {
576 close (strrecvfd
.fd
);
584 #endif /* MAY_HAVE_X11_PIPES */
600 syslog (LOG_ERR
, "fork: %m");
603 close_connection(fd
, strerror(errno
));
604 } else if (child
== 0) {
605 for (i
= 0; i
< nsockets
; ++i
)
606 close (sockets
[i
].fd
);
607 return doit_conn (kc
, fd
, sock
, flags
, cookiesp
);
615 * Handle an active session on `sock'
619 doit_active (kx_context
*kc
,
624 u_char msg
[1024], *p
;
626 check_user_console (kc
, sock
);
631 if(kx_write (kc
, sock
, msg
, p
- msg
) < 0) {
632 syslog (LOG_ERR
, "write: %m");
639 len
= kx_read (kc
, sock
, msg
, sizeof(msg
));
641 syslog (LOG_ERR
, "read: %m");
645 if (*p
!= NEW_CONN
) {
646 syslog (LOG_ERR
, "bad_message: %d", *p
);
652 syslog (LOG_ERR
, "fork: %m");
655 } else if (child
== 0) {
656 return doit_conn (kc
, sock
, sock
, flags
, 1);
663 * Receive a connection on `sock' and process it.
667 doit(int sock
, int tcp_flag
)
673 struct x_socket
*sockets
;
676 flags
= recv_conn (sock
, &context
, &dispnr
, &nsockets
, &sockets
, tcp_flag
);
679 ret
= doit_passive (&context
, sock
, flags
, dispnr
,
680 nsockets
, sockets
, tcp_flag
);
682 ret
= doit_active (&context
, sock
, flags
, tcp_flag
);
683 context_destroy (&context
);
687 static char *port_str
= NULL
;
688 static int inetd_flag
= 1;
689 static int tcp_flag
= 0;
690 static int version_flag
= 0;
691 static int help_flag
= 0;
693 struct getargs args
[] = {
694 { "inetd", 'i', arg_negative_flag
, &inetd_flag
,
695 "Not started from inetd" },
696 { "tcp", 't', arg_flag
, &tcp_flag
, "Use TCP" },
697 { "port", 'p', arg_string
, &port_str
, "Use this port",
699 { "version", 0, arg_flag
, &version_flag
},
700 { "help", 0, arg_flag
, &help_flag
}
706 arg_printusage (args
,
707 sizeof(args
) / sizeof(args
[0]),
714 * kxd - receive a forwarded X conncection
718 main (int argc
, char **argv
)
723 setprogname (argv
[0]);
724 roken_openlog ("kxd", LOG_ODELAY
| LOG_PID
, LOG_DAEMON
);
726 if (getarg (args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
,
734 print_version (NULL
);
739 struct servent
*s
= roken_getservbyname (port_str
, "tcp");
746 port
= strtol (port_str
, &ptr
, 10);
747 if (port
== 0 && ptr
== port_str
)
748 errx (1, "bad port `%s'", port_str
);
753 port
= krb5_getportbyname(NULL
, "kx", "tcp", KX_PORT
);
755 port
= k_getportbyname ("kx", "tcp", htons(KX_PORT
));
757 #error define KRB4 or KRB5
764 signal (SIGCHLD
, childhandler
);
765 return doit(STDIN_FILENO
, tcp_flag
);