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