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