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 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 * 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 * 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 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 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 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 * 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 ** 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 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 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 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 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 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 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 * 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 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 * 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 ** 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 ** 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