GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: libexec/talkd/process.c Lines: 0 103 0.0 %
Date: 2017-11-07 Branches: 0 53 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: process.c,v 1.23 2016/03/16 15:41:10 krw 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
 * process.c handles the requests, which can be of three types:
34
 *	ANNOUNCE - announce to a user that a talk is wanted
35
 *	LEAVE_INVITE - insert the request into the table
36
 *	LOOK_UP - look up to see if a request is waiting in
37
 *		  in the table for the local user
38
 *	DELETE - delete invitation
39
 */
40
#include <sys/socket.h>
41
#include <sys/stat.h>
42
#include <arpa/inet.h>
43
#include <protocols/talkd.h>
44
45
#include <ctype.h>
46
#include <limits.h>
47
#include <netdb.h>
48
#include <paths.h>
49
#include <stdio.h>
50
#include <string.h>
51
#include <syslog.h>
52
#include <utmp.h>
53
54
#include "talkd.h"
55
56
#define	satosin(sa)	((struct sockaddr_in *)(sa))
57
58
void
59
process_request(CTL_MSG *mp, CTL_RESPONSE *rp)
60
{
61
	CTL_MSG *ptr;
62
	char *s;
63
64
	rp->vers = TALK_VERSION;
65
	rp->type = mp->type;
66
	rp->id_num = htonl(0);
67
	if (mp->vers != TALK_VERSION) {
68
		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
69
		rp->answer = BADVERSION;
70
		return;
71
	}
72
	mp->id_num = ntohl(mp->id_num);
73
	if (ntohs(mp->addr.sa_family) != AF_INET) {
74
		syslog(LOG_WARNING, "Bad address, family %d",
75
		    ntohs(mp->addr.sa_family));
76
		rp->answer = BADADDR;
77
		return;
78
	}
79
	if (ntohs(mp->ctl_addr.sa_family) != AF_INET) {
80
		syslog(LOG_WARNING, "Bad control address, family %d",
81
		    ntohs(mp->ctl_addr.sa_family));
82
		rp->answer = BADCTLADDR;
83
		return;
84
	}
85
	for (s = mp->l_name; *s; s++)
86
		if (!isprint((unsigned char)*s)) {
87
			syslog(LOG_NOTICE, "Illegal user name. Aborting");
88
			rp->answer = FAILED;
89
			return;
90
		}
91
	if (memcmp(&satosin(&rp->addr)->sin_addr,
92
	    &satosin(&mp->ctl_addr)->sin_addr,
93
	    sizeof(struct in_addr))) {
94
		char buf1[32], buf2[32];
95
96
		strlcpy(buf1, inet_ntoa(satosin(&rp->addr)->sin_addr),
97
		    sizeof(buf1));
98
		strlcpy(buf2, inet_ntoa(satosin(&mp->ctl_addr)->sin_addr),
99
		    sizeof(buf2));
100
		syslog(LOG_WARNING, "addresses are different, %s != %s",
101
		    buf1, buf2);
102
	}
103
	rp->addr.sa_family = 0;
104
	mp->pid = ntohl(mp->pid);
105
	if (debug)
106
		print_request("process_request", mp);
107
	switch (mp->type) {
108
109
	case ANNOUNCE:
110
		do_announce(mp, rp);
111
		break;
112
113
	case LEAVE_INVITE:
114
		ptr = find_request(mp);
115
		if (ptr != NULL) {
116
			rp->id_num = htonl(ptr->id_num);
117
			rp->answer = SUCCESS;
118
		} else
119
			insert_table(mp, rp);
120
		break;
121
122
	case LOOK_UP:
123
		ptr = find_match(mp);
124
		if (ptr != NULL) {
125
			rp->id_num = htonl(ptr->id_num);
126
			rp->addr = ptr->addr;
127
			rp->addr.sa_family = ptr->addr.sa_family;
128
			rp->answer = SUCCESS;
129
		} else
130
			rp->answer = NOT_HERE;
131
		break;
132
133
	case DELETE:
134
		rp->answer = delete_invite(mp->id_num);
135
		break;
136
137
	default:
138
		rp->answer = UNKNOWN_REQUEST;
139
		break;
140
	}
141
	if (debug)
142
		print_response("process_request", rp);
143
}
144
145
void
146
do_announce(CTL_MSG *mp, CTL_RESPONSE *rp)
147
{
148
	struct hostent *hp;
149
	CTL_MSG *ptr;
150
	int result;
151
152
	/* see if the user is logged */
153
	result = find_user(mp->r_name, mp->r_tty, sizeof(mp->r_tty));
154
	if (result != SUCCESS) {
155
		rp->answer = result;
156
		return;
157
	}
158
	hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
159
		sizeof(struct in_addr), AF_INET);
160
	if (hp == NULL) {
161
		rp->answer = MACHINE_UNKNOWN;
162
		return;
163
	}
164
	ptr = find_request(mp);
165
	if (ptr == (CTL_MSG *) 0) {
166
		insert_table(mp, rp);
167
		rp->answer = announce(mp, hp->h_name);
168
		return;
169
	}
170
	if (mp->id_num > ptr->id_num) {
171
		/*
172
		 * This is an explicit re-announce, so update the id_num
173
		 * field to avoid duplicates and re-announce the talk.
174
		 */
175
		ptr->id_num = new_id();
176
		rp->id_num = htonl(ptr->id_num);
177
		rp->answer = announce(mp, hp->h_name);
178
	} else {
179
		/* a duplicated request, so ignore it */
180
		rp->id_num = htonl(ptr->id_num);
181
		rp->answer = SUCCESS;
182
	}
183
}
184
185
/*
186
 * Search utmp for the local user
187
 */
188
int
189
find_user(char *name, char *tty, size_t ttyl)
190
{
191
	struct utmp ubuf, ubuf1;
192
	int status;
193
	FILE *fp;
194
	char line[UT_LINESIZE+1];
195
	char ftty[PATH_MAX];
196
	time_t	idle, now;
197
198
	time(&now);
199
	idle = INT_MAX;
200
	if ((fp = fopen(_PATH_UTMP, "r")) == NULL) {
201
		fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
202
		return (FAILED);
203
	}
204
#define SCMPN(a, b)	strncmp(a, b, sizeof(a))
205
	status = NOT_HERE;
206
	(void) strlcpy(ftty, _PATH_DEV, sizeof(ftty));
207
	while (fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1)
208
		if (SCMPN(ubuf.ut_name, name) == 0) {
209
			if (*tty == '\0') {
210
				/* no particular tty was requested */
211
				struct stat statb;
212
213
				memcpy(line, ubuf.ut_line, UT_LINESIZE);
214
				line[sizeof(line)-1] = '\0';
215
				ftty[sizeof(_PATH_DEV)-1] = '\0';
216
				strlcat(ftty, line, sizeof(ftty));
217
				if (stat(ftty, &statb) == 0) {
218
					if (!(statb.st_mode & S_IWGRP)) {
219
						if (status == NOT_HERE)
220
							status = PERMISSION_DENIED;
221
					} else if (now - statb.st_atime < idle) {
222
						idle = now - statb.st_atime;
223
						status = SUCCESS;
224
						ubuf1 = ubuf;
225
					}
226
				}
227
			} else if (SCMPN(ubuf.ut_line, tty) == 0) {
228
				status = SUCCESS;
229
				break;
230
			}
231
		}
232
	fclose(fp);
233
	if (*tty == '\0' && status == SUCCESS) {
234
		memcpy(line, ubuf1.ut_line, UT_LINESIZE);
235
		line[sizeof(line)-1] = '\0';
236
		strlcpy(tty, line, ttyl);
237
	}
238
	return (status);
239
}