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