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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * CIFS configuration management library 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <synch.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <syslog.h> 39 #include <netdb.h> 40 #include <ctype.h> 41 #include <sys/types.h> 42 #include <libscf.h> 43 #include <smbsrv/libsmb.h> 44 45 typedef struct smb_cfg_param { 46 char *sc_pg; 47 char *sc_name; 48 int sc_type; 49 char *sc_value; 50 uint32_t sc_flags; 51 } smb_cfg_param_t; 52 53 /* 54 * config parameter flags 55 */ 56 #define SMB_CF_NOTINIT 0x00 /* Not initialized yet */ 57 #define SMB_CF_DEFINED 0x01 /* Defined/read from env */ 58 #define SMB_CF_MODIFIED 0x02 /* Has been modified */ 59 #define SMB_CF_SYSTEM 0x04 /* system; not part of cifs config */ 60 61 #define SMB_CL_NONE 0 62 #define SMB_CL_READ 1 63 #define SMB_CL_WRITE 2 64 65 /* idmap SMF fmri and Property Group */ 66 #define IDMAP_FMRI_PREFIX "system/idmap" 67 #define MACHINE_SID "machine_sid" 68 #define MAPPING_DOMAIN "mapping_domain" 69 #define GLOBAL_CATALOG "global_catalog" 70 #define IDMAP_PG_NAME "config" 71 72 #define SMB_SECMODE_WORKGRP_STR "workgroup" 73 #define SMB_SECMODE_DOMAIN_STR "domain" 74 75 #define SMB_ENC_LEN 1024 76 #define SMB_DEC_LEN 256 77 78 static char *b64_data = 79 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 80 81 static rwlock_t smb_cfg_rwlk; 82 static int lock_type = SMB_CL_NONE; 83 84 /* 85 * IMPORTANT: any changes to the order of this table's entries 86 * need to be reflected in smb_cfg_id_t enum in libsmb.h 87 */ 88 static smb_cfg_param_t smb_cfg_table[] = 89 { 90 /* Redirector configuration, User space */ 91 {SMBD_PG_NAME, SMB_CD_RDR_IPCMODE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 92 {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCUSER, 93 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 94 {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCPWD, 95 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 96 97 /* Oplock configuration, Kernel Only */ 98 {SMBD_PG_NAME, SMB_CD_OPLOCK_ENABLE, 99 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 100 {SMBD_PG_NAME, SMB_CD_OPLOCK_TIMEOUT, 101 SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 102 103 /* Autohome configuration */ 104 {SMBD_PG_NAME, SMB_CD_AUTOHOME_MAP, 105 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 106 107 /* Domain/PDC configuration */ 108 {SMBD_PG_NAME, SMB_CD_DOMAIN_SID, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 109 {SMBD_PG_NAME, SMB_CD_DOMAIN_MEMB, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 110 {SMBD_PG_NAME, SMB_CD_DOMAIN_NAME, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 111 {SMBD_PG_NAME, SMB_CD_DOMAIN_SRV, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 112 113 /* WINS configuration */ 114 {SMBD_PG_NAME, SMB_CD_WINS_SRV1, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 115 {SMBD_PG_NAME, SMB_CD_WINS_SRV2, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 116 {SMBD_PG_NAME, SMB_CD_WINS_EXCL, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 117 118 /* RPC services configuration */ 119 {SMBD_PG_NAME, SMB_CD_SRVSVC_SHRSET_ENABLE, 120 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 121 {SMBD_PG_NAME, SMB_CD_LOGR_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 122 {SMBD_PG_NAME, SMB_CD_MLRPC_KALIVE, 123 SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 124 125 /* Kmod specific configuration */ 126 {SMBD_PG_NAME, SMB_CD_MAX_BUFSIZE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 127 {SMBD_PG_NAME, SMB_CD_MAX_WORKERS, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 128 {SMBD_PG_NAME, SMB_CD_MAX_CONNECTIONS, 129 SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 130 {SMBD_PG_NAME, SMB_CD_KEEPALIVE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 131 {SMBD_PG_NAME, SMB_CD_RESTRICT_ANON, 132 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 133 134 {SMBD_PG_NAME, SMB_CD_SIGNING_ENABLE, 135 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 136 {SMBD_PG_NAME, SMB_CD_SIGNING_REQD, 137 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 138 {SMBD_PG_NAME, SMB_CD_SIGNING_CHECK, 139 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 140 141 /* Kmod tuning configuration */ 142 {SMBD_PG_NAME, SMB_CD_FLUSH_REQUIRED, 143 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 144 {SMBD_PG_NAME, SMB_CD_SYNC_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 145 {SMBD_PG_NAME, SMB_CD_DIRSYMLINK_DISABLE, 146 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 147 {SMBD_PG_NAME, SMB_CD_ANNONCE_QUOTA, 148 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 149 150 /* SMBd configuration */ 151 {SMBD_PG_NAME, SMB_CD_SECURITY, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 152 {SMBD_PG_NAME, SMB_CD_NBSCOPE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 153 {SMBD_PG_NAME, SMB_CD_SYS_CMNT, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 154 {SMBD_PG_NAME, SMB_CD_LM_LEVEL, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 155 {SMBD_PG_NAME, SMB_CD_MSDCS_DISABLE, 156 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 157 158 /* ADS Configuration */ 159 {SMBD_PG_NAME, SMB_CD_ADS_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 160 {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_USER, 161 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 162 {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_PASSWD, 163 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 164 {SMBD_PG_NAME, SMB_CD_ADS_DOMAIN, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 165 {SMBD_PG_NAME, SMB_CD_ADS_USER_CONTAINER, 166 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 167 {SMBD_PG_NAME, SMB_CD_ADS_SITE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, 168 {SMBD_PG_NAME, SMB_CD_ADS_IPLOOKUP, 169 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 170 171 /* Dynamic DNS */ 172 {SMBD_PG_NAME, SMB_CD_DYNDNS_ENABLE, 173 SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, 174 {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_COUNT, 175 SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 176 {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_SEC, 177 SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, 178 179 {SMBD_PROTECTED_PG_NAME, SMB_CD_MACHINE_PASSWD, 180 SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT} 181 /* SMB_CI_MAX */ 182 }; 183 184 static boolean_t smb_is_base64(unsigned char c); 185 static char *smb_base64_encode(char *str_to_encode); 186 static char *smb_base64_decode(char *encoded_str); 187 static int smb_config_update(smb_cfg_param_t *cfg, char *value); 188 static int smb_config_save_all(); 189 static int smb_config_save(char *pgname); 190 191 static boolean_t 192 smb_is_base64(unsigned char c) 193 { 194 return (isalnum(c) || (c == '+') || (c == '/')); 195 } 196 197 /* 198 * smb_base64_encode 199 * 200 * Encode a string using base64 algorithm. 201 * Caller should free the returned buffer when done. 202 */ 203 static char * 204 smb_base64_encode(char *str_to_encode) 205 { 206 int ret_cnt = 0; 207 int i = 0, j = 0; 208 char arr_3[3], arr_4[4]; 209 int len = strlen(str_to_encode); 210 char *ret = malloc(SMB_ENC_LEN); 211 212 if (ret == NULL) { 213 return (NULL); 214 } 215 216 while (len--) { 217 arr_3[i++] = *(str_to_encode++); 218 if (i == 3) { 219 arr_4[0] = (arr_3[0] & 0xfc) >> 2; 220 arr_4[1] = ((arr_3[0] & 0x03) << 4) + 221 ((arr_3[1] & 0xf0) >> 4); 222 arr_4[2] = ((arr_3[1] & 0x0f) << 2) + 223 ((arr_3[2] & 0xc0) >> 6); 224 arr_4[3] = arr_3[2] & 0x3f; 225 226 for (i = 0; i < 4; i++) 227 ret[ret_cnt++] = b64_data[arr_4[i]]; 228 i = 0; 229 } 230 } 231 232 if (i) { 233 for (j = i; j < 3; j++) 234 arr_3[j] = '\0'; 235 236 arr_4[0] = (arr_3[0] & 0xfc) >> 2; 237 arr_4[1] = ((arr_3[0] & 0x03) << 4) + 238 ((arr_3[1] & 0xf0) >> 4); 239 arr_4[2] = ((arr_3[1] & 0x0f) << 2) + 240 ((arr_3[2] & 0xc0) >> 6); 241 arr_4[3] = arr_3[2] & 0x3f; 242 243 for (j = 0; j < (i + 1); j++) 244 ret[ret_cnt++] = b64_data[arr_4[j]]; 245 246 while (i++ < 3) 247 ret[ret_cnt++] = '='; 248 } 249 250 ret[ret_cnt++] = '\0'; 251 return (ret); 252 } 253 254 /* 255 * smb_base64_decode 256 * 257 * Decode using base64 algorithm. 258 * Caller should free the returned buffer when done. 259 */ 260 static char * 261 smb_base64_decode(char *encoded_str) 262 { 263 int len = strlen(encoded_str); 264 int i = 0, j = 0; 265 int en_ind = 0; 266 char arr_4[4], arr_3[3]; 267 int ret_cnt = 0; 268 char *ret = malloc(SMB_DEC_LEN); 269 char *p; 270 271 if (ret == NULL) { 272 return (NULL); 273 } 274 275 while (len-- && (encoded_str[en_ind] != '=') && 276 smb_is_base64(encoded_str[en_ind])) { 277 arr_4[i++] = encoded_str[en_ind]; 278 en_ind++; 279 if (i == 4) { 280 for (i = 0; i < 4; i++) { 281 if ((p = strchr(b64_data, arr_4[i])) == NULL) 282 return (NULL); 283 284 arr_4[i] = (int)(p - b64_data); 285 } 286 287 arr_3[0] = (arr_4[0] << 2) + 288 ((arr_4[1] & 0x30) >> 4); 289 arr_3[1] = ((arr_4[1] & 0xf) << 4) + 290 ((arr_4[2] & 0x3c) >> 2); 291 arr_3[2] = ((arr_4[2] & 0x3) << 6) + 292 arr_4[3]; 293 294 for (i = 0; i < 3; i++) 295 ret[ret_cnt++] = arr_3[i]; 296 297 i = 0; 298 } 299 } 300 301 if (i) { 302 for (j = i; j < 4; j++) 303 arr_4[j] = 0; 304 305 for (j = 0; j < 4; j++) { 306 if ((p = strchr(b64_data, arr_4[j])) == NULL) 307 return (NULL); 308 309 arr_4[j] = (int)(p - b64_data); 310 } 311 arr_3[0] = (arr_4[0] << 2) + 312 ((arr_4[1] & 0x30) >> 4); 313 arr_3[1] = ((arr_4[1] & 0xf) << 4) + 314 ((arr_4[2] & 0x3c) >> 2); 315 arr_3[2] = ((arr_4[2] & 0x3) << 6) + 316 arr_4[3]; 317 for (j = 0; j < (i - 1); j++) 318 ret[ret_cnt++] = arr_3[j]; 319 } 320 321 ret[ret_cnt++] = '\0'; 322 return (ret); 323 } 324 325 /* 326 * Basically commit the transaction. 327 */ 328 static int 329 smb_config_saveenv(smb_scfhandle_t *handle) 330 { 331 int ret = 0; 332 333 ret = smb_smf_end_transaction(handle); 334 335 smb_smf_scf_fini(handle); 336 return (ret); 337 } 338 339 /* 340 * smb_config_getenv 341 * 342 * Get the property value from SMF. 343 */ 344 char * 345 smb_config_getenv(smb_cfg_id_t id) 346 { 347 smb_scfhandle_t *handle; 348 char *value; 349 350 if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) 351 return (NULL); 352 353 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 354 if (handle == NULL) { 355 free(value); 356 return (NULL); 357 } 358 359 (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); 360 361 if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, 362 smb_cfg_table[id].sc_name, value, 363 sizeof (char) * MAX_VALUE_BUFLEN) != 0) { 364 smb_smf_scf_fini(handle); 365 free(value); 366 return (NULL); 367 } 368 369 smb_smf_scf_fini(handle); 370 return (value); 371 } 372 373 /* 374 * smb_config_getenv_dec 375 * 376 * For protected property, the value obtained from SMF will be decoded. 377 * The decoded property value will be returned. 378 * 379 * This function should only be called by smb_config_load to populate 380 * the SMB config cache. 381 */ 382 static char * 383 smb_config_getenv_dec(smb_cfg_id_t id) 384 { 385 smb_scfhandle_t *handle; 386 char *value; 387 char *dec; 388 389 if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) 390 return (NULL); 391 392 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 393 if (handle == NULL) { 394 free(value); 395 return (NULL); 396 } 397 398 (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); 399 400 if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, 401 smb_cfg_table[id].sc_name, value, 402 sizeof (char) * MAX_VALUE_BUFLEN) != 0) { 403 smb_smf_scf_fini(handle); 404 free(value); 405 return (NULL); 406 } 407 smb_smf_scf_fini(handle); 408 if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME)) 409 return (value); 410 411 if (!value) 412 return (NULL); 413 414 if (*value == '\0') { 415 free(value); 416 return (NULL); 417 } 418 419 dec = smb_base64_decode(value); 420 free(value); 421 return (dec); 422 } 423 424 static char * 425 smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) 426 { 427 smb_scfhandle_t *handle; 428 char *value; 429 430 if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) 431 return (NULL); 432 433 handle = smb_smf_scf_init(svc_fmri_prefix); 434 if (handle == NULL) { 435 free(value); 436 return (NULL); 437 } 438 439 (void) smb_smf_create_service_pgroup(handle, svc_propgrp); 440 441 if (smb_smf_get_string_property(handle, name, value, 442 sizeof (char) * MAX_VALUE_BUFLEN) != 0) { 443 smb_smf_scf_fini(handle); 444 free(value); 445 return (NULL); 446 } 447 448 smb_smf_scf_fini(handle); 449 return (value); 450 451 } 452 453 int 454 smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, 455 char *name, char *value) 456 { 457 smb_scfhandle_t *handle = NULL; 458 int rc = 0; 459 460 461 handle = smb_smf_scf_init(svc_fmri_prefix); 462 if (handle == NULL) { 463 return (1); 464 } 465 466 (void) smb_smf_create_service_pgroup(handle, svc_propgrp); 467 468 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { 469 smb_smf_scf_fini(handle); 470 return (1); 471 } 472 473 if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK) 474 rc = 1; 475 476 if (smb_smf_end_transaction(handle) != SMBD_SMF_OK) 477 rc = 1; 478 479 smb_smf_scf_fini(handle); 480 return (rc); 481 } 482 483 /* 484 * smb_config_setenv 485 * 486 * For protected properties, the value will be encoded using base64 487 * algorithm. The encoded string will be stored in SMF. 488 */ 489 int 490 smb_config_setenv(smb_cfg_id_t id, char *value) 491 { 492 smb_scfhandle_t *handle = NULL; 493 char *enc = NULL; 494 int is_protected = 0; 495 496 if ((id >= SMB_CI_MAX) || (id < 0)) { 497 return (1); 498 } 499 500 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 501 if (handle == NULL) { 502 return (1); 503 } 504 505 (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); 506 507 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { 508 smb_smf_scf_fini(handle); 509 return (1); 510 } 511 512 if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME) == 0) { 513 if ((value == NULL) || (*value == '\0')) { 514 (void) smb_smf_end_transaction(handle); 515 smb_smf_scf_fini(handle); 516 return (1); 517 } 518 519 if ((enc = smb_base64_encode(value)) == NULL) { 520 (void) smb_smf_end_transaction(handle); 521 smb_smf_scf_fini(handle); 522 return (1); 523 } 524 525 is_protected = 1; 526 } 527 528 if (smb_smf_set_property(handle, smb_cfg_table[id].sc_type, 529 smb_cfg_table[id].sc_name, is_protected ? enc : value) 530 != SMBD_SMF_OK) { 531 if (enc) 532 free(enc); 533 (void) smb_smf_end_transaction(handle); 534 smb_smf_scf_fini(handle); 535 return (1); 536 } 537 538 if (enc) 539 free(enc); 540 541 if (smb_smf_end_transaction(handle) != SMBD_SMF_OK) { 542 smb_smf_scf_fini(handle); 543 return (1); 544 } 545 546 smb_smf_scf_fini(handle); 547 return (0); 548 } 549 550 static void 551 smb_config_setenv_trans(smb_scfhandle_t *handle, int type, 552 char *name, char *value) 553 { 554 if (smb_smf_set_property(handle, type, name, value) != SMBD_SMF_OK) { 555 syslog(LOG_ERR, "Failed to save service property %s", name); 556 } 557 } 558 559 /* 560 * smb_config_setenv_trans_protected 561 * 562 * This function should only be called to set protected properties 563 * in SMF. The argument 'value' will be encoded using base64 algorithm. 564 * The encoded string will be stored in SMF. 565 */ 566 static void 567 smb_config_setenv_trans_protected(smb_scfhandle_t *handle, char *name, 568 char *value) 569 { 570 char *enc; 571 572 if ((value == NULL) || (*value == '\0')) 573 return; 574 575 if ((enc = smb_base64_encode(value)) == NULL) 576 return; 577 578 if (smb_smf_set_string_property(handle, name, enc) != SMBD_SMF_OK) { 579 syslog(LOG_ERR, "Failed to save service protected property" 580 " %s", name); 581 } 582 583 free(enc); 584 } 585 586 int 587 smb_config_unsetenv(smb_cfg_id_t id) 588 { 589 smb_scfhandle_t *handle = NULL; 590 int ret = 1; 591 592 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 593 if (handle == NULL) { 594 return (ret); 595 } 596 597 (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); 598 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { 599 smb_smf_scf_fini(handle); 600 return (ret); 601 } 602 ret = smb_smf_delete_property(handle, smb_cfg_table[id].sc_name); 603 (void) smb_smf_end_transaction(handle); 604 605 smb_smf_scf_fini(handle); 606 return (ret); 607 } 608 609 static int 610 smb_config_unsetenv_trans(smb_scfhandle_t *handle, char *name) 611 { 612 return (smb_smf_delete_property(handle, name)); 613 } 614 615 /* 616 * smb_config_load 617 * 618 * Loads all the CIFS configuration parameters and sets up the 619 * config table. 620 */ 621 int 622 smb_config_load() 623 { 624 smb_cfg_id_t id; 625 smb_cfg_param_t *cfg; 626 char *value; 627 628 (void) rw_rdlock(&smb_cfg_rwlk); 629 for (id = 0; id < SMB_CI_MAX; id++) { 630 value = smb_config_getenv_dec(id); 631 cfg = &smb_cfg_table[id]; 632 /* 633 * enval == 0 could mean two things, either the 634 * config param is not defined, or it has been 635 * removed. If the variable has already been defined 636 * and now enval is 0, it should be removed, otherwise 637 * we don't need to do anything in this case. 638 */ 639 if ((cfg->sc_flags & SMB_CF_DEFINED) || value) { 640 if (smb_config_update(cfg, value) != 0) { 641 (void) rw_unlock(&smb_cfg_rwlk); 642 if (value) 643 free(value); 644 return (1); 645 } 646 } 647 if (value) { 648 free(value); 649 } 650 } 651 652 (void) rw_unlock(&smb_cfg_rwlk); 653 654 return (0); 655 } 656 657 /* 658 * smb_config_get 659 * 660 * Returns value of the specified config param. 661 * The return value is a string pointer to the locally 662 * allocated memory if the config param is defined 663 * otherwise it would be NULL. 664 * 665 * This function MUST be called after a smb_config_rd/wrlock 666 * function. Caller MUST NOT modify the returned buffer directly. 667 */ 668 char * 669 smb_config_get(smb_cfg_id_t id) 670 { 671 if (id < SMB_CI_MAX) 672 return (smb_cfg_table[id].sc_value); 673 674 return (0); 675 } 676 677 /* 678 * smb_config_getstr 679 * 680 * Returns value of the specified config param. 681 * The returned pointer never will be NULL if the given 682 * 'id' is valid. If the config param is not defined its 683 * default value will be returned. 684 * 685 * This function MUST be called after a smb_config_rd/wrlock 686 * function. Caller MUST NOT modify the returned buffer directly. 687 */ 688 char * 689 smb_config_getstr(smb_cfg_id_t id) 690 { 691 smb_cfg_param_t *cfg; 692 693 if (id < SMB_CI_MAX) { 694 cfg = &smb_cfg_table[id]; 695 if (cfg->sc_value) 696 return (cfg->sc_value); 697 } 698 699 return (NULL); 700 } 701 702 /* 703 * smb_config_getnum 704 * 705 * Returns the value of a numeric config param. 706 * If the config param is not defined it'll return the 707 * default value. 708 * 709 * This function MUST be called after a smb_config_rd/wrlock 710 * function. 711 */ 712 uint32_t 713 smb_config_getnum(smb_cfg_id_t id) 714 { 715 smb_cfg_param_t *cfg; 716 char *strval = NULL; 717 718 if (id < SMB_CI_MAX) { 719 cfg = &smb_cfg_table[id]; 720 if (cfg->sc_value) 721 strval = cfg->sc_value; 722 723 if (strval) 724 return (strtol(strval, 0, 10)); 725 } 726 727 return (0); 728 } 729 730 /* 731 * smb_config_getyorn 732 * 733 * Returns the value of a yes/no config param. 734 * Returns 1 is config is set to "yes", otherwise 0. 735 * 736 * This function MUST be called after a smb_config_rd/wrlock 737 * function. 738 */ 739 int 740 smb_config_getyorn(smb_cfg_id_t id) 741 { 742 char *val; 743 744 val = smb_config_get(id); 745 if (val) { 746 if (strcasecmp(val, "true") == 0) 747 return (1); 748 } 749 750 return (0); 751 } 752 753 /* 754 * smb_config_set 755 * 756 * Set/update the specified config param with the given 757 * value. If the value is NULL the config param will be 758 * unset as if it is not defined. 759 * 760 * This function MUST be called after a smb_config_wrlock 761 * function. 762 */ 763 int 764 smb_config_set(smb_cfg_id_t id, char *value) 765 { 766 smb_cfg_param_t *cfg; 767 int rc = 0; 768 769 if (id < SMB_CI_MAX) { 770 cfg = &smb_cfg_table[id]; 771 rc = smb_config_update(cfg, value); 772 if (rc == 0) 773 cfg->sc_flags |= SMB_CF_MODIFIED; 774 return (rc); 775 } 776 777 return (1); 778 } 779 780 /* 781 * smb_config_setnum 782 * 783 * Set/update the specified config param with the given 784 * value. This is used for numeric config params. The given 785 * number will be converted to string before setting the 786 * config param. 787 * 788 * This function MUST be called after a smb_config_wrlock 789 * function. 790 */ 791 int 792 smb_config_setnum(smb_cfg_id_t id, uint32_t num) 793 { 794 smb_cfg_param_t *cfg; 795 char value[32]; 796 int rc = 0; 797 798 if (id < SMB_CI_MAX) { 799 cfg = &smb_cfg_table[id]; 800 (void) snprintf(value, sizeof (value), "%u", num); 801 rc = smb_config_update(cfg, value); 802 if (rc == 0) 803 cfg->sc_flags |= SMB_CF_MODIFIED; 804 return (rc); 805 } 806 807 return (1); 808 } 809 810 /* 811 * smb_config_rdlock 812 * 813 * Lock the config table for read access. 814 * This function MUST be called before any kind of 815 * read access to the config table i.e. all flavors of 816 * smb_config_get function 817 */ 818 void 819 smb_config_rdlock() 820 { 821 (void) rw_rdlock(&smb_cfg_rwlk); 822 lock_type = SMB_CL_READ; 823 } 824 825 /* 826 * smb_config_wrlock 827 * 828 * Lock the config table for write access. 829 * This function MUST be called before any kind of 830 * write access to the config table i.e. all flavors of 831 * smb_config_set function 832 */ 833 void 834 smb_config_wrlock() 835 { 836 (void) rw_wrlock(&smb_cfg_rwlk); 837 lock_type = SMB_CL_WRITE; 838 } 839 840 /* 841 * smb_config_wrlock 842 * 843 * Unlock the config table. 844 * If the config table has been locked for write access 845 * smb_config_save_all() will be called to save the changes 846 * before unlocking the table. 847 * 848 * This function MUST be called after smb_config_rd/wrlock 849 */ 850 void 851 smb_config_unlock() 852 { 853 if (lock_type == SMB_CL_WRITE) 854 (void) smb_config_save_all(); 855 (void) rw_unlock(&smb_cfg_rwlk); 856 } 857 858 /* 859 * smb_config_save_all 860 * 861 * Save all modified parameters to SMF. 862 */ 863 static int 864 smb_config_save_all() 865 { 866 int rc; 867 868 if ((rc = smb_config_save(SMBD_PG_NAME)) != 0) 869 return (rc); 870 871 return (smb_config_save(SMBD_PROTECTED_PG_NAME)); 872 } 873 874 /* 875 * smb_config_save 876 * 877 * Scan the config table and call smb_config_setenv/smb_config_unsetenv 878 * for params in the specified property group that has been modified. 879 * When the scan is finished, smb_config_saveenv() will be called to 880 * make the changes persistent. 881 */ 882 static int 883 smb_config_save(char *pgname) 884 { 885 smb_cfg_id_t id; 886 smb_cfg_param_t *cfg; 887 smb_scfhandle_t *handle = NULL; 888 int dorefresh = 0; 889 890 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 891 if (handle == NULL) { 892 syslog(LOG_ERR, "smbd: cannot save configuration"); 893 return (1); 894 } 895 896 (void) smb_smf_create_service_pgroup(handle, pgname); 897 if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { 898 syslog(LOG_ERR, "smbd: cannot save configuration"); 899 return (1); 900 } 901 902 for (id = 0; id < SMB_CI_MAX; id++) { 903 cfg = &smb_cfg_table[id]; 904 if (strcmp(cfg->sc_pg, pgname)) 905 continue; 906 907 if (cfg->sc_flags & SMB_CF_MODIFIED) { 908 if (cfg->sc_value) { 909 if (strcmp(pgname, SMBD_PG_NAME) == 0) 910 smb_config_setenv_trans(handle, 911 cfg->sc_type, cfg->sc_name, 912 cfg->sc_value); 913 else 914 smb_config_setenv_trans_protected( 915 handle, cfg->sc_name, 916 cfg->sc_value); 917 } else { 918 (void) smb_config_unsetenv_trans(handle, 919 cfg->sc_name); 920 } 921 cfg->sc_flags &= ~SMB_CF_MODIFIED; 922 dorefresh = 1; 923 } 924 } 925 926 if (smb_config_saveenv(handle) != 0) { 927 syslog(LOG_ERR, "smbd: cannot save configuration"); 928 return (1); 929 } 930 if (dorefresh) 931 (void) smf_refresh_instance(SMBD_DEFAULT_INSTANCE_FMRI); 932 return (0); 933 } 934 935 /* 936 * smb_config_update 937 * 938 * Updates the specified config param with the given value. 939 * This function is called both on (re)load and set. 940 */ 941 static int 942 smb_config_update(smb_cfg_param_t *cfg, char *value) 943 { 944 char *curval; 945 int rc = 0; 946 int len; 947 948 if (value) { 949 len = strlen(value); 950 if (cfg->sc_value) { 951 curval = (char *)realloc(cfg->sc_value, 952 (len + 1)); 953 } else { 954 curval = (char *)malloc(len + 1); 955 } 956 957 if (curval) { 958 cfg->sc_value = curval; 959 (void) strcpy(cfg->sc_value, value); 960 cfg->sc_flags |= SMB_CF_DEFINED; 961 } else { 962 rc = 1; 963 } 964 } else if (cfg->sc_value) { 965 free(cfg->sc_value); 966 cfg->sc_value = NULL; 967 cfg->sc_flags &= ~SMB_CF_DEFINED; 968 } 969 970 return (rc); 971 } 972 973 uint8_t 974 smb_config_get_fg_flag() 975 { 976 uint8_t run_fg = 0; /* Default is to run in daemon mode */ 977 smb_scfhandle_t *handle = NULL; 978 979 handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); 980 if (handle == NULL) { 981 return (run_fg); 982 } 983 984 if (smb_smf_create_service_pgroup(handle, 985 SMBD_PG_NAME) != SMBD_SMF_OK) { 986 smb_smf_scf_fini(handle); 987 return (run_fg); 988 } 989 990 if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) { 991 smb_smf_scf_fini(handle); 992 return (run_fg); 993 } 994 995 smb_smf_scf_fini(handle); 996 997 return (run_fg); 998 } 999 1000 /* 1001 * smb_config_get_localsid 1002 * 1003 * Returns value of the "config/machine_sid" parameter 1004 * from the IDMAP SMF configuration repository. 1005 * 1006 */ 1007 char * 1008 smb_config_get_localsid(void) 1009 { 1010 return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX, 1011 IDMAP_PG_NAME)); 1012 } 1013 1014 /* 1015 * smb_config_set_idmap_domain 1016 * 1017 * Set the "config/mapping_domain" parameter from IDMAP SMF repository. 1018 */ 1019 int 1020 smb_config_set_idmap_domain(char *value) 1021 { 1022 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, 1023 MAPPING_DOMAIN, value)); 1024 } 1025 1026 /* 1027 * smb_config_set_idmap_gc 1028 * 1029 * Set the "config/global_catalog" parameter from IDMAP SMF repository. 1030 */ 1031 int 1032 smb_config_set_idmap_gc(char *value) 1033 { 1034 return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME, 1035 GLOBAL_CATALOG, value)); 1036 } 1037 1038 /* 1039 * smb_config_refresh_idmap 1040 * 1041 * Refresh IDMAP SMF service after making changes to its configuration. 1042 */ 1043 int 1044 smb_config_refresh_idmap(void) 1045 { 1046 char instance[32]; 1047 1048 (void) snprintf(instance, sizeof (instance), "%s:default", 1049 IDMAP_FMRI_PREFIX); 1050 return (smf_refresh_instance(instance)); 1051 } 1052 1053 int 1054 smb_config_secmode_fromstr(char *secmode) 1055 { 1056 if (secmode == NULL) 1057 return (SMB_SECMODE_WORKGRP); 1058 1059 if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0) 1060 return (SMB_SECMODE_DOMAIN); 1061 1062 return (SMB_SECMODE_WORKGRP); 1063 } 1064 1065 char * 1066 smb_config_secmode_tostr(int secmode) 1067 { 1068 if (secmode == SMB_SECMODE_DOMAIN) 1069 return (SMB_SECMODE_DOMAIN_STR); 1070 1071 return (SMB_SECMODE_WORKGRP_STR); 1072 } 1073 1074 int 1075 smb_config_get_secmode() 1076 { 1077 char *p; 1078 1079 p = smb_config_getstr(SMB_CI_SECURITY); 1080 return (smb_config_secmode_fromstr(p)); 1081 } 1082 1083 int 1084 smb_config_set_secmode(int secmode) 1085 { 1086 char *p; 1087 1088 p = smb_config_secmode_tostr(secmode); 1089 return (smb_config_set(SMB_CI_SECURITY, p)); 1090 } 1091