Print this page
NEX-17457 kernel share list fails to be updated after fs import
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
NEX-16159 Time spent sharing SMB filesystems could be reduced by optimizing smb_getdataset for default mount points
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.(cstyle)
NEX-10098 Disabling SMB server service does not change the sharestate of a smb share to “offline”.
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@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-6949 SMB shares with no permission for root fail after restart
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6135 Pool cannot get exported while deletes is running
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexent.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4865 Still creating .$EXTEND directory with quotas disabled
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3673 CLONE NEX-2525 Customer cannot set Share Properties using MMC in Windows Server 2008 R2
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-1473 share unavailable after failover (copyright update)
NEX-1473 share unavailable after failover
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/smb_share.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.
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
22 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
22 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * SMB/CIFS share cache implementation.
27 27 */
28 28
29 29 #include <errno.h>
30 30 #include <synch.h>
31 31 #include <stdlib.h>
32 32 #include <strings.h>
33 33 #include <syslog.h>
34 34 #include <thread.h>
35 35 #include <pthread.h>
36 36 #include <assert.h>
37 37 #include <libshare.h>
38 38 #include <libzfs.h>
39 39 #include <priv_utils.h>
40 40 #include <sys/types.h>
41 41 #include <sys/wait.h>
42 42 #include <unistd.h>
43 43 #include <pwd.h>
44 44 #include <signal.h>
45 45 #include <dirent.h>
46 46 #include <dlfcn.h>
47 47
48 48 #include <smbsrv/libsmb.h>
49 49 #include <smbsrv/libsmbns.h>
50 50 #include <smbsrv/libmlsvc.h>
51 51 #include <smbsrv/smb_share.h>
52 52 #include <smbsrv/smb.h>
53 53 #include <mlsvc.h>
54 54 #include <dfs.h>
55 55
56 56 #define SMB_SHR_ERROR_THRESHOLD 3
57 57 #define SMB_SHR_CSC_BUFSZ 64
58 58
59 59 typedef struct smb_transient {
60 60 char *name;
61 61 char *cmnt;
62 62 char *path;
63 63 char drive;
64 64 boolean_t check;
65 65 } smb_transient_t;
66 66
67 67 static smb_transient_t tshare[] = {
68 68 { "IPC$", "Remote IPC", NULL, '\0', B_FALSE },
69 69 { "c$", "Default Share", SMB_CVOL, 'C', B_FALSE },
70 70 { "vss$", "VSS", SMB_VSS, 'V', B_TRUE }
71 71 };
72 72
73 73 static struct {
74 74 char *value;
75 75 uint32_t flag;
76 76 } cscopt[] = {
77 77 { "disabled", SMB_SHRF_CSC_DISABLED },
78 78 { "manual", SMB_SHRF_CSC_MANUAL },
79 79 { "auto", SMB_SHRF_CSC_AUTO },
80 80 { "vdo", SMB_SHRF_CSC_VDO }
81 81 };
82 82
83 83 /*
84 84 * Cache functions and vars
85 85 */
86 86 #define SMB_SHR_HTAB_SZ 1024
87 87
88 88 /*
89 89 * Cache handle
90 90 *
91 91 * Shares cache is a hash table.
92 92 *
93 93 * sc_cache pointer to hash table handle
94 94 * sc_cache_lck synchronize cache read/write accesses
95 95 * sc_state cache state machine values
96 96 * sc_nops number of inflight/pending cache operations
97 97 * sc_mtx protects handle fields
98 98 */
99 99 typedef struct smb_shr_cache {
100 100 HT_HANDLE *sc_cache;
101 101 rwlock_t sc_cache_lck;
102 102 mutex_t sc_mtx;
103 103 cond_t sc_cv;
104 104 uint32_t sc_state;
105 105 uint32_t sc_nops;
106 106 } smb_shr_cache_t;
107 107
108 108 /*
109 109 * Cache states
110 110 */
111 111 #define SMB_SHR_CACHE_STATE_NONE 0
112 112 #define SMB_SHR_CACHE_STATE_CREATED 1
113 113 #define SMB_SHR_CACHE_STATE_DESTROYING 2
114 114
115 115 /*
116 116 * Cache lock modes
117 117 */
118 118 #define SMB_SHR_CACHE_RDLOCK 0
119 119 #define SMB_SHR_CACHE_WRLOCK 1
120 120
121 121 static smb_shr_cache_t smb_shr_cache;
122 122
123 123 static uint32_t smb_shr_cache_create(void);
124 124 static void smb_shr_cache_destroy(void);
125 125 static uint32_t smb_shr_cache_lock(int);
126 126 static void smb_shr_cache_unlock(void);
127 127 static int smb_shr_cache_count(void);
128 128 static smb_share_t *smb_shr_cache_iterate(smb_shriter_t *);
129 129
130 130 static smb_share_t *smb_shr_cache_findent(char *);
131 131 static uint32_t smb_shr_cache_addent(smb_share_t *);
132 132 static void smb_shr_cache_delent(char *);
133 133 static void smb_shr_cache_freent(HT_ITEM *);
134 134
135 135 static boolean_t smb_shr_is_empty(const char *);
136 136 static boolean_t smb_shr_is_dot_or_dotdot(const char *);
137 137
138 138 /*
139 139 * sharemgr functions
140 140 */
141 141 static void smb_shr_sa_loadgrp(sa_group_t);
142 142 static uint32_t smb_shr_sa_load(sa_share_t, sa_resource_t);
143 143 static uint32_t smb_shr_sa_loadbyname(char *);
144 144 static uint32_t smb_shr_sa_get(sa_share_t, sa_resource_t, smb_share_t *);
145 145
146 146 /*
147 147 * .ZFS management functions
148 148 */
149 149 static void smb_shr_zfs_add(smb_share_t *);
150 150 static void smb_shr_zfs_remove(smb_share_t *);
151 151 static void smb_shr_zfs_rename(smb_share_t *, smb_share_t *);
152 152
153 153 /*
154 154 * share publishing
155 155 */
156 156 #define SMB_SHR_PUBLISH 0
157 157 #define SMB_SHR_UNPUBLISH 1
158 158
159 159 typedef struct smb_shr_pitem {
160 160 list_node_t spi_lnd;
161 161 char spi_name[MAXNAMELEN];
162 162 char spi_container[MAXPATHLEN];
163 163 char spi_op;
164 164 } smb_shr_pitem_t;
165 165
166 166 /*
167 167 * publish queue states
168 168 */
169 169 #define SMB_SHR_PQS_NOQUEUE 0
170 170 #define SMB_SHR_PQS_READY 1 /* the queue is ready */
171 171 #define SMB_SHR_PQS_PUBLISHING 2 /* publisher thread is running */
172 172 #define SMB_SHR_PQS_STOPPING 3
173 173
174 174 /*
175 175 * share publishing queue
176 176 */
177 177 typedef struct smb_shr_pqueue {
178 178 list_t spq_list;
179 179 mutex_t spq_mtx;
180 180 cond_t spq_cv;
181 181 uint32_t spq_state;
182 182 } smb_shr_pqueue_t;
183 183
184 184 static smb_shr_pqueue_t ad_queue;
185 185
186 186 static int smb_shr_publisher_start(void);
187 187 static void smb_shr_publisher_stop(void);
188 188 static void smb_shr_publisher_send(smb_ads_handle_t *, list_t *, const char *);
189 189 static void smb_shr_publisher_queue(const char *, const char *, char);
190 190 static void *smb_shr_publisher(void *);
191 191 static void smb_shr_publisher_flush(list_t *);
192 192 static void smb_shr_publish(const char *, const char *);
193 193 static void smb_shr_unpublish(const char *, const char *);
194 194
195 195 /*
196 196 * Utility/helper functions
197 197 */
198 198 static uint32_t smb_shr_lookup(char *, smb_share_t *);
199 199 static uint32_t smb_shr_add_transient(char *, char *, char *);
200 200 static int smb_shr_enable_all_privs(void);
201 201 static int smb_shr_expand_subs(char **, smb_share_t *, smb_shr_execinfo_t *);
202 202 static char **smb_shr_tokenize_cmd(char *);
203 203 static void smb_shr_sig_abnormal_term(int);
204 204 static void smb_shr_sig_child(int);
205 205 static int smb_shr_encode(smb_share_t *, nvlist_t **);
206 206
207 207 /*
208 208 * libshare handle and synchronization
209 209 */
210 210 typedef struct smb_sa_handle {
211 211 sa_handle_t sa_handle;
212 212 mutex_t sa_mtx;
213 213 boolean_t sa_in_service;
214 214 } smb_sa_handle_t;
215 215
216 216 static smb_sa_handle_t smb_sa_handle;
217 217
218 218 static char smb_shr_exec_map[MAXPATHLEN];
219 219 static char smb_shr_exec_unmap[MAXPATHLEN];
220 220 static mutex_t smb_shr_exec_mtx;
221 221
222 222 /*
223 223 * Semaphore held during temporary, process-wide changes
224 224 * such as process privileges. It is a seamaphore and
225 225 * not a mutex so a child of fork can reset it.
226 226 */
227 227 static sema_t smb_proc_sem = DEFAULTSEMA;
228 228
229 229 /*
230 230 * Creates and initializes the cache and starts the publisher
231 231 * thread.
232 232 */
233 233 int
234 234 smb_shr_start(void)
235 235 {
236 236 smb_transient_t *ts;
237 237 uint32_t nerr;
238 238 int i;
239 239
240 240 (void) mutex_lock(&smb_sa_handle.sa_mtx);
241 241 smb_sa_handle.sa_in_service = B_TRUE;
242 242 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
243 243
244 244 if (smb_shr_cache_create() != NERR_Success)
245 245 return (ENOMEM);
246 246
247 247 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
248 248 ts = &tshare[i];
249 249
250 250 if (ts->check && smb_shr_is_empty(ts->path))
251 251 continue;
252 252
253 253 nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path);
254 254 if (nerr != NERR_Success)
255 255 return (ENOMEM);
256 256 }
257 257
258 258 return (smb_shr_publisher_start());
259 259 }
260 260
261 261 void
262 262 smb_shr_stop(void)
263 263 {
264 264 smb_shr_cache_destroy();
265 265 smb_shr_publisher_stop();
266 266
267 267 (void) mutex_lock(&smb_sa_handle.sa_mtx);
268 268 smb_sa_handle.sa_in_service = B_FALSE;
269 269
270 270 if (smb_sa_handle.sa_handle != NULL) {
271 271 sa_fini(smb_sa_handle.sa_handle);
272 272 smb_sa_handle.sa_handle = NULL;
273 273 }
274 274
275 275 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
276 276 }
277 277
278 278 /*
279 279 * Get a handle and exclusive access to the libshare API.
280 280 */
281 281 sa_handle_t
282 282 smb_shr_sa_enter(void)
283 283 {
284 284 (void) mutex_lock(&smb_sa_handle.sa_mtx);
285 285 if (!smb_sa_handle.sa_in_service) {
286 286 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
287 287 return (NULL);
288 288 }
289 289
290 290 if (smb_sa_handle.sa_handle != NULL &&
291 291 sa_needs_refresh(smb_sa_handle.sa_handle)) {
292 292 sa_fini(smb_sa_handle.sa_handle);
293 293 smb_sa_handle.sa_handle = NULL;
294 294 }
295 295
296 296 if (smb_sa_handle.sa_handle == NULL) {
297 297 smb_sa_handle.sa_handle = sa_init(SA_INIT_SHARE_API);
298 298 if (smb_sa_handle.sa_handle == NULL) {
299 299 syslog(LOG_ERR, "share: failed to get libshare handle");
300 300 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
301 301 return (NULL);
302 302 }
303 303 }
304 304
305 305 return (smb_sa_handle.sa_handle);
306 306 }
307 307
308 308 /*
309 309 * Release exclusive access to the libshare API.
310 310 */
311 311 void
312 312 smb_shr_sa_exit(void)
313 313 {
314 314 (void) mutex_unlock(&smb_sa_handle.sa_mtx);
315 315 }
316 316
317 317 /*
318 318 * Return the total number of shares
319 319 */
320 320 int
321 321 smb_shr_count(void)
322 322 {
323 323 int n_shares = 0;
324 324
325 325 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
326 326 n_shares = smb_shr_cache_count();
327 327 smb_shr_cache_unlock();
328 328 }
329 329
330 330 return (n_shares);
331 331 }
332 332
333 333 /*
334 334 * smb_shr_iterinit
335 335 *
336 336 * Initialize given iterator for traversing hash table.
337 337 */
338 338 void
339 339 smb_shr_iterinit(smb_shriter_t *shi)
340 340 {
341 341 bzero(shi, sizeof (smb_shriter_t));
342 342 shi->si_first = B_TRUE;
343 343 }
344 344
345 345 /*
346 346 * smb_shr_iterate
347 347 *
348 348 * Iterate on the shares in the hash table. The iterator must be initialized
349 349 * before the first iteration. On subsequent calls, the iterator must be
350 350 * passed unchanged.
351 351 *
352 352 * Returns NULL on failure or when all shares are visited, otherwise
353 353 * returns information of visited share.
354 354 */
355 355 smb_share_t *
356 356 smb_shr_iterate(smb_shriter_t *shi)
357 357 {
358 358 smb_share_t *share = NULL;
359 359 smb_share_t *cached_si;
360 360
361 361 if (shi == NULL)
362 362 return (NULL);
363 363
364 364 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
365 365 if ((cached_si = smb_shr_cache_iterate(shi)) != NULL) {
366 366 share = &shi->si_share;
367 367 bcopy(cached_si, share, sizeof (smb_share_t));
368 368 }
369 369 smb_shr_cache_unlock();
370 370 }
371 371
372 372 return (share);
373 373 }
374 374
375 375 /*
376 376 * Adds the given share to cache, publishes the share in ADS
377 377 * if it has an AD container, calls kernel to take a hold on
378 378 * the shared file system. If it can't take a hold on the
379 379 * shared file system, it's either because shared directory
380 380 * does not exist or some other error has occurred, in any
381 381 * case the share is removed from the cache.
|
↓ open down ↓ |
349 lines elided |
↑ open up ↑ |
382 382 *
383 383 * If the specified share is an autohome share which already
384 384 * exists in the cache, just increments the reference count.
385 385 */
386 386 uint32_t
387 387 smb_shr_add(smb_share_t *si)
388 388 {
389 389 struct stat st;
390 390 smb_share_t *cached_si;
391 391 nvlist_t *shrlist;
392 + boolean_t created_zfs = B_FALSE;
392 393 uint32_t status;
393 394 int rc;
394 395
395 396 assert(si != NULL);
396 397
397 398 if (smb_name_validate_share(si->shr_name) != ERROR_SUCCESS)
398 399 return (ERROR_INVALID_NAME);
399 400
400 401 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
401 402 return (NERR_InternalError);
402 403
403 404 cached_si = smb_shr_cache_findent(si->shr_name);
404 405 if (cached_si) {
405 406 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
406 407 cached_si->shr_refcnt++;
407 408 status = NERR_Success;
408 409 } else {
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
409 410 status = NERR_DuplicateShare;
410 411 }
411 412 smb_shr_cache_unlock();
412 413 return (status);
413 414 }
414 415
415 416 if (STYPE_ISDSK(si->shr_type)) {
416 417 /*
417 418 * If share type is STYPE_DISKTREE then the path to the
418 419 * share should exist so that we can add the share to cache.
420 + * If path is ZFS, add the .zfs/shares/<share> entry.
421 + *
422 + * Both actions may require privileges that main dropped,
423 + * so we need to temporarily make those effective.
419 424 */
420 - rc = stat(si->shr_path, &st);
425 + if (smb_proc_takesem() == 0) {
426 +
427 + (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
428 + PRIV_FILE_DAC_READ,
429 + PRIV_FILE_DAC_SEARCH,
430 + PRIV_FILE_DAC_WRITE,
431 + NULL);
432 +
433 + rc = stat(si->shr_path, &st);
434 + if (rc == 0) {
435 + smb_shr_zfs_add(si);
436 + created_zfs = B_TRUE;
437 + }
438 +
439 + (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
440 + PRIV_FILE_DAC_READ,
441 + PRIV_FILE_DAC_SEARCH,
442 + PRIV_FILE_DAC_WRITE,
443 + NULL);
444 + smb_proc_givesem();
445 + } else {
446 + rc = NERR_InternalError;
447 + }
421 448 if (rc != 0) {
422 449 smb_shr_cache_unlock();
423 450 return (NERR_ItemNotFound);
424 451 }
425 452 }
426 453
427 454 if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
455 + /* This error should be impossible after findent above. */
428 456 smb_shr_cache_unlock();
429 457 return (status);
430 458 }
431 459
432 460 /* don't hold the lock across door call */
433 461 smb_shr_cache_unlock();
434 462
435 463 if ((rc = smb_shr_encode(si, &shrlist)) == 0) {
436 464 /* send the share to kernel */
437 465 rc = smb_kmod_share(shrlist);
438 466 nvlist_free(shrlist);
439 467
440 468 if (rc == 0) {
441 469 smb_shr_publish(si->shr_name, si->shr_container);
442 470
443 - /* If path is ZFS, add the .zfs/shares/<share> entry. */
444 - smb_shr_zfs_add(si);
445 -
446 471 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
447 472 dfs_namespace_load(si->shr_name);
448 473
449 474 return (NERR_Success);
450 475 }
451 476 }
452 477
478 + /*
479 + * Error code path, i.e. when the kernel could not accept
480 + * the new share for some reason.
481 + */
453 482 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
454 483 smb_shr_cache_delent(si->shr_name);
455 484 smb_shr_cache_unlock();
456 485 }
457 486
487 + if (created_zfs && smb_proc_takesem() == 0) {
488 +
489 + (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
490 + PRIV_FILE_DAC_READ,
491 + PRIV_FILE_DAC_SEARCH,
492 + PRIV_FILE_DAC_WRITE,
493 + NULL);
494 +
495 + smb_shr_zfs_remove(si);
496 +
497 + (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
498 + PRIV_FILE_DAC_READ,
499 + PRIV_FILE_DAC_SEARCH,
500 + PRIV_FILE_DAC_WRITE,
501 + NULL);
502 +
503 + smb_proc_givesem();
504 + }
505 +
458 506 /*
459 507 * rc == ENOENT means the shared directory doesn't exist
460 508 */
461 509 return ((rc == ENOENT) ? NERR_UnknownDevDir : NERR_InternalError);
462 510 }
463 511
464 512 /*
465 513 * Removes the specified share from cache, removes it from AD
466 514 * if it has an AD container, and calls the kernel to release
467 515 * the hold on the shared file system.
468 516 *
469 517 * If this is an autohome share then decrement the reference
470 518 * count. If it reaches 0 then it proceeds with removing steps.
471 519 */
472 520 uint32_t
473 521 smb_shr_remove(char *sharename)
474 522 {
475 523 smb_share_t *si;
476 524 char container[MAXPATHLEN];
477 525 boolean_t dfsroot;
478 526 nvlist_t *shrlist;
479 527
480 528 assert(sharename != NULL);
481 529
482 530 if (smb_name_validate_share(sharename) != ERROR_SUCCESS)
483 531 return (ERROR_INVALID_NAME);
484 532
485 533 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
486 534 return (NERR_InternalError);
487 535
488 536 if ((si = smb_shr_cache_findent(sharename)) == NULL) {
489 537 smb_shr_cache_unlock();
490 538 return (NERR_NetNameNotFound);
491 539 }
492 540
493 541 if (STYPE_ISIPC(si->shr_type)) {
494 542 /* IPC$ share cannot be removed */
495 543 smb_shr_cache_unlock();
496 544 return (ERROR_ACCESS_DENIED);
497 545 }
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
498 546
499 547 if (si->shr_flags & SMB_SHRF_AUTOHOME) {
500 548 if ((--si->shr_refcnt) > 0) {
501 549 smb_shr_cache_unlock();
502 550 return (NERR_Success);
503 551 }
504 552 }
505 553
506 554 /*
507 555 * If path is ZFS, remove the .zfs/shares/<share> entry. Need
508 - * to remove before cleanup of cache occurs.
556 + * to remove before cleanup of cache occurs. These actions
557 + * require temporary elevation of privileges.
509 558 */
510 - smb_shr_zfs_remove(si);
559 + if (smb_proc_takesem() == 0) {
560 +
561 + (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
562 + PRIV_FILE_DAC_READ,
563 + PRIV_FILE_DAC_SEARCH,
564 + PRIV_FILE_DAC_WRITE,
565 + NULL);
566 +
567 + smb_shr_zfs_remove(si);
568 +
569 + (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
570 + PRIV_FILE_DAC_READ,
571 + PRIV_FILE_DAC_SEARCH,
572 + PRIV_FILE_DAC_WRITE,
573 + NULL);
574 +
575 + smb_proc_givesem();
576 + }
577 +
511 578 (void) smb_shr_encode(si, &shrlist);
512 579
513 580 (void) strlcpy(container, si->shr_container, sizeof (container));
514 581 dfsroot = ((si->shr_flags & SMB_SHRF_DFSROOT) != 0);
515 582 smb_shr_cache_delent(sharename);
516 583 smb_shr_cache_unlock();
517 584
518 585 smb_shr_unpublish(sharename, container);
519 586
520 587 /* call kernel to release the hold on the shared file system */
521 588 if (shrlist != NULL) {
522 589 (void) smb_kmod_unshare(shrlist);
523 590 nvlist_free(shrlist);
524 591 }
525 592
526 593 if (dfsroot)
527 594 dfs_namespace_unload(sharename);
528 595
529 596 return (NERR_Success);
530 597 }
531 598
532 599 /*
533 600 * Rename a share. Check that the current name exists and the new name
534 601 * doesn't exist. The rename is performed by deleting the current share
535 602 * definition and creating a new share with the new name.
536 603 */
537 604 uint32_t
538 605 smb_shr_rename(char *from_name, char *to_name)
539 606 {
540 607 smb_share_t *from_si;
541 608 smb_share_t to_si;
542 609 uint32_t status;
543 610 nvlist_t *shrlist;
544 611
545 612 assert((from_name != NULL) && (to_name != NULL));
546 613
547 614 if (smb_name_validate_share(from_name) != ERROR_SUCCESS ||
548 615 smb_name_validate_share(to_name) != ERROR_SUCCESS)
549 616 return (ERROR_INVALID_NAME);
550 617
551 618 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
552 619 return (NERR_InternalError);
553 620
554 621 if ((from_si = smb_shr_cache_findent(from_name)) == NULL) {
555 622 smb_shr_cache_unlock();
556 623 return (NERR_NetNameNotFound);
557 624 }
558 625
559 626 if (STYPE_ISIPC(from_si->shr_type)) {
560 627 /* IPC$ share cannot be renamed */
561 628 smb_shr_cache_unlock();
562 629 return (ERROR_ACCESS_DENIED);
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
563 630 }
564 631
565 632 if (smb_shr_cache_findent(to_name) != NULL) {
566 633 smb_shr_cache_unlock();
567 634 return (NERR_DuplicateShare);
568 635 }
569 636
570 637 bcopy(from_si, &to_si, sizeof (smb_share_t));
571 638 (void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
572 639
573 -
574 640 /* If path is ZFS, rename the .zfs/shares/<share> entry. */
575 - smb_shr_zfs_rename(from_si, &to_si);
641 + if (smb_proc_takesem() == 0) {
576 642
643 + (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
644 + PRIV_FILE_DAC_READ,
645 + PRIV_FILE_DAC_SEARCH,
646 + PRIV_FILE_DAC_WRITE,
647 + NULL);
648 +
649 + smb_shr_zfs_rename(from_si, &to_si);
650 +
651 + (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
652 + PRIV_FILE_DAC_READ,
653 + PRIV_FILE_DAC_SEARCH,
654 + PRIV_FILE_DAC_WRITE,
655 + NULL);
656 +
657 + smb_proc_givesem();
658 + }
659 +
577 660 if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
578 661 smb_shr_cache_unlock();
579 662 return (status);
580 663 }
581 664
582 665 smb_shr_cache_delent(from_name);
583 666 smb_shr_cache_unlock();
584 667
585 668 if (smb_shr_encode(from_si, &shrlist) == 0) {
586 669 (void) smb_kmod_unshare(shrlist);
587 670 nvlist_free(shrlist);
588 671
589 672 if (smb_shr_encode(&to_si, &shrlist) == 0) {
590 673 (void) smb_kmod_share(shrlist);
591 674 nvlist_free(shrlist);
592 675 }
593 676 }
594 677
595 678 smb_shr_unpublish(from_name, to_si.shr_container);
596 679 smb_shr_publish(to_name, to_si.shr_container);
597 680
598 681 return (NERR_Success);
599 682 }
600 683
601 684 /*
602 685 * Load the information for the specified share into the supplied share
603 686 * info structure.
604 687 *
605 688 * First looks up the cache to see if the specified share exists, if there
606 689 * is a miss then it looks up sharemgr.
607 690 */
608 691 uint32_t
609 692 smb_shr_get(char *sharename, smb_share_t *si)
610 693 {
611 694 uint32_t status;
612 695
613 696 if (sharename == NULL || *sharename == '\0')
614 697 return (NERR_NetNameNotFound);
615 698
616 699 if ((status = smb_shr_lookup(sharename, si)) == NERR_Success)
617 700 return (status);
618 701
619 702 if ((status = smb_shr_sa_loadbyname(sharename)) == NERR_Success)
620 703 status = smb_shr_lookup(sharename, si);
|
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
621 704
622 705 return (status);
623 706 }
624 707
625 708 /*
626 709 * Modifies an existing share. Properties that can be modified are:
627 710 *
628 711 * o comment
629 712 * o AD container
630 713 * o host access
631 - * o abe
714 + * o flags
632 715 */
633 716 uint32_t
634 717 smb_shr_modify(smb_share_t *new_si)
635 718 {
719 + smb_share_t old_si;
636 720 smb_share_t *si;
637 721 boolean_t adc_changed = B_FALSE;
638 - char old_container[MAXPATHLEN];
722 + boolean_t quota_flag_changed = B_FALSE;
639 723 uint32_t access, flag;
640 724 nvlist_t *shrlist;
641 725
642 726 assert(new_si != NULL);
643 727
644 728 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) != NERR_Success)
645 729 return (NERR_InternalError);
646 730
647 731 if ((si = smb_shr_cache_findent(new_si->shr_name)) == NULL) {
648 732 smb_shr_cache_unlock();
649 733 return (NERR_NetNameNotFound);
650 734 }
651 735
652 736 if (STYPE_ISIPC(si->shr_type)) {
653 737 /* IPC$ share cannot be modified */
654 738 smb_shr_cache_unlock();
655 739 return (ERROR_ACCESS_DENIED);
656 740 }
657 741
742 + /*
743 + * Keep a copy of what the share entry looks like before we
744 + * modify it. We need this for things like unpublishing
745 + * from the old share container, removing the quota dir.
746 + */
747 + bcopy(si, &old_si, sizeof (old_si));
748 +
749 + /* Share comment */
658 750 (void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
659 751
660 - adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
661 - if (adc_changed) {
662 - /* save current container - needed for unpublishing */
663 - (void) strlcpy(old_container, si->shr_container,
664 - sizeof (old_container));
665 - (void) strlcpy(si->shr_container, new_si->shr_container,
666 - sizeof (si->shr_container));
667 - }
752 + /* Container */
753 + (void) strlcpy(si->shr_container, new_si->shr_container,
754 + sizeof (si->shr_container));
755 + adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0);
668 756
669 757 flag = (new_si->shr_flags & SMB_SHRF_ABE);
670 758 si->shr_flags &= ~SMB_SHRF_ABE;
671 759 si->shr_flags |= flag;
672 760
673 761 flag = (new_si->shr_flags & SMB_SHRF_CATIA);
674 762 si->shr_flags &= ~SMB_SHRF_CATIA;
675 763 si->shr_flags |= flag;
676 764
677 765 flag = (new_si->shr_flags & SMB_SHRF_GUEST_OK);
678 766 si->shr_flags &= ~SMB_SHRF_GUEST_OK;
679 767 si->shr_flags |= flag;
680 768
681 769 flag = (new_si->shr_flags & SMB_SHRF_DFSROOT);
682 770 si->shr_flags &= ~SMB_SHRF_DFSROOT;
683 771 si->shr_flags |= flag;
684 772
773 + flag = (new_si->shr_flags & SMB_SHRF_CA);
774 + si->shr_flags &= ~SMB_SHRF_CA;
775 + si->shr_flags |= flag;
776 +
777 + flag = (new_si->shr_flags & SMB_SHRF_FSO);
778 + si->shr_flags &= ~SMB_SHRF_FSO;
779 + si->shr_flags |= flag;
780 +
781 + flag = (new_si->shr_flags & SMB_SHRF_QUOTAS);
782 + si->shr_flags &= ~SMB_SHRF_QUOTAS;
783 + si->shr_flags |= flag;
784 + if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS)
785 + quota_flag_changed = B_TRUE;
786 +
685 787 flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
686 788 si->shr_flags &= ~SMB_SHRF_CSC_MASK;
687 789 si->shr_flags |= flag;
688 790
689 791 access = (new_si->shr_flags & SMB_SHRF_ACC_ALL);
690 792 si->shr_flags &= ~SMB_SHRF_ACC_ALL;
691 793 si->shr_flags |= access;
692 794
795 + si->shr_encrypt = new_si->shr_encrypt;
796 +
693 797 if (access & SMB_SHRF_ACC_NONE)
694 798 (void) strlcpy(si->shr_access_none, new_si->shr_access_none,
695 799 sizeof (si->shr_access_none));
696 800
697 801 if (access & SMB_SHRF_ACC_RO)
698 802 (void) strlcpy(si->shr_access_ro, new_si->shr_access_ro,
699 803 sizeof (si->shr_access_ro));
700 804
701 805 if (access & SMB_SHRF_ACC_RW)
702 806 (void) strlcpy(si->shr_access_rw, new_si->shr_access_rw,
703 807 sizeof (si->shr_access_rw));
704 808
705 809 smb_shr_cache_unlock();
706 810
707 811 if (smb_shr_encode(si, &shrlist) == 0) {
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
708 812 (void) smb_kmod_unshare(shrlist);
709 813 nvlist_free(shrlist);
710 814
711 815 if (smb_shr_encode(new_si, &shrlist) == 0) {
712 816 (void) smb_kmod_share(shrlist);
713 817 nvlist_free(shrlist);
714 818 }
715 819 }
716 820
717 821 if (adc_changed) {
718 - smb_shr_unpublish(new_si->shr_name, old_container);
822 + smb_shr_unpublish(old_si.shr_name, old_si.shr_container);
719 823 smb_shr_publish(new_si->shr_name, new_si->shr_container);
720 824 }
721 825
826 + /* The following required privileges we dropped. */
827 + if (quota_flag_changed && smb_proc_takesem() == 0) {
828 +
829 + (void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
830 + PRIV_FILE_DAC_READ,
831 + PRIV_FILE_DAC_SEARCH,
832 + PRIV_FILE_DAC_WRITE,
833 + NULL);
834 +
835 + smb_shr_zfs_remove(&old_si);
836 + smb_shr_zfs_add(si);
837 +
838 + (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
839 + PRIV_FILE_DAC_READ,
840 + PRIV_FILE_DAC_SEARCH,
841 + PRIV_FILE_DAC_WRITE,
842 + NULL);
843 +
844 + smb_proc_givesem();
845 + }
846 +
722 847 return (NERR_Success);
723 848 }
724 849
725 850 /*
726 851 * smb_shr_exists
727 852 *
728 853 * Returns B_TRUE if the share exists. Otherwise returns B_FALSE
729 854 */
730 855 boolean_t
731 856 smb_shr_exists(char *sharename)
732 857 {
733 858 boolean_t exists = B_FALSE;
734 859
735 860 if (sharename == NULL || *sharename == '\0')
736 861 return (B_FALSE);
737 862
738 863 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
739 864 exists = (smb_shr_cache_findent(sharename) != NULL);
740 865 smb_shr_cache_unlock();
741 866 }
742 867
743 868 return (exists);
744 869 }
745 870
746 871 /*
747 872 * If the shared directory does not begin with a /, one will be
748 873 * inserted as a prefix. If ipaddr is not zero, then also return
749 874 * information about access based on the host level access lists, if
750 875 * present. Also return access check if there is an IP address and
751 876 * shr_accflags.
752 877 *
753 878 * The value of smb_chk_hostaccess is checked for an access match.
754 879 * -1 is wildcard match
755 880 * 0 is no match
756 881 * 1 is match
757 882 *
758 883 * Precedence is none is checked first followed by ro then rw if
759 884 * needed. If x is wildcard (< 0) then check to see if the other
760 885 * values are a match. If a match, that wins.
761 886 */
762 887 uint32_t
763 888 smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list,
764 889 char *rw_list, uint32_t flag)
765 890 {
766 891 uint32_t acc = SMB_SHRF_ACC_NONE;
767 892 int none = 0;
768 893 int ro = 0;
769 894 int rw = 0;
770 895
771 896 if (!smb_inet_iszero(ipaddr)) {
772 897 if ((flag & SMB_SHRF_ACC_NONE) != 0)
773 898 none = smb_chk_hostaccess(ipaddr, none_list);
774 899 if ((flag & SMB_SHRF_ACC_RO) != 0)
775 900 ro = smb_chk_hostaccess(ipaddr, ro_list);
776 901 if ((flag & SMB_SHRF_ACC_RW) != 0)
777 902 rw = smb_chk_hostaccess(ipaddr, rw_list);
778 903
779 904 /* make first pass to get basic value */
780 905 if (none != 0)
781 906 acc = SMB_SHRF_ACC_NONE;
782 907 else if (ro != 0)
783 908 acc = SMB_SHRF_ACC_RO;
784 909 else if (rw != 0)
785 910 acc = SMB_SHRF_ACC_RW;
786 911
787 912 /* make second pass to handle '*' case */
788 913 if (none < 0) {
789 914 acc = SMB_SHRF_ACC_NONE;
790 915 if (ro > 0)
791 916 acc = SMB_SHRF_ACC_RO;
792 917 else if (rw > 0)
793 918 acc = SMB_SHRF_ACC_RW;
794 919 } else if (ro < 0) {
795 920 acc = SMB_SHRF_ACC_RO;
796 921 if (none > 0)
797 922 acc = SMB_SHRF_ACC_NONE;
798 923 else if (rw > 0)
799 924 acc = SMB_SHRF_ACC_RW;
800 925 } else if (rw < 0) {
801 926 acc = SMB_SHRF_ACC_RW;
802 927 if (none > 0)
803 928 acc = SMB_SHRF_ACC_NONE;
804 929 else if (ro > 0)
805 930 acc = SMB_SHRF_ACC_RO;
806 931 }
807 932 }
808 933
809 934 return (acc);
810 935 }
811 936
812 937 /*
813 938 * smb_shr_is_special
814 939 *
815 940 * Special share reserved for interprocess communication (IPC$) or
816 941 * remote administration of the server (ADMIN$). Can also refer to
817 942 * administrative shares such as C$, D$, E$, and so forth.
818 943 */
819 944 int
820 945 smb_shr_is_special(char *sharename)
821 946 {
822 947 int len;
823 948
824 949 if (sharename == NULL)
825 950 return (0);
826 951
827 952 if ((len = strlen(sharename)) == 0)
828 953 return (0);
829 954
830 955 if (sharename[len - 1] == '$')
831 956 return (STYPE_SPECIAL);
832 957
833 958 return (0);
834 959 }
835 960
836 961 /*
837 962 * smb_shr_is_restricted
838 963 *
839 964 * Check whether or not there is a restriction on a share. Restricted
840 965 * shares are generally STYPE_SPECIAL, for example, IPC$. All the
841 966 * administration share names are restricted: C$, D$ etc. Returns B_TRUE
842 967 * if the share is restricted. Otherwise B_FALSE is returned to indicate
843 968 * that there are no restrictions.
844 969 */
845 970 boolean_t
846 971 smb_shr_is_restricted(char *sharename)
847 972 {
848 973 static char *restricted[] = {
849 974 "IPC$"
850 975 };
851 976
852 977 int i;
853 978
854 979 if (sharename == NULL)
855 980 return (B_FALSE);
856 981
857 982 for (i = 0; i < sizeof (restricted)/sizeof (restricted[0]); i++) {
858 983 if (smb_strcasecmp(restricted[i], sharename, 0) == 0)
859 984 return (B_TRUE);
860 985 }
861 986
862 987 return (smb_shr_is_admin(sharename));
863 988 }
864 989
865 990 /*
866 991 * smb_shr_is_admin
867 992 *
868 993 * Check whether or not access to the share should be restricted to
869 994 * administrators. This is a bit of a hack because what we're doing
870 995 * is checking for the default admin shares: C$, D$ etc.. There are
871 996 * other shares that have restrictions: see smb_shr_is_restricted().
872 997 *
873 998 * Returns B_TRUE if the shares is an admin share. Otherwise B_FALSE
874 999 * is returned to indicate that there are no restrictions.
875 1000 */
876 1001 boolean_t
877 1002 smb_shr_is_admin(char *sharename)
878 1003 {
879 1004 if (sharename == NULL)
880 1005 return (B_FALSE);
881 1006
882 1007 if (strlen(sharename) == 2 &&
883 1008 smb_isalpha(sharename[0]) && sharename[1] == '$') {
884 1009 return (B_TRUE);
885 1010 }
886 1011
887 1012 return (B_FALSE);
888 1013 }
889 1014
890 1015 char
891 1016 smb_shr_drive_letter(const char *path)
892 1017 {
893 1018 smb_transient_t *ts;
894 1019 int i;
895 1020
896 1021 if (path == NULL)
897 1022 return ('\0');
898 1023
899 1024 for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) {
900 1025 ts = &tshare[i];
901 1026
902 1027 if (ts->path == NULL)
903 1028 continue;
904 1029
905 1030 if (strcasecmp(ts->path, path) == 0)
906 1031 return (ts->drive);
907 1032 }
908 1033
909 1034 return ('\0');
910 1035 }
911 1036
912 1037 /*
913 1038 * Returns true if the specified directory is empty,
914 1039 * otherwise returns false.
915 1040 */
916 1041 static boolean_t
917 1042 smb_shr_is_empty(const char *path)
918 1043 {
919 1044 DIR *dirp;
920 1045 struct dirent *dp;
921 1046
922 1047 if (path == NULL)
923 1048 return (B_TRUE);
924 1049
925 1050 if ((dirp = opendir(path)) == NULL)
926 1051 return (B_TRUE);
927 1052
928 1053 while ((dp = readdir(dirp)) != NULL) {
929 1054 if (!smb_shr_is_dot_or_dotdot(dp->d_name))
930 1055 return (B_FALSE);
931 1056 }
932 1057
933 1058 (void) closedir(dirp);
934 1059 return (B_TRUE);
935 1060 }
936 1061
937 1062 /*
938 1063 * Returns true if name is "." or "..", otherwise returns false.
939 1064 */
940 1065 static boolean_t
941 1066 smb_shr_is_dot_or_dotdot(const char *name)
942 1067 {
943 1068 if (*name != '.')
944 1069 return (B_FALSE);
945 1070
946 1071 if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0'))
947 1072 return (B_TRUE);
948 1073
949 1074 return (B_FALSE);
950 1075 }
951 1076
952 1077 /*
953 1078 * smb_shr_get_realpath
954 1079 *
955 1080 * Derive the real path for a share from the path provided by a client.
956 1081 * For instance, the real path of C:\ may be /cvol or the real path of
957 1082 * F:\home may be /vol1/home.
958 1083 *
959 1084 * clntpath - path provided by the Windows client is in the
960 1085 * format of <drive letter>:\<dir>
961 1086 * realpath - path that will be stored as the directory field of
962 1087 * the smb_share_t structure of the share.
963 1088 * maxlen - maximum length of the realpath buffer
964 1089 *
965 1090 * Return LAN Manager network error code.
966 1091 */
967 1092 uint32_t
968 1093 smb_shr_get_realpath(const char *clntpath, char *realpath, int maxlen)
969 1094 {
970 1095 const char *p;
971 1096 int len;
972 1097
973 1098 if ((p = strchr(clntpath, ':')) != NULL)
974 1099 ++p;
975 1100 else
976 1101 p = clntpath;
977 1102
978 1103 (void) strlcpy(realpath, p, maxlen);
979 1104 (void) strcanon(realpath, "/\\");
980 1105 (void) strsubst(realpath, '\\', '/');
981 1106
982 1107 len = strlen(realpath);
983 1108 if ((len > 1) && (realpath[len - 1] == '/'))
984 1109 realpath[len - 1] = '\0';
985 1110
986 1111 return (NERR_Success);
987 1112 }
988 1113
989 1114 void
990 1115 smb_shr_list(int offset, smb_shrlist_t *list)
991 1116 {
992 1117 smb_shriter_t iterator;
993 1118 smb_share_t *si;
994 1119 int n = 0;
995 1120
996 1121 bzero(list, sizeof (smb_shrlist_t));
997 1122 smb_shr_iterinit(&iterator);
998 1123
999 1124 while ((si = smb_shr_iterate(&iterator)) != NULL) {
1000 1125 if (--offset > 0)
1001 1126 continue;
1002 1127
1003 1128 if ((si->shr_flags & SMB_SHRF_TRANS) &&
1004 1129 (!STYPE_ISIPC(si->shr_type))) {
1005 1130 bcopy(si, &list->sl_shares[n], sizeof (smb_share_t));
1006 1131 if (++n == LMSHARES_PER_REQUEST)
1007 1132 break;
1008 1133 }
1009 1134 }
1010 1135
1011 1136 list->sl_cnt = n;
1012 1137 }
1013 1138
1014 1139 /*
1015 1140 * Executes the map/unmap command associated with a share.
1016 1141 *
1017 1142 * Returns 0 on success. Otherwise non-zero for errors.
1018 1143 */
1019 1144 int
1020 1145 smb_shr_exec(smb_shr_execinfo_t *subs)
1021 1146 {
1022 1147 char cmd[MAXPATHLEN], **cmd_tokens, *path, *ptr;
1023 1148 pid_t child_pid;
1024 1149 int child_status;
1025 1150 struct sigaction pact, cact;
1026 1151 smb_share_t si;
1027 1152
1028 1153 if (smb_shr_get(subs->e_sharename, &si) != 0)
1029 1154 return (-1);
1030 1155
1031 1156 *cmd = '\0';
1032 1157
1033 1158 (void) mutex_lock(&smb_shr_exec_mtx);
1034 1159
1035 1160 switch (subs->e_type) {
1036 1161 case SMB_EXEC_MAP:
1037 1162 (void) strlcpy(cmd, smb_shr_exec_map, sizeof (cmd));
1038 1163 break;
1039 1164 case SMB_EXEC_UNMAP:
1040 1165 (void) strlcpy(cmd, smb_shr_exec_unmap, sizeof (cmd));
1041 1166 break;
1042 1167 default:
1043 1168 (void) mutex_unlock(&smb_shr_exec_mtx);
1044 1169 return (-1);
1045 1170 }
1046 1171
1047 1172 (void) mutex_unlock(&smb_shr_exec_mtx);
1048 1173
1049 1174 if (*cmd == '\0')
1050 1175 return (0);
1051 1176
1052 1177 if (smb_proc_takesem() != 0)
1053 1178 return (-1);
1054 1179
1055 1180 pact.sa_handler = smb_shr_sig_child;
1056 1181 pact.sa_flags = 0;
1057 1182 (void) sigemptyset(&pact.sa_mask);
1058 1183 sigaction(SIGCHLD, &pact, NULL);
1059 1184
1060 1185 (void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1061 1186
1062 1187 if ((child_pid = fork()) == -1) {
1063 1188 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1064 1189 smb_proc_givesem();
1065 1190 return (-1);
1066 1191 }
1067 1192
1068 1193 if (child_pid == 0) {
1069 1194
1070 1195 /* child process */
1071 1196
1072 1197 cact.sa_handler = smb_shr_sig_abnormal_term;
1073 1198 cact.sa_flags = 0;
1074 1199 (void) sigemptyset(&cact.sa_mask);
1075 1200 sigaction(SIGTERM, &cact, NULL);
1076 1201 sigaction(SIGABRT, &cact, NULL);
1077 1202 sigaction(SIGSEGV, &cact, NULL);
1078 1203
1079 1204 if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_EXEC,
1080 1205 PRIV_FILE_DAC_EXECUTE, NULL))
1081 1206 _exit(-1);
1082 1207
1083 1208 if (smb_shr_enable_all_privs())
1084 1209 _exit(-1);
1085 1210
1086 1211 smb_proc_initsem();
1087 1212
1088 1213 (void) trim_whitespace(cmd);
1089 1214 (void) strcanon(cmd, " ");
1090 1215
1091 1216 if ((cmd_tokens = smb_shr_tokenize_cmd(cmd)) != NULL) {
1092 1217
1093 1218 if (smb_shr_expand_subs(cmd_tokens, &si, subs) != 0) {
1094 1219 free(cmd_tokens[0]);
1095 1220 free(cmd_tokens);
1096 1221 _exit(-1);
1097 1222 }
1098 1223
1099 1224 ptr = cmd;
1100 1225 path = strsep(&ptr, " ");
1101 1226
1102 1227 (void) execv(path, cmd_tokens);
1103 1228 }
1104 1229
1105 1230 _exit(-1);
1106 1231 }
1107 1232
1108 1233 (void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
1109 1234 smb_proc_givesem();
1110 1235
1111 1236 /* parent process */
1112 1237
1113 1238 while (waitpid(child_pid, &child_status, 0) < 0) {
1114 1239 if (errno != EINTR)
1115 1240 break;
1116 1241
1117 1242 /* continue if waitpid got interrupted by a signal */
1118 1243 errno = 0;
1119 1244 continue;
1120 1245 }
1121 1246
1122 1247 if (WIFEXITED(child_status))
1123 1248 return (WEXITSTATUS(child_status));
1124 1249
1125 1250 return (child_status);
1126 1251 }
1127 1252
1128 1253 /*
1129 1254 * Locking for process-wide settings (i.e. privileges)
1130 1255 */
1131 1256 void
1132 1257 smb_proc_initsem(void)
1133 1258 {
1134 1259 (void) sema_init(&smb_proc_sem, 1, USYNC_THREAD, NULL);
1135 1260 }
1136 1261
1137 1262 int
1138 1263 smb_proc_takesem(void)
1139 1264 {
1140 1265 return (sema_wait(&smb_proc_sem));
1141 1266 }
1142 1267
1143 1268 void
1144 1269 smb_proc_givesem(void)
1145 1270 {
1146 1271 (void) sema_post(&smb_proc_sem);
1147 1272 }
1148 1273
1149 1274 /*
1150 1275 * ============================================
1151 1276 * Private helper/utility functions
1152 1277 * ============================================
1153 1278 */
1154 1279
1155 1280 /*
1156 1281 * Looks up the given share in the cache and return
1157 1282 * the info in 'si'
1158 1283 */
1159 1284 static uint32_t
1160 1285 smb_shr_lookup(char *sharename, smb_share_t *si)
1161 1286 {
1162 1287 smb_share_t *cached_si;
1163 1288 uint32_t status = NERR_NetNameNotFound;
1164 1289
1165 1290 if (sharename == NULL || *sharename == '\0')
1166 1291 return (NERR_NetNameNotFound);
1167 1292 if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
1168 1293 cached_si = smb_shr_cache_findent(sharename);
1169 1294 if (cached_si != NULL) {
1170 1295 bcopy(cached_si, si, sizeof (smb_share_t));
1171 1296 status = NERR_Success;
1172 1297 }
1173 1298
1174 1299 smb_shr_cache_unlock();
1175 1300 }
1176 1301 return (status);
1177 1302 }
1178 1303
1179 1304 /*
1180 1305 * Add IPC$ or Admin shares to the cache upon startup.
1181 1306 */
1182 1307 static uint32_t
1183 1308 smb_shr_add_transient(char *name, char *cmnt, char *path)
1184 1309 {
1185 1310 smb_share_t trans;
1186 1311 uint32_t status = NERR_InternalError;
1187 1312
1188 1313 if (name == NULL)
1189 1314 return (status);
1190 1315
1191 1316 bzero(&trans, sizeof (smb_share_t));
1192 1317 (void) strlcpy(trans.shr_name, name, MAXNAMELEN);
1193 1318 if (cmnt)
1194 1319 (void) strlcpy(trans.shr_cmnt, cmnt, SMB_SHARE_CMNT_MAX);
1195 1320
1196 1321 if (path)
1197 1322 (void) strlcpy(trans.shr_path, path, MAXPATHLEN);
1198 1323
1199 1324 if (strcasecmp(name, "IPC$") == 0)
1200 1325 trans.shr_type = STYPE_IPC;
1201 1326
1202 1327 trans.shr_flags = SMB_SHRF_TRANS;
1203 1328
1204 1329 if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
1205 1330 status = smb_shr_cache_addent(&trans);
1206 1331 smb_shr_cache_unlock();
1207 1332 }
1208 1333
1209 1334 return (status);
1210 1335 }
1211 1336
1212 1337 /*
1213 1338 * ============================================
1214 1339 * Cache management functions
1215 1340 *
1216 1341 * All cache functions are private
1217 1342 * ============================================
1218 1343 */
1219 1344
1220 1345 /*
1221 1346 * Create the share cache (hash table).
1222 1347 */
1223 1348 static uint32_t
1224 1349 smb_shr_cache_create(void)
1225 1350 {
1226 1351 uint32_t status = NERR_Success;
1227 1352
1228 1353 (void) mutex_lock(&smb_shr_cache.sc_mtx);
1229 1354 switch (smb_shr_cache.sc_state) {
1230 1355 case SMB_SHR_CACHE_STATE_NONE:
1231 1356 smb_shr_cache.sc_cache = ht_create_table(SMB_SHR_HTAB_SZ,
1232 1357 MAXNAMELEN, 0);
1233 1358 if (smb_shr_cache.sc_cache == NULL) {
1234 1359 status = NERR_InternalError;
1235 1360 break;
1236 1361 }
1237 1362
1238 1363 (void) ht_register_callback(smb_shr_cache.sc_cache,
1239 1364 smb_shr_cache_freent);
1240 1365 smb_shr_cache.sc_nops = 0;
1241 1366 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_CREATED;
1242 1367 break;
1243 1368
1244 1369 default:
1245 1370 assert(0);
1246 1371 status = NERR_InternalError;
1247 1372 break;
1248 1373 }
1249 1374 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1250 1375
1251 1376 return (status);
1252 1377 }
1253 1378
1254 1379 /*
1255 1380 * Destroy the share cache (hash table).
1256 1381 * Wait for inflight/pending operations to finish or abort before
1257 1382 * destroying the cache.
1258 1383 */
1259 1384 static void
1260 1385 smb_shr_cache_destroy(void)
1261 1386 {
1262 1387 (void) mutex_lock(&smb_shr_cache.sc_mtx);
1263 1388 if (smb_shr_cache.sc_state == SMB_SHR_CACHE_STATE_CREATED) {
1264 1389 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_DESTROYING;
1265 1390 while (smb_shr_cache.sc_nops > 0)
1266 1391 (void) cond_wait(&smb_shr_cache.sc_cv,
1267 1392 &smb_shr_cache.sc_mtx);
1268 1393
1269 1394 smb_shr_cache.sc_cache = NULL;
1270 1395 smb_shr_cache.sc_state = SMB_SHR_CACHE_STATE_NONE;
1271 1396 }
1272 1397 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1273 1398 }
1274 1399
1275 1400 /*
1276 1401 * If the cache is in "created" state, lock the cache for read
1277 1402 * or read/write based on the specified mode.
1278 1403 *
1279 1404 * Whenever a lock is granted, the number of inflight cache
1280 1405 * operations is incremented.
1281 1406 */
1282 1407 static uint32_t
1283 1408 smb_shr_cache_lock(int mode)
1284 1409 {
1285 1410 (void) mutex_lock(&smb_shr_cache.sc_mtx);
1286 1411 if (smb_shr_cache.sc_state != SMB_SHR_CACHE_STATE_CREATED) {
1287 1412 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1288 1413 return (NERR_InternalError);
1289 1414 }
1290 1415 smb_shr_cache.sc_nops++;
1291 1416 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1292 1417
1293 1418 /*
1294 1419 * Lock has to be taken outside the mutex otherwise
1295 1420 * there could be a deadlock
1296 1421 */
1297 1422 if (mode == SMB_SHR_CACHE_RDLOCK)
1298 1423 (void) rw_rdlock(&smb_shr_cache.sc_cache_lck);
1299 1424 else
1300 1425 (void) rw_wrlock(&smb_shr_cache.sc_cache_lck);
1301 1426
1302 1427 return (NERR_Success);
1303 1428 }
1304 1429
1305 1430 /*
1306 1431 * Decrement the number of inflight operations and then unlock.
1307 1432 */
1308 1433 static void
1309 1434 smb_shr_cache_unlock(void)
1310 1435 {
1311 1436 (void) mutex_lock(&smb_shr_cache.sc_mtx);
1312 1437 assert(smb_shr_cache.sc_nops > 0);
1313 1438 smb_shr_cache.sc_nops--;
1314 1439 (void) cond_broadcast(&smb_shr_cache.sc_cv);
1315 1440 (void) mutex_unlock(&smb_shr_cache.sc_mtx);
1316 1441
1317 1442 (void) rw_unlock(&smb_shr_cache.sc_cache_lck);
1318 1443 }
1319 1444
1320 1445 /*
1321 1446 * Return the total number of shares
1322 1447 */
1323 1448 static int
1324 1449 smb_shr_cache_count(void)
1325 1450 {
1326 1451 return (ht_get_total_items(smb_shr_cache.sc_cache));
1327 1452 }
1328 1453
1329 1454 /*
1330 1455 * looks up the given share name in the cache and if it
1331 1456 * finds a match returns a pointer to the cached entry.
1332 1457 * Note that since a pointer is returned this function
1333 1458 * MUST be protected by smb_shr_cache_lock/unlock pair
1334 1459 */
1335 1460 static smb_share_t *
1336 1461 smb_shr_cache_findent(char *sharename)
1337 1462 {
1338 1463 HT_ITEM *item;
1339 1464
1340 1465 (void) smb_strlwr(sharename);
1341 1466 item = ht_find_item(smb_shr_cache.sc_cache, sharename);
1342 1467 if (item && item->hi_data)
1343 1468 return ((smb_share_t *)item->hi_data);
1344 1469
1345 1470 return (NULL);
1346 1471 }
1347 1472
1348 1473 /*
1349 1474 * Return a pointer to the first/next entry in
1350 1475 * the cache based on the given iterator.
1351 1476 *
1352 1477 * Calls to this function MUST be protected by
1353 1478 * smb_shr_cache_lock/unlock.
1354 1479 */
1355 1480 static smb_share_t *
1356 1481 smb_shr_cache_iterate(smb_shriter_t *shi)
1357 1482 {
1358 1483 HT_ITEM *item;
1359 1484
1360 1485 if (shi->si_first) {
1361 1486 item = ht_findfirst(smb_shr_cache.sc_cache, &shi->si_hashiter);
1362 1487 shi->si_first = B_FALSE;
1363 1488 } else {
1364 1489 item = ht_findnext(&shi->si_hashiter);
1365 1490 }
1366 1491
1367 1492 if (item && item->hi_data)
1368 1493 return ((smb_share_t *)item->hi_data);
1369 1494
1370 1495 return (NULL);
1371 1496 }
1372 1497
1373 1498 /*
1374 1499 * Add the specified share to the cache. Memory needs to be allocated
1375 1500 * for the cache entry and the passed information is copied to the
1376 1501 * allocated space.
1377 1502 */
1378 1503 static uint32_t
1379 1504 smb_shr_cache_addent(smb_share_t *si)
1380 1505 {
1381 1506 smb_share_t *cache_ent;
1382 1507 uint32_t status = NERR_Success;
1383 1508
1384 1509 if ((cache_ent = malloc(sizeof (smb_share_t))) == NULL)
1385 1510 return (ERROR_NOT_ENOUGH_MEMORY);
1386 1511
1387 1512 (void) smb_strlwr(si->shr_name);
1388 1513
1389 1514 si->shr_type |= smb_shr_is_special(cache_ent->shr_name);
1390 1515
1391 1516 if (smb_shr_is_admin(cache_ent->shr_name))
1392 1517 si->shr_flags |= SMB_SHRF_ADMIN;
1393 1518
1394 1519 bcopy(si, cache_ent, sizeof (smb_share_t));
1395 1520
1396 1521 if (si->shr_flags & SMB_SHRF_AUTOHOME)
1397 1522 cache_ent->shr_refcnt = 1;
1398 1523
1399 1524 if (ht_add_item(smb_shr_cache.sc_cache, cache_ent->shr_name, cache_ent)
1400 1525 == NULL) {
1401 1526 syslog(LOG_DEBUG, "share: %s: cache update failed",
1402 1527 cache_ent->shr_name);
1403 1528 free(cache_ent);
1404 1529 status = NERR_InternalError;
1405 1530 }
1406 1531
1407 1532 return (status);
1408 1533 }
1409 1534
1410 1535 /*
1411 1536 * Delete the specified share from the cache.
1412 1537 */
1413 1538 static void
1414 1539 smb_shr_cache_delent(char *sharename)
1415 1540 {
1416 1541 (void) smb_strlwr(sharename);
1417 1542 (void) ht_remove_item(smb_shr_cache.sc_cache, sharename);
1418 1543 }
1419 1544
1420 1545 /*
1421 1546 * Call back to free the given cache entry.
1422 1547 */
1423 1548 static void
1424 1549 smb_shr_cache_freent(HT_ITEM *item)
1425 1550 {
1426 1551 if (item && item->hi_data)
1427 1552 free(item->hi_data);
1428 1553 }
|
↓ open down ↓ |
697 lines elided |
↑ open up ↑ |
1429 1554
1430 1555 /*
1431 1556 * ============================================
1432 1557 * Interfaces to sharemgr
1433 1558 *
1434 1559 * All functions in this section are private
1435 1560 * ============================================
1436 1561 */
1437 1562
1438 1563 /*
1439 - * Load shares from sharemgr
1564 + * Loads the SMB shares, from sharemgr, then:
1565 + * - calls smb_shr_add which:
1566 + * - adds the share into the share cache
1567 + * - adds the share into in-kernel kshare table
1568 + * - publishes the share in ADS
1569 + * - updates the share list in sharefs/sharetab
1440 1570 */
1441 1571 /*ARGSUSED*/
1442 1572 void *
1443 1573 smb_shr_load(void *args)
1444 1574 {
1445 1575 sa_handle_t handle;
1446 1576 sa_group_t group, subgroup;
1447 1577 char *gstate;
1448 1578 boolean_t gdisabled;
1449 1579
1450 - (void) mutex_lock(&smb_shr_exec_mtx);
1451 - (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1452 - MAXPATHLEN);
1453 - (void) mutex_unlock(&smb_shr_exec_mtx);
1580 + smb_shr_load_execinfo();
1454 1581
1455 1582 if ((handle = smb_shr_sa_enter()) == NULL) {
1456 1583 syslog(LOG_ERR, "smb_shr_load: load failed");
1457 1584 return (NULL);
1458 1585 }
1459 1586
1460 1587 for (group = sa_get_group(handle, NULL);
1461 1588 group != NULL; group = sa_get_next_group(group)) {
1462 1589 gstate = sa_get_group_attr(group, "state");
1463 1590 if (gstate == NULL)
1464 1591 continue;
1465 1592
1466 1593 gdisabled = (strcasecmp(gstate, "disabled") == 0);
1467 1594 sa_free_attr_string(gstate);
1468 1595 if (gdisabled)
1469 1596 continue;
1470 1597
1471 1598 smb_shr_sa_loadgrp(group);
1472 1599
1473 1600 for (subgroup = sa_get_sub_group(group);
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1474 1601 subgroup != NULL;
1475 1602 subgroup = sa_get_next_group(subgroup)) {
1476 1603 smb_shr_sa_loadgrp(subgroup);
1477 1604 }
1478 1605
1479 1606 }
1480 1607 smb_shr_sa_exit();
1481 1608 return (NULL);
1482 1609 }
1483 1610
1611 +void
1612 +smb_shr_load_execinfo()
1613 +{
1614 + (void) mutex_lock(&smb_shr_exec_mtx);
1615 + (void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
1616 + MAXPATHLEN);
1617 + (void) mutex_unlock(&smb_shr_exec_mtx);
1618 +}
1619 +
1484 1620 /*
1621 + * Handles disabling shares in sharefs when stoping smbd
1622 + */
1623 +void
1624 +smb_shr_unload()
1625 +{
1626 + smb_shriter_t iterator;
1627 + smb_share_t *si;
1628 + sa_handle_t handle;
1629 + int rc;
1630 +
1631 + if ((handle = smb_shr_sa_enter()) == NULL) {
1632 + syslog(LOG_ERR, "smb_shr_unload: failed");
1633 + return;
1634 + }
1635 +
1636 + smb_shr_iterinit(&iterator);
1637 +
1638 + while ((si = smb_shr_iterate(&iterator)) != NULL) {
1639 +
1640 + /* Skip transient shares, IPC$, ... */
1641 + if ((si->shr_flags & SMB_SHRF_TRANS) ||
1642 + STYPE_ISIPC(si->shr_type))
1643 + continue;
1644 +
1645 + rc = sa_delete_sharetab(handle, si->shr_path, "smb");
1646 + if (rc) {
1647 + syslog(LOG_ERR,
1648 + "sharefs remove %s failed, rc=%d, err=%d",
1649 + si->shr_path, rc, errno);
1650 + }
1651 + }
1652 + smb_shr_sa_exit();
1653 +}
1654 +
1655 +/*
1485 1656 * Load the shares contained in the specified group.
1486 1657 *
1487 1658 * Don't process groups on which the smb protocol is disabled.
1488 1659 * The top level ZFS group won't have the smb protocol enabled
1489 1660 * but sub-groups will.
1490 1661 *
1491 1662 * We will tolerate a limited number of errors and then give
1492 1663 * up on the current group. A typical error might be that the
1493 1664 * shared directory no longer exists.
1494 1665 */
1495 1666 static void
1496 1667 smb_shr_sa_loadgrp(sa_group_t group)
1497 1668 {
1498 1669 sa_share_t share;
1499 1670 sa_resource_t resource;
1500 1671 int error_count = 0;
1501 1672
1502 1673 if (sa_get_optionset(group, SMB_PROTOCOL_NAME) == NULL)
1503 1674 return;
1504 1675
1505 1676 for (share = sa_get_share(group, NULL);
1506 1677 share != NULL;
1507 1678 share = sa_get_next_share(share)) {
1508 1679 for (resource = sa_get_share_resource(share, NULL);
1509 1680 resource != NULL;
1510 1681 resource = sa_get_next_resource(resource)) {
1511 1682 if (smb_shr_sa_load(share, resource))
1512 1683 ++error_count;
1513 1684
1514 1685 if (error_count > SMB_SHR_ERROR_THRESHOLD)
1515 1686 break;
1516 1687 }
1517 1688
1518 1689 if (error_count > SMB_SHR_ERROR_THRESHOLD)
1519 1690 break;
1520 1691 }
1521 1692 }
1522 1693
1523 1694 /*
1524 1695 * Load a share definition from sharemgr and add it to the cache.
1525 1696 * If the share is already in the cache then it doesn't do anything.
1526 1697 *
1527 1698 * This function does not report duplicate shares as error since
|
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
1528 1699 * a share might have been added by smb_shr_get() while load is
1529 1700 * in progress.
1530 1701 */
1531 1702 static uint32_t
1532 1703 smb_shr_sa_load(sa_share_t share, sa_resource_t resource)
1533 1704 {
1534 1705 smb_share_t si;
1535 1706 char *sharename;
1536 1707 uint32_t status;
1537 1708 boolean_t loaded;
1709 + int rc;
1538 1710
1539 1711 if ((sharename = sa_get_resource_attr(resource, "name")) == NULL)
1540 1712 return (NERR_InternalError);
1541 1713
1542 1714 loaded = smb_shr_exists(sharename);
1543 1715 sa_free_attr_string(sharename);
1544 1716
1545 1717 if (loaded)
1546 1718 return (NERR_Success);
1547 1719
1548 1720 if ((status = smb_shr_sa_get(share, resource, &si)) != NERR_Success) {
1549 1721 syslog(LOG_DEBUG, "share: failed to load %s (%d)",
1550 1722 si.shr_name, status);
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
1551 1723 return (status);
1552 1724 }
1553 1725
1554 1726 status = smb_shr_add(&si);
1555 1727 if ((status != NERR_Success) && (status != NERR_DuplicateShare)) {
1556 1728 syslog(LOG_DEBUG, "share: failed to cache %s (%d)",
1557 1729 si.shr_name, status);
1558 1730 return (status);
1559 1731 }
1560 1732
1733 + rc = sa_update_sharetab(share, "smb");
1734 + if (rc) {
1735 + syslog(LOG_ERR, "sharefs add %s failed, rc=%d, err=%d",
1736 + sharename, rc, errno);
1737 + }
1738 +
1561 1739 return (NERR_Success);
1562 1740 }
1563 1741
1564 1742 static char *
1565 1743 smb_shr_sa_getprop(sa_optionset_t opts, char *propname)
1566 1744 {
1567 1745 sa_property_t prop;
1568 1746 char *val = NULL;
1569 1747
1570 1748 prop = sa_get_property(opts, propname);
1571 1749 if (prop != NULL)
1572 1750 val = sa_get_property_attr(prop, "value");
1573 1751
1574 1752 return (val);
1575 1753 }
1576 1754
1577 1755 /*
1578 1756 * Read the specified share information from sharemgr and return
1579 1757 * it in the given smb_share_t structure.
1580 1758 *
1581 1759 * Shares read from sharemgr are marked as permanent/persistent.
1582 1760 */
1583 1761 static uint32_t
1584 1762 smb_shr_sa_get(sa_share_t share, sa_resource_t resource, smb_share_t *si)
1585 1763 {
1586 1764 sa_optionset_t opts;
1587 1765 char *val = NULL;
1588 1766 char *path;
1589 1767 char *rname;
1590 1768
1591 1769 if ((path = sa_get_share_attr(share, "path")) == NULL)
1592 1770 return (NERR_InternalError);
1593 1771
1594 1772 if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
1595 1773 sa_free_attr_string(path);
1596 1774 return (NERR_InternalError);
1597 1775 }
1598 1776
1599 1777 bzero(si, sizeof (smb_share_t));
1600 1778 si->shr_flags = SMB_SHRF_PERM;
1601 1779
1602 1780 (void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
1603 1781 (void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
1604 1782 sa_free_attr_string(path);
1605 1783 sa_free_attr_string(rname);
1606 1784
1607 1785 val = sa_get_resource_description(resource);
1608 1786 if (val == NULL)
1609 1787 val = sa_get_share_description(share);
1610 1788
1611 1789 if (val != NULL) {
1612 1790 (void) strlcpy(si->shr_cmnt, val, sizeof (si->shr_cmnt));
1613 1791 sa_free_share_description(val);
1614 1792 }
1615 1793
1616 1794 opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
1617 1795 if (opts == NULL)
1618 1796 return (NERR_Success);
1619 1797
1620 1798 val = smb_shr_sa_getprop(opts, SHOPT_AD_CONTAINER);
1621 1799 if (val != NULL) {
1622 1800 (void) strlcpy(si->shr_container, val,
1623 1801 sizeof (si->shr_container));
1624 1802 free(val);
1625 1803 }
1626 1804
1627 1805 val = smb_shr_sa_getprop(opts, SHOPT_CATIA);
1628 1806 if (val != NULL) {
1629 1807 smb_shr_sa_setflag(val, si, SMB_SHRF_CATIA);
1630 1808 free(val);
1631 1809 }
1632 1810
1633 1811 val = smb_shr_sa_getprop(opts, SHOPT_ABE);
1634 1812 if (val != NULL) {
1635 1813 smb_shr_sa_setflag(val, si, SMB_SHRF_ABE);
1636 1814 free(val);
1637 1815 }
1638 1816
1639 1817 val = smb_shr_sa_getprop(opts, SHOPT_GUEST);
1640 1818 if (val != NULL) {
|
↓ open down ↓ |
70 lines elided |
↑ open up ↑ |
1641 1819 smb_shr_sa_setflag(val, si, SMB_SHRF_GUEST_OK);
1642 1820 free(val);
1643 1821 }
1644 1822
1645 1823 val = smb_shr_sa_getprop(opts, SHOPT_DFSROOT);
1646 1824 if (val != NULL) {
1647 1825 smb_shr_sa_setflag(val, si, SMB_SHRF_DFSROOT);
1648 1826 free(val);
1649 1827 }
1650 1828
1829 + val = smb_shr_sa_getprop(opts, SHOPT_CA);
1830 + if (val != NULL) {
1831 + smb_shr_sa_setflag(val, si, SMB_SHRF_CA);
1832 + free(val);
1833 + }
1834 +
1835 + val = smb_shr_sa_getprop(opts, SHOPT_FSO);
1836 + if (val != NULL) {
1837 + smb_shr_sa_setflag(val, si, SMB_SHRF_FSO);
1838 + free(val);
1839 + }
1840 +
1841 + val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS);
1842 + if (val != NULL) {
1843 + /* Turn the flag on or off */
1844 + smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS);
1845 + free(val);
1846 + } else {
1847 + /* Default for this is enabled. */
1848 + si->shr_flags |= SMB_SHRF_QUOTAS;
1849 + }
1850 +
1851 + val = smb_shr_sa_getprop(opts, SHOPT_ENCRYPT);
1852 + if (val != NULL) {
1853 + smb_cfg_set_require(val, &si->shr_encrypt);
1854 + free(val);
1855 + }
1856 +
1651 1857 val = smb_shr_sa_getprop(opts, SHOPT_CSC);
1652 1858 if (val != NULL) {
1653 1859 smb_shr_sa_csc_option(val, si);
1654 1860 free(val);
1655 1861 }
1656 1862
1657 1863 val = smb_shr_sa_getprop(opts, SHOPT_NONE);
1658 1864 if (val != NULL) {
1659 1865 (void) strlcpy(si->shr_access_none, val,
1660 1866 sizeof (si->shr_access_none));
1661 1867 free(val);
1662 1868 si->shr_flags |= SMB_SHRF_ACC_NONE;
1663 1869 }
1664 1870
1665 1871 val = smb_shr_sa_getprop(opts, SHOPT_RO);
1666 1872 if (val != NULL) {
1667 1873 (void) strlcpy(si->shr_access_ro, val,
1668 1874 sizeof (si->shr_access_ro));
1669 1875 free(val);
1670 1876 si->shr_flags |= SMB_SHRF_ACC_RO;
1671 1877 }
1672 1878
1673 1879 val = smb_shr_sa_getprop(opts, SHOPT_RW);
1674 1880 if (val != NULL) {
1675 1881 (void) strlcpy(si->shr_access_rw, val,
1676 1882 sizeof (si->shr_access_rw));
1677 1883 free(val);
1678 1884 si->shr_flags |= SMB_SHRF_ACC_RW;
1679 1885 }
1680 1886
1681 1887 sa_free_derived_optionset(opts);
1682 1888 return (NERR_Success);
1683 1889 }
1684 1890
1685 1891 /*
1686 1892 * Map a client-side caching (CSC) option to the appropriate share
1687 1893 * flag. Only one option is allowed; an error will be logged if
1688 1894 * multiple options have been specified. We don't need to do anything
1689 1895 * about multiple values here because the SRVSVC will not recognize
1690 1896 * a value containing multiple flags and will return the default value.
1691 1897 *
1692 1898 * If the option value is not recognized, it will be ignored: invalid
1693 1899 * values will typically be caught and rejected by sharemgr.
1694 1900 */
1695 1901 void
1696 1902 smb_shr_sa_csc_option(const char *value, smb_share_t *si)
1697 1903 {
1698 1904 int i;
1699 1905
1700 1906 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1701 1907 if (strcasecmp(value, cscopt[i].value) == 0) {
1702 1908 si->shr_flags |= cscopt[i].flag;
1703 1909 break;
1704 1910 }
1705 1911 }
1706 1912
1707 1913 switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
1708 1914 case 0:
1709 1915 case SMB_SHRF_CSC_DISABLED:
1710 1916 case SMB_SHRF_CSC_MANUAL:
1711 1917 case SMB_SHRF_CSC_AUTO:
1712 1918 case SMB_SHRF_CSC_VDO:
1713 1919 break;
1714 1920
1715 1921 default:
1716 1922 syslog(LOG_INFO, "csc option conflict: 0x%08x",
1717 1923 si->shr_flags & SMB_SHRF_CSC_MASK);
1718 1924 break;
1719 1925 }
1720 1926 }
1721 1927
1722 1928 /*
1723 1929 * Return the option name for the first CSC flag (there should be only
1724 1930 * one) encountered in the share flags.
1725 1931 */
1726 1932 char *
1727 1933 smb_shr_sa_csc_name(const smb_share_t *si)
1728 1934 {
1729 1935 int i;
1730 1936
1731 1937 for (i = 0; i < (sizeof (cscopt) / sizeof (cscopt[0])); ++i) {
1732 1938 if (si->shr_flags & cscopt[i].flag)
1733 1939 return (cscopt[i].value);
1734 1940 }
1735 1941
1736 1942 return (NULL);
1737 1943 }
1738 1944
1739 1945 /*
1740 1946 * Takes the value of a boolean share property and set/clear the
1741 1947 * specified flag based on the property's value.
1742 1948 */
1743 1949 void
1744 1950 smb_shr_sa_setflag(const char *value, smb_share_t *si, uint32_t flag)
1745 1951 {
1746 1952 if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0))
1747 1953 si->shr_flags |= flag;
1748 1954 else
1749 1955 si->shr_flags &= ~flag;
1750 1956 }
1751 1957
1752 1958 /*
1753 1959 * looks up sharemgr for the given share (resource) and loads
1754 1960 * the definition into cache if lookup is successful
1755 1961 */
1756 1962 static uint32_t
1757 1963 smb_shr_sa_loadbyname(char *sharename)
1758 1964 {
1759 1965 sa_handle_t handle;
1760 1966 sa_share_t share;
1761 1967 sa_resource_t resource;
1762 1968 uint32_t status;
1763 1969
1764 1970 if ((handle = smb_shr_sa_enter()) == NULL)
1765 1971 return (NERR_InternalError);
1766 1972
1767 1973 resource = sa_find_resource(handle, sharename);
1768 1974 if (resource == NULL) {
1769 1975 smb_shr_sa_exit();
1770 1976 return (NERR_NetNameNotFound);
1771 1977 }
1772 1978
1773 1979 share = sa_get_resource_parent(resource);
1774 1980 if (share == NULL) {
1775 1981 smb_shr_sa_exit();
1776 1982 return (NERR_InternalError);
1777 1983 }
1778 1984
1779 1985 status = smb_shr_sa_load(share, resource);
1780 1986
1781 1987 smb_shr_sa_exit();
1782 1988 return (status);
1783 1989 }
1784 1990
1785 1991 /*
1786 1992 * ============================================
1787 1993 * Share publishing functions
1788 1994 *
1789 1995 * All the functions are private
1790 1996 * ============================================
1791 1997 */
1792 1998
1793 1999 static void
1794 2000 smb_shr_publish(const char *sharename, const char *container)
1795 2001 {
1796 2002 smb_shr_publisher_queue(sharename, container, SMB_SHR_PUBLISH);
1797 2003 }
1798 2004
1799 2005 static void
1800 2006 smb_shr_unpublish(const char *sharename, const char *container)
1801 2007 {
1802 2008 smb_shr_publisher_queue(sharename, container, SMB_SHR_UNPUBLISH);
1803 2009 }
1804 2010
1805 2011 /*
1806 2012 * In domain mode, put a share on the publisher queue.
1807 2013 * This is a no-op if the smb service is in Workgroup mode.
1808 2014 */
1809 2015 static void
1810 2016 smb_shr_publisher_queue(const char *sharename, const char *container, char op)
1811 2017 {
1812 2018 smb_shr_pitem_t *item = NULL;
1813 2019
1814 2020 if (container == NULL || *container == '\0')
1815 2021 return;
1816 2022
1817 2023 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1818 2024 return;
1819 2025
1820 2026 (void) mutex_lock(&ad_queue.spq_mtx);
1821 2027 switch (ad_queue.spq_state) {
1822 2028 case SMB_SHR_PQS_READY:
1823 2029 case SMB_SHR_PQS_PUBLISHING:
1824 2030 break;
1825 2031 default:
1826 2032 (void) mutex_unlock(&ad_queue.spq_mtx);
1827 2033 return;
1828 2034 }
1829 2035 (void) mutex_unlock(&ad_queue.spq_mtx);
1830 2036
1831 2037 if ((item = malloc(sizeof (smb_shr_pitem_t))) == NULL)
1832 2038 return;
1833 2039
1834 2040 item->spi_op = op;
1835 2041 (void) strlcpy(item->spi_name, sharename, sizeof (item->spi_name));
1836 2042 (void) strlcpy(item->spi_container, container,
1837 2043 sizeof (item->spi_container));
1838 2044
1839 2045 (void) mutex_lock(&ad_queue.spq_mtx);
1840 2046 list_insert_tail(&ad_queue.spq_list, item);
1841 2047 (void) cond_signal(&ad_queue.spq_cv);
1842 2048 (void) mutex_unlock(&ad_queue.spq_mtx);
1843 2049 }
1844 2050
1845 2051 /*
1846 2052 * Publishing won't be activated if the smb service is running in
1847 2053 * Workgroup mode.
1848 2054 */
1849 2055 static int
1850 2056 smb_shr_publisher_start(void)
1851 2057 {
1852 2058 pthread_t publish_thr;
1853 2059 pthread_attr_t tattr;
1854 2060 int rc;
1855 2061
1856 2062 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1857 2063 return (0);
1858 2064
1859 2065 (void) mutex_lock(&ad_queue.spq_mtx);
1860 2066 if (ad_queue.spq_state != SMB_SHR_PQS_NOQUEUE) {
1861 2067 (void) mutex_unlock(&ad_queue.spq_mtx);
1862 2068 errno = EINVAL;
1863 2069 return (-1);
1864 2070 }
1865 2071
1866 2072 list_create(&ad_queue.spq_list, sizeof (smb_shr_pitem_t),
1867 2073 offsetof(smb_shr_pitem_t, spi_lnd));
1868 2074 ad_queue.spq_state = SMB_SHR_PQS_READY;
1869 2075 (void) mutex_unlock(&ad_queue.spq_mtx);
1870 2076
1871 2077 (void) pthread_attr_init(&tattr);
1872 2078 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
1873 2079 rc = pthread_create(&publish_thr, &tattr, smb_shr_publisher, 0);
1874 2080 (void) pthread_attr_destroy(&tattr);
1875 2081
1876 2082 return (rc);
1877 2083 }
1878 2084
1879 2085 static void
1880 2086 smb_shr_publisher_stop(void)
1881 2087 {
1882 2088 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
1883 2089 return;
1884 2090
1885 2091 (void) mutex_lock(&ad_queue.spq_mtx);
1886 2092 switch (ad_queue.spq_state) {
1887 2093 case SMB_SHR_PQS_READY:
1888 2094 case SMB_SHR_PQS_PUBLISHING:
1889 2095 ad_queue.spq_state = SMB_SHR_PQS_STOPPING;
1890 2096 (void) cond_signal(&ad_queue.spq_cv);
1891 2097 break;
1892 2098 default:
1893 2099 break;
1894 2100 }
1895 2101 (void) mutex_unlock(&ad_queue.spq_mtx);
1896 2102 }
1897 2103
1898 2104 /*
1899 2105 * This is the publisher daemon thread. While running, the thread waits
1900 2106 * on a conditional variable until notified that a share needs to be
1901 2107 * [un]published or that the thread should be terminated.
1902 2108 *
1903 2109 * Entries may remain in the outgoing queue if the Active Directory
1904 2110 * service is inaccessible, in which case the thread wakes up every 60
1905 2111 * seconds to retry.
1906 2112 */
1907 2113 /*ARGSUSED*/
1908 2114 static void *
1909 2115 smb_shr_publisher(void *arg)
1910 2116 {
1911 2117 smb_ads_handle_t *ah;
1912 2118 smb_shr_pitem_t *shr;
1913 2119 list_t publist;
1914 2120 timestruc_t pubretry;
1915 2121 char hostname[MAXHOSTNAMELEN];
1916 2122
1917 2123 (void) mutex_lock(&ad_queue.spq_mtx);
1918 2124 if (ad_queue.spq_state != SMB_SHR_PQS_READY) {
1919 2125 (void) mutex_unlock(&ad_queue.spq_mtx);
1920 2126 return (NULL);
1921 2127 }
1922 2128 ad_queue.spq_state = SMB_SHR_PQS_PUBLISHING;
1923 2129 (void) mutex_unlock(&ad_queue.spq_mtx);
1924 2130
1925 2131 (void) smb_gethostname(hostname, MAXHOSTNAMELEN,
1926 2132 SMB_CASE_PRESERVE);
1927 2133
1928 2134 list_create(&publist, sizeof (smb_shr_pitem_t),
1929 2135 offsetof(smb_shr_pitem_t, spi_lnd));
1930 2136
1931 2137 for (;;) {
1932 2138 (void) mutex_lock(&ad_queue.spq_mtx);
1933 2139
1934 2140 while (list_is_empty(&ad_queue.spq_list) &&
1935 2141 (ad_queue.spq_state == SMB_SHR_PQS_PUBLISHING)) {
1936 2142 if (list_is_empty(&publist)) {
1937 2143 (void) cond_wait(&ad_queue.spq_cv,
1938 2144 &ad_queue.spq_mtx);
1939 2145 } else {
1940 2146 pubretry.tv_sec = 60;
1941 2147 pubretry.tv_nsec = 0;
1942 2148 (void) cond_reltimedwait(&ad_queue.spq_cv,
1943 2149 &ad_queue.spq_mtx, &pubretry);
1944 2150 break;
1945 2151 }
1946 2152 }
1947 2153
1948 2154 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
1949 2155 (void) mutex_unlock(&ad_queue.spq_mtx);
1950 2156 break;
1951 2157 }
1952 2158
1953 2159 /*
1954 2160 * Transfer queued items to the local list so that
1955 2161 * the mutex can be released.
1956 2162 */
1957 2163 while ((shr = list_head(&ad_queue.spq_list)) != NULL) {
1958 2164 list_remove(&ad_queue.spq_list, shr);
1959 2165 list_insert_tail(&publist, shr);
1960 2166 }
1961 2167
1962 2168 (void) mutex_unlock(&ad_queue.spq_mtx);
1963 2169
1964 2170 if ((ah = smb_ads_open()) != NULL) {
1965 2171 smb_shr_publisher_send(ah, &publist, hostname);
1966 2172 smb_ads_close(ah);
1967 2173 }
1968 2174 }
1969 2175
1970 2176 (void) mutex_lock(&ad_queue.spq_mtx);
1971 2177 smb_shr_publisher_flush(&ad_queue.spq_list);
1972 2178 list_destroy(&ad_queue.spq_list);
1973 2179 ad_queue.spq_state = SMB_SHR_PQS_NOQUEUE;
1974 2180 (void) mutex_unlock(&ad_queue.spq_mtx);
1975 2181
1976 2182 smb_shr_publisher_flush(&publist);
1977 2183 list_destroy(&publist);
1978 2184 return (NULL);
1979 2185 }
1980 2186
1981 2187 /*
1982 2188 * Remove items from the specified queue and [un]publish them.
1983 2189 */
1984 2190 static void
1985 2191 smb_shr_publisher_send(smb_ads_handle_t *ah, list_t *publist, const char *host)
1986 2192 {
1987 2193 smb_shr_pitem_t *shr;
1988 2194
1989 2195 while ((shr = list_head(publist)) != NULL) {
1990 2196 (void) mutex_lock(&ad_queue.spq_mtx);
1991 2197 if (ad_queue.spq_state != SMB_SHR_PQS_PUBLISHING) {
1992 2198 (void) mutex_unlock(&ad_queue.spq_mtx);
1993 2199 return;
1994 2200 }
1995 2201 (void) mutex_unlock(&ad_queue.spq_mtx);
1996 2202
1997 2203 list_remove(publist, shr);
1998 2204
1999 2205 if (shr->spi_op == SMB_SHR_PUBLISH)
2000 2206 (void) smb_ads_publish_share(ah, shr->spi_name,
2001 2207 NULL, shr->spi_container, host);
2002 2208 else
2003 2209 (void) smb_ads_remove_share(ah, shr->spi_name,
2004 2210 NULL, shr->spi_container, host);
2005 2211
2006 2212 free(shr);
2007 2213 }
2008 2214 }
2009 2215
2010 2216 /*
2011 2217 * Flush all remaining items from the specified list/queue.
2012 2218 */
2013 2219 static void
2014 2220 smb_shr_publisher_flush(list_t *lst)
2015 2221 {
|
↓ open down ↓ |
355 lines elided |
↑ open up ↑ |
2016 2222 smb_shr_pitem_t *shr;
2017 2223
2018 2224 while ((shr = list_head(lst)) != NULL) {
2019 2225 list_remove(lst, shr);
2020 2226 free(shr);
2021 2227 }
2022 2228 }
2023 2229
2024 2230 /*
2025 2231 * If the share path refers to a ZFS file system, add the
2026 - * .zfs/shares/<share> object and call smb_quota_add_fs()
2027 - * to initialize quota support for the share.
2232 + * .zfs/shares/<share> object and add or remove the special
2233 + * directory and file telling clients about quota support.
2028 2234 */
2029 2235 static void
2030 2236 smb_shr_zfs_add(smb_share_t *si)
2031 2237 {
2032 2238 libzfs_handle_t *libhd;
2033 2239 zfs_handle_t *zfshd;
2034 2240 int ret;
2035 2241 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2036 2242
2037 - if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
2243 + if ((libhd = libzfs_init()) == NULL)
2038 2244 return;
2039 2245
2040 - if ((libhd = libzfs_init()) == NULL)
2246 + if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
2247 + libzfs_fini(libhd);
2041 2248 return;
2249 + }
2042 2250
2043 2251 if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2044 2252 libzfs_fini(libhd);
2045 2253 return;
2046 2254 }
2047 2255
2048 2256 errno = 0;
2049 2257 ret = zfs_smb_acl_add(libhd, buf, si->shr_path, si->shr_name);
2050 2258 if (ret != 0 && errno != EAGAIN && errno != EEXIST)
2051 2259 syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
2052 2260 si->shr_name, strerror(errno));
2053 2261
2054 - if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2055 - NULL, NULL, 0, B_FALSE) == 0) {
2056 - smb_quota_add_fs(buf);
2262 + ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT,
2263 + buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE);
2264 + if (ret != 0) {
2265 + syslog(LOG_INFO, "share: failed to get mountpoint: "
2266 + "%s\n", si->shr_name);
2267 + } else {
2268 + if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) {
2269 + smb_quota_add_fs(buf);
2270 + } else {
2271 + smb_quota_remove_fs(buf);
2272 + }
2057 2273 }
2058 2274
2059 -
2060 2275 zfs_close(zfshd);
2061 2276 libzfs_fini(libhd);
2062 2277 }
2063 2278
2064 2279 /*
2065 2280 * If the share path refers to a ZFS file system, remove the
2066 - * .zfs/shares/<share> object, and call smb_quota_remove_fs()
2067 - * to end quota support for the share.
2281 + * .zfs/shares/<share> object.
2068 2282 */
2069 2283 static void
2070 2284 smb_shr_zfs_remove(smb_share_t *si)
2071 2285 {
2072 2286 libzfs_handle_t *libhd;
2073 - zfs_handle_t *zfshd;
2074 2287 int ret;
2075 2288 char buf[MAXPATHLEN]; /* dataset or mountpoint */
2076 2289
2077 - if (smb_getdataset(si->shr_path, buf, MAXPATHLEN) != 0)
2078 - return;
2079 -
2080 2290 if ((libhd = libzfs_init()) == NULL)
2081 2291 return;
2082 2292
2083 - if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
2293 + if (smb_getdataset(libhd, si->shr_path, buf, MAXPATHLEN) != 0) {
2084 2294 libzfs_fini(libhd);
2085 2295 return;
2086 2296 }
2087 2297
2088 2298 errno = 0;
2089 2299 ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
2090 2300 if (ret != 0 && errno != EAGAIN)
2091 2301 syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
2092 2302 si->shr_name, strerror(errno));
2093 2303
2094 - if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
2095 - NULL, NULL, 0, B_FALSE) == 0) {
2096 - smb_quota_remove_fs(buf);
2097 - }
2304 + /*
2305 + * We could remove the quotas directory here, but that adds
2306 + * significantly to the time required for a zpool export,
2307 + * so just leave it here and fixup when we share next.
2308 + */
2098 2309
2099 - zfs_close(zfshd);
2100 2310 libzfs_fini(libhd);
2101 2311 }
2102 2312
2103 2313 /*
2104 2314 * If the share path refers to a ZFS file system, rename the
2105 2315 * .zfs/shares/<share> object.
2106 2316 */
2107 2317 static void
2108 2318 smb_shr_zfs_rename(smb_share_t *from, smb_share_t *to)
2109 2319 {
2110 2320 libzfs_handle_t *libhd;
2111 2321 zfs_handle_t *zfshd;
2112 2322 int ret;
2113 2323 char dataset[MAXPATHLEN];
2114 2324
2115 - if (smb_getdataset(from->shr_path, dataset, MAXPATHLEN) != 0)
2325 + if ((libhd = libzfs_init()) == NULL)
2116 2326 return;
2117 2327
2118 - if ((libhd = libzfs_init()) == NULL)
2328 + if (smb_getdataset(libhd, from->shr_path, dataset, MAXPATHLEN) != 0) {
2329 + libzfs_fini(libhd);
2119 2330 return;
2331 + }
2120 2332
2121 2333 if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
2122 2334 libzfs_fini(libhd);
2123 2335 return;
2124 2336 }
2125 2337
2126 2338 errno = 0;
2127 2339 ret = zfs_smb_acl_rename(libhd, dataset, from->shr_path,
2128 2340 from->shr_name, to->shr_name);
2129 2341 if (ret != 0 && errno != EAGAIN)
2130 2342 syslog(LOG_INFO, "share: failed to rename ACL object: %s: %s\n",
2131 2343 from->shr_name, strerror(errno));
2132 2344
2133 2345 zfs_close(zfshd);
2134 2346 libzfs_fini(libhd);
2135 2347 }
2136 2348
2137 2349 /*
2138 2350 * Enable all privileges in the inheritable set to execute command.
2139 2351 */
2140 2352 static int
2141 2353 smb_shr_enable_all_privs(void)
2142 2354 {
2143 2355 priv_set_t *pset;
2144 2356
2145 2357 pset = priv_allocset();
2146 2358 if (pset == NULL)
2147 2359 return (-1);
2148 2360
2149 2361 if (getppriv(PRIV_LIMIT, pset)) {
2150 2362 priv_freeset(pset);
2151 2363 return (-1);
2152 2364 }
2153 2365
2154 2366 if (setppriv(PRIV_ON, PRIV_INHERITABLE, pset)) {
2155 2367 priv_freeset(pset);
2156 2368 return (-1);
2157 2369 }
2158 2370
2159 2371 priv_freeset(pset);
2160 2372 return (0);
2161 2373 }
2162 2374
2163 2375 /*
2164 2376 * Tokenizes the command string and returns the list of tokens in an array.
2165 2377 *
2166 2378 * Returns NULL if there are no tokens.
2167 2379 */
2168 2380 static char **
2169 2381 smb_shr_tokenize_cmd(char *cmdstr)
2170 2382 {
2171 2383 char *cmd, *buf, *bp, *value;
2172 2384 char **argv, **ap;
2173 2385 int argc, i;
2174 2386
2175 2387 if (cmdstr == NULL || *cmdstr == '\0')
2176 2388 return (NULL);
2177 2389
2178 2390 if ((buf = malloc(MAXPATHLEN)) == NULL)
2179 2391 return (NULL);
2180 2392
2181 2393 (void) strlcpy(buf, cmdstr, MAXPATHLEN);
2182 2394
2183 2395 for (argc = 2, bp = cmdstr; *bp != '\0'; ++bp)
2184 2396 if (*bp == ' ')
2185 2397 ++argc;
2186 2398
2187 2399 if ((argv = calloc(argc, sizeof (char *))) == NULL) {
2188 2400 free(buf);
2189 2401 return (NULL);
2190 2402 }
2191 2403
2192 2404 ap = argv;
2193 2405 for (bp = buf, i = 0; i < argc; ++i) {
2194 2406 do {
2195 2407 if ((value = strsep(&bp, " ")) == NULL)
2196 2408 break;
2197 2409 } while (*value == '\0');
2198 2410
2199 2411 if (value == NULL)
2200 2412 break;
2201 2413
2202 2414 *ap++ = value;
2203 2415 }
2204 2416
2205 2417 /* get the filename of the command from the path */
2206 2418 if ((cmd = strrchr(argv[0], '/')) != NULL)
2207 2419 (void) strlcpy(argv[0], ++cmd, strlen(argv[0]));
2208 2420
2209 2421 return (argv);
2210 2422 }
2211 2423
2212 2424 /*
2213 2425 * Expands the command string for the following substitution tokens:
2214 2426 *
2215 2427 * %U - Windows username
2216 2428 * %D - Name of the domain or workgroup of %U
2217 2429 * %h - The server hostname
2218 2430 * %M - The client hostname
2219 2431 * %L - The server NetBIOS name
2220 2432 * %m - The client NetBIOS name. This option is only valid for NetBIOS
2221 2433 * connections (port 139).
2222 2434 * %I - The IP address of the client machine
2223 2435 * %i - The local IP address to which the client is connected
2224 2436 * %S - The name of the share
2225 2437 * %P - The root directory of the share
2226 2438 * %u - The UID of the Unix user
2227 2439 *
2228 2440 * Returns 0 on success. Otherwise -1.
2229 2441 */
2230 2442 static int
2231 2443 smb_shr_expand_subs(char **cmd_toks, smb_share_t *si, smb_shr_execinfo_t *subs)
2232 2444 {
2233 2445 char *fmt, *sub_chr, *ptr;
2234 2446 boolean_t unknown;
2235 2447 char hostname[MAXHOSTNAMELEN];
2236 2448 char ip_str[INET6_ADDRSTRLEN];
2237 2449 char name[SMB_PI_MAX_HOST];
2238 2450 smb_wchar_t wbuf[SMB_PI_MAX_HOST];
2239 2451 int i;
2240 2452
2241 2453 if (cmd_toks == NULL || *cmd_toks == NULL)
2242 2454 return (-1);
2243 2455
2244 2456 for (i = 1; cmd_toks[i]; i++) {
2245 2457 fmt = cmd_toks[i];
2246 2458 if (*fmt == '%') {
2247 2459 sub_chr = fmt + 1;
2248 2460 unknown = B_FALSE;
2249 2461
2250 2462 switch (*sub_chr) {
2251 2463 case 'U':
2252 2464 ptr = strdup(subs->e_winname);
2253 2465 break;
2254 2466 case 'D':
2255 2467 ptr = strdup(subs->e_userdom);
2256 2468 break;
2257 2469 case 'h':
2258 2470 if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
2259 2471 unknown = B_TRUE;
2260 2472 else
2261 2473 ptr = strdup(hostname);
2262 2474 break;
2263 2475 case 'M':
2264 2476 if (smb_getnameinfo(&subs->e_cli_ipaddr,
2265 2477 hostname, sizeof (hostname), 0) != 0)
2266 2478 unknown = B_TRUE;
2267 2479 else
2268 2480 ptr = strdup(hostname);
2269 2481 break;
2270 2482 case 'L':
2271 2483 if (smb_getnetbiosname(hostname,
2272 2484 NETBIOS_NAME_SZ) != 0)
2273 2485 unknown = B_TRUE;
2274 2486 else
2275 2487 ptr = strdup(hostname);
2276 2488 break;
2277 2489 case 'm':
2278 2490 if (*subs->e_cli_netbiosname == '\0')
2279 2491 unknown = B_TRUE;
2280 2492 else {
2281 2493 (void) smb_mbstowcs(wbuf,
2282 2494 subs->e_cli_netbiosname,
2283 2495 SMB_PI_MAX_HOST - 1);
2284 2496
2285 2497 if (ucstooem(name, wbuf,
2286 2498 SMB_PI_MAX_HOST, OEM_CPG_850) == 0)
2287 2499 (void) strlcpy(name,
2288 2500 subs->e_cli_netbiosname,
2289 2501 SMB_PI_MAX_HOST);
2290 2502
2291 2503 ptr = strdup(name);
2292 2504 }
2293 2505 break;
2294 2506 case 'I':
2295 2507 if (smb_inet_ntop(&subs->e_cli_ipaddr, ip_str,
2296 2508 SMB_IPSTRLEN(subs->e_cli_ipaddr.a_family))
2297 2509 != NULL)
2298 2510 ptr = strdup(ip_str);
2299 2511 else
2300 2512 unknown = B_TRUE;
2301 2513 break;
2302 2514 case 'i':
2303 2515 if (smb_inet_ntop(&subs->e_srv_ipaddr, ip_str,
2304 2516 SMB_IPSTRLEN(subs->e_srv_ipaddr.a_family))
2305 2517 != NULL)
2306 2518 ptr = strdup(ip_str);
2307 2519 else
2308 2520 unknown = B_TRUE;
2309 2521 break;
2310 2522 case 'S':
2311 2523 ptr = strdup(si->shr_name);
2312 2524 break;
2313 2525 case 'P':
2314 2526 ptr = strdup(si->shr_path);
2315 2527 break;
2316 2528 case 'u':
2317 2529 (void) snprintf(name, sizeof (name), "%u",
2318 2530 subs->e_uid);
2319 2531 ptr = strdup(name);
2320 2532 break;
2321 2533 default:
2322 2534 /* unknown sub char */
2323 2535 unknown = B_TRUE;
2324 2536 break;
2325 2537 }
2326 2538
2327 2539 if (unknown)
2328 2540 ptr = strdup("");
2329 2541
2330 2542 } else /* first char of cmd's arg is not '%' char */
2331 2543 ptr = strdup("");
2332 2544
2333 2545 cmd_toks[i] = ptr;
2334 2546
2335 2547 if (ptr == NULL) {
2336 2548 for (i = 1; cmd_toks[i]; i++)
2337 2549 free(cmd_toks[i]);
2338 2550
2339 2551 return (-1);
2340 2552 }
2341 2553 }
2342 2554
2343 2555 return (0);
2344 2556 }
2345 2557
2346 2558 /*ARGSUSED*/
2347 2559 static void
2348 2560 smb_shr_sig_abnormal_term(int sig_val)
2349 2561 {
2350 2562 /*
2351 2563 * Calling _exit() prevents parent process from getting SIGTERM/SIGINT
2352 2564 * signal.
2353 2565 */
2354 2566 _exit(-1);
2355 2567 }
2356 2568
2357 2569 /*ARGSUSED*/
2358 2570 static void
2359 2571 smb_shr_sig_child(int sig_val)
2360 2572 {
2361 2573 /*
2362 2574 * Catch the signal and allow the exit status of the child process
2363 2575 * to be available for reaping.
2364 2576 */
2365 2577 }
2366 2578
2367 2579 /*
2368 2580 * This is a temporary function which converts the given smb_share_t
2369 2581 * structure to the nvlist format that will be provided by libsharev2
2370 2582 */
2371 2583 static int
2372 2584 smb_shr_encode(smb_share_t *si, nvlist_t **nvlist)
2373 2585 {
2374 2586 nvlist_t *list;
2375 2587 nvlist_t *share;
2376 2588 nvlist_t *smb;
2377 2589 char *csc;
2378 2590 int rc = 0;
2379 2591
2380 2592 *nvlist = NULL;
2381 2593
2382 2594 if ((rc = nvlist_alloc(&list, NV_UNIQUE_NAME, 0)) != 0)
2383 2595 return (rc);
2384 2596
2385 2597 if ((rc = nvlist_alloc(&share, NV_UNIQUE_NAME, 0)) != 0) {
2386 2598 nvlist_free(list);
2387 2599 return (rc);
2388 2600 }
2389 2601
2390 2602 if ((rc = nvlist_alloc(&smb, NV_UNIQUE_NAME, 0)) != 0) {
2391 2603 nvlist_free(share);
2392 2604 nvlist_free(list);
2393 2605 return (rc);
2394 2606 }
2395 2607
2396 2608 /* global share properties */
2397 2609 rc |= nvlist_add_string(share, "name", si->shr_name);
2398 2610 rc |= nvlist_add_string(share, "path", si->shr_path);
2399 2611 rc |= nvlist_add_string(share, "desc", si->shr_cmnt);
2400 2612
2401 2613 /* smb protocol properties */
2402 2614 rc = nvlist_add_string(smb, SHOPT_AD_CONTAINER, si->shr_container);
2403 2615 if ((si->shr_flags & SMB_SHRF_ACC_NONE) != 0)
2404 2616 rc |= nvlist_add_string(smb, SHOPT_NONE, si->shr_access_none);
2405 2617 if ((si->shr_flags & SMB_SHRF_ACC_RO) != 0)
2406 2618 rc |= nvlist_add_string(smb, SHOPT_RO, si->shr_access_ro);
2407 2619 if ((si->shr_flags & SMB_SHRF_ACC_RW) != 0)
|
↓ open down ↓ |
278 lines elided |
↑ open up ↑ |
2408 2620 rc |= nvlist_add_string(smb, SHOPT_RW, si->shr_access_rw);
2409 2621
2410 2622 if ((si->shr_flags & SMB_SHRF_ABE) != 0)
2411 2623 rc |= nvlist_add_string(smb, SHOPT_ABE, "true");
2412 2624 if ((si->shr_flags & SMB_SHRF_CATIA) != 0)
2413 2625 rc |= nvlist_add_string(smb, SHOPT_CATIA, "true");
2414 2626 if ((si->shr_flags & SMB_SHRF_GUEST_OK) != 0)
2415 2627 rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
2416 2628 if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
2417 2629 rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
2630 + if ((si->shr_flags & SMB_SHRF_CA) != 0)
2631 + rc |= nvlist_add_string(smb, SHOPT_CA, "true");
2632 + if ((si->shr_flags & SMB_SHRF_FSO) != 0)
2633 + rc |= nvlist_add_string(smb, SHOPT_FSO, "true");
2634 + if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0)
2635 + rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true");
2418 2636
2637 + if (si->shr_encrypt == SMB_CONFIG_REQUIRED)
2638 + rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "required");
2639 + else if (si->shr_encrypt == SMB_CONFIG_ENABLED)
2640 + rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "enabled");
2641 + else
2642 + rc |= nvlist_add_string(smb, SHOPT_ENCRYPT, "disabled");
2643 +
2419 2644 if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
2420 - rc |= nvlist_add_string(smb, "Autohome", "true");
2645 + rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true");
2421 2646 rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
2422 2647 rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
2423 2648 }
2424 2649
2425 2650 if ((csc = smb_shr_sa_csc_name(si)) != NULL)
2426 2651 rc |= nvlist_add_string(smb, SHOPT_CSC, csc);
2427 2652
2428 2653 rc |= nvlist_add_uint32(smb, "type", si->shr_type);
2429 2654
2430 2655 rc |= nvlist_add_nvlist(share, "smb", smb);
2431 2656 rc |= nvlist_add_nvlist(list, si->shr_name, share);
2432 2657
2433 2658 nvlist_free(share);
2434 2659 nvlist_free(smb);
2435 2660
2436 2661 if (rc != 0)
2437 2662 nvlist_free(list);
2438 2663 else
2439 2664 *nvlist = list;
2440 2665
2441 2666 return (rc);
2442 2667 }
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX