Print this page
1666 libwrap is 32bit only
Reviewed by: Andrew Stormont <andyjstormont@gmail.com>
Reviewed by: Garrett D'Amore <garrett.damore@dey-sys.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libwrap/tli.c
+++ new/usr/src/lib/libwrap/tli.c
1 1 /*
2 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 -#pragma ident "%Z%%M% %I% %E% SMI"
7 -
8 6 /*
9 7 * tli_host() determines the type of transport (connected, connectionless),
10 8 * the transport address of a client host, and the transport address of a
11 9 * server endpoint. In addition, it provides methods to map a transport
12 10 * address to a printable host name or address. Socket address results are
13 11 * in static memory; tli structures are allocated from the heap.
14 12 *
15 13 * The result from the hostname lookup method is STRING_PARANOID when a host
16 14 * pretends to have someone elses name, or when a host name is available but
17 15 * could not be verified.
18 16 *
19 17 * Diagnostics are reported through syslog(3).
20 18 *
21 19 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
22 20 */
23 21
24 22 #ifndef lint
25 23 static char sccsid[] = "@(#) tli.c 1.15 97/03/21 19:27:25";
26 24 #endif
27 25
28 26 #ifdef TLI
29 27
30 28 /* System libraries. */
31 29
32 30 #include <sys/types.h>
33 31 #include <sys/param.h>
34 32 #include <sys/stream.h>
35 33 #include <sys/stat.h>
36 34 #include <sys/mkdev.h>
37 35 #include <sys/tiuser.h>
38 36 #include <sys/timod.h>
39 37 #include <sys/socket.h>
40 38 #include <netinet/in.h>
41 39 #include <stdio.h>
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
42 40 #include <stdlib.h>
43 41 #include <unistd.h>
44 42 #include <syslog.h>
45 43 #include <errno.h>
46 44 #include <netconfig.h>
47 45 #include <netdir.h>
48 46 #include <string.h>
49 47
50 48 extern char *nc_sperror();
51 49 extern int errno;
52 -extern char *sys_errlist[];
53 -extern int sys_nerr;
54 50 extern int t_errno;
55 51 extern char *t_errlist[];
56 52 extern int t_nerr;
57 53
58 54 /* Local stuff. */
59 55
60 56 #include "tcpd.h"
61 57
62 58 /* Forward declarations. */
63 59
64 60 static void tli_endpoints();
65 61 static struct netconfig *tli_transport();
66 62 static void tli_hostname();
67 63 static void tli_hostaddr();
68 64 static void tli_cleanup();
69 65 static char *tli_error();
70 66 static void tli_sink();
71 67
72 68 /* tli_host - look up endpoint addresses and install conversion methods */
73 69
74 70 void tli_host(request)
75 71 struct request_info *request;
76 72 {
77 73 static struct sockaddr_gen client;
78 74 static struct sockaddr_gen server;
79 75
80 76 /*
81 77 * If we discover that we are using an IP transport, pretend we never
82 78 * were here. Otherwise, use the transport-independent method and stick
83 79 * to generic network addresses. XXX hard-coded protocol family name.
84 80 */
85 81
86 82 tli_endpoints(request);
87 83 if ((request->config = tli_transport(request->fd)) != 0
88 84 && (STR_EQ(request->config->nc_protofmly, "inet")
89 85 #ifdef HAVE_IPV6
90 86 || STR_EQ(request->config->nc_protofmly, "inet6")
91 87 #endif
92 88 )) {
93 89 if (request->client->unit != 0) {
94 90 memcpy(&client, request->client->unit->addr.buf,
95 91 SGSOCKADDRSZ((struct sockaddr_gen*)
96 92 request->client->unit->addr.buf));
97 93 request->client->sin = &client;
98 94 sockgen_simplify(&client);
99 95 }
100 96 if (request->server->unit != 0) {
101 97 memcpy(&server, request->server->unit->addr.buf,
102 98 SGSOCKADDRSZ((struct sockaddr_gen*)
103 99 request->server->unit->addr.buf));
104 100 request->server->sin = &server;
105 101 sockgen_simplify(&server);
106 102 }
107 103 tli_cleanup(request);
108 104 sock_methods(request);
109 105 } else {
110 106 request->hostname = tli_hostname;
111 107 request->hostaddr = tli_hostaddr;
112 108 request->cleanup = tli_cleanup;
113 109 }
114 110 }
115 111
116 112 /* tli_cleanup - cleanup some dynamically-allocated data structures */
117 113
118 114 static void tli_cleanup(request)
119 115 struct request_info *request;
120 116 {
121 117 if (request->config != 0)
122 118 freenetconfigent(request->config);
123 119 if (request->client->unit != 0)
124 120 t_free((char *) request->client->unit, T_UNITDATA);
125 121 if (request->server->unit != 0)
126 122 t_free((char *) request->server->unit, T_UNITDATA);
127 123 }
128 124
129 125 /* tli_endpoints - determine TLI client and server endpoint information */
130 126
131 127 static void tli_endpoints(request)
132 128 struct request_info *request;
133 129 {
134 130 struct t_unitdata *server;
135 131 struct t_unitdata *client;
136 132 int fd = request->fd;
137 133 int flags;
138 134
139 135 /*
140 136 * Determine the client endpoint address. With unconnected services, peek
141 137 * at the sender address of the pending protocol data unit without
142 138 * popping it off the receive queue. This trick works because only the
143 139 * address member of the unitdata structure has been allocated.
144 140 *
145 141 * Beware of successful returns with zero-length netbufs (for example,
146 142 * Solaris 2.3 with ticlts transport). The netdir(3) routines can't
147 143 * handle that. Assume connection-less transport when TI_GETPEERNAME
148 144 * produces no usable result, even when t_rcvudata() is unable to figure
149 145 * out the peer address. Better to hang than to loop.
150 146 */
151 147
152 148 if ((client = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
153 149 tcpd_warn("t_alloc: %s", tli_error());
154 150 return;
155 151 }
156 152 if (ioctl(fd, TI_GETPEERNAME, &client->addr) < 0 || client->addr.len == 0) {
157 153 request->sink = tli_sink;
158 154 if (t_rcvudata(fd, client, &flags) < 0 || client->addr.len == 0) {
159 155 tcpd_warn("can't get client address: %s", tli_error());
160 156 t_free((void *) client, T_UNITDATA);
161 157 return;
162 158 }
163 159 }
164 160 request->client->unit = client;
165 161
166 162 /*
167 163 * Look up the server endpoint address. This can be used for filtering on
168 164 * server address or name, or to look up the client user.
169 165 */
170 166
171 167 if ((server = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ADDR)) == 0) {
172 168 tcpd_warn("t_alloc: %s", tli_error());
173 169 return;
174 170 }
175 171 if (ioctl(fd, TI_GETMYNAME, &server->addr) < 0) {
176 172 tcpd_warn("TI_GETMYNAME: %m");
177 173 t_free((void *) server, T_UNITDATA);
178 174 return;
179 175 }
180 176 request->server->unit = server;
181 177 }
182 178
183 179 /* tli_transport - find out TLI transport type */
184 180
185 181 static struct netconfig *tli_transport(fd)
186 182 int fd;
187 183 {
188 184 struct stat from_client;
189 185 struct stat from_config;
190 186 void *handlep;
191 187 struct netconfig *config;
192 188
193 189 /*
194 190 * Assuming that the network device is a clone device, we must compare
195 191 * the major device number of stdin to the minor device number of the
196 192 * devices listed in the netconfig table.
197 193 */
198 194
199 195 if (fstat(fd, &from_client) != 0) {
200 196 tcpd_warn("fstat(fd %d): %m", fd);
201 197 return (0);
202 198 }
203 199 if ((handlep = setnetconfig()) == 0) {
204 200 tcpd_warn("setnetconfig: %m");
205 201 return (0);
206 202 }
207 203 while (config = getnetconfig(handlep)) {
208 204 if (stat(config->nc_device, &from_config) == 0) {
209 205 if (minor(from_config.st_rdev) == major(from_client.st_rdev) ||
210 206 /* XXX: Solaris 8 no longer has clone devices for IP */
211 207 major(from_config.st_rdev) == major(from_client.st_rdev))
212 208 break;
213 209 }
214 210 }
215 211 if (config == 0) {
216 212 tcpd_warn("unable to identify transport protocol");
217 213 return (0);
218 214 }
219 215
220 216 /*
221 217 * Something else may clobber our getnetconfig() result, so we'd better
222 218 * acquire our private copy.
223 219 */
224 220
225 221 if ((config = getnetconfigent(config->nc_netid)) == 0) {
226 222 tcpd_warn("getnetconfigent(%s): %s", config->nc_netid, nc_sperror());
227 223 return (0);
228 224 }
229 225 return (config);
230 226 }
231 227
232 228 /* tli_hostaddr - map TLI transport address to printable address */
233 229
234 230 static void tli_hostaddr(host)
235 231 struct host_info *host;
236 232 {
237 233 struct request_info *request = host->request;
238 234 struct netconfig *config = request->config;
239 235 struct t_unitdata *unit = host->unit;
240 236 char *uaddr;
241 237
242 238 if (config != 0 && unit != 0
243 239 && (uaddr = taddr2uaddr(config, &unit->addr)) != 0) {
244 240 STRN_CPY(host->addr, uaddr, sizeof(host->addr));
245 241 free(uaddr);
246 242 }
247 243 }
248 244
249 245 /* tli_hostname - map TLI transport address to hostname */
250 246
251 247 static void tli_hostname(host)
252 248 struct host_info *host;
253 249 {
254 250 struct request_info *request = host->request;
255 251 struct netconfig *config = request->config;
256 252 struct t_unitdata *unit = host->unit;
257 253 struct nd_hostservlist *servlist;
258 254
259 255 if (config != 0 && unit != 0
260 256 && netdir_getbyaddr(config, &servlist, &unit->addr) == ND_OK) {
261 257
262 258 struct nd_hostserv *service = servlist->h_hostservs;
263 259 struct nd_addrlist *addr_list;
264 260 int found = 0;
265 261
266 262 if (netdir_getbyname(config, service, &addr_list) != ND_OK) {
267 263
268 264 /*
269 265 * Unable to verify that the name matches the address. This may
270 266 * be a transient problem or a botched name server setup. We
271 267 * decide to play safe.
272 268 */
273 269
274 270 tcpd_warn("can't verify hostname: netdir_getbyname(%.*s) failed",
275 271 STRING_LENGTH, service->h_host);
276 272
277 273 } else {
278 274
279 275 /*
280 276 * Look up the host address in the address list we just got. The
281 277 * comparison is done on the textual representation, because the
282 278 * transport address is an opaque structure that may have holes
283 279 * with uninitialized garbage. This approach obviously loses when
284 280 * the address does not have a textual representation.
285 281 */
286 282
287 283 char *uaddr = eval_hostaddr(host);
288 284 char *ua;
289 285 int i;
290 286
291 287 for (i = 0; found == 0 && i < addr_list->n_cnt; i++) {
292 288 if ((ua = taddr2uaddr(config, &(addr_list->n_addrs[i]))) != 0) {
293 289 found = !strcmp(ua, uaddr);
294 290 free(ua);
295 291 }
296 292 }
297 293 netdir_free((void *) addr_list, ND_ADDRLIST);
298 294
299 295 /*
300 296 * When the host name does not map to the initial address, assume
301 297 * someone has compromised a name server. More likely someone
302 298 * botched it, but that could be dangerous, too.
303 299 */
304 300
305 301 if (found == 0)
306 302 tcpd_warn("host name/address mismatch: %s != %.*s",
307 303 host->addr, STRING_LENGTH, service->h_host);
308 304 }
309 305 STRN_CPY(host->name, found ? service->h_host : paranoid,
310 306 sizeof(host->name));
311 307 netdir_free((void *) servlist, ND_HOSTSERVLIST);
312 308 }
↓ open down ↓ |
249 lines elided |
↑ open up ↑ |
313 309 }
314 310
315 311 /* tli_error - convert tli error number to text */
316 312
317 313 static char *tli_error()
318 314 {
319 315 static char buf[40];
320 316
321 317 if (t_errno != TSYSERR) {
322 318 if (t_errno < 0 || t_errno >= t_nerr) {
323 - sprintf(buf, "Unknown TLI error %d", t_errno);
319 + snprintf(buf, sizeof (buf), "Unknown TLI error %d", t_errno);
324 320 return (buf);
325 321 } else {
326 322 return (t_errlist[t_errno]);
327 323 }
328 324 } else {
329 - if (errno < 0 || errno >= sys_nerr) {
330 - sprintf(buf, "Unknown UNIX error %d", errno);
331 - return (buf);
332 - } else {
333 - return (sys_errlist[errno]);
334 - }
325 + STRN_CPY(buf, strerror(errno), sizeof (buf));
326 + return (buf);
335 327 }
336 328 }
337 329
338 330 /* tli_sink - absorb unreceived datagram */
339 331
340 332 static void tli_sink(fd)
341 333 int fd;
342 334 {
343 335 struct t_unitdata *unit;
344 336 int flags;
345 337
346 338 /*
347 339 * Something went wrong. Absorb the datagram to keep inetd from looping.
348 340 * Allocate storage for address, control and data. If that fails, sleep
349 341 * for a couple of seconds in an attempt to keep inetd from looping too
350 342 * fast.
351 343 */
352 344
353 345 if ((unit = (struct t_unitdata *) t_alloc(fd, T_UNITDATA, T_ALL)) == 0) {
354 346 tcpd_warn("t_alloc: %s", tli_error());
355 347 sleep(5);
356 348 } else {
357 349 (void) t_rcvudata(fd, unit, &flags);
358 350 t_free((void *) unit, T_UNITDATA);
359 351 }
360 352 }
361 353
362 354 #endif /* TLI */
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX