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

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
          +++ new/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * CIFS configuration management library
  28   28   */
  29   29  
  30   30  #include <stdio.h>
  31   31  #include <stdlib.h>
  32   32  #include <unistd.h>
  33   33  #include <synch.h>
↓ open down ↓ 25 lines elided ↑ open up ↑
  59   59   */
  60   60  #define SMB_CF_PROTECTED        0x01
  61   61  #define SMB_CF_EXEC             0x02
  62   62  
  63   63  /* idmap SMF fmri and Property Group */
  64   64  #define IDMAP_FMRI_PREFIX               "system/idmap"
  65   65  #define MACHINE_SID                     "machine_sid"
  66   66  #define MACHINE_UUID                    "machine_uuid"
  67   67  #define IDMAP_DOMAIN                    "domain_name"
  68   68  #define IDMAP_PREF_DC                   "preferred_dc"
       69 +#define IDMAP_SITE_NAME                 "site_name"
  69   70  #define IDMAP_PG_NAME                   "config"
  70   71  
  71   72  #define SMB_SECMODE_WORKGRP_STR         "workgroup"
  72   73  #define SMB_SECMODE_DOMAIN_STR          "domain"
  73   74  
  74   75  #define SMB_ENC_LEN     1024
  75   76  #define SMB_DEC_LEN     256
  76   77  
  77   78  static char *b64_data =
  78   79          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
↓ open down ↓ 59 lines elided ↑ open up ↑
 138  139          {SMB_CI_PRINT_ENABLE, "print_enable", SCF_TYPE_BOOLEAN, 0},
 139  140          {SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 140  141          {SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 141  142          {SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 142  143          {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
 143  144          {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
 144  145          {SMB_CI_SMB2_ENABLE_OLD, "smb2_enable", SCF_TYPE_BOOLEAN, 0},
 145  146          {SMB_CI_INITIAL_CREDITS, "initial_credits", SCF_TYPE_INTEGER, 0},
 146  147          {SMB_CI_MAXIMUM_CREDITS, "maximum_credits", SCF_TYPE_INTEGER, 0},
 147  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},
 148  153  
 149  154          /* SMB_CI_MAX */
 150  155  };
 151  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 +
 152  176  static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t);
 153  177  
 154  178  static boolean_t smb_is_base64(unsigned char c);
 155  179  static char *smb_base64_encode(char *str_to_encode);
 156  180  static char *smb_base64_decode(char *encoded_str);
 157  181  static int smb_config_get_idmap_preferred_dc(char *, int);
 158  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 *);
 159  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 +
 160  200  char *
 161  201  smb_config_getname(smb_cfg_id_t id)
 162  202  {
 163  203          smb_cfg_param_t *cfg;
 164  204          cfg = smb_config_getent(id);
 165  205          return (cfg->sc_name);
 166  206  }
 167  207  
 168  208  static boolean_t
 169  209  smb_is_base64(unsigned char c)
↓ open down ↓ 200 lines elided ↑ open up ↑
 370  410          smb_cfg_param_t *cfg;
 371  411          int rc = SMBD_SMF_OK;
 372  412          char *pg;
 373  413          char protbuf[SMB_ENC_LEN];
 374  414          char *tmp;
 375  415  
 376  416          *cbuf = '\0';
 377  417          cfg = smb_config_getent(id);
 378  418          assert(cfg->sc_type == SCF_TYPE_ASTRING);
 379  419  
      420 +        if (id == SMB_CI_ADS_SITE)
      421 +                return (smb_config_get_idmap_site_name(cbuf, bufsz));
 380  422          if (id == SMB_CI_DOMAIN_SRV)
 381  423                  return (smb_config_get_idmap_preferred_dc(cbuf, bufsz));
 382  424  
 383  425          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 384  426          if (handle == NULL)
 385  427                  return (SMBD_SMF_SYSTEM_ERR);
 386  428  
 387  429          if (cfg->sc_flags & SMB_CF_PROTECTED) {
 388  430                  if ((rc = smb_smf_create_service_pgroup(handle,
 389  431                      SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK)
↓ open down ↓ 186 lines elided ↑ open up ↑
 576  618          smb_scfhandle_t *handle;
 577  619          smb_cfg_param_t *cfg;
 578  620          int rc = SMBD_SMF_OK;
 579  621          boolean_t protected;
 580  622          char *tmp = NULL;
 581  623          char *pg;
 582  624  
 583  625          cfg = smb_config_getent(id);
 584  626          assert(cfg->sc_type == SCF_TYPE_ASTRING);
 585  627  
      628 +        if (id == SMB_CI_ADS_SITE)
      629 +                return (smb_config_set_idmap_site_name(value));
 586  630          if (id == SMB_CI_DOMAIN_SRV)
 587  631                  return (smb_config_set_idmap_preferred_dc(value));
 588  632  
 589  633          protected = B_FALSE;
 590  634  
 591  635          switch (cfg->sc_flags) {
 592  636          case SMB_CF_PROTECTED:
 593  637                  protected = B_TRUE;
 594  638                  pg = SMBD_PROTECTED_PG_NAME;
 595  639                  break;
↓ open down ↓ 21 lines elided ↑ open up ↑
 617  661          if (protected && value && (*value != '\0')) {
 618  662                  if ((tmp = smb_base64_encode(value)) == NULL) {
 619  663                          (void) smb_smf_end_transaction(handle);
 620  664                          smb_smf_scf_fini(handle);
 621  665                          return (SMBD_SMF_NO_MEMORY);
 622  666                  }
 623  667  
 624  668                  value = tmp;
 625  669          }
 626  670  
 627      -        rc = smb_smf_set_string_property(handle, cfg->sc_name, value);
      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;
 628  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 +
 629  715          free(tmp);
 630  716          (void) smb_smf_end_transaction(handle);
 631  717          smb_smf_scf_fini(handle);
 632  718          return (rc);
 633  719  }
 634  720  
 635  721  /*
 636  722   * smb_config_setnum
 637  723   *
 638  724   * Sets a numeric configuration iterm
↓ open down ↓ 231 lines elided ↑ open up ↑
 870  956          return (rc);
 871  957  }
 872  958  
 873  959  static int
 874  960  smb_config_set_idmap_preferred_dc(char *value)
 875  961  {
 876  962          return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 877  963              IDMAP_PREF_DC, value));
 878  964  }
 879  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 +
 880  990  /*
 881  991   * smb_config_set_idmap_domain
 882  992   *
 883  993   * Set the "config/domain_name" parameter from IDMAP SMF repository.
 884  994   */
 885  995  int
 886  996  smb_config_set_idmap_domain(char *value)
 887  997  {
 888  998          return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
 889  999              IDMAP_DOMAIN, value));
↓ open down ↓ 190 lines elided ↑ open up ↑
1080 1190          int i;
1081 1191  
1082 1192          for (i = 0; i < SMB_CI_MAX; i++)
1083 1193                  if (smb_cfg_table[i].sc_id == id)
1084 1194                          return (&smb_cfg_table[id]);
1085 1195  
1086 1196          assert(0);
1087 1197          return (NULL);
1088 1198  }
1089 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;
1090 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 +
1091 1220  /*
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.
     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.
1099 1226   */
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      -};
     1227 +uint32_t max_protocol_default = SMB_VERS_3_02;
1108 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 +
1109 1240  /*
1110      - * This really should be the latest (SMB_VERS_3_0)
1111      - * but we're being cautious with SMB3 for a while.
     1241 + * This should eventually be SMB_VERS_2_BASE
1112 1242   */
1113      -uint32_t max_protocol_default = SMB_VERS_2_1;
     1243 +uint32_t min_protocol_default = SMB_VERS_1;
1114 1244  
1115 1245  uint32_t
1116      -smb_config_get_max_protocol(void)
     1246 +smb_config_get_min_protocol(void)
1117 1247  {
1118      -        char str[SMB_VERSTR_LEN];
1119      -        int i, rc;
     1248 +        uint32_t min;
1120 1249  
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      -        }
     1250 +        min = smb_config_get_protocol(SMB_CI_MIN_PROTOCOL, "min_protocol",
     1251 +            min_protocol_default);
1131 1252  
1132      -        return (max_protocol_default);
     1253 +        return (min);
1133 1254  }
1134 1255  
1135 1256  int
1136 1257  smb_config_check_protocol(char *value)
1137 1258  {
1138      -        int i;
     1259 +        if (smb_convert_version_str(value) != 0)
     1260 +                return (0);
1139 1261  
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 1262          return (-1);
1146 1263  }
1147 1264  
1148 1265  /*
1149 1266   * If smb2_enable is present and max_protocol is empty,
1150 1267   * set max_protocol.  Delete smb2_enable.
1151 1268   */
1152 1269  static void
1153 1270  upgrade_smb2_enable()
1154 1271  {
↓ open down ↓ 85 lines elided ↑ open up ↑
1240 1357  }
1241 1358  
1242 1359  
1243 1360  /*
1244 1361   * Run once at startup convert old SMF settings to current.
1245 1362   */
1246 1363  void
1247 1364  smb_config_upgrade(void)
1248 1365  {
1249 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);
1250 1385  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX