1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2020 Tintri by DDN, Inc. All rights reserved. 24 * Copyright 2021 RackTop Systems, Inc. 25 */ 26 27 /* 28 * CIFS configuration management library 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <synch.h> 35 #include <string.h> 36 #include <strings.h> 37 #include <syslog.h> 38 #include <netdb.h> 39 #include <ctype.h> 40 #include <sys/types.h> 41 #include <libscf.h> 42 #include <assert.h> 43 #include <uuid/uuid.h> 44 #include <smbsrv/libsmb.h> 45 46 typedef struct smb_cfg_param { 47 smb_cfg_id_t sc_id; 48 char *sc_name; 49 int sc_type; 50 uint32_t sc_flags; 51 } smb_cfg_param_t; 52 53 struct str_val { 54 char *str; 55 uint32_t val; 56 }; 57 58 /* 59 * config parameter flags 60 */ 61 #define SMB_CF_PROTECTED 0x01 62 #define SMB_CF_EXEC 0x02 63 64 /* idmap SMF fmri and Property Group */ 65 #define IDMAP_FMRI_PREFIX "system/idmap" 66 #define MACHINE_SID "machine_sid" 67 #define MACHINE_UUID "machine_uuid" 68 #define IDMAP_DOMAIN "domain_name" 69 #define IDMAP_PREF_DC "preferred_dc" 70 #define IDMAP_SITE_NAME "site_name" 71 #define IDMAP_PG_NAME "config" 72 73 #define SMB_SECMODE_WORKGRP_STR "workgroup" 74 #define SMB_SECMODE_DOMAIN_STR "domain" 75 76 #define SMB_ENC_LEN 1024 77 #define SMB_DEC_LEN 256 78 79 static char *b64_data = 80 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 81 82 static smb_cfg_param_t smb_cfg_table[] = 83 { 84 {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0}, 85 86 /* Oplock configuration, Kernel Only */ 87 {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0}, 88 89 /* Autohome configuration */ 90 {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0}, 91 92 /* Domain/PDC configuration */ 93 {SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0}, 94 {SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0}, 95 {SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0}, 96 {SMB_CI_DOMAIN_FQDN, "fqdn", SCF_TYPE_ASTRING, 0}, 97 {SMB_CI_DOMAIN_FOREST, "forest", SCF_TYPE_ASTRING, 0}, 98 {SMB_CI_DOMAIN_GUID, "domain_guid", SCF_TYPE_ASTRING, 0}, 99 {SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0}, 100 101 /* WINS configuration */ 102 {SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0}, 103 {SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0}, 104 {SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0}, 105 106 /* Kmod specific configuration */ 107 {SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0}, 108 {SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0}, 109 {SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0}, 110 {SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0}, 111 112 {SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0}, 113 {SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0}, 114 115 /* Kmod tuning configuration */ 116 {SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0}, 117 118 /* SMBd configuration */ 119 {SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0}, 120 {SMB_CI_NETBIOS_ENABLE, "netbios_enable", SCF_TYPE_BOOLEAN, 0}, 121 {SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0}, 122 {SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0}, 123 {SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0}, 124 125 /* ADS Configuration */ 126 {SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0}, 127 128 /* Dynamic DNS */ 129 {SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0}, 130 131 {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING, 132 SMB_CF_PROTECTED}, 133 134 {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0}, 135 {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0}, 136 {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0}, 137 {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0}, 138 {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0}, 139 {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0}, 140 {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0}, 141 {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC}, 142 {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC}, 143 {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC}, 144 {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0}, 145 {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0}, 146 {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0}, 147 {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0}, 148 {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0}, 149 {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0}, 150 {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0}, 151 {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0}, 152 {SMB_CI_BYPASS_TRAVERSE_CHECKING, 153 "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0}, 154 {SMB_CI_ENCRYPT_CIPHER, "encrypt_cipher", SCF_TYPE_ASTRING, 0}, 155 {SMB_CI_NETLOGON_FLAGS, "netlogon_flags", SCF_TYPE_INTEGER, 0}, 156 157 /* SMB_CI_MAX */ 158 }; 159 160 /* 161 * We store the max SMB protocol version in SMF as a string, 162 * (for convenience of svccfg etc) but the programmatic get/set 163 * interfaces use the numeric form. 164 * 165 * The numeric values are as defined in the [MS-SMB2] spec. 166 * except for how we represent "1" (for SMB1) which is an 167 * arbitrary value below SMB2_VERS_BASE. 168 */ 169 static struct str_val 170 smb_versions[] = { 171 { "3.11", SMB_VERS_3_11 }, 172 { "3.02", SMB_VERS_3_02 }, 173 { "3.0", SMB_VERS_3_0 }, 174 { "2.1", SMB_VERS_2_1 }, 175 { "2.002", SMB_VERS_2_002 }, 176 { "1", SMB_VERS_1 }, 177 { NULL, 0 } 178 }; 179 180 /* 181 * Supported encryption ciphers. 182 */ 183 static struct str_val 184 smb31_enc_ciphers[] = { 185 { "aes128-ccm", SMB3_CIPHER_FLAG_AES128_CCM }, /* SMB 3.x */ 186 { "aes128-gcm", SMB3_CIPHER_FLAG_AES128_GCM }, /* SMB 3.1.1 */ 187 { "all", SMB3_ALL_CIPHERS }, 188 { NULL, 0 } 189 }; 190 191 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t); 192 193 static boolean_t smb_is_base64(unsigned char c); 194 static char *smb_base64_encode(char *str_to_encode); 195 static char *smb_base64_decode(char *encoded_str); 196 static int smb_config_get_idmap_preferred_dc(char *, int); 197 static int smb_config_set_idmap_preferred_dc(char *); 198 static int smb_config_get_idmap_site_name(char *, int); 199 static int smb_config_set_idmap_site_name(char *); 200 201 static uint32_t 202 smb_convert_version_str(const char *version) 203 { 204 uint32_t dialect = 0; 205 int i; 206 207 for (i = 0; smb_versions[i].str != NULL; i++) { 208 if (strcmp(version, smb_versions[i].str) == 0) 209 dialect = smb_versions[i].val; 210 } 211 212 return (dialect); 213 } 214 215 char * 216 smb_config_getname(smb_cfg_id_t id) 217 { 218 smb_cfg_param_t *cfg; 219 cfg = smb_config_getent(id); 220 return (cfg->sc_name); 221 } 222 223 static boolean_t 224 smb_is_base64(unsigned char c) 225 { 226 return (isalnum(c) || (c == '+') || (c == '/')); 227 } 228 229 /* 230 * smb_base64_encode 231 * 232 * Encode a string using base64 algorithm. 233 * Caller should free the returned buffer when done. 234 */ 235 static char * 236 smb_base64_encode(char *str_to_encode) 237 { 238 int ret_cnt = 0; 239 int i = 0, j = 0; 240 char arr_3[3], arr_4[4]; 241 int len = strlen(str_to_encode); 242 char *ret = malloc(SMB_ENC_LEN); 243 244 if (ret == NULL) { 245 return (NULL); 246 } 247 248 while (len--) { 249 arr_3[i++] = *(str_to_encode++); 250 if (i == 3) { 251 arr_4[0] = (arr_3[0] & 0xfc) >> 2; 252 arr_4[1] = ((arr_3[0] & 0x03) << 4) + 253 ((arr_3[1] & 0xf0) >> 4); 254 arr_4[2] = ((arr_3[1] & 0x0f) << 2) + 255 ((arr_3[2] & 0xc0) >> 6); 256 arr_4[3] = arr_3[2] & 0x3f; 257 258 for (i = 0; i < 4; i++) 259 ret[ret_cnt++] = b64_data[arr_4[i]]; 260 i = 0; 261 } 262 } 263 264 if (i) { 265 for (j = i; j < 3; j++) 266 arr_3[j] = '\0'; 267 268 arr_4[0] = (arr_3[0] & 0xfc) >> 2; 269 arr_4[1] = ((arr_3[0] & 0x03) << 4) + 270 ((arr_3[1] & 0xf0) >> 4); 271 arr_4[2] = ((arr_3[1] & 0x0f) << 2) + 272 ((arr_3[2] & 0xc0) >> 6); 273 arr_4[3] = arr_3[2] & 0x3f; 274 275 for (j = 0; j < (i + 1); j++) 276 ret[ret_cnt++] = b64_data[arr_4[j]]; 277 278 while (i++ < 3) 279 ret[ret_cnt++] = '='; 280 } 281 282 ret[ret_cnt++] = '\0'; 283 return (ret); 284 } 285 286 /* 287 * smb_base64_decode 288 * 289 * Decode using base64 algorithm. 290 * Caller should free the returned buffer when done. 291 */ 292 static char * 293 smb_base64_decode(char *encoded_str) 294 { 295 int len = strlen(encoded_str); 296 int i = 0, j = 0; 297 int en_ind = 0; 298 char arr_4[4], arr_3[3]; 299 int ret_cnt = 0; 300 char *ret = malloc(SMB_DEC_LEN); 301 char *p; 302 303 if (ret == NULL) { 304 return (NULL); 305 } 306 307 while (len-- && (encoded_str[en_ind] != '=') && 308 smb_is_base64(encoded_str[en_ind])) { 309 arr_4[i++] = encoded_str[en_ind]; 310 en_ind++; 311 if (i == 4) { 312 for (i = 0; i < 4; i++) { 313 if ((p = strchr(b64_data, arr_4[i])) == NULL) 314 return (NULL); 315 316 arr_4[i] = (int)(p - b64_data); 317 } 318 319 arr_3[0] = (arr_4[0] << 2) + 320 ((arr_4[1] & 0x30) >> 4); 321 arr_3[1] = ((arr_4[1] & 0xf) << 4) + 322 ((arr_4[2] & 0x3c) >> 2); 323 arr_3[2] = ((arr_4[2] & 0x3) << 6) + 324 arr_4[3]; 325 326 for (i = 0; i < 3; i++) 327 ret[ret_cnt++] = arr_3[i]; 328 329 i = 0; 330 } 331 } 332 333 if (i) { 334 for (j = i; j < 4; j++) 335 arr_4[j] = 0; 336 337 for (j = 0; j < 4; j++) { 338 if ((p = strchr(b64_data, arr_4[j])) == NULL) 339 return (NULL); 340 341 arr_4[j] = (int)(p - b64_data); 342 } 343 arr_3[0] = (arr_4[0] << 2) + 344 ((arr_4[1] & 0x30) >> 4); 345 arr_3[1] = ((arr_4[1] & 0xf) << 4) + 346 ((arr_4[2] & 0x3c) >> 2); 347 arr_3[2] = ((arr_4[2] & 0x3) << 6) + 348 arr_4[3]; 349 for (j = 0; j < (i - 1); j++) 350 ret[ret_cnt++] = arr_3[j]; 351 } 352 353 ret[ret_cnt++] = '\0'; 354 return (ret); 355 } 356 357 static char * 358 smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) 359 { 360 smb_scfhandle_t *handle; 361 char *value; 362 363 if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) 364 return (NULL); 365 366 handle = smb_smf_scf_init(svc_fmri_prefix); 367 if (handle == NULL) { 368 free(value); 369 return (NULL); 370 } 371 372 (void) smb_smf_create_service_pgroup(handle, svc_propgrp); 373 374 if (smb_smf_get_string_property(handle, name, value, 375 sizeof (char) * MAX_VALUE_BUFLEN) != 0) { 376 smb_smf_scf_fini(handle); 377 free(value); 378 return (NULL); 379 } 380 381 smb_smf_scf_fini(handle); 382 return (value); 383 384 } 385 386 static int 387 smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, 388 char *name, char *value) 389 { 390 smb_scfhandle_t *handle = NULL; 391 int rc = 0; 392 393 394 handle = smb_smf_scf_init(svc_fmri_prefix); 395 if (handle == NULL) { 396 return (1); 397 } 398 399 (void) smb_smf_create_service_pgroup(handle, svc_propgrp); 400 401 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { 402 smb_smf_scf_fini(handle); 403 return (1); 404 } 405 406 if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK) 407 rc = 1; 408 409 if (smb_smf_end_transaction(handle) != SMBD_SMF_OK) 410 rc = 1; 411 412 smb_smf_scf_fini(handle); 413 return (rc); 414 } 415 416 /* 417 * smb_config_getstr 418 * 419 * Fetch the specified string configuration item from SMF 420 */ 421 int 422 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz) 423 { 424 smb_scfhandle_t *handle; 425 smb_cfg_param_t *cfg; 426 int rc = SMBD_SMF_OK; 427 char *pg; 428 char protbuf[SMB_ENC_LEN]; 429 char *tmp; 430 431 *cbuf = '\0'; 432 cfg = smb_config_getent(id); 433 assert(cfg->sc_type == SCF_TYPE_ASTRING); 434 435 if (id == SMB_CI_ADS_SITE) 436 return (smb_config_get_idmap_site_name(cbuf, bufsz)); 437 if (id == SMB_CI_DOMAIN_SRV) 438 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz)); 439 440 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 441 if (handle == NULL) 442 return (SMBD_SMF_SYSTEM_ERR); 443 444 if (cfg->sc_flags & SMB_CF_PROTECTED) { 445 if ((rc = smb_smf_create_service_pgroup(handle, 446 SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK) 447 goto error; 448 449 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name, 450 protbuf, sizeof (protbuf))) != SMBD_SMF_OK) 451 goto error; 452 453 if (*protbuf != '\0') { 454 tmp = smb_base64_decode(protbuf); 455 (void) strlcpy(cbuf, tmp, bufsz); 456 free(tmp); 457 } 458 } else { 459 pg = (cfg->sc_flags & SMB_CF_EXEC) ? SMBD_EXEC_PG_NAME : 460 SMBD_PG_NAME; 461 rc = smb_smf_create_service_pgroup(handle, pg); 462 if (rc == SMBD_SMF_OK) 463 rc = smb_smf_get_string_property(handle, cfg->sc_name, 464 cbuf, bufsz); 465 } 466 467 error: 468 smb_smf_scf_fini(handle); 469 return (rc); 470 } 471 472 /* 473 * Translate the value of an astring SMF property into a binary 474 * IP address. If the value is neither a valid IPv4 nor IPv6 475 * address, attempt to look it up as a hostname using the 476 * configured address type. 477 */ 478 int 479 smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr) 480 { 481 int rc, error; 482 int a_family; 483 char ipstr[MAXHOSTNAMELEN]; 484 struct hostent *h; 485 smb_cfg_param_t *cfg; 486 487 if (ipaddr == NULL) 488 return (SMBD_SMF_INVALID_ARG); 489 490 bzero(ipaddr, sizeof (smb_inaddr_t)); 491 rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr)); 492 if (rc == SMBD_SMF_OK) { 493 if (*ipstr == '\0') 494 return (SMBD_SMF_INVALID_ARG); 495 496 if (inet_pton(AF_INET, ipstr, &ipaddr->a_ipv4) == 1) { 497 ipaddr->a_family = AF_INET; 498 return (SMBD_SMF_OK); 499 } 500 501 if (inet_pton(AF_INET6, ipstr, &ipaddr->a_ipv6) == 1) { 502 ipaddr->a_family = AF_INET6; 503 return (SMBD_SMF_OK); 504 } 505 506 /* 507 * The value is neither an IPv4 nor IPv6 address; 508 * so check if it's a hostname. 509 */ 510 a_family = smb_config_getbool(SMB_CI_IPV6_ENABLE) ? 511 AF_INET6 : AF_INET; 512 h = getipnodebyname(ipstr, a_family, AI_DEFAULT, 513 &error); 514 if (h != NULL) { 515 bcopy(*(h->h_addr_list), &ipaddr->a_ip, 516 h->h_length); 517 ipaddr->a_family = a_family; 518 freehostent(h); 519 rc = SMBD_SMF_OK; 520 } else { 521 cfg = smb_config_getent(sc_id); 522 syslog(LOG_ERR, "smbd/%s: %s unable to get %s " 523 "address: %d", cfg->sc_name, ipstr, 524 a_family == AF_INET ? "IPv4" : "IPv6", error); 525 rc = SMBD_SMF_INVALID_ARG; 526 } 527 } 528 529 return (rc); 530 } 531 532 /* 533 * smb_config_getnum 534 * 535 * Returns the value of a numeric config param. 536 */ 537 int 538 smb_config_getnum(smb_cfg_id_t id, int64_t *cint) 539 { 540 smb_scfhandle_t *handle; 541 smb_cfg_param_t *cfg; 542 int rc = SMBD_SMF_OK; 543 544 *cint = 0; 545 cfg = smb_config_getent(id); 546 assert(cfg->sc_type == SCF_TYPE_INTEGER); 547 548 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 549 if (handle == NULL) 550 return (SMBD_SMF_SYSTEM_ERR); 551 552 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); 553 if (rc == SMBD_SMF_OK) 554 rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint); 555 smb_smf_scf_fini(handle); 556 557 return (rc); 558 } 559 560 /* 561 * smb_config_getbool 562 * 563 * Returns the value of a boolean config param. 564 */ 565 boolean_t 566 smb_config_getbool(smb_cfg_id_t id) 567 { 568 smb_scfhandle_t *handle; 569 smb_cfg_param_t *cfg; 570 int rc = SMBD_SMF_OK; 571 uint8_t vbool; 572 573 cfg = smb_config_getent(id); 574 assert(cfg->sc_type == SCF_TYPE_BOOLEAN); 575 576 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 577 if (handle == NULL) 578 return (B_FALSE); 579 580 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); 581 if (rc == SMBD_SMF_OK) 582 rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool); 583 smb_smf_scf_fini(handle); 584 585 return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE); 586 } 587 588 /* 589 * smb_config_get 590 * 591 * This function returns the value of the requested config 592 * iterm regardless of its type in string format. This should 593 * be used when the config item type is not known by the caller. 594 */ 595 int 596 smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz) 597 { 598 smb_cfg_param_t *cfg; 599 int64_t cint; 600 int rc; 601 602 cfg = smb_config_getent(id); 603 switch (cfg->sc_type) { 604 case SCF_TYPE_ASTRING: 605 return (smb_config_getstr(id, cbuf, bufsz)); 606 607 case SCF_TYPE_INTEGER: 608 rc = smb_config_getnum(id, &cint); 609 if (rc == SMBD_SMF_OK) 610 (void) snprintf(cbuf, bufsz, "%lld", cint); 611 return (rc); 612 613 case SCF_TYPE_BOOLEAN: 614 if (smb_config_getbool(id)) 615 (void) strlcpy(cbuf, "true", bufsz); 616 else 617 (void) strlcpy(cbuf, "false", bufsz); 618 return (SMBD_SMF_OK); 619 } 620 621 return (SMBD_SMF_INVALID_ARG); 622 } 623 624 /* 625 * smb_config_setstr 626 * 627 * Set the specified config param with the given 628 * value. 629 */ 630 int 631 smb_config_setstr(smb_cfg_id_t id, char *value) 632 { 633 smb_scfhandle_t *handle; 634 smb_cfg_param_t *cfg; 635 int rc = SMBD_SMF_OK; 636 boolean_t protected; 637 char *tmp = NULL; 638 char *pg; 639 640 cfg = smb_config_getent(id); 641 assert(cfg->sc_type == SCF_TYPE_ASTRING); 642 643 if (id == SMB_CI_ADS_SITE) 644 return (smb_config_set_idmap_site_name(value)); 645 if (id == SMB_CI_DOMAIN_SRV) 646 return (smb_config_set_idmap_preferred_dc(value)); 647 648 protected = B_FALSE; 649 650 switch (cfg->sc_flags) { 651 case SMB_CF_PROTECTED: 652 protected = B_TRUE; 653 pg = SMBD_PROTECTED_PG_NAME; 654 break; 655 case SMB_CF_EXEC: 656 pg = SMBD_EXEC_PG_NAME; 657 break; 658 default: 659 pg = SMBD_PG_NAME; 660 break; 661 } 662 663 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 664 if (handle == NULL) 665 return (SMBD_SMF_SYSTEM_ERR); 666 667 rc = smb_smf_create_service_pgroup(handle, pg); 668 if (rc == SMBD_SMF_OK) 669 rc = smb_smf_start_transaction(handle); 670 671 if (rc != SMBD_SMF_OK) { 672 smb_smf_scf_fini(handle); 673 return (rc); 674 } 675 676 if (protected && value && (*value != '\0')) { 677 if ((tmp = smb_base64_encode(value)) == NULL) { 678 (void) smb_smf_end_transaction(handle); 679 smb_smf_scf_fini(handle); 680 return (SMBD_SMF_NO_MEMORY); 681 } 682 683 value = tmp; 684 } 685 686 /* 687 * We don't want people who care enough about protecting their data 688 * by requiring encryption to accidentally expose their data 689 * by lowering the protocol, so prevent them from going below 3.0 690 * if encryption is required. 691 * Also, ensure that max_protocol >= min_protocol. 692 */ 693 if (id == SMB_CI_MAX_PROTOCOL) { 694 smb_cfg_val_t encrypt; 695 uint32_t min; 696 uint32_t val; 697 698 encrypt = smb_config_get_require(SMB_CI_ENCRYPT); 699 min = smb_config_get_min_protocol(); 700 val = smb_convert_version_str(value); 701 702 if (encrypt == SMB_CONFIG_REQUIRED && 703 val < SMB_VERS_3_0) { 704 syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0" 705 " while smbd/encrypt == required."); 706 rc = SMBD_SMF_INVALID_ARG; 707 } else if (val < min) { 708 syslog(LOG_ERR, "Cannot set smbd/max_protocol to less" 709 " than smbd/min_protocol."); 710 rc = SMBD_SMF_INVALID_ARG; 711 } 712 } else if (id == SMB_CI_MIN_PROTOCOL) { 713 uint32_t max; 714 uint32_t val; 715 716 max = smb_config_get_max_protocol(); 717 val = smb_convert_version_str(value); 718 719 if (val > max) { 720 syslog(LOG_ERR, "Cannot set smbd/min_protocol to more" 721 " than smbd/max_protocol."); 722 rc = SMBD_SMF_INVALID_ARG; 723 } 724 } 725 726 if (rc == SMBD_SMF_OK) { 727 rc = smb_smf_set_string_property(handle, cfg->sc_name, value); 728 } 729 730 free(tmp); 731 (void) smb_smf_end_transaction(handle); 732 smb_smf_scf_fini(handle); 733 return (rc); 734 } 735 736 /* 737 * smb_config_setnum 738 * 739 * Sets a numeric configuration iterm 740 */ 741 int 742 smb_config_setnum(smb_cfg_id_t id, int64_t value) 743 { 744 smb_scfhandle_t *handle; 745 smb_cfg_param_t *cfg; 746 int rc = SMBD_SMF_OK; 747 748 cfg = smb_config_getent(id); 749 assert(cfg->sc_type == SCF_TYPE_INTEGER); 750 751 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 752 if (handle == NULL) 753 return (SMBD_SMF_SYSTEM_ERR); 754 755 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); 756 if (rc == SMBD_SMF_OK) 757 rc = smb_smf_start_transaction(handle); 758 759 if (rc != SMBD_SMF_OK) { 760 smb_smf_scf_fini(handle); 761 return (rc); 762 } 763 764 rc = smb_smf_set_integer_property(handle, cfg->sc_name, value); 765 766 (void) smb_smf_end_transaction(handle); 767 smb_smf_scf_fini(handle); 768 return (rc); 769 } 770 771 /* 772 * smb_config_setbool 773 * 774 * Sets a boolean configuration iterm 775 */ 776 int 777 smb_config_setbool(smb_cfg_id_t id, boolean_t value) 778 { 779 smb_scfhandle_t *handle; 780 smb_cfg_param_t *cfg; 781 int rc = SMBD_SMF_OK; 782 783 cfg = smb_config_getent(id); 784 assert(cfg->sc_type == SCF_TYPE_BOOLEAN); 785 786 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 787 if (handle == NULL) 788 return (SMBD_SMF_SYSTEM_ERR); 789 790 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); 791 if (rc == SMBD_SMF_OK) 792 rc = smb_smf_start_transaction(handle); 793 794 if (rc != SMBD_SMF_OK) { 795 smb_smf_scf_fini(handle); 796 return (rc); 797 } 798 799 rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value); 800 801 (void) smb_smf_end_transaction(handle); 802 smb_smf_scf_fini(handle); 803 return (rc); 804 } 805 806 /* 807 * smb_config_set 808 * 809 * This function sets the value of the specified config 810 * iterm regardless of its type in string format. This should 811 * be used when the config item type is not known by the caller. 812 */ 813 int 814 smb_config_set(smb_cfg_id_t id, char *value) 815 { 816 smb_cfg_param_t *cfg; 817 int64_t cint; 818 819 cfg = smb_config_getent(id); 820 switch (cfg->sc_type) { 821 case SCF_TYPE_ASTRING: 822 return (smb_config_setstr(id, value)); 823 824 case SCF_TYPE_INTEGER: 825 cint = atoi(value); 826 return (smb_config_setnum(id, cint)); 827 828 case SCF_TYPE_BOOLEAN: 829 return (smb_config_setbool(id, strcasecmp(value, "true") == 0)); 830 } 831 832 return (SMBD_SMF_INVALID_ARG); 833 } 834 835 int 836 smb_config_get_debug() 837 { 838 int64_t val64; 839 int val = 0; /* default */ 840 smb_scfhandle_t *handle = NULL; 841 842 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 843 if (handle == NULL) { 844 return (val); 845 } 846 847 if (smb_smf_create_service_pgroup(handle, 848 SMBD_PG_NAME) != SMBD_SMF_OK) { 849 smb_smf_scf_fini(handle); 850 return (val); 851 } 852 853 if (smb_smf_get_integer_property(handle, "debug", &val64) != 0) { 854 smb_smf_scf_fini(handle); 855 return (val); 856 } 857 val = (int)val64; 858 859 smb_smf_scf_fini(handle); 860 861 return (val); 862 } 863 864 uint8_t 865 smb_config_get_fg_flag() 866 { 867 uint8_t run_fg = 0; /* Default is to run in daemon mode */ 868 smb_scfhandle_t *handle = NULL; 869 870 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 871 if (handle == NULL) { 872 return (run_fg); 873 } 874 875 if (smb_smf_create_service_pgroup(handle, 876 SMBD_PG_NAME) != SMBD_SMF_OK) { 877 smb_smf_scf_fini(handle); 878 return (run_fg); 879 } 880 881 if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) { 882 smb_smf_scf_fini(handle); 883 return (run_fg); 884 } 885 886 smb_smf_scf_fini(handle); 887 888 return (run_fg); 889 } 890 891 /* 892 * smb_config_get_ads_enable 893 * 894 * Returns value of the "config/use_ads" parameter 895 * from the IDMAP SMF configuration repository. 896 * 897 */ 898 boolean_t 899 smb_config_get_ads_enable(void) 900 { 901 smb_scfhandle_t *handle = NULL; 902 uint8_t vbool; 903 int rc = 0; 904 905 handle = smb_smf_scf_init(IDMAP_FMRI_PREFIX); 906 if (handle == NULL) 907 return (B_FALSE); 908 909 rc = smb_smf_create_service_pgroup(handle, IDMAP_PG_NAME); 910 if (rc == SMBD_SMF_OK) 911 rc = smb_smf_get_boolean_property(handle, "use_ads", &vbool); 912 smb_smf_scf_fini(handle); 913 914 return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_TRUE); 915 } 916 917 /* 918 * smb_config_get_localsid 919 * 920 * Returns value of the "config/machine_sid" parameter 921 * from the IDMAP SMF configuration repository. 922 * Result is allocated; caller should free. 923 */ 924 char * 925 smb_config_get_localsid(void) 926 { 927 return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX, 928 IDMAP_PG_NAME)); 929 } 930 931 /* 932 * smb_config_get_localuuid 933 * 934 * Returns value of the "config/machine_uuid" parameter 935 * from the IDMAP SMF configuration repository. 936 * 937 */ 938 int 939 smb_config_get_localuuid(uuid_t uu) 940 { 941 char *s; 942 943 uuid_clear(uu); 944 s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX, 945 IDMAP_PG_NAME); 946 if (s == NULL) 947 return (-1); 948 949 if (uuid_parse(s, uu) < 0) { 950 free(s); 951 return (-1); 952 } 953 954 return (0); 955 } 956 957 static int 958 smb_config_get_idmap_preferred_dc(char *cbuf, int bufsz) 959 { 960 char *s; 961 int len, rc = -1; 962 963 s = smb_config_getenv_generic(IDMAP_PREF_DC, 964 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME); 965 if (s != NULL) { 966 len = strlcpy(cbuf, s, bufsz); 967 if (len < bufsz) 968 rc = 0; 969 free(s); 970 } 971 return (rc); 972 } 973 974 static int 975 smb_config_set_idmap_preferred_dc(char *value) 976 { 977 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, 978 IDMAP_PREF_DC, value)); 979 } 980 981 static int 982 smb_config_get_idmap_site_name(char *cbuf, int bufsz) 983 { 984 char *s; 985 int len, rc = -1; 986 987 s = smb_config_getenv_generic(IDMAP_SITE_NAME, 988 IDMAP_FMRI_PREFIX, IDMAP_PG_NAME); 989 if (s != NULL) { 990 len = strlcpy(cbuf, s, bufsz); 991 if (len < bufsz) 992 rc = 0; 993 free(s); 994 } 995 return (rc); 996 } 997 998 static int 999 smb_config_set_idmap_site_name(char *value) 1000 { 1001 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, 1002 IDMAP_SITE_NAME, value)); 1003 } 1004 1005 /* 1006 * smb_config_set_idmap_domain 1007 * 1008 * Set the "config/domain_name" parameter from IDMAP SMF repository. 1009 */ 1010 int 1011 smb_config_set_idmap_domain(char *value) 1012 { 1013 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, 1014 IDMAP_DOMAIN, value)); 1015 } 1016 1017 /* 1018 * smb_config_refresh_idmap 1019 * 1020 * Refresh IDMAP SMF service after making changes to its configuration. 1021 */ 1022 int 1023 smb_config_refresh_idmap(void) 1024 { 1025 char instance[32]; 1026 1027 (void) snprintf(instance, sizeof (instance), "%s:default", 1028 IDMAP_FMRI_PREFIX); 1029 return (smf_refresh_instance(instance)); 1030 } 1031 1032 int 1033 smb_config_secmode_fromstr(char *secmode) 1034 { 1035 if (secmode == NULL) 1036 return (SMB_SECMODE_WORKGRP); 1037 1038 if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0) 1039 return (SMB_SECMODE_DOMAIN); 1040 1041 return (SMB_SECMODE_WORKGRP); 1042 } 1043 1044 char * 1045 smb_config_secmode_tostr(int secmode) 1046 { 1047 if (secmode == SMB_SECMODE_DOMAIN) 1048 return (SMB_SECMODE_DOMAIN_STR); 1049 1050 return (SMB_SECMODE_WORKGRP_STR); 1051 } 1052 1053 int 1054 smb_config_get_secmode() 1055 { 1056 char p[16]; 1057 1058 (void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p)); 1059 return (smb_config_secmode_fromstr(p)); 1060 } 1061 1062 int 1063 smb_config_set_secmode(int secmode) 1064 { 1065 char *p; 1066 1067 p = smb_config_secmode_tostr(secmode); 1068 return (smb_config_setstr(SMB_CI_SECURITY, p)); 1069 } 1070 1071 void 1072 smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest, 1073 char *guid) 1074 { 1075 if (domain) 1076 (void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain, 1077 NETBIOS_NAME_SZ); 1078 1079 if (fqdn) 1080 (void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn, 1081 MAXHOSTNAMELEN); 1082 1083 if (sid) 1084 (void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid, 1085 SMB_SID_STRSZ); 1086 1087 if (forest) 1088 (void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest, 1089 MAXHOSTNAMELEN); 1090 1091 if (guid) 1092 (void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid, 1093 UUID_PRINTABLE_STRING_LENGTH); 1094 } 1095 1096 void 1097 smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest, 1098 char *guid) 1099 { 1100 if (domain) 1101 (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain); 1102 if (fqdn) 1103 (void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn); 1104 if (sid) 1105 (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid); 1106 if (forest) 1107 (void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest); 1108 if (guid) 1109 (void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid); 1110 } 1111 1112 /* 1113 * The version stored in SMF in string format as N.N where 1114 * N is a number defined by Microsoft. The first number represents 1115 * the major version and the second number is the minor version. 1116 * Current defined values can be found here in 'ver_table'. 1117 * 1118 * This function reads the SMF string value and converts it to 1119 * two numbers returned in the given 'version' structure. 1120 * Current default version number is 5.0 which is for Windows 2000. 1121 */ 1122 void 1123 smb_config_get_version(smb_version_t *version) 1124 { 1125 smb_version_t tmpver; 1126 char verstr[SMB_VERSTR_LEN]; 1127 char *p; 1128 int rc, i; 1129 static smb_version_t ver_table [] = { 1130 { 0, SMB_MAJOR_NT, SMB_MINOR_NT, 1381, 0 }, 1131 { 0, SMB_MAJOR_2000, SMB_MINOR_2000, 2195, 0 }, 1132 { 0, SMB_MAJOR_XP, SMB_MINOR_XP, 2196, 0 }, 1133 { 0, SMB_MAJOR_2003, SMB_MINOR_2003, 2196, 0 }, 1134 { 0, SMB_MAJOR_VISTA, SMB_MINOR_VISTA, 6000, 0 }, 1135 { 0, SMB_MAJOR_2008, SMB_MINOR_2008, 6000, 0 }, 1136 { 0, SMB_MAJOR_2008R2, SMB_MINOR_2008R2, 7007, 0 }, 1137 { 0, SMB_MAJOR_7, SMB_MINOR_7, 7007, 0 } 1138 }; 1139 1140 *version = ver_table[1]; 1141 version->sv_size = sizeof (smb_version_t); 1142 1143 rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr)); 1144 if (rc != SMBD_SMF_OK) 1145 return; 1146 1147 if ((p = strchr(verstr, '.')) == NULL) 1148 return; 1149 1150 *p = '\0'; 1151 tmpver.sv_major = (uint8_t)atoi(verstr); 1152 tmpver.sv_minor = (uint8_t)atoi(p + 1); 1153 1154 for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) { 1155 if ((tmpver.sv_major == ver_table[i].sv_major) && 1156 (tmpver.sv_minor == ver_table[i].sv_minor)) { 1157 *version = ver_table[i]; 1158 version->sv_size = sizeof (smb_version_t); 1159 break; 1160 } 1161 } 1162 } 1163 1164 /* 1165 * Reads share exec script properties 1166 */ 1167 uint32_t 1168 smb_config_get_execinfo(char *map, char *unmap, size_t bufsz) 1169 { 1170 char buf[MAXPATHLEN]; 1171 uint32_t flags = 0; 1172 1173 if (map == NULL) { 1174 map = buf; 1175 bufsz = MAXPATHLEN; 1176 } 1177 1178 *map = '\0'; 1179 (void) smb_config_getstr(SMB_CI_MAP, map, bufsz); 1180 if (*map != '\0') 1181 flags |= SMB_EXEC_MAP; 1182 1183 if (unmap == NULL) { 1184 unmap = buf; 1185 bufsz = MAXPATHLEN; 1186 } 1187 1188 *unmap = '\0'; 1189 (void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz); 1190 if (*unmap != '\0') 1191 flags |= SMB_EXEC_UNMAP; 1192 1193 *buf = '\0'; 1194 (void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf)); 1195 if (*buf != '\0') 1196 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0) 1197 flags |= SMB_EXEC_TERM; 1198 1199 return (flags); 1200 } 1201 1202 static smb_cfg_param_t * 1203 smb_config_getent(smb_cfg_id_t id) 1204 { 1205 int i; 1206 1207 for (i = 0; i < SMB_CI_MAX; i++) 1208 if (smb_cfg_table[i].sc_id == id) 1209 return (&smb_cfg_table[id]); 1210 1211 assert(0); 1212 return (NULL); 1213 } 1214 1215 static uint32_t 1216 smb_config_get_protocol(smb_cfg_id_t id, char *name, uint32_t default_val) 1217 { 1218 char str[SMB_VERSTR_LEN]; 1219 int rc; 1220 uint32_t val; 1221 1222 rc = smb_config_getstr(id, str, sizeof (str)); 1223 if (rc == SMBD_SMF_OK) { 1224 val = smb_convert_version_str(str); 1225 if (val != 0) 1226 return (val); 1227 if (str[0] != '\0') { 1228 syslog(LOG_ERR, "smbd/%s value invalid: %s", name, str); 1229 } 1230 } 1231 1232 return (default_val); 1233 } 1234 1235 /* 1236 * The service manifest has empty values by default for min_protocol and 1237 * max_protocol. The expectation is that when those values are empty, we don't 1238 * constrain the range of supported protocol versions (and allow use of the 1239 * whole range that we implement). For that reason, this should usually be the 1240 * highest protocol version we implement. 1241 */ 1242 uint32_t max_protocol_default = SMB_VERS_3_11; 1243 1244 uint32_t 1245 smb_config_get_max_protocol(void) 1246 { 1247 uint32_t max; 1248 1249 max = smb_config_get_protocol(SMB_CI_MAX_PROTOCOL, "max_protocol", 1250 max_protocol_default); 1251 1252 return (max); 1253 } 1254 1255 /* 1256 * This should eventually be SMB_VERS_2_BASE 1257 */ 1258 uint32_t min_protocol_default = SMB_VERS_1; 1259 1260 uint32_t 1261 smb_config_get_min_protocol(void) 1262 { 1263 uint32_t min; 1264 1265 min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol", 1266 min_protocol_default); 1267 1268 return (min); 1269 } 1270 1271 int 1272 smb_config_check_protocol(char *value) 1273 { 1274 if (smb_convert_version_str(value) != 0) 1275 return (0); 1276 1277 return (-1); 1278 } 1279 1280 /* 1281 * Only SMB 3.x supports encryption. 1282 * SMB 3.0.2 uses AES128-CCM only. 1283 * SMB 3.1.1 - AES128-CCM or AES128-GCM. 1284 * This function returns bitmask for enabled ciphers 1285 */ 1286 uint16_t 1287 smb31_config_get_encrypt_cipher(void) 1288 { 1289 uint32_t max_proto = smb_config_get_max_protocol(); 1290 uint16_t cipher = 0; 1291 char str[50]; 1292 int i; 1293 1294 /* SMB 3.0 supports only AES-128-CCM */ 1295 if (max_proto < SMB_VERS_3_11) 1296 return (SMB3_CIPHER_FLAG_AES128_CCM); 1297 1298 /* SMB 3.1.1 */ 1299 if (smb_config_getstr(SMB_CI_ENCRYPT_CIPHER, str, sizeof (str)) 1300 == SMBD_SMF_OK) { 1301 char *s = str; 1302 char *p = NULL; 1303 1304 do { 1305 p = strchr(s, ','); 1306 if (p != NULL) 1307 *p++ = '\0'; 1308 1309 /* # of ciphers too small - don't care about O(n2) */ 1310 for (i = 0; smb31_enc_ciphers[i].str != NULL; i++) { 1311 if (strcmp(s, smb31_enc_ciphers[i].str) == 0) 1312 cipher |= smb31_enc_ciphers[i].val; 1313 } 1314 1315 if (p != NULL) 1316 s = p; 1317 } while (p != NULL && *s != '\0'); 1318 } 1319 1320 if (cipher == 0) 1321 cipher = SMB3_ALL_CIPHERS; 1322 1323 return (cipher); 1324 } 1325 1326 /* 1327 * If smb2_enable is present and max_protocol is empty, 1328 * set max_protocol. Delete smb2_enable. 1329 */ 1330 static void 1331 upgrade_smb2_enable() 1332 { 1333 smb_scfhandle_t *handle; 1334 char *s2e_name = "smb2_enable"; 1335 char *s2e_sval; 1336 uint8_t s2e_bval; 1337 char *maxp_name = "max_protocol"; 1338 char *maxp_sval; 1339 char verstr[SMB_VERSTR_LEN]; 1340 int rc; 1341 1342 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 1343 if (handle == NULL) 1344 return; 1345 rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); 1346 if (rc != SMBD_SMF_OK) 1347 goto out; 1348 1349 /* Is there an "smb2_enable" property? */ 1350 rc = smb_smf_get_boolean_property(handle, s2e_name, &s2e_bval); 1351 if (rc != SMBD_SMF_OK) { 1352 syslog(LOG_DEBUG, "upgrade: smb2_enable not found"); 1353 goto out; 1354 } 1355 1356 /* 1357 * We will try to delete the smb2_enable property, so we need 1358 * the transaction to start now, before we modify max_protocol 1359 */ 1360 if ((rc = smb_smf_start_transaction(handle)) != 0) { 1361 syslog(LOG_DEBUG, "upgrade_smb2_enable: start trans (%d)", rc); 1362 goto out; 1363 } 1364 1365 /* 1366 * Old (smb2_enable) property exists. 1367 * Does the new one? (max_protocol) 1368 */ 1369 rc = smb_smf_get_string_property(handle, maxp_name, 1370 verstr, sizeof (verstr)); 1371 if (rc == SMBD_SMF_OK && !smb_config_check_protocol(verstr)) { 1372 syslog(LOG_DEBUG, "upgrade: found %s = %s", 1373 maxp_name, verstr); 1374 /* Leave existing max_protocol as we found it. */ 1375 } else { 1376 /* 1377 * New property missing or invalid. 1378 * Upgrade from "smb2_enable". 1379 */ 1380 if (s2e_bval == 0) { 1381 s2e_sval = "false"; 1382 maxp_sval = "1"; 1383 } else { 1384 s2e_sval = "true"; 1385 maxp_sval = "2.1"; 1386 } 1387 /* 1388 * Note: Need this in the same transaction as the 1389 * delete of smb2_enable below. 1390 */ 1391 rc = smb_smf_set_string_property(handle, maxp_name, maxp_sval); 1392 if (rc != SMBD_SMF_OK) { 1393 syslog(LOG_ERR, "failed to set smbd/%d (%d)", 1394 maxp_name, rc); 1395 goto out; 1396 } 1397 syslog(LOG_INFO, "upgrade smbd/smb2_enable=%s " 1398 "converted to smbd/max_protocol=%s", 1399 s2e_sval, maxp_sval); 1400 } 1401 1402 /* 1403 * Delete the old smb2_enable property. 1404 */ 1405 if ((rc = smb_smf_delete_property(handle, s2e_name)) != 0) { 1406 syslog(LOG_DEBUG, "upgrade_smb2_enable: delete prop (%d)", rc); 1407 } else if ((rc = smb_smf_end_transaction(handle)) != 0) { 1408 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc); 1409 } 1410 if (rc != 0) { 1411 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)", 1412 s2e_name, rc); 1413 } 1414 1415 out: 1416 (void) smb_smf_end_transaction(handle); 1417 smb_smf_scf_fini(handle); 1418 } 1419 1420 1421 /* 1422 * Run once at startup convert old SMF settings to current. 1423 */ 1424 void 1425 smb_config_upgrade(void) 1426 { 1427 upgrade_smb2_enable(); 1428 } 1429 1430 smb_cfg_val_t 1431 smb_config_get_require(smb_cfg_id_t id) 1432 { 1433 int rc; 1434 char str[sizeof ("required")]; 1435 1436 rc = smb_config_getstr(id, str, sizeof (str)); 1437 if (rc != SMBD_SMF_OK) 1438 return (SMB_CONFIG_DISABLED); 1439 1440 if (strncmp(str, "required", sizeof (str)) == 0) 1441 return (SMB_CONFIG_REQUIRED); 1442 if (strncmp(str, "enabled", sizeof (str)) == 0) 1443 return (SMB_CONFIG_ENABLED); 1444 1445 return (SMB_CONFIG_DISABLED); 1446 } 1447