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