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