1 /* $OpenBSD: talkd.c,v 1.26 2019/06/28 13:32:53 deraadt Exp $ */
2
3 /*
4 * Copyright (c) 1983 Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * The top level of the daemon, the format is heavily borrowed
34 * from rwhod.c. Basically: find out who and where you are;
35 * disconnect all descriptors and ttys, and then endless
36 * loop on waiting for and processing requests
37 */
38 #include <sys/socket.h>
39 #include <protocols/talkd.h>
40
41 #include <errno.h>
42 #include <limits.h>
43 #include <paths.h>
44 #include <signal.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <syslog.h>
49 #include <unistd.h>
50
51 #include "talkd.h"
52
53 int debug = 0;
54 void timeout(int);
55 long lastmsgtime;
56
57 char hostname[HOST_NAME_MAX+1];
58
59 #define TIMEOUT 30
60 #define MAXIDLE 120
61
62 int
main(int argc,char * argv[])63 main(int argc, char *argv[])
64 {
65 if (getuid() != 0) {
66 fprintf(stderr, "%s: getuid: not super-user\n", argv[0]);
67 exit(1);
68 }
69 openlog("talkd", LOG_PID, LOG_DAEMON);
70 if (gethostname(hostname, sizeof(hostname)) == -1) {
71 syslog(LOG_ERR, "gethostname: %m");
72 _exit(1);
73 }
74 if (chdir(_PATH_DEV) == -1) {
75 syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV);
76 _exit(1);
77 }
78 if (argc > 1 && strcmp(argv[1], "-d") == 0)
79 debug = 1;
80 init_table();
81 signal(SIGALRM, timeout);
82 alarm(TIMEOUT);
83
84 if (pledge("stdio rpath wpath cpath inet dns", NULL) == -1) {
85 syslog(LOG_ERR, "pledge: %m");
86 _exit(1);
87 }
88
89 for (;;) {
90 CTL_RESPONSE response;
91 socklen_t len = sizeof(response.addr);
92 CTL_MSG request;
93 int cc;
94 struct sockaddr ctl_addr;
95
96 memset(&response, 0, sizeof(response));
97 cc = recvfrom(STDIN_FILENO, (char *)&request,
98 sizeof(request), 0, (struct sockaddr *)&response.addr,
99 &len);
100 if (cc != sizeof(request)) {
101 if (cc == -1 && errno != EINTR)
102 syslog(LOG_WARNING, "recvfrom: %m");
103 continue;
104 }
105
106 /* Force NUL termination */
107 request.l_name[sizeof(request.l_name) - 1] = '\0';
108 request.r_name[sizeof(request.r_name) - 1] = '\0';
109 request.r_tty[sizeof(request.r_tty) - 1] = '\0';
110
111 memcpy(&ctl_addr, &request.ctl_addr, sizeof(ctl_addr));
112 ctl_addr.sa_family = ntohs(request.ctl_addr.sa_family);
113 ctl_addr.sa_len = sizeof(ctl_addr);
114 if (ctl_addr.sa_family != AF_INET)
115 continue;
116
117 lastmsgtime = time(0);
118 process_request(&request, &response);
119 /* can block here, is this what I want? */
120 cc = sendto(STDOUT_FILENO, (char *)&response,
121 sizeof(response), 0, &ctl_addr, sizeof(ctl_addr));
122 if (cc != sizeof(response))
123 syslog(LOG_WARNING, "sendto: %m");
124 }
125 }
126
127 void
timeout(int signo)128 timeout(int signo)
129 {
130 int save_errno = errno;
131
132 if (time(0) - lastmsgtime >= MAXIDLE)
133 _exit(0);
134 alarm(TIMEOUT);
135 errno = save_errno;
136 }
137