Print this page
NEX-19857 ads_site broken in sharectl get/set smb
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-17523 Enable SMB3 server by default
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10019 SMB server min_protocol setting
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-2314 SMB server debug logging needs improvement
NEX-1852 re-enable Kerberos-style AD join (try 2)
NEX-1638 Updated DC Locator
 Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
NEX-1050 enable_smb2 should be smb2_enable
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-56 extended security NTLMSSP, inbound
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SFR-56 Identity Management for UNIX (IDMU) authentication support
re #6813 rb1757 port 2976 Child folder visibility through shares


   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 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * CIFS configuration management library
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <unistd.h>
  33 #include <synch.h>
  34 #include <string.h>
  35 #include <strings.h>
  36 #include <syslog.h>
  37 #include <netdb.h>
  38 #include <ctype.h>
  39 #include <sys/types.h>
  40 #include <libscf.h>
  41 #include <assert.h>
  42 #include <uuid/uuid.h>
  43 #include <smbsrv/libsmb.h>


  49         uint32_t sc_flags;
  50 } smb_cfg_param_t;
  51 
  52 struct str_val {
  53         char *str;
  54         uint32_t val;
  55 };
  56 
  57 /*
  58  * config parameter flags
  59  */
  60 #define SMB_CF_PROTECTED        0x01
  61 #define SMB_CF_EXEC             0x02
  62 
  63 /* idmap SMF fmri and Property Group */
  64 #define IDMAP_FMRI_PREFIX               "system/idmap"
  65 #define MACHINE_SID                     "machine_sid"
  66 #define MACHINE_UUID                    "machine_uuid"
  67 #define IDMAP_DOMAIN                    "domain_name"
  68 #define IDMAP_PREF_DC                   "preferred_dc"

  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 smb_cfg_param_t smb_cfg_table[] =
  81 {
  82         {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
  83 
  84         /* Oplock configuration, Kernel Only */
  85         {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
  86 
  87         /* Autohome configuration */
  88         {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},


 128 
 129         {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
 130             SMB_CF_PROTECTED},
 131 
 132         {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
 133         {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
 134         {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
 135         {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
 136         {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
 137         {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
 138         {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
 139         {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 140         {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 141         {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 142         {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
 143         {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
 144         {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
 145         {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
 146         {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
 147         {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},




 148 
 149         /* SMB_CI_MAX */
 150 };
 151 



















 152 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
 153 
 154 static boolean_t smb_is_base64(unsigned char c);
 155 static char *smb_base64_encode(char *str_to_encode);
 156 static char *smb_base64_decode(char *encoded_str);
 157 static int smb_config_get_idmap_preferred_dc(char *, int);
 158 static int smb_config_set_idmap_preferred_dc(char *);


 159 














 160 char *
 161 smb_config_getname(smb_cfg_id_t id)
 162 {
 163         smb_cfg_param_t *cfg;
 164         cfg = smb_config_getent(id);
 165         return (cfg->sc_name);
 166 }
 167 
 168 static boolean_t
 169 smb_is_base64(unsigned char c)
 170 {
 171         return (isalnum(c) || (c == '+') || (c == '/'));
 172 }
 173 
 174 /*
 175  * smb_base64_encode
 176  *
 177  * Encode a string using base64 algorithm.
 178  * Caller should free the returned buffer when done.
 179  */


 360 
 361 /*
 362  * smb_config_getstr
 363  *
 364  * Fetch the specified string configuration item from SMF
 365  */
 366 int
 367 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
 368 {
 369         smb_scfhandle_t *handle;
 370         smb_cfg_param_t *cfg;
 371         int rc = SMBD_SMF_OK;
 372         char *pg;
 373         char protbuf[SMB_ENC_LEN];
 374         char *tmp;
 375 
 376         *cbuf = '\0';
 377         cfg = smb_config_getent(id);
 378         assert(cfg->sc_type == SCF_TYPE_ASTRING);
 379 


 380         if (id == SMB_CI_DOMAIN_SRV)
 381                 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
 382 
 383         handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 384         if (handle == NULL)
 385                 return (SMBD_SMF_SYSTEM_ERR);
 386 
 387         if (cfg->sc_flags & SMB_CF_PROTECTED) {
 388                 if ((rc = smb_smf_create_service_pgroup(handle,
 389                     SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
 390                         goto error;
 391 
 392                 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
 393                     protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
 394                         goto error;
 395 
 396                 if (*protbuf != '\0') {
 397                         tmp = smb_base64_decode(protbuf);
 398                         (void) strlcpy(cbuf, tmp, bufsz);
 399                         free(tmp);


 566 
 567 /*
 568  * smb_config_setstr
 569  *
 570  * Set the specified config param with the given
 571  * value.
 572  */
 573 int
 574 smb_config_setstr(smb_cfg_id_t id, char *value)
 575 {
 576         smb_scfhandle_t *handle;
 577         smb_cfg_param_t *cfg;
 578         int rc = SMBD_SMF_OK;
 579         boolean_t protected;
 580         char *tmp = NULL;
 581         char *pg;
 582 
 583         cfg = smb_config_getent(id);
 584         assert(cfg->sc_type == SCF_TYPE_ASTRING);
 585 


 586         if (id == SMB_CI_DOMAIN_SRV)
 587                 return (smb_config_set_idmap_preferred_dc(value));
 588 
 589         protected = B_FALSE;
 590 
 591         switch (cfg->sc_flags) {
 592         case SMB_CF_PROTECTED:
 593                 protected = B_TRUE;
 594                 pg = SMBD_PROTECTED_PG_NAME;
 595                 break;
 596         case SMB_CF_EXEC:
 597                 pg = SMBD_EXEC_PG_NAME;
 598                 break;
 599         default:
 600                 pg = SMBD_PG_NAME;
 601                 break;
 602         }
 603 
 604         handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 605         if (handle == NULL)


 607 
 608         rc = smb_smf_create_service_pgroup(handle, pg);
 609         if (rc == SMBD_SMF_OK)
 610                 rc = smb_smf_start_transaction(handle);
 611 
 612         if (rc != SMBD_SMF_OK) {
 613                 smb_smf_scf_fini(handle);
 614                 return (rc);
 615         }
 616 
 617         if (protected && value && (*value != '\0')) {
 618                 if ((tmp = smb_base64_encode(value)) == NULL) {
 619                         (void) smb_smf_end_transaction(handle);
 620                         smb_smf_scf_fini(handle);
 621                         return (SMBD_SMF_NO_MEMORY);
 622                 }
 623 
 624                 value = tmp;
 625         }
 626 









































 627         rc = smb_smf_set_string_property(handle, cfg->sc_name, value);

 628 
 629         free(tmp);
 630         (void) smb_smf_end_transaction(handle);
 631         smb_smf_scf_fini(handle);
 632         return (rc);
 633 }
 634 
 635 /*
 636  * smb_config_setnum
 637  *
 638  * Sets a numeric configuration iterm
 639  */
 640 int
 641 smb_config_setnum(smb_cfg_id_t id, int64_t value)
 642 {
 643         smb_scfhandle_t *handle;
 644         smb_cfg_param_t *cfg;
 645         int rc = SMBD_SMF_OK;
 646 
 647         cfg = smb_config_getent(id);


 860         int len, rc = -1;
 861 
 862         s = smb_config_getenv_generic(IDMAP_PREF_DC,
 863             IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
 864         if (s != NULL) {
 865                 len = strlcpy(cbuf, s, bufsz);
 866                 if (len < bufsz)
 867                         rc = 0;
 868                 free(s);
 869         }
 870         return (rc);
 871 }
 872 
 873 static int
 874 smb_config_set_idmap_preferred_dc(char *value)
 875 {
 876         return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 877             IDMAP_PREF_DC, value));
 878 }
 879 
























 880 /*
 881  * smb_config_set_idmap_domain
 882  *
 883  * Set the "config/domain_name" parameter from IDMAP SMF repository.
 884  */
 885 int
 886 smb_config_set_idmap_domain(char *value)
 887 {
 888         return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 889             IDMAP_DOMAIN, value));
 890 }
 891 
 892 /*
 893  * smb_config_refresh_idmap
 894  *
 895  * Refresh IDMAP SMF service after making changes to its configuration.
 896  */
 897 int
 898 smb_config_refresh_idmap(void)
 899 {


1070         if (*buf != '\0')
1071                 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1072                         flags |= SMB_EXEC_TERM;
1073 
1074         return (flags);
1075 }
1076 
1077 static smb_cfg_param_t *
1078 smb_config_getent(smb_cfg_id_t id)
1079 {
1080         int i;
1081 
1082         for (i = 0; i < SMB_CI_MAX; i++)
1083                 if (smb_cfg_table[i].sc_id == id)
1084                         return (&smb_cfg_table[id]);
1085 
1086         assert(0);
1087         return (NULL);
1088 }
1089 






1090 













1091 /*
1092  * We store the max SMB protocol version in SMF as a string,
1093  * (for convenience of svccfg etc) but the programmatic get/set
1094  * interfaces use the numeric form.
1095  *
1096  * The numeric values are as defined in the [MS-SMB2] spec.
1097  * except for how we represent "1" (for SMB1) which is an
1098  * arbitrary value below SMB2_VERS_BASE.
1099  */
1100 static struct str_val
1101 smb_versions[] = {
1102         { "3.0",        SMB_VERS_3_0 },
1103         { "2.1",        SMB_VERS_2_1 },
1104         { "2.002",      SMB_VERS_2_002 },
1105         { "1",          SMB_VERS_1 },
1106         { NULL,         0 }
1107 };
1108 











1109 /*
1110  * This really should be the latest (SMB_VERS_3_0)
1111  * but we're being cautious with SMB3 for a while.
1112  */
1113 uint32_t max_protocol_default = SMB_VERS_2_1;
1114 
1115 uint32_t
1116 smb_config_get_max_protocol(void)
1117 {
1118         char str[SMB_VERSTR_LEN];
1119         int i, rc;
1120 
1121         rc = smb_config_getstr(SMB_CI_MAX_PROTOCOL, str, sizeof (str));
1122         if (rc == SMBD_SMF_OK) {
1123                 for (i = 0; smb_versions[i].str != NULL; i++) {
1124                         if (strcmp(str, smb_versions[i].str) == 0)
1125                                 return (smb_versions[i].val);
1126                 }
1127                 if (str[0] != '\0') {
1128                         syslog(LOG_ERR, "smbd/max_protocol value invalid");
1129                 }
1130         }
1131 
1132         return (max_protocol_default);
1133 }
1134 
1135 int
1136 smb_config_check_protocol(char *value)
1137 {
1138         int i;
1139 
1140         for (i = 0; smb_versions[i].str != NULL; i++) {
1141                 if (strcmp(value, smb_versions[i].str) == 0)
1142                         return (0);
1143         }
1144 
1145         return (-1);
1146 }
1147 
1148 /*
1149  * If smb2_enable is present and max_protocol is empty,
1150  * set max_protocol.  Delete smb2_enable.
1151  */
1152 static void
1153 upgrade_smb2_enable()
1154 {
1155         smb_scfhandle_t *handle;
1156         char *s2e_name = "smb2_enable";
1157         char *s2e_sval;
1158         uint8_t s2e_bval;
1159         char *maxp_name = "max_protocol";
1160         char *maxp_sval;
1161         char verstr[SMB_VERSTR_LEN];
1162         int rc;
1163 


1230                 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1231         }
1232         if (rc != 0) {
1233                 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1234                     s2e_name, rc);
1235         }
1236 
1237 out:
1238         (void) smb_smf_end_transaction(handle);
1239         smb_smf_scf_fini(handle);
1240 }
1241 
1242 
1243 /*
1244  * Run once at startup convert old SMF settings to current.
1245  */
1246 void
1247 smb_config_upgrade(void)
1248 {
1249         upgrade_smb2_enable();


















1250 }


   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 2018 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * CIFS configuration management library
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <unistd.h>
  33 #include <synch.h>
  34 #include <string.h>
  35 #include <strings.h>
  36 #include <syslog.h>
  37 #include <netdb.h>
  38 #include <ctype.h>
  39 #include <sys/types.h>
  40 #include <libscf.h>
  41 #include <assert.h>
  42 #include <uuid/uuid.h>
  43 #include <smbsrv/libsmb.h>


  49         uint32_t sc_flags;
  50 } smb_cfg_param_t;
  51 
  52 struct str_val {
  53         char *str;
  54         uint32_t val;
  55 };
  56 
  57 /*
  58  * config parameter flags
  59  */
  60 #define SMB_CF_PROTECTED        0x01
  61 #define SMB_CF_EXEC             0x02
  62 
  63 /* idmap SMF fmri and Property Group */
  64 #define IDMAP_FMRI_PREFIX               "system/idmap"
  65 #define MACHINE_SID                     "machine_sid"
  66 #define MACHINE_UUID                    "machine_uuid"
  67 #define IDMAP_DOMAIN                    "domain_name"
  68 #define IDMAP_PREF_DC                   "preferred_dc"
  69 #define IDMAP_SITE_NAME                 "site_name"
  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 smb_cfg_param_t smb_cfg_table[] =
  82 {
  83         {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
  84 
  85         /* Oplock configuration, Kernel Only */
  86         {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
  87 
  88         /* Autohome configuration */
  89         {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},


 129 
 130         {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
 131             SMB_CF_PROTECTED},
 132 
 133         {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
 134         {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
 135         {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
 136         {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
 137         {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
 138         {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
 139         {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
 140         {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 141         {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 142         {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 143         {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
 144         {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
 145         {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
 146         {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
 147         {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
 148         {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0},
 149         {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0},
 150         {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0},
 151         {SMB_CI_BYPASS_TRAVERSE_CHECKING,
 152             "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0},
 153 
 154         /* SMB_CI_MAX */
 155 };
 156 
 157 /*
 158  * We store the max SMB protocol version in SMF as a string,
 159  * (for convenience of svccfg etc) but the programmatic get/set
 160  * interfaces use the numeric form.
 161  *
 162  * The numeric values are as defined in the [MS-SMB2] spec.
 163  * except for how we represent "1" (for SMB1) which is an
 164  * arbitrary value below SMB2_VERS_BASE.
 165  */
 166 static struct str_val
 167 smb_versions[] = {
 168         { "3.02",       SMB_VERS_3_02 },
 169         { "3.0",        SMB_VERS_3_0 },
 170         { "2.1",        SMB_VERS_2_1 },
 171         { "2.002",      SMB_VERS_2_002 },
 172         { "1",          SMB_VERS_1 },
 173         { NULL,         0 }
 174 };
 175 
 176 static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
 177 
 178 static boolean_t smb_is_base64(unsigned char c);
 179 static char *smb_base64_encode(char *str_to_encode);
 180 static char *smb_base64_decode(char *encoded_str);
 181 static int smb_config_get_idmap_preferred_dc(char *, int);
 182 static int smb_config_set_idmap_preferred_dc(char *);
 183 static int smb_config_get_idmap_site_name(char *, int);
 184 static int smb_config_set_idmap_site_name(char *);
 185 
 186 static uint32_t
 187 smb_convert_version_str(const char *version)
 188 {
 189         uint32_t dialect = 0;
 190         int i;
 191 
 192         for (i = 0; smb_versions[i].str != NULL; i++) {
 193                 if (strcmp(version, smb_versions[i].str) == 0)
 194                         dialect = smb_versions[i].val;
 195         }
 196 
 197         return (dialect);
 198 }
 199 
 200 char *
 201 smb_config_getname(smb_cfg_id_t id)
 202 {
 203         smb_cfg_param_t *cfg;
 204         cfg = smb_config_getent(id);
 205         return (cfg->sc_name);
 206 }
 207 
 208 static boolean_t
 209 smb_is_base64(unsigned char c)
 210 {
 211         return (isalnum(c) || (c == '+') || (c == '/'));
 212 }
 213 
 214 /*
 215  * smb_base64_encode
 216  *
 217  * Encode a string using base64 algorithm.
 218  * Caller should free the returned buffer when done.
 219  */


 400 
 401 /*
 402  * smb_config_getstr
 403  *
 404  * Fetch the specified string configuration item from SMF
 405  */
 406 int
 407 smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
 408 {
 409         smb_scfhandle_t *handle;
 410         smb_cfg_param_t *cfg;
 411         int rc = SMBD_SMF_OK;
 412         char *pg;
 413         char protbuf[SMB_ENC_LEN];
 414         char *tmp;
 415 
 416         *cbuf = '\0';
 417         cfg = smb_config_getent(id);
 418         assert(cfg->sc_type == SCF_TYPE_ASTRING);
 419 
 420         if (id == SMB_CI_ADS_SITE)
 421                 return (smb_config_get_idmap_site_name(cbuf, bufsz));
 422         if (id == SMB_CI_DOMAIN_SRV)
 423                 return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
 424 
 425         handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 426         if (handle == NULL)
 427                 return (SMBD_SMF_SYSTEM_ERR);
 428 
 429         if (cfg->sc_flags & SMB_CF_PROTECTED) {
 430                 if ((rc = smb_smf_create_service_pgroup(handle,
 431                     SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
 432                         goto error;
 433 
 434                 if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
 435                     protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
 436                         goto error;
 437 
 438                 if (*protbuf != '\0') {
 439                         tmp = smb_base64_decode(protbuf);
 440                         (void) strlcpy(cbuf, tmp, bufsz);
 441                         free(tmp);


 608 
 609 /*
 610  * smb_config_setstr
 611  *
 612  * Set the specified config param with the given
 613  * value.
 614  */
 615 int
 616 smb_config_setstr(smb_cfg_id_t id, char *value)
 617 {
 618         smb_scfhandle_t *handle;
 619         smb_cfg_param_t *cfg;
 620         int rc = SMBD_SMF_OK;
 621         boolean_t protected;
 622         char *tmp = NULL;
 623         char *pg;
 624 
 625         cfg = smb_config_getent(id);
 626         assert(cfg->sc_type == SCF_TYPE_ASTRING);
 627 
 628         if (id == SMB_CI_ADS_SITE)
 629                 return (smb_config_set_idmap_site_name(value));
 630         if (id == SMB_CI_DOMAIN_SRV)
 631                 return (smb_config_set_idmap_preferred_dc(value));
 632 
 633         protected = B_FALSE;
 634 
 635         switch (cfg->sc_flags) {
 636         case SMB_CF_PROTECTED:
 637                 protected = B_TRUE;
 638                 pg = SMBD_PROTECTED_PG_NAME;
 639                 break;
 640         case SMB_CF_EXEC:
 641                 pg = SMBD_EXEC_PG_NAME;
 642                 break;
 643         default:
 644                 pg = SMBD_PG_NAME;
 645                 break;
 646         }
 647 
 648         handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 649         if (handle == NULL)


 651 
 652         rc = smb_smf_create_service_pgroup(handle, pg);
 653         if (rc == SMBD_SMF_OK)
 654                 rc = smb_smf_start_transaction(handle);
 655 
 656         if (rc != SMBD_SMF_OK) {
 657                 smb_smf_scf_fini(handle);
 658                 return (rc);
 659         }
 660 
 661         if (protected && value && (*value != '\0')) {
 662                 if ((tmp = smb_base64_encode(value)) == NULL) {
 663                         (void) smb_smf_end_transaction(handle);
 664                         smb_smf_scf_fini(handle);
 665                         return (SMBD_SMF_NO_MEMORY);
 666                 }
 667 
 668                 value = tmp;
 669         }
 670 
 671         /*
 672          * We don't want people who care enough about protecting their data
 673          * by requiring encryption to accidentally expose their data
 674          * by lowering the protocol, so prevent them from going below 3.0
 675          * if encryption is required.
 676          * Also, ensure that max_protocol >= min_protocol.
 677          */
 678         if (id == SMB_CI_MAX_PROTOCOL) {
 679                 smb_cfg_val_t encrypt;
 680                 uint32_t min;
 681                 uint32_t val;
 682 
 683                 encrypt = smb_config_get_require(SMB_CI_ENCRYPT);
 684                 min = smb_config_get_min_protocol();
 685                 val = smb_convert_version_str(value);
 686 
 687                 if (encrypt == SMB_CONFIG_REQUIRED &&
 688                     val < SMB_VERS_3_0) {
 689                         syslog(LOG_ERR, "Cannot set smbd/max_protocol below 3.0"
 690                             " while smbd/encrypt == required.");
 691                         rc = SMBD_SMF_INVALID_ARG;
 692                 } else if (val < min) {
 693                         syslog(LOG_ERR, "Cannot set smbd/max_protocol to less"
 694                             " than smbd/min_protocol.");
 695                         rc = SMBD_SMF_INVALID_ARG;
 696                 }
 697         } else if (id == SMB_CI_MIN_PROTOCOL) {
 698                 uint32_t max;
 699                 uint32_t val;
 700 
 701                 max = smb_config_get_max_protocol();
 702                 val = smb_convert_version_str(value);
 703 
 704                 if (val > max) {
 705                         syslog(LOG_ERR, "Cannot set smbd/min_protocol to more"
 706                             " than smbd/max_protocol.");
 707                         rc = SMBD_SMF_INVALID_ARG;
 708                 }
 709         }
 710 
 711         if (rc == SMBD_SMF_OK) {
 712                 rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
 713         }
 714 
 715         free(tmp);
 716         (void) smb_smf_end_transaction(handle);
 717         smb_smf_scf_fini(handle);
 718         return (rc);
 719 }
 720 
 721 /*
 722  * smb_config_setnum
 723  *
 724  * Sets a numeric configuration iterm
 725  */
 726 int
 727 smb_config_setnum(smb_cfg_id_t id, int64_t value)
 728 {
 729         smb_scfhandle_t *handle;
 730         smb_cfg_param_t *cfg;
 731         int rc = SMBD_SMF_OK;
 732 
 733         cfg = smb_config_getent(id);


 946         int len, rc = -1;
 947 
 948         s = smb_config_getenv_generic(IDMAP_PREF_DC,
 949             IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
 950         if (s != NULL) {
 951                 len = strlcpy(cbuf, s, bufsz);
 952                 if (len < bufsz)
 953                         rc = 0;
 954                 free(s);
 955         }
 956         return (rc);
 957 }
 958 
 959 static int
 960 smb_config_set_idmap_preferred_dc(char *value)
 961 {
 962         return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 963             IDMAP_PREF_DC, value));
 964 }
 965 
 966 static int
 967 smb_config_get_idmap_site_name(char *cbuf, int bufsz)
 968 {
 969         char *s;
 970         int len, rc = -1;
 971 
 972         s = smb_config_getenv_generic(IDMAP_SITE_NAME,
 973             IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
 974         if (s != NULL) {
 975                 len = strlcpy(cbuf, s, bufsz);
 976                 if (len < bufsz)
 977                         rc = 0;
 978                 free(s);
 979         }
 980         return (rc);
 981 }
 982 
 983 static int
 984 smb_config_set_idmap_site_name(char *value)
 985 {
 986         return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 987             IDMAP_SITE_NAME, value));
 988 }
 989 
 990 /*
 991  * smb_config_set_idmap_domain
 992  *
 993  * Set the "config/domain_name" parameter from IDMAP SMF repository.
 994  */
 995 int
 996 smb_config_set_idmap_domain(char *value)
 997 {
 998         return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 999             IDMAP_DOMAIN, value));
1000 }
1001 
1002 /*
1003  * smb_config_refresh_idmap
1004  *
1005  * Refresh IDMAP SMF service after making changes to its configuration.
1006  */
1007 int
1008 smb_config_refresh_idmap(void)
1009 {


1180         if (*buf != '\0')
1181                 if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1182                         flags |= SMB_EXEC_TERM;
1183 
1184         return (flags);
1185 }
1186 
1187 static smb_cfg_param_t *
1188 smb_config_getent(smb_cfg_id_t id)
1189 {
1190         int i;
1191 
1192         for (i = 0; i < SMB_CI_MAX; i++)
1193                 if (smb_cfg_table[i].sc_id == id)
1194                         return (&smb_cfg_table[id]);
1195 
1196         assert(0);
1197         return (NULL);
1198 }
1199 
1200 static uint32_t
1201 smb_config_get_protocol(smb_cfg_id_t id, char *name, uint32_t default_val)
1202 {
1203         char str[SMB_VERSTR_LEN];
1204         int rc;
1205         uint32_t val;
1206 
1207         rc = smb_config_getstr(id, str, sizeof (str));
1208         if (rc == SMBD_SMF_OK) {
1209                 val = smb_convert_version_str(str);
1210                 if (val != 0)
1211                         return (val);
1212                 if (str[0] != '\0') {
1213                         syslog(LOG_ERR, "smbd/%s value invalid: %s", name, str);
1214                 }
1215         }
1216 
1217         return (default_val);
1218 }
1219 
1220 /*
1221  * The service manifest has empty values by default for min_protocol and
1222  * max_protocol. The expectation is that when those values are empty, we don't
1223  * constrain the range of supported protocol versions (and allow use of the
1224  * whole range that we implement). For that reason, this should usually be the
1225  * highest protocol version we implement.


1226  */
1227 uint32_t max_protocol_default = SMB_VERS_3_02;







1228 
1229 uint32_t
1230 smb_config_get_max_protocol(void)
1231 {
1232         uint32_t max;
1233 
1234         max = smb_config_get_protocol(SMB_CI_MAX_PROTOCOL, "max_protocol",
1235             max_protocol_default);
1236 
1237         return (max);
1238 }
1239 
1240 /*
1241  * This should eventually be SMB_VERS_2_BASE

1242  */
1243 uint32_t min_protocol_default = SMB_VERS_1;
1244 
1245 uint32_t
1246 smb_config_get_min_protocol(void)
1247 {
1248         uint32_t min;

1249 
1250         min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol",
1251             min_protocol_default);








1252 
1253         return (min);
1254 }
1255 
1256 int
1257 smb_config_check_protocol(char *value)
1258 {
1259         if (smb_convert_version_str(value) != 0)



1260                 return (0);

1261 
1262         return (-1);
1263 }
1264 
1265 /*
1266  * If smb2_enable is present and max_protocol is empty,
1267  * set max_protocol.  Delete smb2_enable.
1268  */
1269 static void
1270 upgrade_smb2_enable()
1271 {
1272         smb_scfhandle_t *handle;
1273         char *s2e_name = "smb2_enable";
1274         char *s2e_sval;
1275         uint8_t s2e_bval;
1276         char *maxp_name = "max_protocol";
1277         char *maxp_sval;
1278         char verstr[SMB_VERSTR_LEN];
1279         int rc;
1280 


1347                 syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1348         }
1349         if (rc != 0) {
1350                 syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1351                     s2e_name, rc);
1352         }
1353 
1354 out:
1355         (void) smb_smf_end_transaction(handle);
1356         smb_smf_scf_fini(handle);
1357 }
1358 
1359 
1360 /*
1361  * Run once at startup convert old SMF settings to current.
1362  */
1363 void
1364 smb_config_upgrade(void)
1365 {
1366         upgrade_smb2_enable();
1367 }
1368 
1369 smb_cfg_val_t
1370 smb_config_get_require(smb_cfg_id_t id)
1371 {
1372         int rc;
1373         char str[sizeof ("required")];
1374 
1375         rc = smb_config_getstr(id, str, sizeof (str));
1376         if (rc != SMBD_SMF_OK)
1377                 return (SMB_CONFIG_DISABLED);
1378 
1379         if (strncmp(str, "required", sizeof (str)) == 0)
1380                 return (SMB_CONFIG_REQUIRED);
1381         if (strncmp(str, "enabled", sizeof (str)) == 0)
1382                 return (SMB_CONFIG_ENABLED);
1383 
1384         return (SMB_CONFIG_DISABLED);
1385 }