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
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ 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>
  34   34  #include <string.h>
  35   35  #include <strings.h>
  36   36  #include <syslog.h>
  37   37  #include <netdb.h>
  38   38  #include <ctype.h>
  39   39  #include <sys/types.h>
  40   40  #include <libscf.h>
  41   41  #include <assert.h>
  42   42  #include <uuid/uuid.h>
  43   43  #include <smbsrv/libsmb.h>
  44   44  
  45   45  typedef struct smb_cfg_param {
  46   46          smb_cfg_id_t sc_id;
  47   47          char *sc_name;
  48   48          int sc_type;
  49   49          uint32_t sc_flags;
  50   50  } smb_cfg_param_t;
  51   51  
  52   52  struct str_val {
  53   53          char *str;
  54   54          uint32_t val;
  55   55  };
  56   56  
  57   57  /*
  58   58   * config parameter flags
  
    | 
      ↓ 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+/";
  79   80  
  80   81  static smb_cfg_param_t smb_cfg_table[] =
  81   82  {
  82   83          {SMB_CI_VERSION, "sv_version", SCF_TYPE_ASTRING, 0},
  83   84  
  84   85          /* Oplock configuration, Kernel Only */
  85   86          {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0},
  86   87  
  87   88          /* Autohome configuration */
  88   89          {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0},
  89   90  
  90   91          /* Domain/PDC configuration */
  91   92          {SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0},
  92   93          {SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0},
  93   94          {SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0},
  94   95          {SMB_CI_DOMAIN_FQDN, "fqdn", SCF_TYPE_ASTRING, 0},
  95   96          {SMB_CI_DOMAIN_FOREST, "forest", SCF_TYPE_ASTRING, 0},
  96   97          {SMB_CI_DOMAIN_GUID, "domain_guid", SCF_TYPE_ASTRING, 0},
  97   98          {SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0},
  98   99  
  99  100          /* WINS configuration */
 100  101          {SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0},
 101  102          {SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0},
 102  103          {SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0},
 103  104  
 104  105          /* Kmod specific configuration */
 105  106          {SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0},
 106  107          {SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0},
 107  108          {SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0},
 108  109          {SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0},
 109  110  
 110  111          {SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0},
 111  112          {SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0},
 112  113  
 113  114          /* Kmod tuning configuration */
 114  115          {SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0},
 115  116  
 116  117          /* SMBd configuration */
 117  118          {SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0},
 118  119          {SMB_CI_NETBIOS_ENABLE, "netbios_enable", SCF_TYPE_BOOLEAN, 0},
 119  120          {SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0},
 120  121          {SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0},
 121  122          {SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0},
 122  123  
 123  124          /* ADS Configuration */
 124  125          {SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0},
 125  126  
 126  127          /* Dynamic DNS */
 127  128          {SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0},
 128  129  
 129  130          {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING,
 130  131              SMB_CF_PROTECTED},
 131  132  
 132  133          {SMB_CI_MACHINE_UUID, "machine_uuid", SCF_TYPE_ASTRING, 0},
 133  134          {SMB_CI_KPASSWD_SRV, "kpasswd_server", SCF_TYPE_ASTRING, 0},
 134  135          {SMB_CI_KPASSWD_DOMAIN, "kpasswd_domain", SCF_TYPE_ASTRING, 0},
 135  136          {SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER, 0},
 136  137          {SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER, 0},
 137  138          {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0},
  
    | 
      ↓ 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)
 170  210  {
 171  211          return (isalnum(c) || (c == '+') || (c == '/'));
 172  212  }
 173  213  
 174  214  /*
 175  215   * smb_base64_encode
 176  216   *
 177  217   * Encode a string using base64 algorithm.
 178  218   * Caller should free the returned buffer when done.
 179  219   */
 180  220  static char *
 181  221  smb_base64_encode(char *str_to_encode)
 182  222  {
 183  223          int ret_cnt = 0;
 184  224          int i = 0, j = 0;
 185  225          char arr_3[3], arr_4[4];
 186  226          int len = strlen(str_to_encode);
 187  227          char *ret = malloc(SMB_ENC_LEN);
 188  228  
 189  229          if (ret == NULL) {
 190  230                  return (NULL);
 191  231          }
 192  232  
 193  233          while (len--) {
 194  234                  arr_3[i++] = *(str_to_encode++);
 195  235                  if (i == 3) {
 196  236                          arr_4[0] = (arr_3[0] & 0xfc) >> 2;
 197  237                          arr_4[1] = ((arr_3[0] & 0x03) << 4) +
 198  238                              ((arr_3[1] & 0xf0) >> 4);
 199  239                          arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
 200  240                              ((arr_3[2] & 0xc0) >> 6);
 201  241                          arr_4[3] = arr_3[2] & 0x3f;
 202  242  
 203  243                          for (i = 0; i < 4; i++)
 204  244                                  ret[ret_cnt++] = b64_data[arr_4[i]];
 205  245                          i = 0;
 206  246                  }
 207  247          }
 208  248  
 209  249          if (i) {
 210  250                  for (j = i; j < 3; j++)
 211  251                          arr_3[j] = '\0';
 212  252  
 213  253                  arr_4[0] = (arr_3[0] & 0xfc) >> 2;
 214  254                  arr_4[1] = ((arr_3[0] & 0x03) << 4) +
 215  255                      ((arr_3[1] & 0xf0) >> 4);
 216  256                  arr_4[2] = ((arr_3[1] & 0x0f) << 2) +
 217  257                      ((arr_3[2] & 0xc0) >> 6);
 218  258                  arr_4[3] = arr_3[2] & 0x3f;
 219  259  
 220  260                  for (j = 0; j < (i + 1); j++)
 221  261                          ret[ret_cnt++] = b64_data[arr_4[j]];
 222  262  
 223  263                  while (i++ < 3)
 224  264                          ret[ret_cnt++] = '=';
 225  265          }
 226  266  
 227  267          ret[ret_cnt++] = '\0';
 228  268          return (ret);
 229  269  }
 230  270  
 231  271  /*
 232  272   * smb_base64_decode
 233  273   *
 234  274   * Decode using base64 algorithm.
 235  275   * Caller should free the returned buffer when done.
 236  276   */
 237  277  static char *
 238  278  smb_base64_decode(char *encoded_str)
 239  279  {
 240  280          int len = strlen(encoded_str);
 241  281          int i = 0, j = 0;
 242  282          int en_ind = 0;
 243  283          char arr_4[4], arr_3[3];
 244  284          int ret_cnt = 0;
 245  285          char *ret = malloc(SMB_DEC_LEN);
 246  286          char *p;
 247  287  
 248  288          if (ret == NULL) {
 249  289                  return (NULL);
 250  290          }
 251  291  
 252  292          while (len-- && (encoded_str[en_ind] != '=') &&
 253  293              smb_is_base64(encoded_str[en_ind])) {
 254  294                  arr_4[i++] = encoded_str[en_ind];
 255  295                  en_ind++;
 256  296                  if (i == 4) {
 257  297                          for (i = 0; i < 4; i++) {
 258  298                                  if ((p = strchr(b64_data, arr_4[i])) == NULL)
 259  299                                          return (NULL);
 260  300  
 261  301                                  arr_4[i] = (int)(p - b64_data);
 262  302                          }
 263  303  
 264  304                          arr_3[0] = (arr_4[0] << 2) +
 265  305                              ((arr_4[1] & 0x30) >> 4);
 266  306                          arr_3[1] = ((arr_4[1] & 0xf) << 4) +
 267  307                              ((arr_4[2] & 0x3c) >> 2);
 268  308                          arr_3[2] = ((arr_4[2] & 0x3) << 6) +
 269  309                              arr_4[3];
 270  310  
 271  311                          for (i = 0; i < 3; i++)
 272  312                                  ret[ret_cnt++] = arr_3[i];
 273  313  
 274  314                          i = 0;
 275  315                  }
 276  316          }
 277  317  
 278  318          if (i) {
 279  319                  for (j = i; j < 4; j++)
 280  320                          arr_4[j] = 0;
 281  321  
 282  322                  for (j = 0; j < 4; j++) {
 283  323                          if ((p = strchr(b64_data, arr_4[j])) == NULL)
 284  324                                  return (NULL);
 285  325  
 286  326                          arr_4[j] = (int)(p - b64_data);
 287  327                  }
 288  328                  arr_3[0] = (arr_4[0] << 2) +
 289  329                      ((arr_4[1] & 0x30) >> 4);
 290  330                  arr_3[1] = ((arr_4[1] & 0xf) << 4) +
 291  331                      ((arr_4[2] & 0x3c) >> 2);
 292  332                  arr_3[2] = ((arr_4[2] & 0x3) << 6) +
 293  333                      arr_4[3];
 294  334                  for (j = 0; j < (i - 1); j++)
 295  335                          ret[ret_cnt++] = arr_3[j];
 296  336          }
 297  337  
 298  338          ret[ret_cnt++] = '\0';
 299  339          return (ret);
 300  340  }
 301  341  
 302  342  static char *
 303  343  smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp)
 304  344  {
 305  345          smb_scfhandle_t *handle;
 306  346          char *value;
 307  347  
 308  348          if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL)
 309  349                  return (NULL);
 310  350  
 311  351          handle = smb_smf_scf_init(svc_fmri_prefix);
 312  352          if (handle == NULL) {
 313  353                  free(value);
 314  354                  return (NULL);
 315  355          }
 316  356  
 317  357          (void) smb_smf_create_service_pgroup(handle, svc_propgrp);
 318  358  
 319  359          if (smb_smf_get_string_property(handle, name, value,
 320  360              sizeof (char) * MAX_VALUE_BUFLEN) != 0) {
 321  361                  smb_smf_scf_fini(handle);
 322  362                  free(value);
 323  363                  return (NULL);
 324  364          }
 325  365  
 326  366          smb_smf_scf_fini(handle);
 327  367          return (value);
 328  368  
 329  369  }
 330  370  
 331  371  static int
 332  372  smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp,
 333  373      char *name, char *value)
 334  374  {
 335  375          smb_scfhandle_t *handle = NULL;
 336  376          int rc = 0;
 337  377  
 338  378  
 339  379          handle = smb_smf_scf_init(svc_fmri_prefix);
 340  380          if (handle == NULL) {
 341  381                  return (1);
 342  382          }
 343  383  
 344  384          (void) smb_smf_create_service_pgroup(handle, svc_propgrp);
 345  385  
 346  386          if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) {
 347  387                  smb_smf_scf_fini(handle);
 348  388                  return (1);
 349  389          }
 350  390  
 351  391          if (smb_smf_set_string_property(handle, name, value) != SMBD_SMF_OK)
 352  392                  rc = 1;
 353  393  
 354  394          if (smb_smf_end_transaction(handle) != SMBD_SMF_OK)
 355  395                  rc = 1;
 356  396  
 357  397          smb_smf_scf_fini(handle);
 358  398          return (rc);
 359  399  }
 360  400  
 361  401  /*
 362  402   * smb_config_getstr
 363  403   *
 364  404   * Fetch the specified string configuration item from SMF
 365  405   */
 366  406  int
 367  407  smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz)
 368  408  {
 369  409          smb_scfhandle_t *handle;
  
    | 
      ↓ 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)
 390  432                          goto error;
 391  433  
 392  434                  if ((rc = smb_smf_get_string_property(handle, cfg->sc_name,
 393  435                      protbuf, sizeof (protbuf))) != SMBD_SMF_OK)
 394  436                          goto error;
 395  437  
 396  438                  if (*protbuf != '\0') {
 397  439                          tmp = smb_base64_decode(protbuf);
 398  440                          (void) strlcpy(cbuf, tmp, bufsz);
 399  441                          free(tmp);
 400  442                  }
 401  443          } else {
 402  444                  pg = (cfg->sc_flags & SMB_CF_EXEC) ? SMBD_EXEC_PG_NAME :
 403  445                      SMBD_PG_NAME;
 404  446                  rc = smb_smf_create_service_pgroup(handle, pg);
 405  447                  if (rc == SMBD_SMF_OK)
 406  448                          rc = smb_smf_get_string_property(handle, cfg->sc_name,
 407  449                              cbuf, bufsz);
 408  450          }
 409  451  
 410  452  error:
 411  453          smb_smf_scf_fini(handle);
 412  454          return (rc);
 413  455  }
 414  456  
 415  457  /*
 416  458   * Translate the value of an astring SMF property into a binary
 417  459   * IP address. If the value is neither a valid IPv4 nor IPv6
 418  460   * address, attempt to look it up as a hostname using the
 419  461   * configured address type.
 420  462   */
 421  463  int
 422  464  smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr)
 423  465  {
 424  466          int rc, error;
 425  467          int a_family;
 426  468          char ipstr[MAXHOSTNAMELEN];
 427  469          struct hostent *h;
 428  470          smb_cfg_param_t *cfg;
 429  471  
 430  472          if (ipaddr == NULL)
 431  473                  return (SMBD_SMF_INVALID_ARG);
 432  474  
 433  475          bzero(ipaddr, sizeof (smb_inaddr_t));
 434  476          rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr));
 435  477          if (rc == SMBD_SMF_OK) {
 436  478                  if (*ipstr == '\0')
 437  479                          return (SMBD_SMF_INVALID_ARG);
 438  480  
 439  481                  if (inet_pton(AF_INET, ipstr, &ipaddr->a_ipv4) == 1) {
 440  482                          ipaddr->a_family = AF_INET;
 441  483                          return (SMBD_SMF_OK);
 442  484                  }
 443  485  
 444  486                  if (inet_pton(AF_INET6, ipstr, &ipaddr->a_ipv6) == 1) {
 445  487                          ipaddr->a_family = AF_INET6;
 446  488                          return (SMBD_SMF_OK);
 447  489                  }
 448  490  
 449  491                  /*
 450  492                   * The value is neither an IPv4 nor IPv6 address;
 451  493                   * so check if it's a hostname.
 452  494                   */
 453  495                  a_family = smb_config_getbool(SMB_CI_IPV6_ENABLE) ?
 454  496                      AF_INET6 : AF_INET;
 455  497                  h = getipnodebyname(ipstr, a_family, AI_DEFAULT,
 456  498                      &error);
 457  499                  if (h != NULL) {
 458  500                          bcopy(*(h->h_addr_list), &ipaddr->a_ip,
 459  501                              h->h_length);
 460  502                          ipaddr->a_family = a_family;
 461  503                          freehostent(h);
 462  504                          rc = SMBD_SMF_OK;
 463  505                  } else {
 464  506                          cfg = smb_config_getent(sc_id);
 465  507                          syslog(LOG_ERR, "smbd/%s: %s unable to get %s "
 466  508                              "address: %d", cfg->sc_name, ipstr,
 467  509                              a_family == AF_INET ?  "IPv4" : "IPv6", error);
 468  510                          rc = SMBD_SMF_INVALID_ARG;
 469  511                  }
 470  512          }
 471  513  
 472  514          return (rc);
 473  515  }
 474  516  
 475  517  /*
 476  518   * smb_config_getnum
 477  519   *
 478  520   * Returns the value of a numeric config param.
 479  521   */
 480  522  int
 481  523  smb_config_getnum(smb_cfg_id_t id, int64_t *cint)
 482  524  {
 483  525          smb_scfhandle_t *handle;
 484  526          smb_cfg_param_t *cfg;
 485  527          int rc = SMBD_SMF_OK;
 486  528  
 487  529          *cint = 0;
 488  530          cfg = smb_config_getent(id);
 489  531          assert(cfg->sc_type == SCF_TYPE_INTEGER);
 490  532  
 491  533          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 492  534          if (handle == NULL)
 493  535                  return (SMBD_SMF_SYSTEM_ERR);
 494  536  
 495  537          rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
 496  538          if (rc == SMBD_SMF_OK)
 497  539                  rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint);
 498  540          smb_smf_scf_fini(handle);
 499  541  
 500  542          return (rc);
 501  543  }
 502  544  
 503  545  /*
 504  546   * smb_config_getbool
 505  547   *
 506  548   * Returns the value of a boolean config param.
 507  549   */
 508  550  boolean_t
 509  551  smb_config_getbool(smb_cfg_id_t id)
 510  552  {
 511  553          smb_scfhandle_t *handle;
 512  554          smb_cfg_param_t *cfg;
 513  555          int rc = SMBD_SMF_OK;
 514  556          uint8_t vbool;
 515  557  
 516  558          cfg = smb_config_getent(id);
 517  559          assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
 518  560  
 519  561          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 520  562          if (handle == NULL)
 521  563                  return (B_FALSE);
 522  564  
 523  565          rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
 524  566          if (rc == SMBD_SMF_OK)
 525  567                  rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool);
 526  568          smb_smf_scf_fini(handle);
 527  569  
 528  570          return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE);
 529  571  }
 530  572  
 531  573  /*
 532  574   * smb_config_get
 533  575   *
 534  576   * This function returns the value of the requested config
 535  577   * iterm regardless of its type in string format. This should
 536  578   * be used when the config item type is not known by the caller.
 537  579   */
 538  580  int
 539  581  smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz)
 540  582  {
 541  583          smb_cfg_param_t *cfg;
 542  584          int64_t cint;
 543  585          int rc;
 544  586  
 545  587          cfg = smb_config_getent(id);
 546  588          switch (cfg->sc_type) {
 547  589          case SCF_TYPE_ASTRING:
 548  590                  return (smb_config_getstr(id, cbuf, bufsz));
 549  591  
 550  592          case SCF_TYPE_INTEGER:
 551  593                  rc = smb_config_getnum(id, &cint);
 552  594                  if (rc == SMBD_SMF_OK)
 553  595                          (void) snprintf(cbuf, bufsz, "%lld", cint);
 554  596                  return (rc);
 555  597  
 556  598          case SCF_TYPE_BOOLEAN:
 557  599                  if (smb_config_getbool(id))
 558  600                          (void) strlcpy(cbuf, "true", bufsz);
 559  601                  else
 560  602                          (void) strlcpy(cbuf, "false", bufsz);
 561  603                  return (SMBD_SMF_OK);
 562  604          }
 563  605  
 564  606          return (SMBD_SMF_INVALID_ARG);
 565  607  }
 566  608  
 567  609  /*
 568  610   * smb_config_setstr
 569  611   *
 570  612   * Set the specified config param with the given
 571  613   * value.
 572  614   */
 573  615  int
 574  616  smb_config_setstr(smb_cfg_id_t id, char *value)
 575  617  {
  
    | 
      ↓ 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;
 596  640          case SMB_CF_EXEC:
 597  641                  pg = SMBD_EXEC_PG_NAME;
 598  642                  break;
 599  643          default:
 600  644                  pg = SMBD_PG_NAME;
 601  645                  break;
 602  646          }
 603  647  
 604  648          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 605  649          if (handle == NULL)
 606  650                  return (SMBD_SMF_SYSTEM_ERR);
 607  651  
 608  652          rc = smb_smf_create_service_pgroup(handle, pg);
 609  653          if (rc == SMBD_SMF_OK)
 610  654                  rc = smb_smf_start_transaction(handle);
 611  655  
 612  656          if (rc != SMBD_SMF_OK) {
 613  657                  smb_smf_scf_fini(handle);
 614  658                  return (rc);
 615  659          }
 616  660  
  
    | 
      ↓ 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
 639  725   */
 640  726  int
 641  727  smb_config_setnum(smb_cfg_id_t id, int64_t value)
 642  728  {
 643  729          smb_scfhandle_t *handle;
 644  730          smb_cfg_param_t *cfg;
 645  731          int rc = SMBD_SMF_OK;
 646  732  
 647  733          cfg = smb_config_getent(id);
 648  734          assert(cfg->sc_type == SCF_TYPE_INTEGER);
 649  735  
 650  736          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 651  737          if (handle == NULL)
 652  738                  return (SMBD_SMF_SYSTEM_ERR);
 653  739  
 654  740          rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
 655  741          if (rc == SMBD_SMF_OK)
 656  742                  rc = smb_smf_start_transaction(handle);
 657  743  
 658  744          if (rc != SMBD_SMF_OK) {
 659  745                  smb_smf_scf_fini(handle);
 660  746                  return (rc);
 661  747          }
 662  748  
 663  749          rc = smb_smf_set_integer_property(handle, cfg->sc_name, value);
 664  750  
 665  751          (void) smb_smf_end_transaction(handle);
 666  752          smb_smf_scf_fini(handle);
 667  753          return (rc);
 668  754  }
 669  755  
 670  756  /*
 671  757   * smb_config_setbool
 672  758   *
 673  759   * Sets a boolean configuration iterm
 674  760   */
 675  761  int
 676  762  smb_config_setbool(smb_cfg_id_t id, boolean_t value)
 677  763  {
 678  764          smb_scfhandle_t *handle;
 679  765          smb_cfg_param_t *cfg;
 680  766          int rc = SMBD_SMF_OK;
 681  767  
 682  768          cfg = smb_config_getent(id);
 683  769          assert(cfg->sc_type == SCF_TYPE_BOOLEAN);
 684  770  
 685  771          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 686  772          if (handle == NULL)
 687  773                  return (SMBD_SMF_SYSTEM_ERR);
 688  774  
 689  775          rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
 690  776          if (rc == SMBD_SMF_OK)
 691  777                  rc = smb_smf_start_transaction(handle);
 692  778  
 693  779          if (rc != SMBD_SMF_OK) {
 694  780                  smb_smf_scf_fini(handle);
 695  781                  return (rc);
 696  782          }
 697  783  
 698  784          rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value);
 699  785  
 700  786          (void) smb_smf_end_transaction(handle);
 701  787          smb_smf_scf_fini(handle);
 702  788          return (rc);
 703  789  }
 704  790  
 705  791  /*
 706  792   * smb_config_set
 707  793   *
 708  794   * This function sets the value of the specified config
 709  795   * iterm regardless of its type in string format. This should
 710  796   * be used when the config item type is not known by the caller.
 711  797   */
 712  798  int
 713  799  smb_config_set(smb_cfg_id_t id, char *value)
 714  800  {
 715  801          smb_cfg_param_t *cfg;
 716  802          int64_t cint;
 717  803  
 718  804          cfg = smb_config_getent(id);
 719  805          switch (cfg->sc_type) {
 720  806          case SCF_TYPE_ASTRING:
 721  807                  return (smb_config_setstr(id, value));
 722  808  
 723  809          case SCF_TYPE_INTEGER:
 724  810                  cint = atoi(value);
 725  811                  return (smb_config_setnum(id, cint));
 726  812  
 727  813          case SCF_TYPE_BOOLEAN:
 728  814                  return (smb_config_setbool(id, strcasecmp(value, "true") == 0));
 729  815          }
 730  816  
 731  817          return (SMBD_SMF_INVALID_ARG);
 732  818  }
 733  819  
 734  820  int
 735  821  smb_config_get_debug()
 736  822  {
 737  823          int64_t val64;
 738  824          int val = 0;    /* default */
 739  825          smb_scfhandle_t *handle = NULL;
 740  826  
 741  827          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 742  828          if (handle == NULL) {
 743  829                  return (val);
 744  830          }
 745  831  
 746  832          if (smb_smf_create_service_pgroup(handle,
 747  833              SMBD_PG_NAME) != SMBD_SMF_OK) {
 748  834                  smb_smf_scf_fini(handle);
 749  835                  return (val);
 750  836          }
 751  837  
 752  838          if (smb_smf_get_integer_property(handle, "debug", &val64) != 0) {
 753  839                  smb_smf_scf_fini(handle);
 754  840                  return (val);
 755  841          }
 756  842          val = (int)val64;
 757  843  
 758  844          smb_smf_scf_fini(handle);
 759  845  
 760  846          return (val);
 761  847  }
 762  848  
 763  849  uint8_t
 764  850  smb_config_get_fg_flag()
 765  851  {
 766  852          uint8_t run_fg = 0; /* Default is to run in daemon mode */
 767  853          smb_scfhandle_t *handle = NULL;
 768  854  
 769  855          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
 770  856          if (handle == NULL) {
 771  857                  return (run_fg);
 772  858          }
 773  859  
 774  860          if (smb_smf_create_service_pgroup(handle,
 775  861              SMBD_PG_NAME) != SMBD_SMF_OK) {
 776  862                  smb_smf_scf_fini(handle);
 777  863                  return (run_fg);
 778  864          }
 779  865  
 780  866          if (smb_smf_get_boolean_property(handle, "run_fg", &run_fg) != 0) {
 781  867                  smb_smf_scf_fini(handle);
 782  868                  return (run_fg);
 783  869          }
 784  870  
 785  871          smb_smf_scf_fini(handle);
 786  872  
 787  873          return (run_fg);
 788  874  }
 789  875  
 790  876  /*
 791  877   * smb_config_get_ads_enable
 792  878   *
 793  879   * Returns value of the "config/use_ads" parameter
 794  880   * from the IDMAP SMF configuration repository.
 795  881   *
 796  882   */
 797  883  boolean_t
 798  884  smb_config_get_ads_enable(void)
 799  885  {
 800  886          smb_scfhandle_t *handle = NULL;
 801  887          uint8_t vbool;
 802  888          int rc = 0;
 803  889  
 804  890          handle = smb_smf_scf_init(IDMAP_FMRI_PREFIX);
 805  891          if (handle == NULL)
 806  892                  return (B_FALSE);
 807  893  
 808  894          rc = smb_smf_create_service_pgroup(handle, IDMAP_PG_NAME);
 809  895          if (rc == SMBD_SMF_OK)
 810  896                  rc = smb_smf_get_boolean_property(handle, "use_ads", &vbool);
 811  897          smb_smf_scf_fini(handle);
 812  898  
 813  899          return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_TRUE);
 814  900  }
 815  901  
 816  902  /*
 817  903   * smb_config_get_localsid
 818  904   *
 819  905   * Returns value of the "config/machine_sid" parameter
 820  906   * from the IDMAP SMF configuration repository.
 821  907   * Result is allocated; caller should free.
 822  908   */
 823  909  char *
 824  910  smb_config_get_localsid(void)
 825  911  {
 826  912          return (smb_config_getenv_generic(MACHINE_SID, IDMAP_FMRI_PREFIX,
 827  913              IDMAP_PG_NAME));
 828  914  }
 829  915  
 830  916  /*
 831  917   * smb_config_get_localuuid
 832  918   *
 833  919   * Returns value of the "config/machine_uuid" parameter
 834  920   * from the IDMAP SMF configuration repository.
 835  921   *
 836  922   */
 837  923  int
 838  924  smb_config_get_localuuid(uuid_t uu)
 839  925  {
 840  926          char *s;
 841  927  
 842  928          uuid_clear(uu);
 843  929          s = smb_config_getenv_generic(MACHINE_UUID, IDMAP_FMRI_PREFIX,
 844  930              IDMAP_PG_NAME);
 845  931          if (s == NULL)
 846  932                  return (-1);
 847  933  
 848  934          if (uuid_parse(s, uu) < 0) {
 849  935                  free(s);
 850  936                  return (-1);
 851  937          }
 852  938  
 853  939          return (0);
 854  940  }
 855  941  
 856  942  static int
 857  943  smb_config_get_idmap_preferred_dc(char *cbuf, int bufsz)
 858  944  {
 859  945          char *s;
 860  946          int len, rc = -1;
 861  947  
 862  948          s = smb_config_getenv_generic(IDMAP_PREF_DC,
 863  949              IDMAP_FMRI_PREFIX, IDMAP_PG_NAME);
 864  950          if (s != NULL) {
 865  951                  len = strlcpy(cbuf, s, bufsz);
 866  952                  if (len < bufsz)
 867  953                          rc = 0;
 868  954                  free(s);
 869  955          }
  
    | 
      ↓ 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));
 890 1000  }
 891 1001  
 892 1002  /*
 893 1003   * smb_config_refresh_idmap
 894 1004   *
 895 1005   * Refresh IDMAP SMF service after making changes to its configuration.
 896 1006   */
 897 1007  int
 898 1008  smb_config_refresh_idmap(void)
 899 1009  {
 900 1010          char instance[32];
 901 1011  
 902 1012          (void) snprintf(instance, sizeof (instance), "%s:default",
 903 1013              IDMAP_FMRI_PREFIX);
 904 1014          return (smf_refresh_instance(instance));
 905 1015  }
 906 1016  
 907 1017  int
 908 1018  smb_config_secmode_fromstr(char *secmode)
 909 1019  {
 910 1020          if (secmode == NULL)
 911 1021                  return (SMB_SECMODE_WORKGRP);
 912 1022  
 913 1023          if (strcasecmp(secmode, SMB_SECMODE_DOMAIN_STR) == 0)
 914 1024                  return (SMB_SECMODE_DOMAIN);
 915 1025  
 916 1026          return (SMB_SECMODE_WORKGRP);
 917 1027  }
 918 1028  
 919 1029  char *
 920 1030  smb_config_secmode_tostr(int secmode)
 921 1031  {
 922 1032          if (secmode == SMB_SECMODE_DOMAIN)
 923 1033                  return (SMB_SECMODE_DOMAIN_STR);
 924 1034  
 925 1035          return (SMB_SECMODE_WORKGRP_STR);
 926 1036  }
 927 1037  
 928 1038  int
 929 1039  smb_config_get_secmode()
 930 1040  {
 931 1041          char p[16];
 932 1042  
 933 1043          (void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p));
 934 1044          return (smb_config_secmode_fromstr(p));
 935 1045  }
 936 1046  
 937 1047  int
 938 1048  smb_config_set_secmode(int secmode)
 939 1049  {
 940 1050          char *p;
 941 1051  
 942 1052          p = smb_config_secmode_tostr(secmode);
 943 1053          return (smb_config_setstr(SMB_CI_SECURITY, p));
 944 1054  }
 945 1055  
 946 1056  void
 947 1057  smb_config_getdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
 948 1058      char *guid)
 949 1059  {
 950 1060          if (domain)
 951 1061                  (void) smb_config_getstr(SMB_CI_DOMAIN_NAME, domain,
 952 1062                      NETBIOS_NAME_SZ);
 953 1063  
 954 1064          if (fqdn)
 955 1065                  (void) smb_config_getstr(SMB_CI_DOMAIN_FQDN, fqdn,
 956 1066                      MAXHOSTNAMELEN);
 957 1067  
 958 1068          if (sid)
 959 1069                  (void) smb_config_getstr(SMB_CI_DOMAIN_SID, sid,
 960 1070                      SMB_SID_STRSZ);
 961 1071  
 962 1072          if (forest)
 963 1073                  (void) smb_config_getstr(SMB_CI_DOMAIN_FOREST, forest,
 964 1074                      MAXHOSTNAMELEN);
 965 1075  
 966 1076          if (guid)
 967 1077                  (void) smb_config_getstr(SMB_CI_DOMAIN_GUID, guid,
 968 1078                      UUID_PRINTABLE_STRING_LENGTH);
 969 1079  }
 970 1080  
 971 1081  void
 972 1082  smb_config_setdomaininfo(char *domain, char *fqdn, char *sid, char *forest,
 973 1083      char *guid)
 974 1084  {
 975 1085          if (domain)
 976 1086                  (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, domain);
 977 1087          if (fqdn)
 978 1088                  (void) smb_config_setstr(SMB_CI_DOMAIN_FQDN, fqdn);
 979 1089          if (sid)
 980 1090                  (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sid);
 981 1091          if (forest)
 982 1092                  (void) smb_config_setstr(SMB_CI_DOMAIN_FOREST, forest);
 983 1093          if (guid)
 984 1094                  (void) smb_config_setstr(SMB_CI_DOMAIN_GUID, guid);
 985 1095  }
 986 1096  
 987 1097  /*
 988 1098   * The version stored in SMF in string format as N.N where
 989 1099   * N is a number defined by Microsoft. The first number represents
 990 1100   * the major version and the second number is the minor version.
 991 1101   * Current defined values can be found here in 'ver_table'.
 992 1102   *
 993 1103   * This function reads the SMF string value and converts it to
 994 1104   * two numbers returned in the given 'version' structure.
 995 1105   * Current default version number is 5.0 which is for Windows 2000.
 996 1106   */
 997 1107  void
 998 1108  smb_config_get_version(smb_version_t *version)
 999 1109  {
1000 1110          smb_version_t tmpver;
1001 1111          char verstr[SMB_VERSTR_LEN];
1002 1112          char *p;
1003 1113          int rc, i;
1004 1114          static smb_version_t ver_table [] = {
1005 1115                  { 0, SMB_MAJOR_NT,      SMB_MINOR_NT,           1381,   0 },
1006 1116                  { 0, SMB_MAJOR_2000,    SMB_MINOR_2000,         2195,   0 },
1007 1117                  { 0, SMB_MAJOR_XP,      SMB_MINOR_XP,           2196,   0 },
1008 1118                  { 0, SMB_MAJOR_2003,    SMB_MINOR_2003,         2196,   0 },
1009 1119                  { 0, SMB_MAJOR_VISTA,   SMB_MINOR_VISTA,        6000,   0 },
1010 1120                  { 0, SMB_MAJOR_2008,    SMB_MINOR_2008,         6000,   0 },
1011 1121                  { 0, SMB_MAJOR_2008R2,  SMB_MINOR_2008R2,       7007,   0 },
1012 1122                  { 0, SMB_MAJOR_7,       SMB_MINOR_7,            7007,   0 }
1013 1123          };
1014 1124  
1015 1125          *version = ver_table[1];
1016 1126          version->sv_size = sizeof (smb_version_t);
1017 1127  
1018 1128          rc = smb_config_getstr(SMB_CI_VERSION, verstr, sizeof (verstr));
1019 1129          if (rc != SMBD_SMF_OK)
1020 1130                  return;
1021 1131  
1022 1132          if ((p = strchr(verstr, '.')) == NULL)
1023 1133                  return;
1024 1134  
1025 1135          *p = '\0';
1026 1136          tmpver.sv_major = (uint8_t)atoi(verstr);
1027 1137          tmpver.sv_minor = (uint8_t)atoi(p + 1);
1028 1138  
1029 1139          for (i = 0; i < sizeof (ver_table)/sizeof (ver_table[0]); ++i) {
1030 1140                  if ((tmpver.sv_major == ver_table[i].sv_major) &&
1031 1141                      (tmpver.sv_minor == ver_table[i].sv_minor)) {
1032 1142                          *version = ver_table[i];
1033 1143                          version->sv_size = sizeof (smb_version_t);
1034 1144                          break;
1035 1145                  }
1036 1146          }
1037 1147  }
1038 1148  
1039 1149  /*
1040 1150   * Reads share exec script properties
1041 1151   */
1042 1152  uint32_t
1043 1153  smb_config_get_execinfo(char *map, char *unmap, size_t bufsz)
1044 1154  {
1045 1155          char buf[MAXPATHLEN];
1046 1156          uint32_t flags = 0;
1047 1157  
1048 1158          if (map == NULL) {
1049 1159                  map = buf;
1050 1160                  bufsz = MAXPATHLEN;
1051 1161          }
1052 1162  
1053 1163          *map = '\0';
1054 1164          (void) smb_config_getstr(SMB_CI_MAP, map, bufsz);
1055 1165          if (*map != '\0')
1056 1166                  flags |= SMB_EXEC_MAP;
1057 1167  
1058 1168          if (unmap == NULL) {
1059 1169                  unmap = buf;
1060 1170                  bufsz = MAXPATHLEN;
1061 1171          }
1062 1172  
1063 1173          *unmap = '\0';
1064 1174          (void) smb_config_getstr(SMB_CI_UNMAP, unmap, bufsz);
1065 1175          if (*unmap != '\0')
1066 1176                  flags |= SMB_EXEC_UNMAP;
1067 1177  
1068 1178          *buf = '\0';
1069 1179          (void) smb_config_getstr(SMB_CI_DISPOSITION, buf, sizeof (buf));
1070 1180          if (*buf != '\0')
1071 1181                  if (strcasecmp(buf, SMB_EXEC_DISP_TERMINATE) == 0)
1072 1182                          flags |= SMB_EXEC_TERM;
1073 1183  
1074 1184          return (flags);
1075 1185  }
1076 1186  
1077 1187  static smb_cfg_param_t *
1078 1188  smb_config_getent(smb_cfg_id_t id)
1079 1189  {
  
    | 
      ↓ 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  {
1155 1272          smb_scfhandle_t *handle;
1156 1273          char *s2e_name = "smb2_enable";
1157 1274          char *s2e_sval;
1158 1275          uint8_t s2e_bval;
1159 1276          char *maxp_name = "max_protocol";
1160 1277          char *maxp_sval;
1161 1278          char verstr[SMB_VERSTR_LEN];
1162 1279          int rc;
1163 1280  
1164 1281          handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
1165 1282          if (handle == NULL)
1166 1283                  return;
1167 1284          rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME);
1168 1285          if (rc != SMBD_SMF_OK)
1169 1286                  goto out;
1170 1287  
1171 1288          /* Is there an "smb2_enable" property? */
1172 1289          rc = smb_smf_get_boolean_property(handle, s2e_name, &s2e_bval);
1173 1290          if (rc != SMBD_SMF_OK) {
1174 1291                  syslog(LOG_DEBUG, "upgrade: smb2_enable not found");
1175 1292                  goto out;
1176 1293          }
1177 1294  
1178 1295          /*
1179 1296           * We will try to delete the smb2_enable property, so we need
1180 1297           * the transaction to start now, before we modify max_protocol
1181 1298           */
1182 1299          if ((rc = smb_smf_start_transaction(handle)) != 0) {
1183 1300                  syslog(LOG_DEBUG, "upgrade_smb2_enable: start trans (%d)", rc);
1184 1301                  goto out;
1185 1302          }
1186 1303  
1187 1304          /*
1188 1305           * Old (smb2_enable) property exists.
1189 1306           * Does the new one? (max_protocol)
1190 1307           */
1191 1308          rc = smb_smf_get_string_property(handle, maxp_name,
1192 1309              verstr, sizeof (verstr));
1193 1310          if (rc == SMBD_SMF_OK && !smb_config_check_protocol(verstr)) {
1194 1311                  syslog(LOG_DEBUG, "upgrade: found %s = %s",
1195 1312                      maxp_name, verstr);
1196 1313                  /* Leave existing max_protocol as we found it. */
1197 1314          } else {
1198 1315                  /*
1199 1316                   * New property missing or invalid.
1200 1317                   * Upgrade from "smb2_enable".
1201 1318                   */
1202 1319                  if (s2e_bval == 0) {
1203 1320                          s2e_sval = "false";
1204 1321                          maxp_sval = "1";
1205 1322                  } else {
1206 1323                          s2e_sval = "true";
1207 1324                          maxp_sval = "2.1";
1208 1325                  }
1209 1326                  /*
1210 1327                   * Note: Need this in the same transaction as the
1211 1328                   * delete of smb2_enable below.
1212 1329                   */
1213 1330                  rc = smb_smf_set_string_property(handle, maxp_name, maxp_sval);
1214 1331                  if (rc != SMBD_SMF_OK) {
1215 1332                          syslog(LOG_ERR, "failed to set smbd/%d (%d)",
1216 1333                              maxp_name, rc);
1217 1334                          goto out;
1218 1335                  }
1219 1336                  syslog(LOG_INFO, "upgrade smbd/smb2_enable=%s "
1220 1337                      "converted to smbd/max_protocol=%s",
1221 1338                      s2e_sval, maxp_sval);
1222 1339          }
1223 1340  
1224 1341          /*
1225 1342           * Delete the old smb2_enable property.
1226 1343           */
1227 1344          if ((rc = smb_smf_delete_property(handle, s2e_name)) != 0) {
1228 1345                  syslog(LOG_DEBUG, "upgrade_smb2_enable: delete prop (%d)", rc);
1229 1346          } else if ((rc = smb_smf_end_transaction(handle)) != 0) {
1230 1347                  syslog(LOG_DEBUG, "upgrade_smb2_enable: end trans (%d)", rc);
1231 1348          }
1232 1349          if (rc != 0) {
1233 1350                  syslog(LOG_ERR, "failed to delete property smbd/%d (%d)",
1234 1351                      s2e_name, rc);
1235 1352          }
1236 1353  
1237 1354  out:
1238 1355          (void) smb_smf_end_transaction(handle);
1239 1356          smb_smf_scf_fini(handle);
  
    | 
      ↓ 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