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