Print this page
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-4598 SMB2 credit shortage with Mac client
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@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-1810 extended security Kerberos (inbound)
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>
re #6813 rb1757 port 2976 Child folder visibility through shares
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libsmb/common/smb_info.c
+++ new/usr/src/lib/smbsrv/libsmb/common/smb_info.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 2017 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/sockio.h>
28 28 #include <sys/socket.h>
29 29 #include <sys/utsname.h>
30 30
31 31 #include <stdarg.h>
32 32 #include <unistd.h>
33 33 #include <stdlib.h>
34 34 #include <time.h>
35 35 #include <synch.h>
36 36 #include <syslog.h>
37 37 #include <string.h>
38 38 #include <strings.h>
39 39 #include <errno.h>
40 40 #include <net/if.h>
41 41 #include <netdb.h>
42 42 #include <netinet/in.h>
43 43 #include <arpa/nameser.h>
44 44 #include <resolv.h>
45 45
46 46 #include <smbsrv/smbinfo.h>
47 47 #include <smbsrv/netbios.h>
48 48 #include <smbsrv/libsmb.h>
49 49 #include <assert.h>
50 50
51 51 static mutex_t seqnum_mtx;
52 52
53 53 /*
54 54 * IPC connection information that may be passed to the SMB Redirector.
55 55 */
56 56 typedef struct {
57 57 char user[SMB_USERNAME_MAXLEN];
58 58 uint8_t passwd[SMBAUTH_HASH_SZ];
59 59 } smb_ipc_t;
60 60
61 61 static smb_ipc_t ipc_info;
62 62 static smb_ipc_t ipc_orig_info;
63 63 static rwlock_t smb_ipc_lock;
64 64
65 65 /*
66 66 * These three parameters are all related:
67 67 * skc_initial_credits
68 68 * skc_maximum_credits
69 69 * skc_maxworkers (max worker threads)
70 70 * They must be in non-decreasing order. Get the values in order:
71 71 * maxworkers, maximum_credits, initial_credits
72 72 * enforcing maximum values and relations as we go. Then in the
73 73 * opposite order check minimum values and relations.
74 74 *
75 75 * smb_config_getnum puts a zero in the &citem if it fails getting
76 76 * the parameter value. When fetch parameters for which zero is OK,
77 77 * the return code is intentionally ignored.
78 78 */
79 79 void
80 80 smb_load_kconfig(smb_kmod_cfg_t *kcfg)
81 81 {
82 82 struct utsname uts;
83 83 int64_t citem;
84 84 int rc;
85 85
86 86 bzero(kcfg, sizeof (smb_kmod_cfg_t));
87 87
88 88 /*
89 89 * skc_maxworkers (max. no. of taskq worker threads)
90 90 */
91 91 rc = smb_config_getnum(SMB_CI_MAX_WORKERS, &citem);
92 92 if (rc != SMBD_SMF_OK)
93 93 citem = SMB_PI_MAX_WORKERS_DEF;
94 94 if (citem > SMB_PI_MAX_WORKERS_MAX)
95 95 citem = SMB_PI_MAX_WORKERS_MAX;
96 96 kcfg->skc_maxworkers = (uint32_t)citem;
97 97
98 98 /*
99 99 * The largest number of credits we let a single client have.
100 100 * It never makes sense for this to be > max_workers
101 101 */
102 102 rc = smb_config_getnum(SMB_CI_MAXIMUM_CREDITS, &citem);
103 103 if (rc != SMBD_SMF_OK)
104 104 citem = SMB_PI_MAXIMUM_CREDITS_DEF;
105 105 if (citem > SMB_PI_MAXIMUM_CREDITS_MAX)
106 106 citem = SMB_PI_MAXIMUM_CREDITS_MAX;
107 107 kcfg->skc_maximum_credits = (uint16_t)citem;
108 108 if (kcfg->skc_maximum_credits > kcfg->skc_maxworkers)
109 109 kcfg->skc_maximum_credits = (uint16_t)kcfg->skc_maxworkers;
110 110
111 111 /*
112 112 * The number of credits we give a client initially.
113 113 * Should be enough for a "light" workload, as the
114 114 * client will request additional credits when the
115 115 * workload increases. Must be <= maximum_credits.
116 116 */
117 117 rc = smb_config_getnum(SMB_CI_INITIAL_CREDITS, &citem);
118 118 if (rc != SMBD_SMF_OK)
119 119 citem = SMB_PI_INITIAL_CREDITS_DEF;
120 120 if (citem > SMB_PI_INITIAL_CREDITS_MAX)
121 121 citem = SMB_PI_INITIAL_CREDITS_MAX;
122 122 kcfg->skc_initial_credits = (uint16_t)citem;
123 123 if (kcfg->skc_initial_credits > kcfg->skc_maximum_credits)
124 124 kcfg->skc_initial_credits = kcfg->skc_maximum_credits;
125 125
126 126 /*
127 127 * Now enforce minimums, smaller to larger.
128 128 */
129 129 if (kcfg->skc_initial_credits < SMB_PI_INITIAL_CREDITS_MIN)
130 130 kcfg->skc_initial_credits = SMB_PI_INITIAL_CREDITS_MIN;
131 131
132 132 if (kcfg->skc_maximum_credits < SMB_PI_MAXIMUM_CREDITS_MIN)
133 133 kcfg->skc_maximum_credits = SMB_PI_MAXIMUM_CREDITS_MIN;
134 134 if (kcfg->skc_maximum_credits < kcfg->skc_initial_credits)
135 135 kcfg->skc_maximum_credits = kcfg->skc_initial_credits;
136 136
137 137 if (kcfg->skc_maxworkers < SMB_PI_MAX_WORKERS_MIN)
138 138 kcfg->skc_maxworkers = SMB_PI_MAX_WORKERS_MIN;
139 139 if (kcfg->skc_maxworkers < kcfg->skc_maximum_credits)
140 140 kcfg->skc_maxworkers = kcfg->skc_maximum_credits;
141 141
142 142 (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem);
143 143 kcfg->skc_keepalive = (uint32_t)citem;
144 144 if ((kcfg->skc_keepalive != 0) &&
145 145 (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN))
146 146 kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN;
147 147
148 148 (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem);
149 149 kcfg->skc_maxconnections = (uint32_t)citem;
|
↓ open down ↓ |
116 lines elided |
↑ open up ↑ |
150 150 kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON);
151 151 kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE);
152 152 kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD);
153 153 kcfg->skc_netbios_enable = smb_config_getbool(SMB_CI_NETBIOS_ENABLE);
154 154 kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE);
155 155 kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
156 156 kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
157 157 kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
158 158 kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS);
159 159 kcfg->skc_max_protocol = smb_config_get_max_protocol();
160 + kcfg->skc_min_protocol = smb_config_get_min_protocol();
160 161 kcfg->skc_secmode = smb_config_get_secmode();
162 + kcfg->skc_encrypt = smb_config_get_require(SMB_CI_ENCRYPT);
161 163
162 164 (void) smb_getdomainname(kcfg->skc_nbdomain,
163 165 sizeof (kcfg->skc_nbdomain));
164 166 (void) smb_getfqdomainname(kcfg->skc_fqdn,
165 167 sizeof (kcfg->skc_fqdn));
166 168 (void) smb_getnetbiosname(kcfg->skc_hostname,
167 169 sizeof (kcfg->skc_hostname));
168 170 (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment,
169 171 sizeof (kcfg->skc_system_comment));
170 172 smb_config_get_version(&kcfg->skc_version);
171 173 kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0);
172 174 if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) {
173 175 syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid");
174 176 uuid_generate_time(kcfg->skc_machine_uuid);
175 177 }
176 178 /* skc_negtok, skc_negtok_len: see smbd_authsvc.c */
177 179
178 180 (void) uname(&uts);
179 181 (void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os),
180 182 "%s %s %s", uts.sysname, uts.release, uts.version);
181 183
182 184 (void) strlcpy(kcfg->skc_native_lm, "Native SMB service",
183 185 sizeof (kcfg->skc_native_lm));
184 186 }
185 187
186 188 /*
187 189 * Get the current system NetBIOS name. The hostname is truncated at
188 190 * the first `.` or 15 bytes, whichever occurs first, and converted
189 191 * to uppercase (by smb_gethostname). Text that appears after the
190 192 * first '.' is considered to be part of the NetBIOS scope.
191 193 *
192 194 * Returns 0 on success, otherwise -1 to indicate an error.
193 195 */
194 196 int
195 197 smb_getnetbiosname(char *buf, size_t buflen)
196 198 {
197 199 if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0)
198 200 return (-1);
199 201
200 202 if (buflen >= NETBIOS_NAME_SZ)
201 203 buf[NETBIOS_NAME_SZ - 1] = '\0';
202 204
203 205 return (0);
204 206 }
205 207
206 208 /*
207 209 * Get the SAM account of the current system.
208 210 * Returns 0 on success, otherwise, -1 to indicate an error.
209 211 */
210 212 int
211 213 smb_getsamaccount(char *buf, size_t buflen)
212 214 {
213 215 if (smb_getnetbiosname(buf, buflen - 1) != 0)
214 216 return (-1);
215 217
216 218 (void) strlcat(buf, "$", buflen);
217 219 return (0);
218 220 }
219 221
220 222 /*
221 223 * Get the current system node name. The returned name is guaranteed
222 224 * to be null-terminated (gethostname may not null terminate the name).
223 225 * If the hostname has been fully-qualified for some reason, the domain
224 226 * part will be removed. The returned hostname is converted to the
225 227 * specified case (lower, upper, or preserved).
226 228 *
227 229 * If gethostname fails, the returned buffer will contain an empty
228 230 * string.
229 231 */
230 232 int
231 233 smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which)
232 234 {
233 235 char *p;
234 236
235 237 if (buf == NULL || buflen == 0)
236 238 return (-1);
237 239
238 240 if (gethostname(buf, buflen) != 0) {
239 241 *buf = '\0';
240 242 return (-1);
241 243 }
242 244
243 245 buf[buflen - 1] = '\0';
244 246
245 247 if ((p = strchr(buf, '.')) != NULL)
246 248 *p = '\0';
247 249
248 250 switch (which) {
249 251 case SMB_CASE_LOWER:
250 252 (void) smb_strlwr(buf);
251 253 break;
252 254
253 255 case SMB_CASE_UPPER:
254 256 (void) smb_strupr(buf);
255 257 break;
256 258
257 259 case SMB_CASE_PRESERVE:
258 260 default:
259 261 break;
260 262 }
261 263
262 264 return (0);
263 265 }
264 266
265 267 /*
266 268 * Obtain the fully-qualified name for this machine in lower case. If
267 269 * the hostname is fully-qualified, accept it. Otherwise, try to find an
268 270 * appropriate domain name to append to the hostname.
269 271 */
270 272 int
271 273 smb_getfqhostname(char *buf, size_t buflen)
272 274 {
273 275 char hostname[MAXHOSTNAMELEN];
274 276 char domain[MAXHOSTNAMELEN];
275 277
276 278 hostname[0] = '\0';
277 279 domain[0] = '\0';
278 280
279 281 if (smb_gethostname(hostname, MAXHOSTNAMELEN,
280 282 SMB_CASE_LOWER) != 0)
281 283 return (-1);
282 284
283 285 if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0)
284 286 return (-1);
285 287
286 288 if (hostname[0] == '\0')
287 289 return (-1);
288 290
289 291 if (domain[0] == '\0') {
290 292 (void) strlcpy(buf, hostname, buflen);
291 293 return (0);
292 294 }
293 295
294 296 (void) snprintf(buf, buflen, "%s.%s", hostname, domain);
295 297 return (0);
296 298 }
297 299
298 300 /*
299 301 * smb_getdomainname
300 302 *
301 303 * Returns NETBIOS name of the domain if the system is in domain
302 304 * mode. Or returns workgroup name if the system is in workgroup
303 305 * mode.
304 306 */
305 307 int
306 308 smb_getdomainname(char *buf, size_t buflen)
307 309 {
308 310 int rc;
309 311
310 312 if (buf == NULL || buflen == 0)
311 313 return (-1);
312 314
313 315 *buf = '\0';
314 316 rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen);
315 317
316 318 if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
317 319 return (-1);
318 320
319 321 return (0);
320 322 }
321 323
322 324 /*
323 325 * smb_getfqdomainname
324 326 *
325 327 * In the system is in domain mode, the dns_domain property value
326 328 * is returned. Otherwise, it returns the local domain obtained via
327 329 * resolver.
328 330 *
329 331 * Returns 0 upon success. Otherwise, returns -1.
330 332 */
331 333 int
332 334 smb_getfqdomainname(char *buf, size_t buflen)
333 335 {
334 336 struct __res_state res_state;
335 337 int rc;
336 338
337 339 if (buf == NULL || buflen == 0)
338 340 return (-1);
339 341
340 342 *buf = '\0';
341 343 if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) {
342 344 rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen);
343 345
344 346 if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
345 347 return (-1);
346 348 } else {
347 349 bzero(&res_state, sizeof (struct __res_state));
348 350 if (res_ninit(&res_state))
349 351 return (-1);
350 352
351 353 if (*res_state.defdname == '\0') {
352 354 res_ndestroy(&res_state);
353 355 return (-1);
354 356 }
355 357
356 358 (void) strlcpy(buf, res_state.defdname, buflen);
357 359 res_ndestroy(&res_state);
358 360 rc = 0;
359 361 }
360 362
361 363 return (rc);
362 364 }
363 365
364 366
365 367 /*
366 368 * smb_set_machine_passwd
367 369 *
368 370 * This function should be used when setting the machine password property.
369 371 * The associated sequence number is incremented.
370 372 */
371 373 static int
372 374 smb_set_machine_passwd(char *passwd)
373 375 {
374 376 int64_t num;
375 377 int rc = -1;
376 378
377 379 if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK)
378 380 return (-1);
379 381
380 382 (void) mutex_lock(&seqnum_mtx);
381 383 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
382 384 if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num)
383 385 == SMBD_SMF_OK)
384 386 rc = 0;
385 387 (void) mutex_unlock(&seqnum_mtx);
386 388 return (rc);
387 389 }
388 390
389 391 static int
390 392 smb_get_machine_passwd(uint8_t *buf, size_t buflen)
391 393 {
392 394 char pwd[SMB_PASSWD_MAXLEN + 1];
393 395 int rc;
394 396
395 397 if (buflen < SMBAUTH_HASH_SZ)
396 398 return (-1);
397 399
398 400 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd));
399 401 if ((rc != SMBD_SMF_OK) || *pwd == '\0')
400 402 return (-1);
401 403
402 404 if (smb_auth_ntlm_hash(pwd, buf) != 0)
403 405 return (-1);
404 406
405 407 return (rc);
406 408 }
407 409
408 410 /*
409 411 * Set up IPC connection credentials.
410 412 */
411 413 void
412 414 smb_ipc_init(void)
413 415 {
414 416 int rc;
415 417
416 418 (void) rw_wrlock(&smb_ipc_lock);
417 419 bzero(&ipc_info, sizeof (smb_ipc_t));
418 420 bzero(&ipc_orig_info, sizeof (smb_ipc_t));
419 421
420 422 (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
421 423 rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
422 424 if (rc != 0)
423 425 *ipc_info.passwd = 0;
424 426 (void) rw_unlock(&smb_ipc_lock);
425 427
426 428 }
427 429
428 430 /*
429 431 * Set the IPC username and password hash in memory. If the domain
430 432 * join succeeds, the credentials will be committed for use with
431 433 * authenticated IPC. Otherwise, they should be rolled back.
432 434 */
433 435 void
434 436 smb_ipc_set(char *plain_user, uint8_t *passwd_hash)
435 437 {
436 438 (void) rw_wrlock(&smb_ipc_lock);
437 439 (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
438 440 (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
439 441 (void) rw_unlock(&smb_ipc_lock);
440 442
441 443 }
442 444
443 445 /*
444 446 * Save the host credentials to be used for authenticated IPC.
445 447 * The credentials are also saved to the original IPC info as
446 448 * rollback data in case the join domain process fails later.
447 449 */
448 450 void
449 451 smb_ipc_commit(void)
450 452 {
451 453 (void) rw_wrlock(&smb_ipc_lock);
452 454 (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
453 455 (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
454 456 (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t));
455 457 (void) rw_unlock(&smb_ipc_lock);
456 458 }
457 459
458 460 /*
459 461 * Restore the original credentials
460 462 */
461 463 void
462 464 smb_ipc_rollback(void)
463 465 {
464 466 (void) rw_wrlock(&smb_ipc_lock);
465 467 (void) strlcpy(ipc_info.user, ipc_orig_info.user,
466 468 sizeof (ipc_info.user));
467 469 (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd,
468 470 sizeof (ipc_info.passwd));
469 471 (void) rw_unlock(&smb_ipc_lock);
470 472 }
471 473
472 474 void
473 475 smb_ipc_get_user(char *buf, size_t buflen)
474 476 {
475 477 (void) rw_rdlock(&smb_ipc_lock);
476 478 (void) strlcpy(buf, ipc_info.user, buflen);
477 479 (void) rw_unlock(&smb_ipc_lock);
478 480 }
479 481
480 482 void
481 483 smb_ipc_get_passwd(uint8_t *buf, size_t buflen)
482 484 {
483 485 if (buflen < SMBAUTH_HASH_SZ)
484 486 return;
485 487
486 488 (void) rw_rdlock(&smb_ipc_lock);
487 489 (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ);
488 490 (void) rw_unlock(&smb_ipc_lock);
489 491 }
490 492
491 493 /*
492 494 * smb_match_netlogon_seqnum
493 495 *
494 496 * A sequence number is associated with each machine password property
495 497 * update and the netlogon credential chain setup. If the
496 498 * sequence numbers don't match, a NETLOGON credential chain
497 499 * establishment is required.
498 500 *
499 501 * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise,
500 502 * returns -1.
501 503 */
502 504 boolean_t
503 505 smb_match_netlogon_seqnum(void)
504 506 {
505 507 int64_t setpasswd_seqnum;
506 508 int64_t netlogon_seqnum;
507 509
508 510 (void) mutex_lock(&seqnum_mtx);
509 511 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum);
510 512 (void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum);
511 513 (void) mutex_unlock(&seqnum_mtx);
512 514 return (setpasswd_seqnum == netlogon_seqnum);
513 515 }
514 516
515 517 /*
516 518 * smb_setdomainprops
517 519 *
518 520 * This function should be called after joining an AD to
519 521 * set all the domain related SMF properties.
520 522 *
521 523 * The kpasswd_domain property is the AD domain to which the system
522 524 * is joined via kclient. If this function is invoked by the SMB
523 525 * daemon, fqdn should be set to NULL.
524 526 */
525 527 int
526 528 smb_setdomainprops(char *fqdn, char *server, char *passwd)
527 529 {
528 530 if (server == NULL || passwd == NULL)
529 531 return (-1);
530 532
531 533 if ((*server == '\0') || (*passwd == '\0'))
532 534 return (-1);
533 535
534 536 if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0))
535 537 return (-1);
536 538
537 539 if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0)
538 540 return (-1);
539 541
540 542 if (smb_set_machine_passwd(passwd) != 0) {
541 543 syslog(LOG_ERR, "smb_setdomainprops: failed to set"
542 544 " machine account password");
543 545 return (-1);
544 546 }
545 547
546 548 /*
547 549 * If we successfully create a trust account, we mark
548 550 * ourselves as a domain member in the environment so
549 551 * that we use the SAMLOGON version of the NETLOGON
550 552 * PDC location protocol.
551 553 */
552 554 (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE);
553 555
554 556 return (0);
555 557 }
556 558
557 559 /*
558 560 * smb_update_netlogon_seqnum
559 561 *
560 562 * This function should only be called upon a successful netlogon
561 563 * credential chain establishment to set the sequence number of the
562 564 * netlogon to match with that of the kpasswd.
563 565 */
564 566 void
565 567 smb_update_netlogon_seqnum(void)
566 568 {
567 569 int64_t num;
568 570
569 571 (void) mutex_lock(&seqnum_mtx);
570 572 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
571 573 (void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num);
572 574 (void) mutex_unlock(&seqnum_mtx);
573 575 }
574 576
575 577
576 578 /*
577 579 * Temporary fbt for dtrace until user space sdt enabled.
578 580 */
579 581 void
580 582 smb_tracef(const char *fmt, ...)
581 583 {
582 584 va_list ap;
583 585 char buf[128];
584 586
585 587 va_start(ap, fmt);
586 588 (void) vsnprintf(buf, 128, fmt, ap);
587 589 va_end(ap);
588 590
589 591 smb_trace(buf);
590 592 }
591 593
592 594 /*
593 595 * Temporary fbt for dtrace until user space sdt enabled.
594 596 *
595 597 * This function is designed to be used with dtrace, i.e. see:
596 598 * usr/src/cmd/smbsrv/dtrace/smbd-all.d
597 599 *
598 600 * Outside of dtrace, the messages passed to this function usually
599 601 * lack sufficient context to be useful, so we don't log them.
600 602 */
601 603 /* ARGSUSED */
602 604 void
603 605 smb_trace(const char *s)
604 606 {
605 607 }
606 608
607 609 /*
608 610 * smb_tonetbiosname
609 611 *
610 612 * Creates a NetBIOS name based on the given name and suffix.
611 613 * NetBIOS name is 15 capital characters, padded with space if needed
612 614 * and the 16th byte is the suffix.
613 615 */
614 616 void
615 617 smb_tonetbiosname(char *name, char *nb_name, char suffix)
616 618 {
617 619 char tmp_name[NETBIOS_NAME_SZ];
618 620 smb_wchar_t wtmp_name[NETBIOS_NAME_SZ];
619 621 int len;
620 622 size_t rc;
621 623
622 624 len = 0;
623 625 rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ);
624 626
625 627 if (rc != (size_t)-1) {
626 628 wtmp_name[NETBIOS_NAME_SZ - 1] = 0;
627 629 rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ,
628 630 OEM_CPG_850);
629 631 if (rc > 0)
630 632 len = strlen(tmp_name);
631 633 }
632 634
633 635 (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1);
634 636 if (len) {
635 637 (void) smb_strupr(tmp_name);
636 638 (void) memcpy(nb_name, tmp_name, len);
637 639 }
638 640 nb_name[NETBIOS_NAME_SZ - 1] = suffix;
639 641 }
640 642
641 643 int
642 644 smb_get_nameservers(smb_inaddr_t *ips, int sz)
643 645 {
644 646 union res_sockaddr_union set[MAXNS];
645 647 int i, cnt;
646 648 struct __res_state res_state;
647 649 char ipstr[INET6_ADDRSTRLEN];
648 650
649 651 if (ips == NULL)
650 652 return (0);
651 653
652 654 bzero(&res_state, sizeof (struct __res_state));
653 655 if (res_ninit(&res_state) < 0)
654 656 return (0);
655 657
656 658 cnt = res_getservers(&res_state, set, MAXNS);
657 659 for (i = 0; i < cnt; i++) {
658 660 if (i >= sz)
659 661 break;
660 662 ips[i].a_family = AF_INET;
661 663 bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, NS_INADDRSZ);
662 664 if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr,
663 665 INET_ADDRSTRLEN)) {
664 666 syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
665 667 continue;
666 668 }
667 669 ips[i].a_family = AF_INET6;
668 670 bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, NS_IN6ADDRSZ);
669 671 if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr,
670 672 INET6_ADDRSTRLEN)) {
671 673 syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
672 674 }
673 675 }
674 676 res_ndestroy(&res_state);
675 677 return (i);
676 678 }
677 679
678 680 /*
679 681 * smb_gethostbyname
680 682 *
681 683 * Looks up a host by the given name. The host entry can come
682 684 * from any of the sources for hosts specified in the
683 685 * /etc/nsswitch.conf and the NetBIOS cache.
684 686 *
685 687 * XXX Invokes nbt_name_resolve API once the NBTD is integrated
686 688 * to look in the NetBIOS cache if getipnodebyname fails.
687 689 *
688 690 * Caller should invoke freehostent to free the returned hostent.
689 691 */
690 692 struct hostent *
691 693 smb_gethostbyname(const char *name, int *err_num)
692 694 {
693 695 struct hostent *h;
694 696
695 697 h = getipnodebyname(name, AF_INET, 0, err_num);
696 698 if ((h == NULL) || h->h_length != INADDRSZ)
697 699 h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num);
698 700 return (h);
699 701 }
700 702
701 703 /*
702 704 * smb_gethostbyaddr
703 705 *
704 706 * Looks up a host by the given IP address. The host entry can come
705 707 * from any of the sources for hosts specified in the
706 708 * /etc/nsswitch.conf and the NetBIOS cache.
707 709 *
708 710 * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated
709 711 * to look in the NetBIOS cache if getipnodebyaddr fails.
710 712 *
711 713 * Caller should invoke freehostent to free the returned hostent.
712 714 */
713 715 struct hostent *
714 716 smb_gethostbyaddr(const char *addr, int len, int type, int *err_num)
715 717 {
716 718 struct hostent *h;
717 719
718 720 h = getipnodebyaddr(addr, len, type, err_num);
719 721
720 722 return (h);
721 723 }
|
↓ open down ↓ |
551 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX