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-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@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>
re #6813 rb1757 port 2976 Child folder visibility through shares
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
+++ new/usr/src/lib/smbsrv/libsmb/common/smb_kmod.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) 2009, 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 * Copyright 2017 Joyent, Inc.
25 25 */
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/stat.h>
29 29 #include <sys/ioccom.h>
30 30 #include <sys/param.h>
31 31 #include <stddef.h>
32 32 #include <stdio.h>
33 33 #include <string.h>
34 34 #include <strings.h>
35 35 #include <stdlib.h>
36 36 #include <unistd.h>
37 37 #include <fcntl.h>
38 38 #include <errno.h>
39 39
40 40 #include <smbsrv/smb_xdr.h>
41 41 #include <smbsrv/smbinfo.h>
42 42 #include <smbsrv/smb_ioctl.h>
43 43 #include <smbsrv/libsmb.h>
44 44
45 45 #define SMBDRV_DEVICE_PATH "/dev/smbsrv"
46 46
47 47 int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t);
48 48
49 49
50 50 int smbdrv_fd = -1;
51 51
52 52 int
53 53 smb_kmod_bind(void)
54 54 {
55 55 if (smbdrv_fd != -1)
56 56 (void) close(smbdrv_fd);
57 57
58 58 if ((smbdrv_fd = open(SMBDRV_DEVICE_PATH, 0)) < 0) {
59 59 smbdrv_fd = -1;
60 60 return (errno);
61 61 }
62 62
63 63 return (0);
64 64 }
65 65
66 66 boolean_t
67 67 smb_kmod_isbound(void)
68 68 {
69 69 return ((smbdrv_fd == -1) ? B_FALSE : B_TRUE);
70 70 }
71 71
72 72 /* See also: smbsrv smb_server_store_cfg */
73 73 int
74 74 smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
75 75 {
76 76 smb_ioc_cfg_t ioc;
77 77
78 78 ioc.maxworkers = cfg->skc_maxworkers;
79 79 ioc.maxconnections = cfg->skc_maxconnections;
80 80 ioc.keepalive = cfg->skc_keepalive;
81 81 ioc.restrict_anon = cfg->skc_restrict_anon;
|
↓ open down ↓ |
48 lines elided |
↑ open up ↑ |
82 82 ioc.signing_enable = cfg->skc_signing_enable;
83 83 ioc.signing_required = cfg->skc_signing_required;
84 84 ioc.oplock_enable = cfg->skc_oplock_enable;
85 85 ioc.sync_enable = cfg->skc_sync_enable;
86 86 ioc.secmode = cfg->skc_secmode;
87 87 ioc.netbios_enable = cfg->skc_netbios_enable;
88 88 ioc.ipv6_enable = cfg->skc_ipv6_enable;
89 89 ioc.print_enable = cfg->skc_print_enable;
90 90 ioc.traverse_mounts = cfg->skc_traverse_mounts;
91 91 ioc.max_protocol = cfg->skc_max_protocol;
92 + ioc.min_protocol = cfg->skc_min_protocol;
92 93 ioc.exec_flags = cfg->skc_execflags;
93 94 ioc.negtok_len = cfg->skc_negtok_len;
94 95 ioc.version = cfg->skc_version;
95 96 ioc.initial_credits = cfg->skc_initial_credits;
96 97 ioc.maximum_credits = cfg->skc_maximum_credits;
98 + ioc.encrypt = cfg->skc_encrypt;
97 99
98 100 (void) memcpy(ioc.machine_uuid, cfg->skc_machine_uuid, sizeof (uuid_t));
99 101 (void) memcpy(ioc.negtok, cfg->skc_negtok, sizeof (ioc.negtok));
100 102 (void) memcpy(ioc.native_os, cfg->skc_native_os,
101 103 sizeof (ioc.native_os));
102 104 (void) memcpy(ioc.native_lm, cfg->skc_native_lm,
103 105 sizeof (ioc.native_lm));
104 106
105 107 (void) strlcpy(ioc.nbdomain, cfg->skc_nbdomain, sizeof (ioc.nbdomain));
106 108 (void) strlcpy(ioc.fqdn, cfg->skc_fqdn, sizeof (ioc.fqdn));
107 109 (void) strlcpy(ioc.hostname, cfg->skc_hostname, sizeof (ioc.hostname));
108 110 (void) strlcpy(ioc.system_comment, cfg->skc_system_comment,
109 111 sizeof (ioc.system_comment));
110 112
111 113 return (smb_kmod_ioctl(SMB_IOC_CONFIG, &ioc.hdr, sizeof (ioc)));
112 114 }
113 115
114 116 int
115 117 smb_kmod_setgmtoff(int32_t gmtoff)
116 118 {
117 119 smb_ioc_gmt_t ioc;
118 120
119 121 ioc.offset = gmtoff;
120 122 return (smb_kmod_ioctl(SMB_IOC_GMTOFF, &ioc.hdr,
121 123 sizeof (ioc)));
122 124 }
123 125
124 126 int
125 127 smb_kmod_start(int opipe, int lmshr, int udoor)
126 128 {
127 129 smb_ioc_start_t ioc;
128 130
129 131 ioc.opipe = opipe;
130 132 ioc.lmshrd = lmshr;
131 133 ioc.udoor = udoor;
132 134 return (smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc)));
133 135 }
134 136
135 137 void
136 138 smb_kmod_stop(void)
137 139 {
138 140 smb_ioc_header_t ioc;
139 141
140 142 (void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc));
141 143 }
142 144
143 145 int
144 146 smb_kmod_event_notify(uint32_t txid)
145 147 {
146 148 smb_ioc_event_t ioc;
147 149
148 150 ioc.txid = txid;
149 151 return (smb_kmod_ioctl(SMB_IOC_EVENT, &ioc.hdr, sizeof (ioc)));
150 152 }
151 153
152 154 int
153 155 smb_kmod_share(nvlist_t *shrlist)
154 156 {
155 157 smb_ioc_share_t *ioc;
156 158 uint32_t ioclen;
157 159 char *shrbuf = NULL;
158 160 size_t bufsz;
159 161 int rc = ENOMEM;
160 162
161 163 if ((rc = nvlist_pack(shrlist, &shrbuf, &bufsz, NV_ENCODE_XDR, 0)) != 0)
162 164 return (rc);
163 165
164 166 ioclen = sizeof (smb_ioc_share_t) + bufsz;
165 167
166 168 if ((ioc = malloc(ioclen)) != NULL) {
167 169 ioc->shrlen = bufsz;
168 170 bcopy(shrbuf, ioc->shr, bufsz);
169 171 rc = smb_kmod_ioctl(SMB_IOC_SHARE, &ioc->hdr, ioclen);
170 172 free(ioc);
171 173 }
172 174
173 175 free(shrbuf);
174 176 return (rc);
175 177 }
176 178
177 179 int
178 180 smb_kmod_unshare(nvlist_t *shrlist)
179 181 {
180 182 smb_ioc_share_t *ioc;
181 183 uint32_t ioclen;
182 184 char *shrbuf = NULL;
183 185 size_t bufsz;
184 186 int rc = ENOMEM;
185 187
186 188 if ((rc = nvlist_pack(shrlist, &shrbuf, &bufsz, NV_ENCODE_XDR, 0)) != 0)
187 189 return (rc);
188 190
189 191 ioclen = sizeof (smb_ioc_share_t) + bufsz;
190 192
191 193 if ((ioc = malloc(ioclen)) != NULL) {
192 194 ioc->shrlen = bufsz;
193 195 bcopy(shrbuf, ioc->shr, bufsz);
194 196 rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr, ioclen);
195 197 free(ioc);
196 198 }
197 199
198 200 free(shrbuf);
199 201 return (rc);
200 202 }
201 203
202 204 int
203 205 smb_kmod_shareinfo(char *shrname, boolean_t *shortnames)
204 206 {
205 207 smb_ioc_shareinfo_t ioc;
206 208 int rc;
207 209
208 210 bzero(&ioc, sizeof (ioc));
209 211 (void) strlcpy(ioc.shrname, shrname, MAXNAMELEN);
210 212
211 213 rc = smb_kmod_ioctl(SMB_IOC_SHAREINFO, &ioc.hdr, sizeof (ioc));
212 214 if (rc == 0)
213 215 *shortnames = ioc.shortnames;
214 216 else
215 217 *shortnames = B_TRUE;
216 218
217 219 return (rc);
218 220 }
219 221
220 222 int
221 223 smb_kmod_get_open_num(smb_opennum_t *opennum)
222 224 {
223 225 smb_ioc_opennum_t ioc;
224 226 int rc;
225 227
226 228 bzero(&ioc, sizeof (ioc));
227 229 ioc.qualtype = opennum->qualtype;
228 230 (void) strlcpy(ioc.qualifier, opennum->qualifier, MAXNAMELEN);
229 231
230 232 rc = smb_kmod_ioctl(SMB_IOC_NUMOPEN, &ioc.hdr, sizeof (ioc));
231 233 if (rc == 0) {
232 234 opennum->open_users = ioc.open_users;
233 235 opennum->open_trees = ioc.open_trees;
234 236 opennum->open_files = ioc.open_files;
235 237 }
236 238
237 239 return (rc);
238 240 }
239 241
240 242 int
241 243 smb_kmod_get_spool_doc(uint32_t *spool_num, char *username,
242 244 char *path, smb_inaddr_t *ipaddr)
243 245 {
244 246 smb_ioc_spooldoc_t ioc;
245 247 int rc;
246 248
247 249 bzero(&ioc, sizeof (ioc));
248 250 rc = smb_kmod_ioctl(SMB_IOC_SPOOLDOC, &ioc.hdr, sizeof (ioc));
249 251 if (rc == 0) {
250 252 *spool_num = ioc.spool_num;
251 253 (void) strlcpy(username, ioc.username, MAXNAMELEN);
252 254 (void) strlcpy(path, ioc.path, MAXPATHLEN);
253 255 *ipaddr = ioc.ipaddr;
254 256 }
255 257 return (rc);
256 258 }
257 259
258 260 /*
259 261 * Initialization for an smb_kmod_enum request. If this call succeeds,
260 262 * smb_kmod_enum_fini() must be called later to deallocate resources.
261 263 */
262 264 smb_netsvc_t *
263 265 smb_kmod_enum_init(smb_svcenum_t *request)
264 266 {
265 267 smb_netsvc_t *ns;
266 268 smb_svcenum_t *svcenum;
267 269 smb_ioc_svcenum_t *ioc;
268 270 uint32_t ioclen;
269 271
270 272 if ((ns = calloc(1, sizeof (smb_netsvc_t))) == NULL)
271 273 return (NULL);
272 274
273 275 ioclen = sizeof (smb_ioc_svcenum_t) + SMB_IOC_DATA_SIZE;
274 276 if ((ioc = malloc(ioclen)) == NULL) {
275 277 free(ns);
276 278 return (NULL);
277 279 }
278 280
279 281 bzero(ioc, ioclen);
280 282 svcenum = &ioc->svcenum;
281 283 svcenum->se_type = request->se_type;
282 284 svcenum->se_level = request->se_level;
283 285 svcenum->se_bavail = SMB_IOC_DATA_SIZE;
284 286 svcenum->se_nlimit = request->se_nlimit;
285 287 svcenum->se_nskip = request->se_nskip;
286 288 svcenum->se_buflen = SMB_IOC_DATA_SIZE;
287 289
288 290 list_create(&ns->ns_list, sizeof (smb_netsvcitem_t),
289 291 offsetof(smb_netsvcitem_t, nsi_lnd));
290 292
291 293 ns->ns_ioc = ioc;
292 294 ns->ns_ioclen = ioclen;
293 295 return (ns);
294 296 }
295 297
296 298 /*
297 299 * Cleanup resources allocated via smb_kmod_enum_init and smb_kmod_enum.
298 300 */
299 301 void
300 302 smb_kmod_enum_fini(smb_netsvc_t *ns)
301 303 {
302 304 list_t *lst;
303 305 smb_netsvcitem_t *item;
304 306 smb_netuserinfo_t *user;
305 307 smb_netconnectinfo_t *tree;
306 308 smb_netfileinfo_t *ofile;
307 309 uint32_t se_type;
308 310
309 311 if (ns == NULL)
310 312 return;
311 313
312 314 lst = &ns->ns_list;
313 315 se_type = ns->ns_ioc->svcenum.se_type;
314 316
315 317 while ((item = list_head(lst)) != NULL) {
316 318 list_remove(lst, item);
317 319
318 320 switch (se_type) {
319 321 case SMB_SVCENUM_TYPE_USER:
320 322 user = &item->nsi_un.nsi_user;
321 323 free(user->ui_domain);
322 324 free(user->ui_account);
323 325 free(user->ui_workstation);
324 326 break;
325 327 case SMB_SVCENUM_TYPE_TREE:
326 328 tree = &item->nsi_un.nsi_tree;
327 329 free(tree->ci_username);
328 330 free(tree->ci_share);
329 331 break;
330 332 case SMB_SVCENUM_TYPE_FILE:
331 333 ofile = &item->nsi_un.nsi_ofile;
332 334 free(ofile->fi_path);
333 335 free(ofile->fi_username);
334 336 break;
335 337 default:
336 338 break;
337 339 }
338 340 }
339 341
340 342 list_destroy(&ns->ns_list);
341 343 free(ns->ns_items);
342 344 free(ns->ns_ioc);
343 345 free(ns);
344 346 }
345 347
346 348 /*
347 349 * Enumerate users, connections or files.
348 350 */
349 351 int
350 352 smb_kmod_enum(smb_netsvc_t *ns)
351 353 {
352 354 smb_ioc_svcenum_t *ioc;
353 355 uint32_t ioclen;
354 356 smb_svcenum_t *svcenum;
355 357 smb_netsvcitem_t *items;
356 358 smb_netuserinfo_t *user;
357 359 smb_netconnectinfo_t *tree;
358 360 smb_netfileinfo_t *ofile;
359 361 uint8_t *data;
360 362 uint32_t len;
361 363 uint32_t se_type;
362 364 uint_t nbytes;
363 365 int i;
364 366 int rc;
365 367
366 368 ioc = ns->ns_ioc;
367 369 ioclen = ns->ns_ioclen;
368 370 rc = smb_kmod_ioctl(SMB_IOC_SVCENUM, &ioc->hdr, ioclen);
369 371 if (rc != 0)
370 372 return (rc);
371 373
372 374 svcenum = &ioc->svcenum;
373 375 items = calloc(svcenum->se_nitems, sizeof (smb_netsvcitem_t));
374 376 if (items == NULL)
375 377 return (ENOMEM);
376 378
377 379 ns->ns_items = items;
378 380 se_type = ns->ns_ioc->svcenum.se_type;
379 381 data = svcenum->se_buf;
380 382 len = svcenum->se_bused;
381 383
382 384 for (i = 0; i < svcenum->se_nitems; ++i) {
383 385 switch (se_type) {
384 386 case SMB_SVCENUM_TYPE_USER:
385 387 user = &items->nsi_un.nsi_user;
386 388 rc = smb_netuserinfo_decode(user, data, len, &nbytes);
387 389 break;
388 390 case SMB_SVCENUM_TYPE_TREE:
389 391 tree = &items->nsi_un.nsi_tree;
390 392 rc = smb_netconnectinfo_decode(tree, data, len,
391 393 &nbytes);
392 394 break;
393 395 case SMB_SVCENUM_TYPE_FILE:
394 396 ofile = &items->nsi_un.nsi_ofile;
395 397 rc = smb_netfileinfo_decode(ofile, data, len, &nbytes);
396 398 break;
397 399 default:
398 400 rc = -1;
399 401 break;
400 402 }
401 403
402 404 if (rc != 0)
403 405 return (EINVAL);
404 406
405 407 list_insert_tail(&ns->ns_list, items);
406 408
407 409 ++items;
408 410 data += nbytes;
409 411 len -= nbytes;
410 412 }
411 413
412 414 return (0);
413 415 }
414 416
415 417 /*
416 418 * A NULL pointer is a wildcard indicator, which we pass on
417 419 * as an empty string (by virtue of the bzero).
418 420 */
419 421 int
420 422 smb_kmod_session_close(const char *client, const char *username)
421 423 {
422 424 smb_ioc_session_t ioc;
423 425 int rc;
424 426
425 427 bzero(&ioc, sizeof (ioc));
426 428
427 429 if (client != NULL)
428 430 (void) strlcpy(ioc.client, client, MAXNAMELEN);
429 431 if (username != NULL)
430 432 (void) strlcpy(ioc.username, username, MAXNAMELEN);
431 433
432 434 rc = smb_kmod_ioctl(SMB_IOC_SESSION_CLOSE, &ioc.hdr, sizeof (ioc));
433 435 return (rc);
434 436 }
435 437
436 438 int
437 439 smb_kmod_file_close(uint32_t uniqid)
438 440 {
439 441 smb_ioc_fileid_t ioc;
440 442 int rc;
441 443
442 444 bzero(&ioc, sizeof (ioc));
443 445 ioc.uniqid = uniqid;
444 446
445 447 rc = smb_kmod_ioctl(SMB_IOC_FILE_CLOSE, &ioc.hdr, sizeof (ioc));
446 448 return (rc);
447 449 }
448 450
449 451 void
450 452 smb_kmod_unbind(void)
451 453 {
452 454 if (smbdrv_fd != -1) {
453 455 (void) close(smbdrv_fd);
454 456 smbdrv_fd = -1;
455 457 }
456 458 }
457 459
458 460 /*
459 461 * Note: The user-space smbd-d provides it own version of this function
460 462 * which directly calls the "kernel" module code (in user space).
461 463 */
462 464 int
463 465 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
464 466 {
465 467 int rc = EINVAL;
466 468
467 469 ioc->version = SMB_IOC_VERSION;
468 470 ioc->cmd = cmd;
469 471 ioc->len = len;
470 472 ioc->crc = 0;
471 473 ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t));
472 474
473 475 if (smbdrv_fd != -1) {
474 476 if (ioctl(smbdrv_fd, cmd, ioc) < 0)
475 477 rc = errno;
476 478 else
477 479 rc = 0;
478 480 }
479 481 return (rc);
480 482 }
|
↓ open down ↓ |
374 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX