Print this page
NEX-19057 All zfs/nfs/smb threads in door calls to idle idmap
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@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-2225 Unable to join NexentaStor to 2008 AD
NEX-2286 smbadm join error messages are uninformative
NEX-1638 Updated DC Locator
Includes work by: matt.barden@nexenta.com, kevin.crowe@nexenta.com
SMB-149 mount.cifs RedHat\Centos 6 doesn't work with default security options (fix lint)
SMB-149 mount.cifs RedHat\Centos 6 doesn't work with default security options
SMB-136 Snapshots not visible in Windows previous versions
SMB-39 Use AF_UNIX pipes for RPC
SMB-50 User-mode SMB server
Includes work by these authors:
Thomas Keiser <thomas.keiser@nexenta.com>
Albert Lee <trisk@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
+++ new/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.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 2014 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <sys/list.h>
27 27 #include <assert.h>
28 28 #include <alloca.h>
29 29 #include <door.h>
30 30 #include <errno.h>
31 31 #include <syslog.h>
32 32 #include <unistd.h>
33 33 #include <stdio.h>
34 34 #include <synch.h>
35 35 #include <string.h>
36 36 #include <stdlib.h>
37 37 #include <sys/stat.h>
38 38 #include <fcntl.h>
39 39 #include <pthread.h>
40 40 #include <strings.h>
41 41 #include <note.h>
42 42 #include <smbsrv/smb_door.h>
43 43 #include <smbsrv/smb_xdr.h>
44 44 #include <smbsrv/smb_token.h>
45 45 #include <smbsrv/libmlsvc.h>
46 46 #include <smbsrv/libsmbns.h>
47 47 #include "smbd.h"
48 48
49 49 /*
50 50 * The list contains asynchronous requests that have been initiated
51 51 * but have not yet been collected (via smbd_dop_async_response).
52 52 */
53 53 typedef struct smbd_doorsvc {
54 54 mutex_t sd_mutex;
55 55 cond_t sd_cv;
56 56 list_t sd_async_list;
57 57 uint32_t sd_async_count;
58 58 } smbd_doorsvc_t;
59 59
60 60 static int smbd_dop_null(smbd_arg_t *);
61 61 static int smbd_dop_async_response(smbd_arg_t *);
62 62 static int smbd_dop_user_auth_logon(smbd_arg_t *);
63 63 static int smbd_dop_user_nonauth_logon(smbd_arg_t *);
64 64 static int smbd_dop_user_auth_logoff(smbd_arg_t *);
65 65 static int smbd_dop_lookup_sid(smbd_arg_t *);
66 66 static int smbd_dop_lookup_name(smbd_arg_t *);
67 67 static int smbd_dop_join(smbd_arg_t *);
68 68 static int smbd_dop_get_dcinfo(smbd_arg_t *);
69 69 static int smbd_dop_vss_get_count(smbd_arg_t *);
70 70 static int smbd_dop_vss_get_snapshots(smbd_arg_t *);
71 71 static int smbd_dop_vss_map_gmttoken(smbd_arg_t *);
72 72 static int smbd_dop_ads_find_host(smbd_arg_t *);
73 73 static int smbd_dop_quota_query(smbd_arg_t *);
74 74 static int smbd_dop_quota_set(smbd_arg_t *);
75 75 static int smbd_dop_dfs_get_referrals(smbd_arg_t *);
76 76 static int smbd_dop_shr_hostaccess(smbd_arg_t *);
77 77 static int smbd_dop_shr_exec(smbd_arg_t *);
78 78 static int smbd_dop_notify_dc_changed(smbd_arg_t *);
79 79
80 80 typedef int (*smbd_dop_t)(smbd_arg_t *);
81 81
82 82 typedef struct smbd_doorop {
83 83 smb_dopcode_t opcode;
84 84 smbd_dop_t op;
85 85 } smbd_doorop_t;
86 86
87 87 smbd_doorop_t smbd_doorops[] = {
88 88 { SMB_DR_NULL, smbd_dop_null },
89 89 { SMB_DR_ASYNC_RESPONSE, smbd_dop_async_response },
90 90 { SMB_DR_USER_AUTH_LOGON, smbd_dop_user_auth_logon },
91 91 { SMB_DR_USER_NONAUTH_LOGON, smbd_dop_user_nonauth_logon },
92 92 { SMB_DR_USER_AUTH_LOGOFF, smbd_dop_user_auth_logoff },
93 93 { SMB_DR_LOOKUP_SID, smbd_dop_lookup_sid },
94 94 { SMB_DR_LOOKUP_NAME, smbd_dop_lookup_name },
95 95 { SMB_DR_JOIN, smbd_dop_join },
|
↓ open down ↓ |
62 lines elided |
↑ open up ↑ |
96 96 { SMB_DR_GET_DCINFO, smbd_dop_get_dcinfo },
97 97 { SMB_DR_VSS_GET_COUNT, smbd_dop_vss_get_count },
98 98 { SMB_DR_VSS_GET_SNAPSHOTS, smbd_dop_vss_get_snapshots },
99 99 { SMB_DR_VSS_MAP_GMTTOKEN, smbd_dop_vss_map_gmttoken },
100 100 { SMB_DR_ADS_FIND_HOST, smbd_dop_ads_find_host },
101 101 { SMB_DR_QUOTA_QUERY, smbd_dop_quota_query },
102 102 { SMB_DR_QUOTA_SET, smbd_dop_quota_set },
103 103 { SMB_DR_DFS_GET_REFERRALS, smbd_dop_dfs_get_referrals },
104 104 { SMB_DR_SHR_HOSTACCESS, smbd_dop_shr_hostaccess },
105 105 { SMB_DR_SHR_EXEC, smbd_dop_shr_exec },
106 - { SMB_DR_NOTIFY_DC_CHANGED, smbd_dop_notify_dc_changed }
106 + { SMB_DR_NOTIFY_DC_CHANGED, smbd_dop_notify_dc_changed },
107 + { SMB_DR_LOOKUP_LSID, smbd_dop_lookup_sid },
108 + { SMB_DR_LOOKUP_LNAME, smbd_dop_lookup_name }
107 109 };
108 110
109 111 static int smbd_ndoorop = (sizeof (smbd_doorops) / sizeof (smbd_doorops[0]));
110 112
111 113 static smbd_doorsvc_t smbd_doorsvc;
112 114 static int smbd_door_fd = -1;
113 115 static int smbd_door_cookie = 0x534D4244; /* SMBD */
114 116 static smbd_door_t smbd_door_sdh;
115 117 static char *smbd_door_name = NULL;
116 118
117 119 static void smbd_door_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
118 120 static int smbd_door_dispatch_async(smbd_arg_t *);
119 121 static void smbd_door_release_async(smbd_arg_t *);
120 122
121 123 /*
122 124 * Start the smbd door service. Create and bind to a door.
123 125 * Returns 0 on success. Otherwise, -1.
124 126 */
125 127 int
126 128 smbd_door_start(void)
127 129 {
128 130 int newfd;
129 131
130 132 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
131 133
132 134 if (smbd_door_fd != -1) {
133 135 (void) fprintf(stderr, "smb_doorsrv_start: already started");
134 136 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
135 137 return (-1);
136 138 }
137 139
138 140 smbd_door_name = getenv("SMBD_DOOR_NAME");
139 141 if (smbd_door_name == NULL)
140 142 smbd_door_name = SMBD_DOOR_NAME;
141 143
142 144 smbd_door_init(&smbd_door_sdh, "doorsrv");
143 145
144 146 list_create(&smbd_doorsvc.sd_async_list, sizeof (smbd_arg_t),
145 147 offsetof(smbd_arg_t, lnd));
146 148 smbd_doorsvc.sd_async_count = 0;
147 149
148 150 if ((smbd_door_fd = door_create(smbd_door_dispatch,
149 151 &smbd_door_cookie, DOOR_UNREF)) < 0) {
150 152 (void) fprintf(stderr, "smb_doorsrv_start: door_create: %s",
151 153 strerror(errno));
152 154 smbd_door_fd = -1;
153 155 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
154 156 return (-1);
155 157 }
156 158
157 159 (void) unlink(smbd_door_name);
158 160
159 161 if ((newfd = creat(smbd_door_name, 0644)) < 0) {
160 162 (void) fprintf(stderr, "smb_doorsrv_start: open: %s",
161 163 strerror(errno));
162 164 (void) door_revoke(smbd_door_fd);
163 165 smbd_door_fd = -1;
164 166 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
165 167 return (-1);
166 168 }
167 169
168 170 (void) close(newfd);
169 171 (void) fdetach(smbd_door_name);
170 172
171 173 if (fattach(smbd_door_fd, smbd_door_name) < 0) {
172 174 (void) fprintf(stderr, "smb_doorsrv_start: fattach: %s",
173 175 strerror(errno));
174 176 (void) door_revoke(smbd_door_fd);
175 177 smbd_door_fd = -1;
176 178 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
177 179 return (-1);
178 180 }
179 181
180 182 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
181 183 return (smbd_door_fd);
182 184 }
183 185
184 186 /*
185 187 * Stop the smbd door service.
186 188 */
187 189 void
188 190 smbd_door_stop(void)
189 191 {
190 192 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
191 193
192 194 smbd_door_fini(&smbd_door_sdh);
193 195
194 196 if (smbd_door_name)
195 197 (void) fdetach(smbd_door_name);
196 198
197 199 if (smbd_door_fd != -1) {
198 200 (void) door_revoke(smbd_door_fd);
199 201 smbd_door_fd = -1;
200 202 }
201 203
202 204 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
203 205 }
204 206
205 207 /*ARGSUSED*/
206 208 static void
207 209 smbd_door_dispatch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp,
208 210 uint_t n_desc)
209 211 {
210 212 smbd_arg_t dop_arg;
211 213 smb_doorhdr_t *hdr;
212 214 size_t hdr_size;
213 215 char *rbuf = NULL;
214 216
215 217 smbd_door_enter(&smbd_door_sdh);
216 218
217 219 if (!smbd_online())
218 220 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
219 221
220 222 bzero(&dop_arg, sizeof (smbd_arg_t));
221 223 hdr = &dop_arg.hdr;
222 224 hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
223 225
224 226 if ((cookie != &smbd_door_cookie) || (argp == NULL) ||
225 227 (arg_size < hdr_size)) {
226 228 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
227 229 }
228 230
229 231 if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
230 232 syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
231 233 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
232 234 }
233 235
234 236 if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) || (hdr->dh_txid == 0)) {
235 237 syslog(LOG_DEBUG, "smbd_door_dispatch: invalid header");
236 238 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
237 239 }
238 240
239 241 dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
240 242 dop_arg.data = argp + hdr_size;
241 243 dop_arg.datalen = hdr->dh_datalen;
242 244
243 245 if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
244 246 /*
245 247 * ASYNC_RESPONSE is used to collect the response
246 248 * to an async call; it cannot be an async call.
247 249 */
248 250 hdr->dh_flags &= ~SMB_DF_ASYNC;
249 251 }
250 252
251 253 if (hdr->dh_flags & SMB_DF_ASYNC) {
252 254 if (smbd_door_dispatch_async(&dop_arg) == 0)
253 255 hdr->dh_door_rc = SMB_DOP_SUCCESS;
254 256 else
255 257 hdr->dh_door_rc = SMB_DOP_NOT_CALLED;
256 258 } else {
257 259 (void) smbd_door_dispatch_op(&dop_arg);
258 260 }
259 261
260 262 if ((rbuf = (char *)alloca(dop_arg.rsize + hdr_size)) == NULL) {
261 263 errno = ENOMEM;
262 264 syslog(LOG_DEBUG, "smbd_door_dispatch[%s]: alloca %m",
263 265 dop_arg.opname);
264 266 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0);
265 267 }
266 268
267 269 if (dop_arg.rbuf != NULL) {
268 270 (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
269 271 free(dop_arg.rbuf);
270 272 }
271 273
272 274 hdr->dh_datalen = dop_arg.rsize;
273 275 (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
274 276 dop_arg.rsize += hdr_size;
275 277
276 278 smbd_door_return(&smbd_door_sdh, rbuf, dop_arg.rsize, NULL, 0);
277 279 /*NOTREACHED*/
278 280 }
279 281
280 282 /*
281 283 * Launch a thread to process an asynchronous door call.
282 284 */
283 285 static int
284 286 smbd_door_dispatch_async(smbd_arg_t *req_arg)
285 287 {
286 288 smbd_arg_t *arg = NULL;
287 289 char *data = NULL;
288 290 pthread_attr_t attr;
289 291 pthread_t tid;
290 292 int rc;
291 293
292 294 if ((req_arg->hdr.dh_flags & SMB_DF_ASYNC) == 0) {
293 295 errno = EINVAL;
294 296 return (-1);
295 297 }
296 298
297 299 if ((arg = malloc(sizeof (smbd_arg_t))) == NULL) {
298 300 syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
299 301 req_arg->opname);
300 302 return (-1);
301 303 }
302 304
303 305 (void) memcpy(arg, req_arg, sizeof (smbd_arg_t));
304 306 arg->data = NULL;
305 307
306 308 if (req_arg->datalen != 0) {
307 309 if ((data = malloc(req_arg->datalen)) == NULL) {
308 310 free(arg);
309 311 syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m",
310 312 req_arg->opname);
311 313 return (-1);
312 314 }
313 315
314 316 (void) memcpy(data, req_arg->data, req_arg->datalen);
315 317 arg->data = data;
316 318 }
317 319
318 320 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
319 321 arg->magic = SMBD_ARG_MAGIC;
320 322 list_insert_tail(&smbd_doorsvc.sd_async_list, arg);
321 323 ++smbd_doorsvc.sd_async_count;
322 324 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
323 325
324 326 (void) pthread_attr_init(&attr);
325 327 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
326 328 rc = pthread_create(&tid, &attr, smbd_door_dispatch_op, arg);
327 329 (void) pthread_attr_destroy(&attr);
328 330
329 331 if (rc != 0) {
330 332 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
331 333 smbd_door_release_async(arg);
332 334 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
333 335 }
334 336
335 337 return (rc);
336 338 }
337 339
338 340 /*
339 341 * Remove an entry from the async response pending list and free
340 342 * the arg and associated data.
341 343 *
342 344 * Must only be called while holding the smbd_doorsvc mutex.
343 345 */
344 346 static void
345 347 smbd_door_release_async(smbd_arg_t *arg)
346 348 {
347 349 if (arg != NULL) {
348 350 assert(arg->magic == SMBD_ARG_MAGIC);
349 351 arg->magic = (uint32_t)~SMBD_ARG_MAGIC;
350 352
351 353 list_remove(&smbd_doorsvc.sd_async_list, arg);
352 354 --smbd_doorsvc.sd_async_count;
353 355 free(arg->data);
354 356 arg->data = NULL;
355 357 free(arg);
356 358 }
357 359 }
358 360
359 361 /*
360 362 * All door calls are processed here: synchronous or asynchronous:
361 363 * - synchronous calls are invoked by direct function call
362 364 * - asynchronous calls are invoked from a launched thread
363 365 *
364 366 * If the kernel has attempted to collect a response before the op
365 367 * has completed, the arg will have been marked as response_abort
366 368 * and we can discard the response data and release the arg.
367 369 *
368 370 * We send a notification when asynchronous (ASYNC) door calls
369 371 * from the kernel (SYSSPACE) have completed.
370 372 */
371 373 void *
372 374 smbd_door_dispatch_op(void *thread_arg)
373 375 {
374 376 smbd_arg_t *arg = (smbd_arg_t *)thread_arg;
375 377 smbd_doorop_t *doorop;
376 378 smb_doorhdr_t *hdr;
377 379 int i;
378 380
379 381 if ((!smbd_online()) || arg == NULL)
380 382 return (NULL);
381 383
382 384 hdr = &arg->hdr;
383 385 arg->opname = smb_doorhdr_opname(hdr->dh_op);
384 386
385 387 for (i = 0; i < smbd_ndoorop; ++i) {
386 388 doorop = &smbd_doorops[i];
387 389
388 390 if (hdr->dh_op == doorop->opcode) {
389 391 hdr->dh_door_rc = doorop->op(arg);
390 392 hdr->dh_status = arg->status;
391 393
392 394 if ((hdr->dh_flags & SMB_DF_SYSSPACE) &&
393 395 (hdr->dh_flags & SMB_DF_ASYNC)) {
394 396 assert(hdr->dh_op != SMB_DR_ASYNC_RESPONSE);
395 397
396 398 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
397 399 if (arg->response_abort) {
398 400 free(arg->rbuf);
399 401 arg->rbuf = NULL;
400 402 smbd_door_release_async(arg);
401 403 } else {
402 404 arg->response_ready = B_TRUE;
403 405 }
404 406 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
405 407
406 408 (void) smb_kmod_event_notify(hdr->dh_txid);
407 409 }
408 410
409 411 return (NULL);
410 412 }
411 413 }
412 414
413 415 syslog(LOG_ERR, "smbd_door_dispatch_op[%s]: invalid op %u",
414 416 arg->opname, hdr->dh_op);
415 417 return (NULL);
416 418 }
417 419
418 420 /*
419 421 * Wrapper for door_return. smbd_door_enter() increments a reference count
420 422 * when a door call is dispatched and smbd_door_return() decrements the
421 423 * reference count when it completes.
422 424 *
423 425 * The reference counting is used in smbd_door_fini() to wait for active
424 426 * calls to complete before closing the door.
425 427 */
426 428 void
427 429 smbd_door_init(smbd_door_t *sdh, const char *name)
428 430 {
429 431 (void) strlcpy(sdh->sd_name, name, sizeof (sdh->sd_name));
430 432 }
431 433
432 434 void
433 435 smbd_door_enter(smbd_door_t *sdh)
434 436 {
435 437 (void) mutex_lock(&sdh->sd_mutex);
436 438 ++sdh->sd_ncalls;
437 439 (void) mutex_unlock(&sdh->sd_mutex);
438 440 }
439 441
440 442 /*
441 443 * We have two calls to door_return because the first call (with data)
442 444 * can fail, which can leave the door call blocked here. The second
443 445 * call (with NULL) is guaranteed to unblock and return to the caller.
444 446 */
445 447 void
446 448 smbd_door_return(smbd_door_t *sdh, char *data_ptr, size_t data_size,
447 449 door_desc_t *desc_ptr, uint_t num_desc)
448 450 {
449 451 (void) mutex_lock(&sdh->sd_mutex);
450 452
451 453 if (sdh->sd_ncalls == 0)
452 454 syslog(LOG_ERR, "smbd_door_return[%s]: unexpected count=0",
453 455 sdh->sd_name);
454 456 else
455 457 --sdh->sd_ncalls;
456 458
457 459 (void) cond_broadcast(&sdh->sd_cv);
458 460 (void) mutex_unlock(&sdh->sd_mutex);
459 461
460 462 (void) door_return(data_ptr, data_size, desc_ptr, num_desc);
461 463 (void) door_return(NULL, 0, NULL, 0);
462 464 /* NOTREACHED */
463 465 }
464 466
465 467 /*
466 468 * A door service is about to terminate.
467 469 * Give active requests a small grace period to complete.
468 470 */
469 471 void
470 472 smbd_door_fini(smbd_door_t *sdh)
471 473 {
472 474 timestruc_t delay;
473 475 int rc = 0;
474 476
475 477 (void) mutex_lock(&sdh->sd_mutex);
476 478
477 479 while (rc != ETIME && sdh->sd_ncalls != 0) {
478 480 delay.tv_sec = 1;
479 481 delay.tv_nsec = 0;
480 482 rc = cond_reltimedwait(&sdh->sd_cv, &sdh->sd_mutex, &delay);
481 483 }
482 484
483 485 if (sdh->sd_ncalls != 0)
484 486 syslog(LOG_NOTICE, "smbd_door_fini[%s]: %d remaining",
485 487 sdh->sd_name, sdh->sd_ncalls);
486 488
487 489 (void) mutex_unlock(&sdh->sd_mutex);
488 490 }
489 491
490 492 /*
491 493 * Null door operation: always returns success.
492 494 * Assumes no request or response data.
493 495 */
494 496 /*ARGSUSED*/
495 497 static int
496 498 smbd_dop_null(smbd_arg_t *arg)
497 499 {
498 500 return (SMB_DOP_SUCCESS);
499 501 }
500 502
501 503 /*
502 504 * Async response handler: setup the rbuf and rsize for the specified
503 505 * transaction. This function is used by the kernel to collect the
504 506 * response half of an asynchronous door call.
505 507 *
506 508 * If a door client attempts to collect a response before the op has
507 509 * completed (!response_ready), mark the arg as response_abort and
508 510 * set an error. The response will be discarded when the op completes.
509 511 */
510 512 static int
511 513 smbd_dop_async_response(smbd_arg_t *rsp_arg)
512 514 {
513 515 list_t *arg_list = &smbd_doorsvc.sd_async_list;
514 516 smbd_arg_t *arg;
515 517
516 518 (void) mutex_lock(&smbd_doorsvc.sd_mutex);
517 519 arg = list_head(arg_list);
518 520
519 521 while (arg != NULL) {
520 522 assert(arg->magic == SMBD_ARG_MAGIC);
521 523
522 524 if (arg->hdr.dh_txid == rsp_arg->hdr.dh_txid) {
523 525 if (!arg->response_ready) {
524 526 arg->response_abort = B_TRUE;
525 527 rsp_arg->hdr.dh_door_rc = SMB_DOP_NOT_CALLED;
526 528 syslog(LOG_NOTICE, "doorsvc[%s]: %u not ready",
527 529 arg->opname, arg->hdr.dh_txid);
528 530 break;
529 531 }
530 532
531 533 rsp_arg->rbuf = arg->rbuf;
532 534 rsp_arg->rsize = arg->rsize;
533 535 arg->rbuf = NULL;
534 536 arg->rsize = 0;
535 537 smbd_door_release_async(arg);
536 538 break;
537 539 }
538 540
539 541 arg = list_next(arg_list, arg);
540 542 }
541 543
542 544 (void) mutex_unlock(&smbd_doorsvc.sd_mutex);
543 545 return (SMB_DOP_SUCCESS);
544 546 }
545 547
546 548 static int
547 549 smbd_dop_user_nonauth_logon(smbd_arg_t *arg)
548 550 {
549 551 uint32_t sid = 0;
550 552
551 553 if (smb_common_decode(arg->data, arg->datalen,
552 554 xdr_uint32_t, &sid) != 0)
553 555 return (SMB_DOP_DECODE_ERROR);
554 556
555 557 smbd_user_nonauth_logon(sid);
556 558 return (SMB_DOP_SUCCESS);
557 559 }
558 560
559 561 static int
560 562 smbd_dop_user_auth_logoff(smbd_arg_t *arg)
561 563 {
562 564 uint32_t sid = 0;
563 565
564 566 if (smb_common_decode(arg->data, arg->datalen,
565 567 xdr_uint32_t, &sid) != 0)
566 568 return (SMB_DOP_DECODE_ERROR);
567 569
568 570 smbd_user_auth_logoff(sid);
569 571 return (SMB_DOP_SUCCESS);
570 572 }
571 573
572 574 /*
573 575 * Obtains an access token on successful user authentication.
|
↓ open down ↓ |
457 lines elided |
↑ open up ↑ |
574 576 */
575 577 static int
576 578 smbd_dop_user_auth_logon(smbd_arg_t *arg)
577 579 {
578 580 _NOTE(ARGUNUSED(arg))
579 581
580 582 /* No longer used */
581 583 return (SMB_DOP_EMPTYBUF);
582 584 }
583 585
586 +/*
587 + * SMB_DR_LOOKUP_NAME,
588 + * SMB_DR_LOOKUP_LNAME (local-only, for idmap)
589 + */
584 590 static int
585 591 smbd_dop_lookup_name(smbd_arg_t *arg)
586 592 {
587 593 smb_domain_t dinfo;
588 594 smb_account_t ainfo;
589 595 lsa_account_t acct;
590 596 char buf[MAXNAMELEN];
591 597
592 598 bzero(&acct, sizeof (lsa_account_t));
593 599
594 600 if (smb_common_decode(arg->data, arg->datalen,
595 601 lsa_account_xdr, &acct) != 0)
596 602 return (SMB_DOP_DECODE_ERROR);
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
597 603
598 604 if (*acct.a_domain == '\0')
599 605 (void) snprintf(buf, MAXNAMELEN, "%s", acct.a_name);
600 606 else if (strchr(acct.a_domain, '.') != NULL)
601 607 (void) snprintf(buf, MAXNAMELEN, "%s@%s", acct.a_name,
602 608 acct.a_domain);
603 609 else
604 610 (void) snprintf(buf, MAXNAMELEN, "%s\\%s", acct.a_domain,
605 611 acct.a_name);
606 612
607 - acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo);
613 + switch (arg->hdr.dh_op) {
614 + case SMB_DR_LOOKUP_NAME:
615 + acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo);
616 + break;
617 +
618 + case SMB_DR_LOOKUP_LNAME:
619 + /*
620 + * Basically for idmap. Don't call out to AD.
621 + */
622 + acct.a_status = lsa_lookup_lname(buf, acct.a_sidtype, &ainfo);
623 + break;
624 +
625 + default:
626 + assert(!"arg->hdr.dh_op");
627 + acct.a_status = NT_STATUS_INTERNAL_ERROR;
628 + break;
629 + }
630 +
608 631 if (acct.a_status == NT_STATUS_SUCCESS) {
609 632 acct.a_sidtype = ainfo.a_type;
610 633 smb_sid_tostr(ainfo.a_sid, acct.a_sid);
611 634 (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
612 635
613 636 if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
614 637 (void) strlcpy(acct.a_domain, dinfo.di_fqname,
615 638 MAXNAMELEN);
616 639 else
617 640 (void) strlcpy(acct.a_domain, ainfo.a_domain,
618 641 MAXNAMELEN);
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
619 642 smb_account_free(&ainfo);
620 643 }
621 644
622 645 arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
623 646
624 647 if (arg->rbuf == NULL)
625 648 return (SMB_DOP_ENCODE_ERROR);
626 649 return (SMB_DOP_SUCCESS);
627 650 }
628 651
652 +/*
653 + * SMB_DR_LOOKUP_SID,
654 + * SMB_DR_LOOKUP_LSID (local-only, for idmap)
655 + */
629 656 static int
630 657 smbd_dop_lookup_sid(smbd_arg_t *arg)
631 658 {
632 659 smb_domain_t dinfo;
633 660 smb_account_t ainfo;
634 661 lsa_account_t acct;
635 662 smb_sid_t *sid;
636 663
637 664 bzero(&acct, sizeof (lsa_account_t));
638 665
639 666 if (smb_common_decode(arg->data, arg->datalen,
640 667 lsa_account_xdr, &acct) != 0)
641 668 return (SMB_DOP_DECODE_ERROR);
642 669
643 670 sid = smb_sid_fromstr(acct.a_sid);
644 - acct.a_status = lsa_lookup_sid(sid, &ainfo);
671 +
672 + switch (arg->hdr.dh_op) {
673 + case SMB_DR_LOOKUP_SID:
674 + acct.a_status = lsa_lookup_sid(sid, &ainfo);
675 + break;
676 +
677 + case SMB_DR_LOOKUP_LSID:
678 + /*
679 + * Basically for idmap. Don't call out to AD.
680 + */
681 + acct.a_status = lsa_lookup_lsid(sid, &ainfo);
682 + break;
683 +
684 + default:
685 + assert(!"arg->hdr.dh_op");
686 + acct.a_status = NT_STATUS_INTERNAL_ERROR;
687 + break;
688 + }
689 +
645 690 smb_sid_free(sid);
646 691
647 692 if (acct.a_status == NT_STATUS_SUCCESS) {
648 693 acct.a_sidtype = ainfo.a_type;
649 694 smb_sid_tostr(ainfo.a_sid, acct.a_sid);
650 695 (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN);
651 696
652 697 if (smb_domain_lookup_name(ainfo.a_domain, &dinfo))
653 698 (void) strlcpy(acct.a_domain, dinfo.di_fqname,
654 699 MAXNAMELEN);
655 700 else
656 701 (void) strlcpy(acct.a_domain, ainfo.a_domain,
657 702 MAXNAMELEN);
658 703
659 704 smb_account_free(&ainfo);
660 705 }
661 706
662 707 arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize);
663 708
664 709 if (arg->rbuf == NULL)
665 710 return (SMB_DOP_ENCODE_ERROR);
666 711 return (SMB_DOP_SUCCESS);
667 712 }
668 713
669 714 static int
670 715 smbd_dop_join(smbd_arg_t *arg)
671 716 {
672 717 smb_joininfo_t jdi;
673 718 smb_joinres_t jdres;
674 719
675 720 bzero(&jdi, sizeof (smb_joininfo_t));
676 721 bzero(&jdres, sizeof (smb_joinres_t));
677 722
678 723 if (smb_common_decode(arg->data, arg->datalen,
679 724 smb_joininfo_xdr, &jdi) != 0)
680 725 return (SMB_DOP_DECODE_ERROR);
681 726
682 727 smbd_join(&jdi, &jdres);
683 728
684 729 arg->rbuf = smb_common_encode(&jdres, smb_joinres_xdr, &arg->rsize);
685 730
686 731 if (arg->rbuf == NULL)
687 732 return (SMB_DOP_ENCODE_ERROR);
688 733 return (SMB_DOP_SUCCESS);
689 734 }
690 735
691 736 static int
692 737 smbd_dop_get_dcinfo(smbd_arg_t *arg)
693 738 {
694 739 smb_domainex_t dxi;
695 740
696 741 if (!smb_domain_getinfo(&dxi))
697 742 return (SMB_DOP_EMPTYBUF);
698 743
699 744 arg->rbuf = smb_string_encode(dxi.d_dci.dc_name, &arg->rsize);
700 745
701 746 if (arg->rbuf == NULL)
702 747 return (SMB_DOP_ENCODE_ERROR);
703 748 return (SMB_DOP_SUCCESS);
704 749 }
705 750
706 751 /*
707 752 * Return the number of snapshots for a dataset
708 753 */
709 754 static int
710 755 smbd_dop_vss_get_count(smbd_arg_t *arg)
711 756 {
712 757 smb_string_t path;
713 758 uint32_t count;
714 759
715 760 bzero(&path, sizeof (smb_string_t));
716 761 arg->rbuf = NULL;
717 762
718 763 if (smb_string_decode(&path, arg->data, arg->datalen) != 0)
719 764 return (SMB_DOP_DECODE_ERROR);
720 765
721 766 if (smbd_vss_get_count(path.buf, &count) == 0)
722 767 arg->rbuf = smb_common_encode(&count, xdr_uint32_t,
723 768 &arg->rsize);
724 769
725 770 xdr_free(smb_string_xdr, (char *)&path);
726 771
727 772 if (arg->rbuf == NULL)
728 773 return (SMB_DOP_ENCODE_ERROR);
729 774 return (SMB_DOP_SUCCESS);
730 775 }
731 776
732 777 /*
733 778 * Return the count and list of snapshots.
734 779 * The list is in @GMT token format.
735 780 */
736 781 static int
737 782 smbd_dop_vss_get_snapshots(smbd_arg_t *arg)
738 783 {
739 784 char **gmtp;
740 785 smb_gmttoken_query_t request;
741 786 smb_gmttoken_response_t reply;
742 787 uint_t i;
743 788
744 789 bzero(&request, sizeof (smb_gmttoken_query_t));
745 790 bzero(&reply, sizeof (smb_gmttoken_response_t));
746 791
747 792 if (smb_common_decode(arg->data, arg->datalen,
748 793 smb_gmttoken_query_xdr, &request) != 0)
749 794 return (SMB_DOP_DECODE_ERROR);
750 795
751 796 reply.gtr_gmttokens.gtr_gmttokens_val = malloc(request.gtq_count *
752 797 sizeof (char *));
753 798 bzero(reply.gtr_gmttokens.gtr_gmttokens_val, request.gtq_count *
754 799 sizeof (char *));
755 800
756 801 if (reply.gtr_gmttokens.gtr_gmttokens_val == NULL) {
757 802 xdr_free(smb_gmttoken_query_xdr, (char *)&request);
758 803 return (SMB_DOP_EMPTYBUF);
759 804 }
760 805
761 806 smbd_vss_get_snapshots(request.gtq_path, request.gtq_count,
762 807 &reply.gtr_count,
763 808 &reply.gtr_gmttokens.gtr_gmttokens_len,
764 809 reply.gtr_gmttokens.gtr_gmttokens_val);
765 810
766 811 arg->rbuf = smb_common_encode(&reply, smb_gmttoken_response_xdr,
767 812 &arg->rsize);
768 813 if (arg->rbuf == NULL) {
769 814 xdr_free(smb_gmttoken_query_xdr, (char *)&request);
770 815 return (SMB_DOP_ENCODE_ERROR);
771 816 }
772 817
773 818 for (i = 0, gmtp = reply.gtr_gmttokens.gtr_gmttokens_val;
774 819 (i < request.gtq_count); i++) {
775 820 if (*gmtp)
776 821 free(*gmtp);
777 822 gmtp++;
778 823 }
779 824
780 825 free(reply.gtr_gmttokens.gtr_gmttokens_val);
781 826 xdr_free(smb_gmttoken_query_xdr, (char *)&request);
782 827 return (SMB_DOP_SUCCESS);
783 828 }
784 829
785 830 /*
786 831 * Return the name of the snapshot that matches the dataset path
787 832 * and @GMT token.
788 833 */
789 834 static int
790 835 smbd_dop_vss_map_gmttoken(smbd_arg_t *arg)
791 836 {
792 837 char *snapname;
793 838 smb_gmttoken_snapname_t request;
794 839
795 840 bzero(&request, sizeof (smb_gmttoken_snapname_t));
796 841
797 842 if (smb_common_decode(arg->data, arg->datalen,
798 843 smb_gmttoken_snapname_xdr, &request) != 0) {
799 844 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
800 845 return (SMB_DOP_DECODE_ERROR);
801 846 }
802 847
803 848 if ((snapname = malloc(MAXPATHLEN)) == NULL) {
804 849 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
805 850 return (NULL);
806 851 }
807 852
808 853 if ((smbd_vss_map_gmttoken(request.gts_path, request.gts_gmttoken,
809 854 request.gts_toktime, snapname) != 0)) {
810 855 *snapname = '\0';
811 856 }
812 857
813 858 arg->rbuf = smb_string_encode(snapname, &arg->rsize);
814 859 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request);
815 860 free(snapname);
816 861
817 862 if (arg->rbuf == NULL)
818 863 return (SMB_DOP_ENCODE_ERROR);
819 864 return (SMB_DOP_SUCCESS);
820 865 }
821 866
822 867 static int
823 868 smbd_dop_ads_find_host(smbd_arg_t *arg)
824 869 {
825 870 smb_ads_host_info_t *hinfo = NULL;
826 871 char *hostname = "";
827 872 smb_string_t fqdn;
828 873
829 874 bzero(&fqdn, sizeof (smb_string_t));
830 875
831 876 if (smb_string_decode(&fqdn, arg->data, arg->datalen) != 0)
832 877 return (SMB_DOP_DECODE_ERROR);
833 878
834 879 if ((hinfo = smb_ads_find_host(fqdn.buf)) != NULL)
835 880 hostname = hinfo->name;
836 881
837 882 xdr_free(smb_string_xdr, (char *)&fqdn);
838 883
839 884 arg->rbuf = smb_string_encode(hostname, &arg->rsize);
840 885 free(hinfo);
841 886
842 887 if (arg->rbuf == NULL)
843 888 return (SMB_DOP_ENCODE_ERROR);
844 889 return (SMB_DOP_SUCCESS);
845 890 }
846 891
847 892 /*
848 893 * Query the list of user/group quota entries for a given filesystem.
849 894 */
850 895 static int
851 896 smbd_dop_quota_query(smbd_arg_t *arg)
852 897 {
853 898 smb_quota_query_t request;
854 899 smb_quota_response_t reply;
855 900 uint32_t status;
856 901
857 902 bzero(&request, sizeof (smb_quota_query_t));
858 903 bzero(&reply, sizeof (smb_quota_response_t));
859 904
860 905 if (smb_common_decode(arg->data, arg->datalen,
861 906 smb_quota_query_xdr, &request) != 0)
862 907 return (SMB_DOP_DECODE_ERROR);
863 908
864 909 status = smb_quota_query(&request, &reply);
865 910 reply.qr_status = status;
866 911
867 912 arg->rbuf = smb_common_encode(&reply, smb_quota_response_xdr,
868 913 &arg->rsize);
869 914
870 915 xdr_free(smb_quota_query_xdr, (char *)&request);
871 916 smb_quota_free(&reply);
872 917
873 918 if (arg->rbuf == NULL)
874 919 return (SMB_DOP_ENCODE_ERROR);
875 920 return (SMB_DOP_SUCCESS);
876 921 }
877 922
878 923 /*
879 924 * Set a list of user/group quota entries for a given filesystem.
880 925 */
881 926 static int
882 927 smbd_dop_quota_set(smbd_arg_t *arg)
883 928 {
884 929 smb_quota_set_t request;
885 930 uint32_t status = 0;
886 931
887 932 bzero(&request, sizeof (smb_quota_set_t));
888 933
889 934 if (smb_common_decode(arg->data, arg->datalen,
890 935 smb_quota_set_xdr, &request) != 0)
891 936 return (SMB_DOP_DECODE_ERROR);
892 937
893 938 status = smb_quota_set(&request);
894 939
895 940 arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize);
896 941 xdr_free(smb_quota_set_xdr, (char *)&request);
897 942
898 943 if (arg->rbuf == NULL)
899 944 return (SMB_DOP_ENCODE_ERROR);
900 945 return (SMB_DOP_SUCCESS);
901 946 }
902 947
903 948 static int
904 949 smbd_dop_dfs_get_referrals(smbd_arg_t *arg)
905 950 {
906 951 dfs_referral_query_t request;
907 952 dfs_referral_response_t reply;
908 953
909 954 bzero(&request, sizeof (request));
910 955 bzero(&reply, sizeof (reply));
911 956
912 957 if (smb_common_decode(arg->data, arg->datalen,
913 958 dfs_referral_query_xdr, &request) != 0)
914 959 return (SMB_DOP_DECODE_ERROR);
915 960
916 961 reply.rp_status = dfs_get_referrals((const char *)request.rq_path,
917 962 request.rq_type, &reply.rp_referrals);
918 963
919 964 if (reply.rp_status != ERROR_SUCCESS)
920 965 bzero(&reply.rp_referrals, sizeof (dfs_info_t));
921 966
922 967 arg->rbuf = smb_common_encode(&reply, dfs_referral_response_xdr,
923 968 &arg->rsize);
924 969
925 970 if (reply.rp_status == ERROR_SUCCESS)
926 971 dfs_info_free(&reply.rp_referrals);
927 972
928 973 xdr_free(dfs_referral_query_xdr, (char *)&request);
929 974
930 975 if (arg->rbuf == NULL)
931 976 return (SMB_DOP_ENCODE_ERROR);
932 977 return (SMB_DOP_SUCCESS);
933 978 }
934 979
935 980 static int
936 981 smbd_dop_shr_hostaccess(smbd_arg_t *arg)
937 982 {
938 983 smb_shr_hostaccess_query_t request;
939 984 uint32_t reply;
940 985
941 986 bzero(&request, sizeof (request));
942 987 bzero(&reply, sizeof (reply));
943 988
944 989 if (smb_common_decode(arg->data, arg->datalen,
945 990 smb_shr_hostaccess_query_xdr, &request) != 0)
946 991 return (SMB_DOP_DECODE_ERROR);
947 992
948 993 reply = smb_shr_hostaccess(&request.shq_ipaddr, request.shq_none,
949 994 request.shq_ro, request.shq_rw, request.shq_flag);
950 995
951 996 arg->rbuf = smb_common_encode(&reply, xdr_uint32_t, &arg->rsize);
952 997
953 998 xdr_free(smb_shr_hostaccess_query_xdr, (char *)&request);
954 999
955 1000 if (arg->rbuf == NULL)
956 1001 return (SMB_DOP_ENCODE_ERROR);
957 1002 return (SMB_DOP_SUCCESS);
958 1003 }
959 1004
960 1005 static int
961 1006 smbd_dop_shr_exec(smbd_arg_t *arg)
962 1007 {
963 1008 smb_shr_execinfo_t request;
964 1009 int reply;
965 1010
966 1011 bzero(&request, sizeof (request));
967 1012 bzero(&reply, sizeof (reply));
968 1013
969 1014 if (smb_common_decode(arg->data, arg->datalen,
970 1015 smb_shr_execinfo_xdr, &request) != 0)
971 1016 return (SMB_DOP_DECODE_ERROR);
972 1017
973 1018 reply = smb_shr_exec(&request);
974 1019
975 1020 if (reply != 0)
976 1021 syslog(LOG_NOTICE, "Failed to execute %s command",
977 1022 (request.e_type == SMB_EXEC_MAP) ? "map" : "unmap");
978 1023
979 1024 arg->rbuf = smb_common_encode(&reply, xdr_int, &arg->rsize);
980 1025
981 1026 xdr_free(smb_shr_execinfo_xdr, (char *)&request);
982 1027
983 1028 if (arg->rbuf == NULL)
984 1029 return (SMB_DOP_ENCODE_ERROR);
985 1030 return (SMB_DOP_SUCCESS);
986 1031 }
987 1032
988 1033 /* ARGSUSED */
989 1034 static int
990 1035 smbd_dop_notify_dc_changed(smbd_arg_t *arg)
991 1036 {
992 1037
993 1038 smbd_dc_monitor_refresh();
994 1039
995 1040 return (SMB_DOP_SUCCESS);
996 1041 }
|
↓ open down ↓ |
342 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX