1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This library contains a set of routines that are shared amongst inetd,
28 * inetadm, inetconv and the formerly internal inetd services. Amongst the
29 * routines are ones for reading and validating the configuration of an
30 * inetd service, a routine for requesting inetd be refreshed, ones for
31 * reading, calculating and writing the hash of an inetd.conf file, and
32 * numerous utility routines shared amongst the formerly internal inetd
33 * services.
34 */
35
36
37 #include <string.h>
38 #include <rpc/rpcent.h>
39 #include <netdb.h>
40 #include <limits.h>
41 #include <errno.h>
42 #include <inetsvc.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <nss_dbdefs.h>
46 #include <stdio.h>
47 #include <fcntl.h>
48 #include <pwd.h>
49 #include <md5.h>
50 #include <arpa/inet.h>
51 #include <netinet/in.h>
52 #include <signal.h>
53 #include <syslog.h>
54 #include <libintl.h>
55 #include <stdlib.h>
56 #include <assert.h>
57 #include <rpc/nettype.h>
58 #include <libuutil.h>
59
60 static inetd_prop_t inetd_properties[] = {
61 {PR_SVC_NAME_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_STRING,
62 B_FALSE, IVE_UNSET, NULL, B_FALSE},
63 {PR_SOCK_TYPE_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_STRING,
64 B_FALSE, IVE_UNSET, NULL, B_FALSE},
65 {PR_PROTO_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_STRING_LIST,
66 B_FALSE, IVE_UNSET, NULL, B_FALSE},
67 {PR_ISRPC_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
68 B_FALSE, IVE_UNSET, NULL, B_FALSE},
69 {PR_RPC_LW_VER_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
70 B_FALSE, IVE_UNSET, NULL, B_FALSE},
71 {PR_RPC_HI_VER_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
72 B_FALSE, IVE_UNSET, NULL, B_FALSE},
73 {PR_ISWAIT_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
74 B_FALSE, IVE_UNSET, NULL, B_FALSE},
75 {PR_EXEC_NAME, START_METHOD_NAME, INET_TYPE_STRING,
76 B_FALSE, IVE_UNSET, NULL, B_FALSE},
77 {PR_ARG0_NAME, START_METHOD_NAME, INET_TYPE_STRING,
78 B_FALSE, IVE_UNSET, NULL, B_FALSE},
79 {PR_USER_NAME, START_METHOD_NAME, INET_TYPE_STRING,
80 B_FALSE, IVE_UNSET, NULL, B_FALSE},
81 {PR_BIND_ADDR_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_STRING,
82 B_TRUE, IVE_UNSET, NULL, B_FALSE},
83 {PR_BIND_FAIL_MAX_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
84 B_TRUE, IVE_UNSET, NULL, B_FALSE},
85 {PR_BIND_FAIL_INTVL_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
86 B_TRUE, IVE_UNSET, NULL, B_FALSE},
87 {PR_CON_RATE_MAX_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
88 B_TRUE, IVE_UNSET, NULL, B_FALSE},
89 {PR_MAX_COPIES_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
90 B_TRUE, IVE_UNSET, NULL, B_FALSE},
91 {PR_CON_RATE_OFFLINE_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
92 B_TRUE, IVE_UNSET, NULL, B_FALSE},
93 {PR_MAX_FAIL_RATE_CNT_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
94 B_TRUE, IVE_UNSET, NULL, B_FALSE},
95 {PR_MAX_FAIL_RATE_INTVL_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
96 B_TRUE, IVE_UNSET, NULL, B_FALSE},
97 {PR_INHERIT_ENV_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
98 B_TRUE, IVE_UNSET, NULL, B_FALSE},
99 {PR_DO_TCP_TRACE_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
100 B_TRUE, IVE_UNSET, NULL, B_FALSE},
101 {PR_DO_TCP_WRAPPERS_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
102 B_TRUE, IVE_UNSET, NULL, B_FALSE},
103 {PR_CONNECTION_BACKLOG_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_INTEGER,
104 B_TRUE, IVE_UNSET, NULL, B_FALSE},
105 {PR_DO_TCP_KEEPALIVE_NAME, PG_NAME_SERVICE_CONFIG, INET_TYPE_BOOLEAN,
106 B_TRUE, IVE_UNSET, NULL, B_FALSE},
107 {NULL},
108 };
109
110 #define INETSVC_SVC_BUF_MAX (NSS_BUFLEN_RPC + sizeof (struct rpcent))
111
112 #define DIGEST_LEN 16
113 #define READ_BUFSIZ 8192
114 #define HASH_PG "hash"
115 #define HASH_PROP "md5sum"
116
117 /*
118 * Inactivity timer used by dg_template(). After this many seconds of network
119 * inactivity dg_template will cease listening for new datagrams and return.
120 */
121 #define DG_INACTIVITY_TIMEOUT 60
122
123 static boolean_t v6_proto(const char *);
124
125 boolean_t
is_tlx_service(inetd_prop_t * props)126 is_tlx_service(inetd_prop_t *props)
127 {
128 return ((strcmp(SOCKTYPE_TLI_STR,
129 props[PT_SOCK_TYPE_INDEX].ip_value.iv_string) == 0) ||
130 (strcmp(SOCKTYPE_XTI_STR,
131 props[PT_SOCK_TYPE_INDEX].ip_value.iv_string) == 0));
132 }
133
134 /*
135 * Return a reference to the property table. Number of entries in table
136 * are returned in num_elements argument.
137 */
138 inetd_prop_t *
get_prop_table(size_t * num_elements)139 get_prop_table(size_t *num_elements)
140 {
141 *num_elements = sizeof (inetd_properties) / sizeof (inetd_prop_t);
142 return (&inetd_properties[0]);
143 }
144
145 /*
146 * find_prop takes an array of inetd_prop_t's, the name of an inetd
147 * property, the type expected, and returns a pointer to the matching member,
148 * or NULL.
149 */
150 inetd_prop_t *
find_prop(const inetd_prop_t * prop,const char * name,inet_type_t type)151 find_prop(const inetd_prop_t *prop, const char *name, inet_type_t type)
152 {
153 int i = 0;
154
155 while (prop[i].ip_name != NULL && strcmp(name, prop[i].ip_name) != 0)
156 i++;
157
158 if (prop[i].ip_name == NULL)
159 return (NULL);
160
161 if (prop[i].ip_type != type)
162 return (NULL);
163
164 return ((inetd_prop_t *)prop + i);
165 }
166
167 /*
168 * get_prop_value_int takes an array of inetd_prop_t's together with the name of
169 * an inetd property and returns the value of the property. It's expected that
170 * the property exists in the searched array.
171 */
172 int64_t
get_prop_value_int(const inetd_prop_t * prop,const char * name)173 get_prop_value_int(const inetd_prop_t *prop, const char *name)
174 {
175 inetd_prop_t *p;
176
177 p = find_prop(prop, name, INET_TYPE_INTEGER);
178 return (p->ip_value.iv_int);
179 }
180
181 /*
182 * get_prop_value_count takes an array of inetd_prop_t's together with the name
183 * of an inetd property and returns the value of the property. It's expected
184 * that the property exists in the searched array.
185 */
186 uint64_t
get_prop_value_count(const inetd_prop_t * prop,const char * name)187 get_prop_value_count(const inetd_prop_t *prop, const char *name)
188 {
189 inetd_prop_t *p;
190
191 p = find_prop(prop, name, INET_TYPE_COUNT);
192 return (p->ip_value.iv_cnt);
193 }
194
195 /*
196 * get_prop_value_boolean takes an array of inetd_prop_t's together with the
197 * name of an inetd property and returns the value of the property. It's
198 * expected that the property exists in the searched array.
199 */
200 boolean_t
get_prop_value_boolean(const inetd_prop_t * prop,const char * name)201 get_prop_value_boolean(const inetd_prop_t *prop, const char *name)
202 {
203 inetd_prop_t *p;
204
205 p = find_prop(prop, name, INET_TYPE_BOOLEAN);
206 return (p->ip_value.iv_boolean);
207 }
208
209 /*
210 * get_prop_value_string takes an array of inetd_prop_t's together with
211 * the name of an inetd property and returns the value of the property.
212 * It's expected that the property exists in the searched array.
213 */
214 const char *
get_prop_value_string(const inetd_prop_t * prop,const char * name)215 get_prop_value_string(const inetd_prop_t *prop, const char *name)
216 {
217 inetd_prop_t *p;
218
219 p = find_prop(prop, name, INET_TYPE_STRING);
220 return (p->ip_value.iv_string);
221 }
222
223 /*
224 * get_prop_value_string_list takes an array of inetd_prop_t's together
225 * with the name of an inetd property and returns the value of the property.
226 * It's expected that the property exists in the searched array.
227 */
228 const char **
get_prop_value_string_list(const inetd_prop_t * prop,const char * name)229 get_prop_value_string_list(const inetd_prop_t *prop, const char *name)
230 {
231 inetd_prop_t *p;
232
233 p = find_prop(prop, name, INET_TYPE_STRING_LIST);
234 return ((const char **)p->ip_value.iv_string_list);
235 }
236
237 /*
238 * put_prop_value_int takes an array of inetd_prop_t's, a name of an inetd
239 * property, and a value. It copies the value into the property
240 * in the array. It's expected that the property exists in the searched array.
241 */
242 void
put_prop_value_int(inetd_prop_t * prop,const char * name,int64_t value)243 put_prop_value_int(inetd_prop_t *prop, const char *name, int64_t value)
244 {
245 inetd_prop_t *p;
246
247 p = find_prop(prop, name, INET_TYPE_INTEGER);
248 p->ip_value.iv_int = value;
249 p->ip_error = IVE_VALID;
250 }
251
252 /*
253 * put_prop_value_count takes an array of inetd_prop_t's, a name of an inetd
254 * property, and a value. It copies the value into the property
255 * in the array. It's expected that the property exists in the searched array.
256 */
257 void
put_prop_value_count(inetd_prop_t * prop,const char * name,uint64_t value)258 put_prop_value_count(inetd_prop_t *prop, const char *name, uint64_t value)
259 {
260 inetd_prop_t *p;
261
262 p = find_prop(prop, name, INET_TYPE_COUNT);
263 p->ip_value.iv_cnt = value;
264 p->ip_error = IVE_VALID;
265 }
266
267 /*
268 * put_prop_value_boolean takes an array of inetd_prop_t's, a name of an inetd
269 * property, and a value. It copies the value into the property
270 * in the array. It's expected that the property exists in the searched array.
271 */
272 void
put_prop_value_boolean(inetd_prop_t * prop,const char * name,boolean_t value)273 put_prop_value_boolean(inetd_prop_t *prop, const char *name, boolean_t value)
274 {
275 inetd_prop_t *p;
276
277 p = find_prop(prop, name, INET_TYPE_BOOLEAN);
278 p->ip_value.iv_boolean = value;
279 p->ip_error = IVE_VALID;
280 }
281
282 /*
283 * put_prop_value_string takes an array of inetd_prop_t's, a name of an inetd
284 * property, and a value. It duplicates the value into the property
285 * in the array, and returns B_TRUE for success and B_FALSE for failure. It's
286 * expected that the property exists in the searched array.
287 */
288 boolean_t
put_prop_value_string(inetd_prop_t * prop,const char * name,const char * value)289 put_prop_value_string(inetd_prop_t *prop, const char *name, const char *value)
290 {
291 inetd_prop_t *p;
292
293 if (strlen(value) >= scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH)) {
294 errno = E2BIG;
295 return (B_FALSE);
296 }
297 p = find_prop(prop, name, INET_TYPE_STRING);
298 if ((p->ip_value.iv_string = strdup(value)) == NULL)
299 return (B_FALSE);
300 p->ip_error = IVE_VALID;
301 return (B_TRUE);
302 }
303
304 /*
305 * put_prop_value_string_list takes an array of inetd_prop_t's, a name of an
306 * inetd property, and a value. It copies the value into the property
307 * in the array. It's expected that the property exists in the searched array.
308 */
309 void
put_prop_value_string_list(inetd_prop_t * prop,const char * name,char ** value)310 put_prop_value_string_list(inetd_prop_t *prop, const char *name, char **value)
311 {
312 inetd_prop_t *p;
313
314 p = find_prop(prop, name, INET_TYPE_STRING_LIST);
315 p->ip_value.iv_string_list = value;
316 p->ip_error = IVE_VALID;
317 }
318
319 static void
destroy_rpc_info(rpc_info_t * rpc)320 destroy_rpc_info(rpc_info_t *rpc)
321 {
322 if (rpc != NULL) {
323 free(rpc->netbuf.buf);
324 free(rpc->netid);
325 free(rpc);
326 }
327 }
328
329 /*
330 * If 'proto' is a valid netid, and no memory allocations fail, returns a
331 * pointer to an allocated and initialized rpc_info_t, else NULL.
332 */
333 static rpc_info_t *
create_rpc_info(const char * proto,int pnum,int low_ver,int high_ver)334 create_rpc_info(const char *proto, int pnum, int low_ver, int high_ver)
335 {
336 struct netconfig *nconf;
337 rpc_info_t *ret;
338
339 if ((ret = calloc(1, sizeof (rpc_info_t))) == NULL)
340 return (NULL);
341
342 ret->netbuf.maxlen = sizeof (struct sockaddr_storage);
343 if ((ret->netbuf.buf = malloc(ret->netbuf.maxlen)) == NULL) {
344 free(ret);
345 return (NULL);
346 }
347
348 ret->prognum = pnum;
349 ret->lowver = low_ver;
350 ret->highver = high_ver;
351
352 if ((ret->netid = strdup(proto)) == NULL) {
353 destroy_rpc_info(ret);
354 return (NULL);
355 }
356
357 /*
358 * Determine whether this is a loopback transport. If getnetconfigent()
359 * fails, we check to see whether it was the result of a v6 proto
360 * being specified and no IPv6 interface was configured on the system;
361 * if this holds, we know it must not be a loopback transport, else
362 * getnetconfigent() must be miss-behaving, so return an error.
363 */
364 if ((nconf = getnetconfigent(proto)) != NULL) {
365 if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
366 ret->is_loopback = B_TRUE;
367 freenetconfigent(nconf);
368 } else if (!v6_proto(proto)) {
369 destroy_rpc_info(ret);
370 return (NULL);
371 }
372
373 return (ret);
374 }
375
376 void
destroy_tlx_info(tlx_info_t * tlx)377 destroy_tlx_info(tlx_info_t *tlx)
378 {
379 tlx_conn_ind_t *ci;
380 void *cookie = NULL;
381
382 if (tlx == NULL)
383 return;
384
385 free(tlx->dev_name);
386
387 if (tlx->conn_ind_queue != NULL) {
388 /* free up conn ind queue */
389 while ((ci = uu_list_teardown(tlx->conn_ind_queue, &cookie)) !=
390 NULL) {
391 (void) t_free((char *)ci->call, T_CALL);
392 free(ci);
393 }
394 uu_list_destroy(tlx->conn_ind_queue);
395 }
396
397 free(tlx->local_addr.buf);
398 free(tlx);
399 }
400
401 /*
402 * Allocate, initialize and return a pointer to a tlx_info_t structure.
403 * On memory allocation failure NULL is returned.
404 */
405 static tlx_info_t *
create_tlx_info(const char * proto,uu_list_pool_t * conn_ind_pool)406 create_tlx_info(const char *proto, uu_list_pool_t *conn_ind_pool)
407 {
408 size_t sz;
409 tlx_info_t *ret;
410
411 if ((ret = calloc(1, sizeof (tlx_info_t))) == NULL)
412 return (NULL);
413
414 ret->local_addr.maxlen = sizeof (struct sockaddr_storage);
415 if ((ret->local_addr.buf = calloc(1, ret->local_addr.maxlen)) == NULL)
416 goto fail;
417
418 if ((ret->conn_ind_queue = uu_list_create(conn_ind_pool, NULL, 0)) ==
419 NULL)
420 goto fail;
421
422 ret->local_addr.len = sizeof (struct sockaddr_in);
423 /* LINTED E_BAD_PTR_CAST_ALIGN */
424 ((struct sockaddr_in *)(ret->local_addr.buf))->sin_family = AF_INET;
425 /* LINTED E_BAD_PTR_CAST_ALIGN */
426 ((struct sockaddr_in *)(ret->local_addr.buf))->sin_addr.s_addr =
427 htonl(INADDR_ANY);
428
429 /* store device name, constructing if necessary */
430 if (proto[0] != '/') {
431 sz = strlen("/dev/") + strlen(proto) + 1;
432 if ((ret->dev_name = malloc(sz)) == NULL)
433 goto fail;
434 (void) snprintf(ret->dev_name, sz, "/dev/%s", proto);
435 } else if ((ret->dev_name = strdup(proto)) == NULL) {
436 goto fail;
437 }
438
439 return (ret);
440
441 fail:
442 destroy_tlx_info(ret);
443 return (NULL);
444 }
445
446 /*
447 * Returns B_TRUE if this is a v6 protocol valid for both TLI and socket
448 * based services, else B_FALSE.
449 */
450 static boolean_t
v6_proto(const char * proto)451 v6_proto(const char *proto)
452 {
453 return ((strcmp(proto, SOCKET_PROTO_TCP6) == 0) ||
454 (strcmp(proto, SOCKET_PROTO_UDP6) == 0));
455 }
456
457 /*
458 * Returns B_TRUE if this is a valid v6 protocol for a socket based service,
459 * else B_FALSE.
460 */
461 static boolean_t
v6_socket_proto(const char * proto)462 v6_socket_proto(const char *proto)
463 {
464 return ((strcmp(proto, SOCKET_PROTO_SCTP6) == 0) ||
465 v6_proto(proto));
466
467 }
468
469 static boolean_t
valid_socket_proto(const char * proto)470 valid_socket_proto(const char *proto)
471 {
472 return (v6_socket_proto(proto) ||
473 (strcmp(proto, SOCKET_PROTO_SCTP) == 0) ||
474 (strcmp(proto, SOCKET_PROTO_TCP) == 0) ||
475 (strcmp(proto, SOCKET_PROTO_UDP) == 0));
476 }
477
478 /*
479 * Free all the memory consumed by 'pi' associated with the instance
480 * with configuration 'cfg'.
481 */
482 static void
destroy_proto_info(basic_cfg_t * cfg,proto_info_t * pi)483 destroy_proto_info(basic_cfg_t *cfg, proto_info_t *pi)
484 {
485 if (pi == NULL)
486 return;
487
488 assert(pi->listen_fd == -1);
489
490 free(pi->proto);
491 if (pi->ri != NULL)
492 destroy_rpc_info(pi->ri);
493 if (cfg->istlx) {
494 destroy_tlx_info((tlx_info_t *)pi);
495 } else {
496 free(pi);
497 }
498 }
499
500 void
destroy_proto_list(basic_cfg_t * cfg)501 destroy_proto_list(basic_cfg_t *cfg)
502 {
503 void *cookie = NULL;
504 proto_info_t *pi;
505
506 if (cfg->proto_list == NULL)
507 return;
508
509 while ((pi = uu_list_teardown(cfg->proto_list, &cookie)) != NULL)
510 destroy_proto_info(cfg, pi);
511 uu_list_destroy(cfg->proto_list);
512 cfg->proto_list = NULL;
513 }
514
515 void
destroy_basic_cfg(basic_cfg_t * cfg)516 destroy_basic_cfg(basic_cfg_t *cfg)
517 {
518 if (cfg == NULL)
519 return;
520
521 free(cfg->bind_addr);
522 destroy_proto_list(cfg);
523 free(cfg->svc_name);
524 free(cfg);
525 }
526
527 /*
528 * Overwrite the socket address with the address specified by the
529 * bind_addr property.
530 */
531 static int
set_bind_addr(struct sockaddr_storage * ss,char * bind_addr)532 set_bind_addr(struct sockaddr_storage *ss, char *bind_addr)
533 {
534 struct addrinfo hints, *res;
535
536 if (bind_addr == NULL || bind_addr[0] == '\0')
537 return (0);
538
539 (void) memset(&hints, 0, sizeof (hints));
540 hints.ai_flags = AI_DEFAULT;
541 hints.ai_socktype = SOCK_STREAM;
542 hints.ai_family = ss->ss_family;
543 if (getaddrinfo(bind_addr, "", &hints, &res) != 0) {
544 return (-1);
545 } else {
546 void *p = res->ai_addr;
547 struct sockaddr_storage *newss = p;
548
549 (void) memcpy(SS_SINADDR(*ss), SS_SINADDR(*newss),
550 SS_ADDRLEN(*ss));
551 freeaddrinfo(res);
552 return (0);
553 }
554 }
555
556 /*
557 * valid_props validates all the properties in an array of inetd_prop_t's,
558 * marking each property as valid or invalid. If any properties are invalid,
559 * it returns B_FALSE, otherwise it returns B_TRUE. Note that some properties
560 * are interdependent, so if one is invalid, it leaves others in an
561 * indeterminate state (such as ISRPC and SVC_NAME). In this case, the
562 * indeterminate property will be marked valid. IE, the only properties
563 * marked invalid are those that are KNOWN to be invalid.
564 *
565 * Piggy-backed onto this validation if 'fmri' is non-NULL is the construction
566 * of a structured configuration, a basic_cfg_t, which is used by inetd.
567 * If 'fmri' is set then the latter three parameters need to be set to
568 * non-NULL values, and if the configuration is valid, the storage referenced
569 * by cfgpp is set to point at an initialized basic_cfg_t.
570 */
571 boolean_t
valid_props(inetd_prop_t * prop,const char * fmri,basic_cfg_t ** cfgpp,uu_list_pool_t * proto_info_pool,uu_list_pool_t * tlx_ci_pool)572 valid_props(inetd_prop_t *prop, const char *fmri, basic_cfg_t **cfgpp,
573 uu_list_pool_t *proto_info_pool, uu_list_pool_t *tlx_ci_pool)
574 {
575 char *bufp, *cp;
576 boolean_t ret = B_TRUE;
577 int i;
578 long uidl;
579 boolean_t isrpc;
580 int sock_type_id;
581 int rpc_pnum;
582 int rpc_lv, rpc_hv;
583 basic_cfg_t *cfg;
584 char *proto = NULL;
585 int pi;
586 char **netids = NULL;
587 int ni = 0;
588
589 if (fmri != NULL)
590 assert((cfgpp != NULL) && (proto_info_pool != NULL) &&
591 (tlx_ci_pool != NULL));
592
593 /*
594 * Set all checkable properties to valid as a baseline. We'll be
595 * marking all invalid properties.
596 */
597 for (i = 0; prop[i].ip_name != NULL; i++) {
598 if (prop[i].ip_error != IVE_UNSET)
599 prop[i].ip_error = IVE_VALID;
600 }
601
602 if (((cfg = calloc(1, sizeof (basic_cfg_t))) == NULL) ||
603 ((fmri != NULL) &&
604 ((cfg->proto_list = uu_list_create(proto_info_pool, NULL, 0)) ==
605 NULL))) {
606 free(cfg);
607 return (B_FALSE);
608 }
609
610 /* Check a service name was supplied */
611 if ((prop[PT_SVC_NAME_INDEX].ip_error == IVE_UNSET) ||
612 ((cfg->svc_name =
613 strdup(prop[PT_SVC_NAME_INDEX].ip_value.iv_string)) == NULL))
614 prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
615
616 /* Check that iswait and isrpc have valid boolean values */
617
618 if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_UNSET) ||
619 (((cfg->iswait = prop[PT_ISWAIT_INDEX].ip_value.iv_boolean) !=
620 B_TRUE) && (cfg->iswait != B_FALSE)))
621 prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;
622
623 if ((prop[PT_ISRPC_INDEX].ip_error == IVE_UNSET) ||
624 (((isrpc = prop[PT_ISRPC_INDEX].ip_value.iv_boolean) != B_TRUE) &&
625 (isrpc != B_FALSE))) {
626 prop[PT_ISRPC_INDEX].ip_error = IVE_INVALID;
627 } else if (isrpc) {
628 /*
629 * This is an RPC service, so ensure that the RPC version
630 * numbers are zero or greater, that the low version isn't
631 * greater than the high version and a valid program name
632 * is supplied.
633 */
634
635 if ((prop[PT_RPC_LW_VER_INDEX].ip_error == IVE_UNSET) ||
636 ((rpc_lv = prop[PT_RPC_LW_VER_INDEX].ip_value.iv_int) <
637 0))
638 prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;
639
640 if ((prop[PT_RPC_HI_VER_INDEX].ip_error == IVE_UNSET) ||
641 ((rpc_hv = prop[PT_RPC_HI_VER_INDEX].ip_value.iv_int) <
642 0))
643 prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;
644
645 if ((prop[PT_RPC_LW_VER_INDEX].ip_error != IVE_INVALID) &&
646 (prop[PT_RPC_HI_VER_INDEX].ip_error != IVE_INVALID) &&
647 (rpc_lv > rpc_hv)) {
648 prop[PT_RPC_LW_VER_INDEX].ip_error = IVE_INVALID;
649 prop[PT_RPC_HI_VER_INDEX].ip_error = IVE_INVALID;
650 }
651
652 if ((cfg->svc_name != NULL) &&
653 ((rpc_pnum = get_rpc_prognum(cfg->svc_name)) == -1))
654 prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
655 }
656
657 /* Check that the socket type is one of the acceptable values. */
658 cfg->istlx = B_FALSE;
659 if ((prop[PT_SOCK_TYPE_INDEX].ip_error == IVE_UNSET) ||
660 ((sock_type_id = get_sock_type_id(
661 prop[PT_SOCK_TYPE_INDEX].ip_value.iv_string)) == -1) &&
662 !(cfg->istlx = is_tlx_service(prop)))
663 prop[PT_SOCK_TYPE_INDEX].ip_error = IVE_INVALID;
664
665 /* Get the bind address */
666 if (!cfg->istlx && prop[PT_BIND_ADDR_INDEX].ip_error != IVE_UNSET &&
667 (cfg->bind_addr =
668 strdup(prop[PT_BIND_ADDR_INDEX].ip_value.iv_string)) == NULL)
669 prop[PT_BIND_ADDR_INDEX].ip_error = IVE_INVALID;
670
671 /*
672 * Iterate through all the different protos/netids resulting from the
673 * proto property and check that they're valid and perform checks on
674 * other fields that are tied-in with the proto.
675 */
676
677 pi = 0;
678 do {
679 socket_info_t *si = NULL;
680 tlx_info_t *ti = NULL;
681 proto_info_t *p_inf = NULL;
682 boolean_t v6only = B_FALSE;
683 char *only;
684 boolean_t invalid_proto = B_FALSE;
685 char **protos;
686 struct protoent pe;
687 char gpbuf[1024];
688 struct netconfig *nconf = NULL;
689
690 /*
691 * If we don't know whether it's an rpc service or its
692 * endpoint type, we can't do any of the proto checks as we
693 * have no context; break out.
694 */
695 if ((prop[PT_ISRPC_INDEX].ip_error != IVE_VALID) ||
696 (prop[PT_SOCK_TYPE_INDEX].ip_error != IVE_VALID))
697 break;
698
699 /* skip proto specific processing if the proto isn't set. */
700 if (prop[PT_PROTO_INDEX].ip_error == IVE_UNSET) {
701 invalid_proto = B_TRUE;
702 goto past_proto_processing;
703 }
704 protos = prop[PT_PROTO_INDEX].ip_value.iv_string_list;
705
706 /*
707 * Get the next netid/proto.
708 */
709
710 if (!cfg->istlx || !isrpc) {
711 proto = protos[pi++];
712 /*
713 * This is a TLI/RPC service, so get the next netid, expanding
714 * any supplied nettype.
715 */
716 } else if ((netids == NULL) ||
717 ((proto = netids[ni++]) == NULL)) {
718 /*
719 * Either this is the first time around or
720 * we've exhausted the last set of netids, so
721 * try and get the next set using the currently
722 * indexed proto entry.
723 */
724
725 if (netids != NULL) {
726 destroy_strings(netids);
727 netids = NULL;
728 }
729
730 if (protos[pi] != NULL) {
731 if ((netids = get_netids(protos[pi++])) ==
732 NULL) {
733 invalid_proto = B_TRUE;
734 proto = protos[pi - 1];
735 } else {
736 ni = 0;
737 proto = netids[ni++];
738 }
739 } else {
740 proto = NULL;
741 }
742 }
743
744 if (proto == NULL)
745 break;
746
747 if (invalid_proto)
748 goto past_proto_processing;
749
750 /* strip a trailing only to simplify further processing */
751 only = proto + strlen(proto) - (sizeof ("6only") - 1);
752 if ((only > proto) && (strcmp(only, "6only") == 0)) {
753 *++only = '\0';
754 v6only = B_TRUE;
755 }
756
757 /* validate the proto/netid */
758
759 if (!cfg->istlx) {
760 if (!valid_socket_proto(proto))
761 invalid_proto = B_TRUE;
762 } else {
763 /*
764 * Check if we've got a valid netid. If
765 * getnetconfigent() fails, we check to see whether
766 * we've got a v6 netid that may have been rejected
767 * because no IPv6 interface was configured before
768 * flagging 'proto' as invalid. If the latter condition
769 * holds, we don't flag the proto as invalid, and
770 * leave inetd to handle the value appropriately
771 * when it tries to listen on behalf of the service.
772 */
773 if (((nconf = getnetconfigent(proto)) == NULL) &&
774 !v6_proto(proto))
775 invalid_proto = B_TRUE;
776 }
777 if (invalid_proto)
778 goto past_proto_processing;
779
780 /*
781 * dissallow datagram type nowait services
782 */
783 if ((prop[PT_ISWAIT_INDEX].ip_error == IVE_VALID) &&
784 !cfg->iswait) {
785 if (strncmp(proto, SOCKET_PROTO_UDP,
786 sizeof (SOCKET_PROTO_UDP) - 1) == 0) {
787 invalid_proto = B_TRUE;
788 } else if (cfg->istlx && (nconf != NULL) &&
789 (nconf->nc_semantics == NC_TPI_CLTS)) {
790 invalid_proto = B_TRUE;
791 }
792 if (invalid_proto) {
793 prop[PT_ISWAIT_INDEX].ip_error = IVE_INVALID;
794 goto past_proto_processing;
795 }
796 }
797
798 /*
799 * We're running in validate only mode. Don't bother creating
800 * any proto structures (they don't do any further validation).
801 */
802 if (fmri == NULL)
803 goto past_proto_processing;
804
805 /*
806 * Create the apropriate transport info structure.
807 */
808 if (cfg->istlx) {
809 if ((ti = create_tlx_info(proto, tlx_ci_pool)) != NULL)
810 p_inf = (proto_info_t *)ti;
811 } else {
812 struct sockaddr_storage *ss;
813
814 if ((si = calloc(1, sizeof (socket_info_t))) != NULL) {
815 p_inf = (proto_info_t *)si;
816 si->type = sock_type_id;
817 ss = &si->local_addr;
818
819 if (v6_socket_proto(proto)) {
820 ss->ss_family = AF_INET6;
821 /* already in network order */
822 ((struct sockaddr_in6 *)ss)->sin6_addr =
823 in6addr_any;
824 } else {
825 ss->ss_family = AF_INET;
826 ((struct sockaddr_in *)ss)->sin_addr.
827 s_addr = htonl(INADDR_ANY);
828 }
829 if (set_bind_addr(ss, cfg->bind_addr) != 0) {
830 prop[PT_BIND_ADDR_INDEX].ip_error =
831 IVE_INVALID;
832 }
833 }
834 }
835 if (p_inf == NULL) {
836 invalid_proto = B_TRUE;
837 goto past_proto_processing;
838 }
839
840 p_inf->v6only = v6only;
841
842 /*
843 * Store the supplied proto string for error reporting,
844 * re-attaching the 'only' suffix if one was taken off.
845 */
846 if ((p_inf->proto = malloc(strlen(proto) + 5)) == NULL) {
847 invalid_proto = B_TRUE;
848 goto past_proto_processing;
849 } else {
850 (void) strlcpy(p_inf->proto, proto, strlen(proto) + 5);
851 if (v6only)
852 (void) strlcat(p_inf->proto, "only",
853 strlen(proto) + 5);
854 }
855
856 /*
857 * Validate and setup RPC/non-RPC specifics.
858 */
859
860 if (isrpc) {
861 rpc_info_t *ri;
862
863 if ((rpc_pnum != -1) && (rpc_lv != -1) &&
864 (rpc_hv != -1)) {
865 if ((ri = create_rpc_info(proto, rpc_pnum,
866 rpc_lv, rpc_hv)) == NULL) {
867 invalid_proto = B_TRUE;
868 } else {
869 p_inf->ri = ri;
870 }
871 }
872 }
873
874 past_proto_processing:
875 /* validate non-RPC service name */
876 if (!isrpc && (cfg->svc_name != NULL)) {
877 struct servent se;
878 char gsbuf[NSS_BUFLEN_SERVICES];
879 char *gsproto = proto;
880
881 if (invalid_proto) {
882 /*
883 * Make getservbyname_r do its lookup without a
884 * proto.
885 */
886 gsproto = NULL;
887 } else if (gsproto != NULL) {
888 /*
889 * Since getservbyname & getprotobyname don't
890 * support tcp6, udp6 or sctp6 take off the 6
891 * digit from protocol.
892 */
893 if (v6_socket_proto(gsproto))
894 gsproto[strlen(gsproto) - 1] = '\0';
895 }
896
897 if (getservbyname_r(cfg->svc_name, gsproto, &se, gsbuf,
898 sizeof (gsbuf)) == NULL) {
899 if (gsproto != NULL)
900 invalid_proto = B_TRUE;
901 prop[PT_SVC_NAME_INDEX].ip_error = IVE_INVALID;
902 } else if (cfg->istlx && (ti != NULL)) {
903 /* LINTED E_BAD_PTR_CAST_ALIGN */
904 SS_SETPORT(*(struct sockaddr_storage *)
905 ti->local_addr.buf, se.s_port);
906 } else if (!cfg->istlx && (si != NULL)) {
907 if ((gsproto != NULL) &&
908 getprotobyname_r(gsproto, &pe, gpbuf,
909 sizeof (gpbuf)) == NULL) {
910 invalid_proto = B_TRUE;
911 } else {
912 si->protocol = pe.p_proto;
913 }
914 SS_SETPORT(si->local_addr, se.s_port);
915 }
916
917 }
918
919 if (p_inf != NULL) {
920 p_inf->listen_fd = -1;
921
922 /* add new proto entry to proto_list */
923 uu_list_node_init(p_inf, &p_inf->link, proto_info_pool);
924 (void) uu_list_insert_after(cfg->proto_list, NULL,
925 p_inf);
926 }
927
928 if (nconf != NULL)
929 freenetconfigent(nconf);
930 if (invalid_proto)
931 prop[PT_PROTO_INDEX].ip_error = IVE_INVALID;
932 } while (proto != NULL); /* while just processed a proto */
933
934 /*
935 * Check that the exec string for the start method actually exists and
936 * that the user is either a valid username or uid. Note we don't
937 * mandate the setting of these fields, and don't do any checks
938 * for arg0, hence its absence.
939 */
940
941 if (prop[PT_EXEC_INDEX].ip_error != IVE_UNSET) {
942 /* Don't pass any arguments to access() */
943 if ((bufp = strdup(
944 prop[PT_EXEC_INDEX].ip_value.iv_string)) == NULL) {
945 prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
946 } else {
947 if ((cp = strpbrk(bufp, " \t")) != NULL)
948 *cp = '\0';
949
950 if ((access(bufp, F_OK) == -1) && (errno == ENOENT))
951 prop[PT_EXEC_INDEX].ip_error = IVE_INVALID;
952 free(bufp);
953 }
954 }
955
956 if (prop[PT_USER_INDEX].ip_error != IVE_UNSET) {
957 char pw_buf[NSS_BUFLEN_PASSWD];
958 struct passwd pw;
959
960 if (getpwnam_r(prop[PT_USER_INDEX].ip_value.iv_string, &pw,
961 pw_buf, NSS_BUFLEN_PASSWD) == NULL) {
962 errno = 0;
963 uidl = strtol(prop[PT_USER_INDEX].ip_value.iv_string,
964 &bufp, 10);
965 if ((errno != 0) || (*bufp != '\0') ||
966 (getpwuid_r(uidl, &pw, pw_buf,
967 NSS_BUFLEN_PASSWD) == NULL))
968 prop[PT_USER_INDEX].ip_error = IVE_INVALID;
969 }
970 }
971
972 /*
973 * Iterate through the properties in the array verifying that any
974 * default properties are valid, and setting the return boolean
975 * according to whether any properties were marked invalid.
976 */
977
978 for (i = 0; prop[i].ip_name != NULL; i++) {
979 if (prop[i].ip_error == IVE_UNSET)
980 continue;
981
982 if (prop[i].ip_default &&
983 !valid_default_prop(prop[i].ip_name, &prop[i].ip_value))
984 prop[i].ip_error = IVE_INVALID;
985
986 if (prop[i].ip_error == IVE_INVALID)
987 ret = B_FALSE;
988 }
989
990 /* pass back the basic_cfg_t if requested and it's a valid config */
991 if ((cfgpp != NULL) && ret) {
992 *cfgpp = cfg;
993 } else {
994 destroy_basic_cfg(cfg);
995 }
996
997 return (ret);
998 }
999
1000 /*
1001 * validate_default_prop takes the name of an inetd property, and a value
1002 * for that property. It returns B_TRUE if the property is valid, and B_FALSE
1003 * if the proposed value isn't valid for that property.
1004 */
1005
1006 boolean_t
valid_default_prop(const char * name,const void * value)1007 valid_default_prop(const char *name, const void *value)
1008 {
1009 int i;
1010
1011 for (i = 0; inetd_properties[i].ip_name != NULL; i++) {
1012 if (strcmp(name, inetd_properties[i].ip_name) != 0)
1013 continue;
1014 if (!inetd_properties[i].ip_default)
1015 return (B_FALSE);
1016
1017 switch (inetd_properties[i].ip_type) {
1018 case INET_TYPE_INTEGER:
1019 if (*((int64_t *)value) >= -1)
1020 return (B_TRUE);
1021 else
1022 return (B_FALSE);
1023 case INET_TYPE_BOOLEAN:
1024 if ((*((boolean_t *)value) == B_FALSE) ||
1025 (*((boolean_t *)value) == B_TRUE))
1026 return (B_TRUE);
1027 else
1028 return (B_FALSE);
1029 case INET_TYPE_COUNT:
1030 case INET_TYPE_STRING_LIST:
1031 case INET_TYPE_STRING:
1032 return (B_TRUE);
1033 }
1034 }
1035
1036 return (B_FALSE);
1037 }
1038
1039 /*ARGSUSED*/
1040 scf_error_t
read_prop(scf_handle_t * h,inetd_prop_t * iprop,int index,const char * inst,const char * pg_name)1041 read_prop(scf_handle_t *h, inetd_prop_t *iprop, int index, const char *inst,
1042 const char *pg_name)
1043 {
1044 scf_simple_prop_t *sprop;
1045 uint8_t *tmp_bool;
1046 int64_t *tmp_int;
1047 uint64_t *tmp_cnt;
1048 char *tmp_char;
1049
1050 if ((sprop = scf_simple_prop_get(h, inst, pg_name, iprop->ip_name)) ==
1051 NULL)
1052 return (scf_error());
1053
1054 switch (iprop->ip_type) {
1055 case INET_TYPE_STRING:
1056 if ((tmp_char = scf_simple_prop_next_astring(sprop)) == NULL)
1057 goto scf_error;
1058 if ((iprop->ip_value.iv_string = strdup(tmp_char)) == NULL) {
1059 scf_simple_prop_free(sprop);
1060 return (SCF_ERROR_NO_MEMORY);
1061 }
1062 break;
1063 case INET_TYPE_STRING_LIST:
1064 {
1065 int j = 0;
1066
1067 while ((tmp_char =
1068 scf_simple_prop_next_astring(sprop)) != NULL) {
1069 char **cpp;
1070
1071 if ((cpp = realloc(
1072 iprop->ip_value.iv_string_list,
1073 (j + 2) * sizeof (char *))) == NULL) {
1074 scf_simple_prop_free(sprop);
1075 return (SCF_ERROR_NO_MEMORY);
1076 }
1077 iprop->ip_value.iv_string_list = cpp;
1078 if ((cpp[j] = strdup(tmp_char)) == NULL) {
1079 scf_simple_prop_free(sprop);
1080 return (SCF_ERROR_NO_MEMORY);
1081 }
1082 cpp[++j] = NULL;
1083 }
1084 if ((j == 0) || (scf_error() != SCF_ERROR_NONE))
1085 goto scf_error;
1086 }
1087 break;
1088 case INET_TYPE_BOOLEAN:
1089 if ((tmp_bool = scf_simple_prop_next_boolean(sprop)) == NULL)
1090 goto scf_error;
1091 iprop->ip_value.iv_boolean =
1092 (*tmp_bool == 0) ? B_FALSE : B_TRUE;
1093 break;
1094 case INET_TYPE_COUNT:
1095 if ((tmp_cnt = scf_simple_prop_next_count(sprop)) == NULL)
1096 goto scf_error;
1097 iprop->ip_value.iv_cnt = *tmp_cnt;
1098 break;
1099 case INET_TYPE_INTEGER:
1100 if ((tmp_int = scf_simple_prop_next_integer(sprop)) == NULL)
1101 goto scf_error;
1102 iprop->ip_value.iv_int = *tmp_int;
1103 break;
1104 default:
1105 assert(0);
1106 }
1107
1108 iprop->ip_error = IVE_VALID;
1109 scf_simple_prop_free(sprop);
1110 return (0);
1111
1112 scf_error:
1113 scf_simple_prop_free(sprop);
1114 if (scf_error() == SCF_ERROR_NONE)
1115 return (SCF_ERROR_NOT_FOUND);
1116 return (scf_error());
1117 }
1118
1119 /*
1120 * read_props reads either the full set of properties for instance 'instance'
1121 * (including defaults - pulling them in from inetd where necessary) if
1122 * 'instance' is non-null, else just the defaults from inetd. The properties
1123 * are returned in an allocated inetd_prop_t array, which must be freed
1124 * using free_instance_props(). If an error occurs NULL is returned and 'err'
1125 * is set to indicate the cause, else a pointer to the read properties is
1126 * returned.
1127 */
1128 static inetd_prop_t *
read_props(scf_handle_t * h,const char * instance,size_t * num_elements,scf_error_t * err)1129 read_props(scf_handle_t *h, const char *instance, size_t *num_elements,
1130 scf_error_t *err)
1131 {
1132 inetd_prop_t *ret = NULL;
1133 int i;
1134 boolean_t defaults_only = (instance == NULL);
1135
1136 if ((ret = malloc(sizeof (inetd_properties))) == NULL) {
1137 *err = SCF_ERROR_NO_MEMORY;
1138 return (NULL);
1139 }
1140 (void) memcpy(ret, &inetd_properties, sizeof (inetd_properties));
1141
1142 if (defaults_only)
1143 instance = INETD_INSTANCE_FMRI;
1144 for (i = 0; ret[i].ip_name != NULL; i++) {
1145 if (defaults_only && !ret[i].ip_default)
1146 continue;
1147
1148 switch (*err = read_prop(h, &ret[i], i, instance,
1149 defaults_only ? PG_NAME_SERVICE_DEFAULTS : ret[i].ip_pg)) {
1150 case 0:
1151 break;
1152 case SCF_ERROR_INVALID_ARGUMENT:
1153 goto failure_cleanup;
1154 case SCF_ERROR_NOT_FOUND:
1155 /*
1156 * In non-default-only mode where we're reading a
1157 * default property, since the property wasn't
1158 * found in the instance, try and read inetd's default
1159 * value.
1160 */
1161 if (!ret[i].ip_default || defaults_only)
1162 continue;
1163 switch (*err = read_prop(h, &ret[i], i,
1164 INETD_INSTANCE_FMRI, PG_NAME_SERVICE_DEFAULTS)) {
1165 case 0:
1166 ret[i].from_inetd = B_TRUE;
1167 continue;
1168 case SCF_ERROR_NOT_FOUND:
1169 continue;
1170 default:
1171 goto failure_cleanup;
1172 }
1173 default:
1174 goto failure_cleanup;
1175 }
1176 }
1177
1178 *num_elements = i;
1179 return (ret);
1180
1181 failure_cleanup:
1182 free_instance_props(ret);
1183 return (NULL);
1184 }
1185
1186 /*
1187 * Read all properties applicable to 'instance' (including defaults).
1188 */
1189 inetd_prop_t *
read_instance_props(scf_handle_t * h,const char * instance,size_t * num_elements,scf_error_t * err)1190 read_instance_props(scf_handle_t *h, const char *instance, size_t *num_elements,
1191 scf_error_t *err)
1192 {
1193 return (read_props(h, instance, num_elements, err));
1194 }
1195
1196 /*
1197 * Read the default properties from inetd's defaults property group.
1198 */
1199 inetd_prop_t *
read_default_props(scf_handle_t * h,size_t * num_elements,scf_error_t * err)1200 read_default_props(scf_handle_t *h, size_t *num_elements, scf_error_t *err)
1201 {
1202 return (read_props(h, NULL, num_elements, err));
1203 }
1204
1205 void
free_instance_props(inetd_prop_t * prop)1206 free_instance_props(inetd_prop_t *prop)
1207 {
1208 int i;
1209
1210 if (prop == NULL)
1211 return;
1212
1213 for (i = 0; prop[i].ip_name != NULL; i++) {
1214 if (prop[i].ip_type == INET_TYPE_STRING) {
1215 free(prop[i].ip_value.iv_string);
1216 } else if (prop[i].ip_type == INET_TYPE_STRING_LIST) {
1217 destroy_strings(prop[i].ip_value.iv_string_list);
1218 }
1219 }
1220 free(prop);
1221 }
1222
1223 int
connect_to_inetd(void)1224 connect_to_inetd(void)
1225 {
1226 struct sockaddr_un addr;
1227 int fd;
1228
1229 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1230 if (fd < 0)
1231 return (-1);
1232
1233 (void) memset(&addr, 0, sizeof (addr));
1234 addr.sun_family = AF_UNIX;
1235 /* CONSTCOND */
1236 assert(sizeof (INETD_UDS_PATH) <= sizeof (addr.sun_path));
1237 (void) strlcpy(addr.sun_path, INETD_UDS_PATH,
1238 sizeof (addr.sun_path));
1239
1240 if (connect(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0) {
1241 (void) close(fd);
1242 return (-1);
1243 }
1244
1245 return (fd);
1246 }
1247
1248 /*
1249 * refresh_inetd requests that inetd re-read all of the information that it's
1250 * monitoring.
1251 */
1252
1253 int
refresh_inetd(void)1254 refresh_inetd(void)
1255 {
1256 uds_request_t req;
1257 int fd;
1258
1259 if ((fd = connect_to_inetd()) < 0)
1260 return (-1);
1261
1262 req = UR_REFRESH_INETD;
1263 if (send(fd, &req, sizeof (req), 0) < 0) {
1264 (void) close(fd);
1265 return (-1);
1266 }
1267
1268 (void) close(fd);
1269 return (0);
1270 }
1271
1272 /*
1273 * Returns the id of the socket type 'type_str' that can be used in a call
1274 * to socket(). If an unknown type string is passed returns -1, else the id.
1275 */
1276
1277 int
get_sock_type_id(const char * type_str)1278 get_sock_type_id(const char *type_str)
1279 {
1280 int ret;
1281
1282 if (strcmp(SOCKTYPE_STREAM_STR, type_str) == 0) {
1283 ret = SOCK_STREAM;
1284 } else if (strcmp(SOCKTYPE_DGRAM_STR, type_str) == 0) {
1285 ret = SOCK_DGRAM;
1286 } else if (strcmp(SOCKTYPE_RAW_STR, type_str) == 0) {
1287 ret = SOCK_RAW;
1288 } else if (strcmp(SOCKTYPE_SEQPKT_STR, type_str) == 0) {
1289 ret = SOCK_SEQPACKET;
1290 } else {
1291 ret = -1;
1292 }
1293 return (ret);
1294 }
1295
1296 /*
1297 * Takes either an RPC service name or number in string form as 'svc_name', and
1298 * returns an integer format program number for the service. If the name isn't
1299 * recognized as a valid RPC service name or isn't a valid number, -1 is
1300 * returned, else the services program number.
1301 */
1302
1303 int
get_rpc_prognum(const char * svc_name)1304 get_rpc_prognum(const char *svc_name)
1305 {
1306 struct rpcent rpc;
1307 char buf[INETSVC_SVC_BUF_MAX];
1308 int pnum;
1309 char *endptr;
1310
1311 if (getrpcbyname_r(svc_name, &rpc, buf, sizeof (buf)) != NULL)
1312 return (rpc.r_number);
1313
1314 pnum = strtol(svc_name, &endptr, 0);
1315 if ((pnum == 0 && errno == EINVAL) ||
1316 (pnum == LONG_MAX && errno == ERANGE) ||
1317 pnum < 0 || *endptr != '\0') {
1318 return (-1);
1319 }
1320
1321 return (pnum);
1322 }
1323
1324 /*
1325 * calculate_hash calculates the MD5 message-digest of the file pathname.
1326 * On success, hash is modified to point to the digest string and 0 is returned.
1327 * Otherwise, -1 is returned and errno is set to indicate the error.
1328 * The space for the digest string is obtained using malloc(3C) and should be
1329 * freed by the caller.
1330 */
1331 int
calculate_hash(const char * pathname,char ** hash)1332 calculate_hash(const char *pathname, char **hash)
1333 {
1334 int fd, i, serrno;
1335 size_t len;
1336 ssize_t n;
1337 char *digest;
1338 MD5_CTX md5_context;
1339 unsigned char md5_digest[DIGEST_LEN];
1340 unsigned char buf[READ_BUFSIZ];
1341
1342 do {
1343 fd = open(pathname, O_RDONLY);
1344 } while (fd == -1 && errno == EINTR);
1345
1346 if (fd == -1)
1347 return (-1);
1348
1349 /* allocate space for a 16-byte MD5 digest as a string of hex digits */
1350 len = 2 * sizeof (md5_digest) + 1;
1351 if ((digest = malloc(len)) == NULL) {
1352 serrno = errno;
1353 (void) close(fd);
1354 errno = serrno;
1355 return (-1);
1356 }
1357
1358 MD5Init(&md5_context);
1359
1360 do {
1361 if ((n = read(fd, buf, sizeof (buf))) > 0)
1362 MD5Update(&md5_context, buf, n);
1363 } while ((n > 0) || (n == -1 && errno == EINTR));
1364
1365 serrno = errno;
1366 MD5Final(md5_digest, &md5_context);
1367
1368 (void) close(fd);
1369
1370 if (n == -1) {
1371 errno = serrno;
1372 return (-1);
1373 }
1374
1375 for (i = 0; i < sizeof (md5_digest); i++) {
1376 (void) snprintf(&digest[2 * i], len - (2 * i), "%02x",
1377 md5_digest[i]);
1378 }
1379 *hash = digest;
1380 return (0);
1381 }
1382
1383 /*
1384 * retrieve_inetd_hash retrieves inetd's configuration file hash from the
1385 * repository. On success, hash is modified to point to the hash string and
1386 * SCF_ERROR_NONE is returned. Otherwise, the scf_error value is returned.
1387 * The space for the hash string is obtained using malloc(3C) and should be
1388 * freed by the caller.
1389 */
1390 scf_error_t
retrieve_inetd_hash(char ** hash)1391 retrieve_inetd_hash(char **hash)
1392 {
1393 scf_simple_prop_t *sp;
1394 char *hashstr, *s;
1395 scf_error_t scf_err;
1396
1397 if ((sp = scf_simple_prop_get(NULL, INETD_INSTANCE_FMRI, HASH_PG,
1398 HASH_PROP)) == NULL)
1399 return (scf_error());
1400
1401 if ((hashstr = scf_simple_prop_next_astring(sp)) == NULL) {
1402 scf_err = scf_error();
1403 scf_simple_prop_free(sp);
1404 return (scf_err);
1405 }
1406
1407 if ((s = strdup(hashstr)) == NULL) {
1408 scf_simple_prop_free(sp);
1409 return (SCF_ERROR_NO_MEMORY);
1410 }
1411 *hash = s;
1412 scf_simple_prop_free(sp);
1413 return (SCF_ERROR_NONE);
1414 }
1415
1416 /*
1417 * store_inetd_hash stores the string hash in inetd's configuration file hash
1418 * in the repository. On success, SCF_ERROR_NONE is returned. Otherwise, the
1419 * scf_error value is returned.
1420 */
1421 scf_error_t
store_inetd_hash(const char * hash)1422 store_inetd_hash(const char *hash)
1423 {
1424 int ret;
1425 scf_error_t rval = SCF_ERROR_NONE;
1426 scf_handle_t *h;
1427 scf_propertygroup_t *pg = NULL;
1428 scf_instance_t *inst = NULL;
1429 scf_transaction_t *tx = NULL;
1430 scf_transaction_entry_t *txent = NULL;
1431 scf_property_t *prop = NULL;
1432 scf_value_t *val = NULL;
1433
1434 if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
1435 scf_handle_bind(h) == -1)
1436 goto error;
1437
1438 if ((pg = scf_pg_create(h)) == NULL ||
1439 (inst = scf_instance_create(h)) == NULL ||
1440 scf_handle_decode_fmri(h, INETD_INSTANCE_FMRI, NULL, NULL, inst,
1441 NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1)
1442 goto error;
1443
1444 if (scf_instance_get_pg(inst, HASH_PG, pg) == -1) {
1445 if (scf_error() != SCF_ERROR_NOT_FOUND ||
1446 scf_instance_add_pg(inst, HASH_PG, SCF_GROUP_APPLICATION,
1447 0, pg) == -1)
1448 goto error;
1449 }
1450
1451 if ((tx = scf_transaction_create(h)) == NULL ||
1452 (txent = scf_entry_create(h)) == NULL ||
1453 (prop = scf_property_create(h)) == NULL ||
1454 (val = scf_value_create(h)) == NULL)
1455 goto error;
1456
1457 do {
1458 if (scf_transaction_start(tx, pg) == -1)
1459 goto error;
1460
1461 if (scf_transaction_property_new(tx, txent, HASH_PROP,
1462 SCF_TYPE_ASTRING) == -1 &&
1463 scf_transaction_property_change_type(tx, txent, HASH_PROP,
1464 SCF_TYPE_ASTRING) == -1)
1465 goto error;
1466
1467 if (scf_value_set_astring(val, hash) == -1 ||
1468 scf_entry_add_value(txent, val) == -1)
1469 goto error;
1470
1471 if ((ret = scf_transaction_commit(tx)) == -1)
1472 goto error;
1473
1474 if (ret == 0) {
1475 scf_transaction_reset(tx);
1476 if (scf_pg_update(pg) == -1)
1477 goto error;
1478 }
1479 } while (ret == 0);
1480
1481 goto success;
1482
1483 error:
1484 rval = scf_error();
1485
1486 success:
1487 scf_value_destroy(val);
1488 scf_property_destroy(prop);
1489 scf_entry_destroy(txent);
1490 scf_transaction_destroy(tx);
1491 scf_instance_destroy(inst);
1492 scf_pg_destroy(pg);
1493 scf_handle_destroy(h);
1494 return (rval);
1495 }
1496
1497 /*
1498 * This is a wrapper function for inet_ntop(). In case the af is AF_INET6
1499 * and the address pointed by src is a IPv4-mapped IPv6 address, it returns
1500 * a printable IPv4 address, not an IPv4-mapped IPv6 address. In other cases it
1501 * behaves just like inet_ntop().
1502 */
1503 const char *
inet_ntop_native(int af,const void * addr,char * dst,size_t size)1504 inet_ntop_native(int af, const void *addr, char *dst, size_t size)
1505 {
1506 struct in_addr v4addr;
1507
1508 if ((af == AF_INET6) && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr)) {
1509 IN6_V4MAPPED_TO_INADDR((struct in6_addr *)addr, &v4addr);
1510 return (inet_ntop(AF_INET, &v4addr, dst, size));
1511 } else {
1512 return (inet_ntop(af, addr, dst, size));
1513 }
1514 }
1515
1516 /*
1517 * inetd specific setproctitle. It sets the title so that it contains
1518 * 'svc_name' followed by, if obtainable, the address of the remote end of
1519 * socket 's'.
1520 * NOTE: The argv manipulation in this function should be replaced when a
1521 * common version of setproctitle is made available.
1522 */
1523 void
setproctitle(const char * svc_name,int s,char * argv[])1524 setproctitle(const char *svc_name, int s, char *argv[])
1525 {
1526 socklen_t size;
1527 struct sockaddr_storage ss;
1528 char abuf[INET6_ADDRSTRLEN];
1529
1530 static char buf[80];
1531
1532 size = (socklen_t)sizeof (ss);
1533 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1534 (void) snprintf(buf, sizeof (buf), "-%s [%s]", svc_name,
1535 inet_ntop_native(ss.ss_family, (ss.ss_family == AF_INET6 ?
1536 (void *)&((struct sockaddr_in6 *)(&ss))->sin6_addr :
1537 (void *)&((struct sockaddr_in *)(&ss))->sin_addr), abuf,
1538 sizeof (abuf)));
1539 } else {
1540 (void) snprintf(buf, sizeof (buf), "-%s", svc_name);
1541 }
1542
1543 /* we set argv[0] to point at our static storage. */
1544 argv[0] = buf;
1545 argv[1] = NULL;
1546 }
1547
1548 static boolean_t
inetd_builtin_srcport(in_port_t p)1549 inetd_builtin_srcport(in_port_t p)
1550 {
1551 p = ntohs(p);
1552
1553 if ((p == IPPORT_ECHO) ||
1554 (p == IPPORT_DISCARD) ||
1555 (p == IPPORT_DAYTIME) ||
1556 (p == IPPORT_CHARGEN) ||
1557 (p == IPPORT_TIMESERVER)) {
1558 return (B_TRUE);
1559 } else {
1560 return (B_FALSE);
1561 }
1562 }
1563
1564 /* ARGSUSED0 */
1565 static void
alarm_handler(int sig)1566 alarm_handler(int sig)
1567 {
1568 exit(0);
1569 }
1570
1571 /*
1572 * This function is a datagram service template. It acts as a datagram wait
1573 * type server, waiting for datagrams to come in, and when they do passing
1574 * their contents, as-well as the socket they came in on and the remote
1575 * address, in a call to the callback function 'cb'. If no datagrams are
1576 * received for DG_INACTIVITY_TIMEOUT seconds the function exits with code 0.
1577 */
1578 void
dg_template(void (* cb)(int,const struct sockaddr *,int,const void *,size_t),int s,void * buf,size_t buflen)1579 dg_template(void (*cb)(int, const struct sockaddr *, int, const void *, size_t),
1580 int s, void *buf, size_t buflen)
1581 {
1582 struct sockaddr_storage sa;
1583 socklen_t sa_size;
1584 ssize_t i;
1585 char tmp[BUFSIZ];
1586
1587 (void) sigset(SIGALRM, alarm_handler);
1588
1589 if (buf == NULL) {
1590 buf = tmp;
1591 buflen = sizeof (tmp);
1592 }
1593 for (;;) {
1594 (void) alarm(DG_INACTIVITY_TIMEOUT);
1595 sa_size = sizeof (sa);
1596 if ((i = recvfrom(s, buf, buflen, 0, (struct sockaddr *)&sa,
1597 &sa_size)) < 0) {
1598 continue;
1599 } else if (inetd_builtin_srcport(
1600 ((struct sockaddr_in *)(&sa))->sin_port)) {
1601 /* denial-of-service attack possibility - ignore it */
1602 syslog(LOG_WARNING,
1603 "Incoming datagram from internal inetd service received; ignoring.");
1604 continue;
1605 }
1606 (void) alarm(0);
1607
1608 cb(s, (struct sockaddr *)&sa, sa_size, buf, i);
1609 }
1610 }
1611
1612 /*
1613 * An extension of write() or sendto() that keeps trying until either the full
1614 * request has completed or a non-EINTR error occurs. If 'to' is set to a
1615 * non-NULL value, sendto() is extended, else write(). Returns 0 on success
1616 * else -1.
1617 */
1618 int
safe_sendto_write(int fd,const void * buf,size_t sz,int flags,const struct sockaddr * to,int tolen)1619 safe_sendto_write(int fd, const void *buf, size_t sz, int flags,
1620 const struct sockaddr *to, int tolen) {
1621
1622 size_t cnt = 0;
1623 ssize_t ret;
1624 const char *cp = buf;
1625
1626 do {
1627 if (to == NULL) {
1628 ret = write(fd, cp + cnt, sz - cnt);
1629 } else {
1630 ret = sendto(fd, cp + cnt, sz - cnt, flags, to, tolen);
1631 }
1632
1633 if (ret > 0)
1634 cnt += ret;
1635 } while ((cnt != sz) && (errno == EINTR));
1636
1637 return ((cnt == sz) ? 0 : -1);
1638 }
1639
1640 int
safe_sendto(int fd,const void * buf,size_t sz,int flags,const struct sockaddr * to,int tolen)1641 safe_sendto(int fd, const void *buf, size_t sz, int flags,
1642 const struct sockaddr *to, int tolen) {
1643 return (safe_sendto_write(fd, buf, sz, flags, to, tolen));
1644 }
1645
1646 int
safe_write(int fd,const void * buf,size_t sz)1647 safe_write(int fd, const void *buf, size_t sz)
1648 {
1649 return (safe_sendto_write(fd, buf, sz, 0, NULL, 0));
1650 }
1651
1652 /*
1653 * Free up the memory occupied by string array 'strs'.
1654 */
1655 void
destroy_strings(char ** strs)1656 destroy_strings(char **strs)
1657 {
1658 int i = 0;
1659
1660 if (strs != NULL) {
1661 while (strs[i] != NULL)
1662 free(strs[i++]);
1663 free(strs);
1664 }
1665 }
1666
1667 /*
1668 * Parse the proto list string into an allocated array of proto strings,
1669 * returning a pointer to this array. If one of the protos is too big
1670 * errno is set to E2BIG and NULL is returned; if memory allocation failure
1671 * occurs errno is set to ENOMEM and NULL is returned; else on success
1672 * a pointer the string array is returned.
1673 */
1674 char **
get_protos(const char * pstr)1675 get_protos(const char *pstr)
1676 {
1677 char *cp;
1678 int i = 0;
1679 char **ret = NULL;
1680 size_t max_proto_len = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
1681 char *str;
1682
1683 /* copy the parameter as strtok modifies its parameters */
1684 if ((str = strdup(pstr)) == NULL)
1685 goto malloc_failure;
1686
1687 for (cp = strtok(str, PROTO_DELIMITERS); cp != NULL;
1688 cp = strtok(NULL, PROTO_DELIMITERS)) {
1689 char **cpp;
1690
1691 if (strlen(cp) >= max_proto_len) {
1692 destroy_strings(ret);
1693 free(str);
1694 errno = E2BIG;
1695 return (NULL);
1696 }
1697 if ((cpp = realloc(ret, (i + 2) * sizeof (char *))) == NULL)
1698 goto malloc_failure;
1699 ret = cpp;
1700 if ((cpp[i] = strdup(cp)) == NULL)
1701 goto malloc_failure;
1702 cpp[++i] = NULL;
1703 }
1704
1705 free(str);
1706 return (ret);
1707
1708 malloc_failure:
1709 destroy_strings(ret);
1710 free(str);
1711 errno = ENOMEM;
1712 return (NULL);
1713 }
1714
1715 /*
1716 * Returns an allocated string array of netids corresponding with 'proto'. The
1717 * function first tries to interpret 'proto' as a nettype to get its netids.
1718 * If this fails it tries to interpret it as a netid. If 'proto' is neither
1719 * a nettype or a netid or a memory allocation failures occurs NULL is
1720 * returned, else a pointer to an array of netids associated with 'proto' is
1721 * returned.
1722 */
1723 char **
get_netids(char * proto)1724 get_netids(char *proto)
1725 {
1726 void *handle;
1727 struct netconfig *nconf;
1728 char **netids = NULL;
1729 char **cpp;
1730 int i = 0;
1731
1732 if (strcmp(proto, "*") == 0)
1733 proto = "visible";
1734
1735 if ((handle = __rpc_setconf(proto)) != NULL) {
1736 /* expand nettype */
1737 while ((nconf = __rpc_getconf(handle)) != NULL) {
1738 if ((cpp = realloc(netids,
1739 (i + 2) * sizeof (char *))) == NULL)
1740 goto failure_cleanup;
1741 netids = cpp;
1742 if ((cpp[i] = strdup(nconf->nc_netid)) == NULL)
1743 goto failure_cleanup;
1744 cpp[++i] = NULL;
1745 }
1746 __rpc_endconf(handle);
1747 } else {
1748 if ((netids = malloc(2 * sizeof (char *))) == NULL)
1749 return (NULL);
1750 if ((netids[0] = strdup(proto)) == NULL) {
1751 free(netids);
1752 return (NULL);
1753 }
1754 netids[1] = NULL;
1755 }
1756
1757 return (netids);
1758
1759 failure_cleanup:
1760 destroy_strings(netids);
1761 __rpc_endconf(handle);
1762 return (NULL);
1763 }
1764