Print this page
NEX-5260 smbd segfaults while running smbtorture:rpc.lsa.lookupnames
NEX-5261 smbd segfaults while running smbtorture:rpc.winreg
NEX-5262 smbd segfaults while running smbtorture:rpc.samba3
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
SMB-39 Use AF_UNIX pipes for RPC
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 - * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * Server Service RPC (SRVSVC) server-side interface definition.
29 29 * The server service provides a remote administration interface.
30 30 *
31 31 * This service uses NERR/Win32 error codes rather than NT status
32 32 * values.
33 33 */
34 34
35 35 #include <sys/errno.h>
36 36 #include <sys/tzfile.h>
37 37 #include <unistd.h>
38 38 #include <netdb.h>
39 39 #include <strings.h>
40 40 #include <time.h>
41 41 #include <thread.h>
42 42 #include <ctype.h>
43 43 #include <stdlib.h>
44 44 #include <string.h>
45 45 #include <sys/types.h>
46 46 #include <sys/socket.h>
47 47 #include <netinet/in.h>
48 48 #include <arpa/inet.h>
49 49 #include <libshare.h>
50 50 #include <libnvpair.h>
51 51 #include <sys/idmap.h>
52 52 #include <pwd.h>
53 53 #include <nss_dbdefs.h>
54 54 #include <smbsrv/libsmb.h>
55 55 #include <smbsrv/libmlsvc.h>
56 56 #include <smbsrv/nmpipes.h>
57 57 #include <smbsrv/smb.h>
58 58 #include <smbsrv/netrauth.h>
59 59 #include <smbsrv/ndl/srvsvc.ndl>
60 60 #include "mlsvc.h"
61 61
62 62 /*
63 63 * Qualifier types for NetConnectEnum.
64 64 */
65 65 #define SRVSVC_CONNECT_ENUM_NULL 0
66 66 #define SRVSVC_CONNECT_ENUM_SHARE 1
67 67 #define SRVSVC_CONNECT_ENUM_WKSTN 2
68 68
69 69 #define SMB_SRVSVC_MAXBUFLEN (8 * 1024 * 1024)
70 70 #define SMB_SRVSVC_MAXPREFLEN ((uint32_t)(-1))
71 71
72 72 typedef struct srvsvc_sd {
73 73 uint8_t *sd_buf;
74 74 uint32_t sd_size;
75 75 } srvsvc_sd_t;
76 76
77 77 typedef struct srvsvc_netshare_setinfo {
78 78 char *nss_netname;
79 79 char *nss_comment;
80 80 char *nss_path;
81 81 uint32_t nss_type;
82 82 srvsvc_sd_t nss_sd;
83 83 } srvsvc_netshare_setinfo_t;
84 84
85 85 typedef union srvsvc_netshare_getinfo {
86 86 struct mslm_NetShareInfo_0 nsg_info0;
87 87 struct mslm_NetShareInfo_1 nsg_info1;
88 88 struct mslm_NetShareInfo_2 nsg_info2;
89 89 struct mslm_NetShareInfo_501 nsg_info501;
90 90 struct mslm_NetShareInfo_502 nsg_info502;
91 91 struct mslm_NetShareInfo_503 nsg_info503;
92 92 struct mslm_NetShareInfo_1004 nsg_info1004;
93 93 struct mslm_NetShareInfo_1005 nsg_info1005;
94 94 struct mslm_NetShareInfo_1006 nsg_info1006;
95 95 struct mslm_NetShareInfo_1501 nsg_info1501;
96 96 } srvsvc_netshare_getinfo_t;
97 97
98 98 typedef struct mslm_infonres srvsvc_infonres_t;
99 99 typedef struct mslm_NetConnectEnum srvsvc_NetConnectEnum_t;
100 100
101 101 static uint32_t srvsvc_netconnectenum_level0(ndr_xa_t *, smb_svcenum_t *,
102 102 srvsvc_NetConnectEnum_t *);
103 103 static uint32_t srvsvc_netconnectenum_level1(ndr_xa_t *, smb_svcenum_t *,
104 104 srvsvc_NetConnectEnum_t *);
105 105 static uint32_t srvsvc_netconnectenum_common(ndr_xa_t *,
106 106 srvsvc_NetConnectInfo_t *, smb_netsvc_t *, smb_svcenum_t *);
107 107
108 108 static DWORD srvsvc_NetFileEnum2(ndr_xa_t *, struct mslm_NetFileEnum *,
109 109 smb_svcenum_t *se);
110 110 static DWORD srvsvc_NetFileEnum3(ndr_xa_t *, struct mslm_NetFileEnum *,
111 111 smb_svcenum_t *se);
112 112
113 113 static uint32_t srvsvc_NetSessionEnumCommon(ndr_xa_t *, srvsvc_infonres_t *,
114 114 smb_netsvc_t *, smb_svcenum_t *);
115 115
116 116 static DWORD mlsvc_NetShareEnumLevel0(ndr_xa_t *, srvsvc_infonres_t *,
117 117 smb_svcenum_t *, int);
118 118 static DWORD mlsvc_NetShareEnumLevel1(ndr_xa_t *, srvsvc_infonres_t *,
119 119 smb_svcenum_t *, int);
120 120 static DWORD mlsvc_NetShareEnumLevel2(ndr_xa_t *, srvsvc_infonres_t *,
121 121 smb_svcenum_t *, int);
122 122 static DWORD mlsvc_NetShareEnumLevel501(ndr_xa_t *, srvsvc_infonres_t *,
123 123 smb_svcenum_t *, int);
124 124 static DWORD mlsvc_NetShareEnumLevel502(ndr_xa_t *, srvsvc_infonres_t *,
125 125 smb_svcenum_t *, int);
126 126 static DWORD mlsvc_NetShareEnumCommon(ndr_xa_t *, smb_svcenum_t *,
127 127 smb_share_t *, void *);
128 128 static boolean_t srvsvc_add_autohome(ndr_xa_t *, smb_svcenum_t *, void *);
129 129 static char *srvsvc_share_mkpath(ndr_xa_t *, char *);
130 130 static uint32_t srvsvc_share_getsd(ndr_xa_t *, smb_share_t *, srvsvc_sd_t *);
131 131
132 132 static int srvsvc_netconnect_qualifier(const char *);
133 133 static void srvsvc_estimate_limit(smb_svcenum_t *, uint32_t);
134 134 static uint32_t srvsvc_open_sessions(void);
135 135 static uint32_t srvsvc_open_connections(uint32_t, const char *);
136 136 static uint32_t srvsvc_open_files(void);
137 137
138 138 static uint32_t srvsvc_modify_share(smb_share_t *,
139 139 srvsvc_netshare_setinfo_t *);
140 140 static uint32_t srvsvc_modify_transient_share(smb_share_t *,
141 141 srvsvc_netshare_setinfo_t *);
142 142 static uint32_t srvsvc_update_share_flags(smb_share_t *, uint32_t);
143 143 static uint32_t srvsvc_get_share_flags(smb_share_t *);
144 144
145 145 static uint32_t srvsvc_sa_add(char *, char *, char *);
146 146 static uint32_t srvsvc_sa_delete(char *);
147 147 static uint32_t srvsvc_sa_modify(smb_share_t *, srvsvc_netshare_setinfo_t *);
148 148 static uint32_t srvsvc_sa_setprop(smb_share_t *, nvlist_t *);
149 149
150 150 static char empty_string[1];
151 151
152 152 static ndr_stub_table_t srvsvc_stub_table[];
153 153
154 154 static ndr_service_t srvsvc_service = {
155 155 "SRVSVC", /* name */
156 156 "Server services", /* desc */
157 157 "\\srvsvc", /* endpoint */
158 158 PIPE_NTSVCS, /* sec_addr_port */
159 159 "4b324fc8-1670-01d3-1278-5a47bf6ee188", 3, /* abstract */
160 160 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */
161 161 0, /* no bind_instance_size */
162 162 0, /* no bind_req() */
163 163 0, /* no unbind_and_close() */
164 164 0, /* use generic_call_stub() */
165 165 &TYPEINFO(srvsvc_interface), /* interface ti */
166 166 srvsvc_stub_table /* stub_table */
167 167 };
168 168
169 169 /*
170 170 * srvsvc_initialize
171 171 *
172 172 * This function registers the SRVSVC RPC interface with the RPC runtime
173 173 * library. It must be called in order to use either the client side
174 174 * or the server side functions.
175 175 */
176 176 void
177 177 srvsvc_initialize(void)
178 178 {
179 179 (void) ndr_svc_register(&srvsvc_service);
180 180 }
181 181
182 182 /*
183 183 * Turn "dfsroot" property on/off for the specified
184 184 * share and save it.
185 185 *
186 186 * If the requested value is the same as what is already
187 187 * set then no change is required and the function returns.
188 188 */
189 189 uint32_t
190 190 srvsvc_shr_setdfsroot(smb_share_t *si, boolean_t on)
191 191 {
192 192 char *dfs = NULL;
193 193 nvlist_t *nvl;
194 194 uint32_t nerr;
195 195
196 196 if (on && ((si->shr_flags & SMB_SHRF_DFSROOT) == 0)) {
197 197 si->shr_flags |= SMB_SHRF_DFSROOT;
198 198 dfs = "true";
199 199 } else if (!on && (si->shr_flags & SMB_SHRF_DFSROOT)) {
200 200 si->shr_flags &= ~SMB_SHRF_DFSROOT;
201 201 dfs = "false";
202 202 }
203 203
204 204 if (dfs == NULL)
205 205 return (ERROR_SUCCESS);
206 206
207 207 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
208 208 return (NERR_InternalError);
209 209
210 210 if (nvlist_add_string(nvl, SHOPT_DFSROOT, dfs) != 0) {
211 211 nvlist_free(nvl);
212 212 return (NERR_InternalError);
213 213 }
214 214
215 215 nerr = srvsvc_sa_setprop(si, nvl);
216 216 nvlist_free(nvl);
217 217
218 218 if (nerr != NERR_Success)
219 219 return (nerr);
220 220
221 221 return (smb_shr_modify(si));
222 222 }
223 223
224 224 /*
225 225 * srvsvc_s_NetConnectEnum
226 226 *
227 227 * List tree connections made to a share on this server or all tree
228 228 * connections established from a specific client. Administrator,
229 229 * Server Operator, Print Operator or Power User group membership
230 230 * is required to use this interface.
231 231 *
232 232 * There are three information levels: 0, 1, and 50. We don't support
233 233 * level 50, which is only used by Windows 9x clients.
234 234 *
235 235 * It seems Server Manger (srvmgr) only sends workstation as the qualifier
236 236 * and the Computer Management Interface on Windows 2000 doesn't request
237 237 * a list of connections.
238 238 *
239 239 * Return Values:
240 240 * ERROR_SUCCESS Success
241 241 * ERROR_ACCESS_DENIED Caller does not have access to this call.
242 242 * ERROR_INVALID_PARAMETER One of the parameters is invalid.
243 243 * ERROR_INVALID_LEVEL Unknown information level specified.
244 244 * ERROR_MORE_DATA Partial date returned, more entries available.
245 245 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
246 246 * NERR_NetNameNotFound The share qualifier cannot be found.
247 247 * NERR_BufTooSmall The supplied buffer is too small.
248 248 */
249 249 static int
250 250 srvsvc_s_NetConnectEnum(void *arg, ndr_xa_t *mxa)
251 251 {
252 252 srvsvc_NetConnectEnum_t *param = arg;
253 253 smb_netsvc_t *ns;
254 254 smb_svcenum_t se;
255 255 char *qualifier;
256 256 int qualtype;
257 257 DWORD status = ERROR_SUCCESS;
258 258
259 259 if (!ndr_is_poweruser(mxa)) {
260 260 status = ERROR_ACCESS_DENIED;
261 261 goto srvsvc_netconnectenum_error;
262 262 }
263 263
264 264 qualifier = (char *)param->qualifier;
265 265 qualtype = srvsvc_netconnect_qualifier(qualifier);
266 266 if (qualtype == SRVSVC_CONNECT_ENUM_NULL) {
267 267 status = NERR_NetNameNotFound;
268 268 goto srvsvc_netconnectenum_error;
269 269 }
270 270
271 271 param->total_entries = srvsvc_open_connections(qualtype, qualifier);
272 272 if (param->total_entries == 0) {
273 273 bzero(param, sizeof (srvsvc_NetConnectEnum_t));
274 274 param->status = ERROR_SUCCESS;
275 275 return (NDR_DRC_OK);
276 276 }
277 277
278 278 bzero(&se, sizeof (smb_svcenum_t));
279 279 se.se_type = SMB_SVCENUM_TYPE_TREE;
280 280 se.se_level = param->info.level;
281 281 se.se_ntotal = param->total_entries;
282 282 se.se_nlimit = se.se_ntotal;
283 283
284 284 if (param->pref_max_len == SMB_SRVSVC_MAXPREFLEN ||
285 285 param->pref_max_len > SMB_SRVSVC_MAXBUFLEN)
286 286 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
287 287 else
288 288 se.se_prefmaxlen = param->pref_max_len;
289 289
290 290 if (param->resume_handle) {
291 291 se.se_resume = *param->resume_handle;
292 292 se.se_nskip = se.se_resume;
293 293 *param->resume_handle = 0;
294 294 }
295 295
296 296 switch (param->info.level) {
297 297 case 0:
298 298 status = srvsvc_netconnectenum_level0(mxa, &se, param);
299 299 break;
300 300 case 1:
301 301 status = srvsvc_netconnectenum_level1(mxa, &se, param);
302 302 break;
303 303 case 50:
304 304 status = ERROR_NOT_SUPPORTED;
305 305 break;
306 306 default:
307 307 status = ERROR_INVALID_LEVEL;
308 308 break;
309 309 }
310 310
311 311 if (status != ERROR_SUCCESS)
312 312 goto srvsvc_netconnectenum_error;
313 313
314 314 if ((ns = smb_kmod_enum_init(&se)) == NULL) {
315 315 status = ERROR_NOT_ENOUGH_MEMORY;
316 316 goto srvsvc_netconnectenum_error;
317 317 }
318 318
319 319 status = srvsvc_netconnectenum_common(mxa, ¶m->info, ns, &se);
320 320 smb_kmod_enum_fini(ns);
321 321
322 322 if (status != ERROR_SUCCESS)
323 323 goto srvsvc_netconnectenum_error;
324 324
325 325 if (param->resume_handle &&
326 326 param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
327 327 if (se.se_resume < param->total_entries) {
328 328 *param->resume_handle = se.se_resume;
329 329 status = ERROR_MORE_DATA;
330 330 }
331 331 }
332 332
333 333 param->status = status;
334 334 return (NDR_DRC_OK);
335 335
336 336 srvsvc_netconnectenum_error:
337 337 bzero(param, sizeof (srvsvc_NetConnectEnum_t));
338 338 param->status = status;
339 339 return (NDR_DRC_OK);
340 340 }
341 341
342 342 /*
343 343 * Allocate memory and estimate the number of objects that can
344 344 * be returned for NetConnectEnum level 0.
345 345 */
346 346 static uint32_t
347 347 srvsvc_netconnectenum_level0(ndr_xa_t *mxa, smb_svcenum_t *se,
348 348 srvsvc_NetConnectEnum_t *param)
349 349 {
350 350 srvsvc_NetConnectInfo0_t *info0;
351 351 srvsvc_NetConnectInfoBuf0_t *ci0;
352 352
353 353 if ((info0 = NDR_NEW(mxa, srvsvc_NetConnectInfo0_t)) == NULL)
354 354 return (ERROR_NOT_ENOUGH_MEMORY);
355 355
356 356 bzero(info0, sizeof (srvsvc_NetConnectInfo0_t));
357 357 param->info.ru.info0 = info0;
358 358
359 359 srvsvc_estimate_limit(se, sizeof (srvsvc_NetConnectInfoBuf0_t));
360 360 if (se->se_nlimit == 0)
361 361 return (NERR_BufTooSmall);
362 362
363 363 do {
364 364 ci0 = NDR_NEWN(mxa, srvsvc_NetConnectInfoBuf0_t, se->se_nlimit);
365 365 if (ci0 == NULL)
366 366 se->se_nlimit >>= 1;
367 367 } while ((se->se_nlimit > 0) && (ci0 == NULL));
368 368
369 369 if (ci0 == NULL)
370 370 return (ERROR_NOT_ENOUGH_MEMORY);
371 371
372 372 info0->ci0 = ci0;
373 373 info0->entries_read = 0;
374 374 return (ERROR_SUCCESS);
375 375 }
376 376
377 377 /*
378 378 * Allocate memory and estimate the number of objects that can
379 379 * be returned for NetConnectEnum level 1.
380 380 */
381 381 static uint32_t
382 382 srvsvc_netconnectenum_level1(ndr_xa_t *mxa, smb_svcenum_t *se,
383 383 srvsvc_NetConnectEnum_t *param)
384 384 {
385 385 srvsvc_NetConnectInfo1_t *info1;
386 386 srvsvc_NetConnectInfoBuf1_t *ci1;
387 387
388 388 if ((info1 = NDR_NEW(mxa, srvsvc_NetConnectInfo1_t)) == NULL)
389 389 return (ERROR_NOT_ENOUGH_MEMORY);
390 390
391 391 bzero(info1, sizeof (srvsvc_NetConnectInfo1_t));
392 392 param->info.ru.info1 = info1;
393 393
394 394 srvsvc_estimate_limit(se,
395 395 sizeof (srvsvc_NetConnectInfoBuf1_t) + MAXNAMELEN);
396 396 if (se->se_nlimit == 0)
397 397 return (NERR_BufTooSmall);
398 398
399 399 do {
400 400 ci1 = NDR_NEWN(mxa, srvsvc_NetConnectInfoBuf1_t, se->se_nlimit);
401 401 if (ci1 == NULL)
402 402 se->se_nlimit >>= 1;
403 403 } while ((se->se_nlimit > 0) && (ci1 == NULL));
404 404
405 405 if (ci1 == NULL)
406 406 return (ERROR_NOT_ENOUGH_MEMORY);
407 407
408 408 info1->ci1 = ci1;
409 409 info1->entries_read = 0;
410 410 return (ERROR_SUCCESS);
411 411 }
412 412
413 413 /*
414 414 * Request a list of connections from the kernel and set up
415 415 * the connection information to be returned to the client.
416 416 */
417 417 static uint32_t
418 418 srvsvc_netconnectenum_common(ndr_xa_t *mxa, srvsvc_NetConnectInfo_t *info,
419 419 smb_netsvc_t *ns, smb_svcenum_t *se)
420 420 {
421 421 srvsvc_NetConnectInfo0_t *info0;
422 422 srvsvc_NetConnectInfo1_t *info1;
423 423 srvsvc_NetConnectInfoBuf0_t *ci0;
424 424 srvsvc_NetConnectInfoBuf1_t *ci1;
425 425 smb_netsvcitem_t *item;
426 426 smb_netconnectinfo_t *tree;
427 427
428 428 if (smb_kmod_enum(ns) != 0)
429 429 return (ERROR_INTERNAL_ERROR);
430 430
431 431 info0 = info->ru.info0;
432 432 ci0 = info0->ci0;
433 433
434 434 info1 = info->ru.info1;
435 435 ci1 = info1->ci1;
436 436
437 437 item = list_head(&ns->ns_list);
438 438 while (item != NULL) {
439 439 tree = &item->nsi_un.nsi_tree;
440 440
441 441 switch (se->se_level) {
442 442 case 0:
443 443 ci0->coni0_id = tree->ci_id;
444 444 ++ci0;
445 445 ++info0->entries_read;
446 446 break;
447 447 case 1:
448 448 ci1->coni1_id = tree->ci_id;
449 449 ci1->coni1_type = tree->ci_type;
450 450 ci1->coni1_num_opens = tree->ci_numopens;
451 451 ci1->coni1_num_users = tree->ci_numusers;
452 452 ci1->coni1_time = tree->ci_time;
453 453 ci1->coni1_username = (uint8_t *)
454 454 NDR_STRDUP(mxa, tree->ci_username);
455 455 ci1->coni1_netname = (uint8_t *)
456 456 NDR_STRDUP(mxa, tree->ci_share);
457 457 ++ci1;
458 458 ++info1->entries_read;
459 459 break;
460 460 default:
461 461 return (ERROR_INVALID_LEVEL);
462 462 }
463 463
464 464 ++se->se_resume;
465 465 item = list_next(&ns->ns_list, item);
466 466 }
467 467
468 468 return (ERROR_SUCCESS);
469 469 }
470 470
471 471 /*
472 472 * srvsvc_netconnect_qualifier
473 473 *
474 474 * The qualifier is a string that specifies a share name or computer name
475 475 * for the connections of interest. If it is a share name then all the
476 476 * connections made to that share name are listed. If it is a computer
477 477 * name (it starts with two backslash characters), then NetConnectEnum
478 478 * lists all connections made from that computer to the specified server.
479 479 */
480 480 static int
481 481 srvsvc_netconnect_qualifier(const char *qualifier)
482 482 {
483 483 if (qualifier == NULL || *qualifier == '\0')
484 484 return (SRVSVC_CONNECT_ENUM_NULL);
485 485
486 486 if (strlen(qualifier) > MAXHOSTNAMELEN)
487 487 return (SRVSVC_CONNECT_ENUM_NULL);
488 488
489 489 if (qualifier[0] == '\\' && qualifier[1] == '\\') {
490 490 return (SRVSVC_CONNECT_ENUM_WKSTN);
491 491 } else {
492 492 if (!smb_shr_exists((char *)qualifier))
493 493 return (SRVSVC_CONNECT_ENUM_NULL);
494 494
495 495 return (SRVSVC_CONNECT_ENUM_SHARE);
496 496 }
497 497 }
498 498
499 499 static uint32_t
500 500 srvsvc_open_sessions(void)
501 501 {
502 502 smb_opennum_t opennum;
503 503
504 504 bzero(&opennum, sizeof (smb_opennum_t));
505 505 if (smb_kmod_get_open_num(&opennum) != 0)
506 506 return (0);
507 507
508 508 return (opennum.open_users);
509 509 }
510 510
511 511 static uint32_t
512 512 srvsvc_open_connections(uint32_t qualtype, const char *qualifier)
513 513 {
514 514 smb_opennum_t opennum;
515 515
516 516 bzero(&opennum, sizeof (smb_opennum_t));
517 517 opennum.qualtype = qualtype;
518 518 (void) strlcpy(opennum.qualifier, qualifier, MAXNAMELEN);
519 519
520 520 if (smb_kmod_get_open_num(&opennum) != 0)
521 521 return (0);
522 522
523 523 return (opennum.open_trees);
524 524 }
525 525
526 526 static uint32_t
527 527 srvsvc_open_files(void)
528 528 {
529 529 smb_opennum_t opennum;
530 530
531 531 bzero(&opennum, sizeof (smb_opennum_t));
532 532 if (smb_kmod_get_open_num(&opennum) != 0)
533 533 return (0);
534 534
535 535 return (opennum.open_files);
536 536 }
537 537
538 538 /*
539 539 * srvsvc_s_NetFileEnum
540 540 *
541 541 * Return information on open files or named pipes. Only members of the
542 542 * Administrators or Server Operators local groups are allowed to make
543 543 * this call. Currently, we only support Administrators.
544 544 *
545 545 * If basepath is null, all open resources are enumerated. If basepath
546 546 * is non-null, only resources that have basepath as a prefix should
547 547 * be returned.
548 548 *
549 549 * If username is specified (non-null), only files opened by username
550 550 * should be returned.
551 551 *
552 552 * Notes:
553 553 * 1. We don't validate the servername because we would have to check
554 554 * all primary IPs and the ROI seems unlikely to be worth it.
555 555 * 2. Both basepath and username are currently ignored because both
556 556 * Server Manger (NT 4.0) and CMI (Windows 2000) always set them to null.
557 557 *
558 558 * The level of information requested may be one of:
559 559 *
560 560 * 2 Return the file identification number.
561 561 * This level is not supported on Windows Me/98/95.
562 562 *
563 563 * 3 Return information about the file.
564 564 * This level is not supported on Windows Me/98/95.
565 565 *
566 566 * 50 Windows Me/98/95: Return information about the file.
567 567 *
568 568 * Note:
569 569 * If pref_max_len is unlimited and resume_handle is null, the client
570 570 * expects to receive all data in a single call.
571 571 * If we are unable to do fit all data in a single response, we would
572 572 * normally return ERROR_MORE_DATA with a partial list.
573 573 *
574 574 * Unfortunately, when both of these conditions occur, Server Manager
575 575 * pops up an error box with the message "more data available" and
576 576 * doesn't display any of the returned data. In this case, it is
577 577 * probably better to return ERROR_SUCCESS with the partial list.
578 578 * Windows 2000 doesn't have this problem because it always sends a
579 579 * non-null resume_handle.
580 580 *
581 581 * Return Values:
582 582 * ERROR_SUCCESS Success
583 583 * ERROR_ACCESS_DENIED Caller does not have access to this call.
584 584 * ERROR_INVALID_PARAMETER One of the parameters is invalid.
585 585 * ERROR_INVALID_LEVEL Unknown information level specified.
586 586 * ERROR_MORE_DATA Partial date returned, more entries available.
587 587 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
588 588 * NERR_BufTooSmall The supplied buffer is too small.
589 589 */
590 590 static int
591 591 srvsvc_s_NetFileEnum(void *arg, ndr_xa_t *mxa)
592 592 {
593 593 struct mslm_NetFileEnum *param = arg;
594 594 smb_svcenum_t se;
595 595 DWORD status;
596 596
597 597 if (!ndr_is_admin(mxa)) {
598 598 bzero(param, sizeof (struct mslm_NetFileEnum));
599 599 param->status = ERROR_ACCESS_DENIED;
600 600 return (NDR_DRC_OK);
601 601 }
602 602
603 603 if ((param->total_entries = srvsvc_open_files()) == 0) {
604 604 bzero(param, sizeof (struct mslm_NetFileEnum));
605 605 param->status = ERROR_SUCCESS;
606 606 return (NDR_DRC_OK);
607 607 }
608 608
609 609 bzero(&se, sizeof (smb_svcenum_t));
610 610 se.se_type = SMB_SVCENUM_TYPE_FILE;
611 611 se.se_level = param->info.switch_value;
612 612 se.se_ntotal = param->total_entries;
613 613 se.se_nlimit = se.se_ntotal;
614 614
615 615 if (param->pref_max_len == SMB_SRVSVC_MAXPREFLEN ||
616 616 param->pref_max_len > SMB_SRVSVC_MAXBUFLEN)
617 617 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
618 618 else
619 619 se.se_prefmaxlen = param->pref_max_len;
620 620
621 621 if (param->resume_handle) {
622 622 se.se_resume = *param->resume_handle;
623 623 se.se_nskip = se.se_resume;
624 624 *param->resume_handle = 0;
625 625 }
626 626
627 627 switch (param->info.switch_value) {
628 628 case 2:
629 629 status = srvsvc_NetFileEnum2(mxa, param, &se);
630 630 break;
631 631
632 632 case 3:
633 633 status = srvsvc_NetFileEnum3(mxa, param, &se);
634 634 break;
635 635
636 636 case 50:
637 637 status = ERROR_NOT_SUPPORTED;
638 638 break;
639 639
640 640 default:
641 641 status = ERROR_INVALID_LEVEL;
642 642 break;
643 643 }
644 644
645 645 if (status != ERROR_SUCCESS) {
646 646 bzero(param, sizeof (struct mslm_NetFileEnum));
647 647 param->status = status;
648 648 return (NDR_DRC_OK);
649 649 }
650 650
651 651 if (param->resume_handle &&
652 652 param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
653 653 if (se.se_resume < param->total_entries) {
654 654 *param->resume_handle = se.se_resume;
655 655 status = ERROR_MORE_DATA;
656 656 }
657 657 }
658 658
659 659 param->status = status;
660 660 return (NDR_DRC_OK);
661 661 }
662 662
663 663 /*
664 664 * Build level 2 file information.
665 665 *
666 666 * SMB fids are 16-bit values but this interface expects 32-bit file ids.
667 667 * So we use the uniqid here.
668 668 *
669 669 * On success, the caller expects that the info2, fi2 and entries_read
670 670 * fields have been set up.
671 671 */
672 672 static DWORD
673 673 srvsvc_NetFileEnum2(ndr_xa_t *mxa, struct mslm_NetFileEnum *param,
674 674 smb_svcenum_t *se)
675 675 {
676 676 struct mslm_NetFileInfoBuf2 *fi2;
677 677 smb_netsvc_t *ns;
678 678 smb_netsvcitem_t *item;
679 679 smb_netfileinfo_t *ofile;
680 680 uint32_t entries_read = 0;
681 681
682 682 param->info.ru.info2 = NDR_NEW(mxa, struct mslm_NetFileInfo2);
683 683 if (param->info.ru.info2 == NULL)
684 684 return (ERROR_NOT_ENOUGH_MEMORY);
685 685
686 686 srvsvc_estimate_limit(se, sizeof (struct mslm_NetFileInfoBuf2));
687 687 if (se->se_nlimit == 0)
688 688 return (NERR_BufTooSmall);
689 689
690 690 do {
691 691 fi2 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf2, se->se_nlimit);
692 692 if (fi2 == NULL)
693 693 se->se_nlimit >>= 1;
694 694 } while ((se->se_nlimit > 0) && (fi2 == NULL));
695 695
696 696 if (fi2 == NULL)
697 697 return (ERROR_NOT_ENOUGH_MEMORY);
698 698
699 699 param->info.ru.info2->fi2 = fi2;
700 700
701 701 if ((ns = smb_kmod_enum_init(se)) == NULL)
702 702 return (ERROR_NOT_ENOUGH_MEMORY);
703 703
704 704 if (smb_kmod_enum(ns) != 0) {
705 705 smb_kmod_enum_fini(ns);
706 706 return (ERROR_INTERNAL_ERROR);
707 707 }
708 708
709 709 item = list_head(&ns->ns_list);
710 710 while (item != NULL) {
711 711 ofile = &item->nsi_un.nsi_ofile;
712 712 fi2->fi2_id = ofile->fi_uniqid;
713 713
714 714 ++entries_read;
715 715 ++fi2;
716 716 item = list_next(&ns->ns_list, item);
717 717 }
718 718
719 719 se->se_resume += entries_read;
720 720 param->info.ru.info2->entries_read = entries_read;
721 721 smb_kmod_enum_fini(ns);
722 722 return (ERROR_SUCCESS);
723 723 }
724 724
725 725 /*
726 726 * Build level 3 file information.
727 727 *
728 728 * SMB fids are 16-bit values but this interface expects 32-bit file ids.
729 729 * So we use the uniqid here.
730 730 *
731 731 * On success, the caller expects that the info3, fi3 and entries_read
732 732 * fields have been set up.
733 733 */
734 734 static DWORD
735 735 srvsvc_NetFileEnum3(ndr_xa_t *mxa, struct mslm_NetFileEnum *param,
736 736 smb_svcenum_t *se)
737 737 {
738 738 struct mslm_NetFileInfoBuf3 *fi3;
739 739 smb_netsvc_t *ns;
740 740 smb_netsvcitem_t *item;
741 741 smb_netfileinfo_t *ofile;
742 742 uint32_t entries_read = 0;
743 743
744 744 param->info.ru.info3 = NDR_NEW(mxa, struct mslm_NetFileInfo3);
745 745 if (param->info.ru.info3 == NULL)
746 746 return (ERROR_NOT_ENOUGH_MEMORY);
747 747
748 748 srvsvc_estimate_limit(se,
749 749 sizeof (struct mslm_NetFileInfoBuf3) + MAXNAMELEN);
750 750 if (se->se_nlimit == 0)
751 751 return (NERR_BufTooSmall);
752 752
753 753 do {
754 754 fi3 = NDR_NEWN(mxa, struct mslm_NetFileInfoBuf3, se->se_nlimit);
755 755 if (fi3 == NULL)
756 756 se->se_nlimit >>= 1;
757 757 } while ((se->se_nlimit > 0) && (fi3 == NULL));
758 758
759 759 if (fi3 == NULL)
760 760 return (ERROR_NOT_ENOUGH_MEMORY);
761 761
762 762 param->info.ru.info3->fi3 = fi3;
763 763
764 764 if ((ns = smb_kmod_enum_init(se)) == NULL)
765 765 return (ERROR_NOT_ENOUGH_MEMORY);
766 766
767 767 if (smb_kmod_enum(ns) != 0) {
768 768 smb_kmod_enum_fini(ns);
769 769 return (ERROR_INTERNAL_ERROR);
770 770 }
771 771
772 772 item = list_head(&ns->ns_list);
773 773 while (item != NULL) {
774 774 ofile = &item->nsi_un.nsi_ofile;
775 775 fi3->fi3_id = ofile->fi_uniqid;
776 776 fi3->fi3_permissions = ofile->fi_permissions;
777 777 fi3->fi3_num_locks = ofile->fi_numlocks;
778 778 fi3->fi3_pathname = (uint8_t *)
779 779 NDR_STRDUP(mxa, ofile->fi_path);
780 780 fi3->fi3_username = (uint8_t *)
781 781 NDR_STRDUP(mxa, ofile->fi_username);
782 782
783 783 ++entries_read;
784 784 ++fi3;
785 785 item = list_next(&ns->ns_list, item);
786 786 }
787 787
788 788 se->se_resume += entries_read;
789 789 param->info.ru.info3->entries_read = entries_read;
790 790 param->total_entries = entries_read;
791 791 smb_kmod_enum_fini(ns);
792 792 return (ERROR_SUCCESS);
793 793 }
794 794
795 795 /*
796 796 * srvsvc_s_NetFileClose
797 797 *
798 798 * NetFileClose forces a file to close. This function can be used when
799 799 * an error prevents closure by other means. Use NetFileClose with
800 800 * caution because it does not flush data, cached on a client, to the
801 801 * file before closing the file.
802 802 *
803 803 * SMB fids are 16-bit values but this interface expects 32-bit file ids.
804 804 * So we use the uniqid here.
805 805 *
806 806 * Return Values
807 807 * ERROR_SUCCESS Operation succeeded.
808 808 * ERROR_ACCESS_DENIED Operation denied.
809 809 * NERR_FileIdNotFound No open file with the specified id.
810 810 *
811 811 * Note: MSDN suggests ERROR_FILE_NOT_FOUND for NetFileClose but network
812 812 * captures using NT show NERR_FileIdNotFound, which is consistent with
813 813 * the NetFileClose2 page on MSDN.
814 814 */
815 815 static int
816 816 srvsvc_s_NetFileClose(void *arg, ndr_xa_t *mxa)
817 817 {
818 818 static struct {
819 819 int errnum;
820 820 int nerr;
821 821 } errmap[] = {
822 822 0, ERROR_SUCCESS,
823 823 EACCES, ERROR_ACCESS_DENIED,
824 824 EPERM, ERROR_ACCESS_DENIED,
825 825 EINVAL, ERROR_INVALID_PARAMETER,
826 826 ENOMEM, ERROR_NOT_ENOUGH_MEMORY,
827 827 ENOENT, NERR_FileIdNotFound
828 828 };
829 829
830 830 struct mslm_NetFileClose *param = arg;
831 831 int i;
832 832 int rc;
833 833
834 834 if (!ndr_is_admin(mxa)) {
835 835 param->status = ERROR_ACCESS_DENIED;
836 836 return (NDR_DRC_OK);
837 837 }
838 838
839 839 rc = smb_kmod_file_close(param->file_id);
840 840
841 841 for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
842 842 if (rc == errmap[i].errnum) {
843 843 param->status = errmap[i].nerr;
844 844 return (NDR_DRC_OK);
845 845 }
846 846 }
847 847
848 848 param->status = ERROR_INTERNAL_ERROR;
849 849 return (NDR_DRC_OK);
850 850 }
851 851
852 852 /*
853 853 * srvsvc_s_NetShareGetInfo
854 854 *
855 855 * Returns Win32 error codes.
856 856 */
857 857 static int
858 858 srvsvc_s_NetShareGetInfo(void *arg, ndr_xa_t *mxa)
859 859 {
860 860 struct mlsm_NetShareGetInfo *param = arg;
861 861 struct mslm_NetShareInfo_0 *info0;
862 862 struct mslm_NetShareInfo_1 *info1;
863 863 struct mslm_NetShareInfo_2 *info2;
864 864 struct mslm_NetShareInfo_501 *info501;
865 865 struct mslm_NetShareInfo_502 *info502;
866 866 struct mslm_NetShareInfo_503 *info503;
867 867 struct mslm_NetShareInfo_1004 *info1004;
868 868 struct mslm_NetShareInfo_1005 *info1005;
869 869 struct mslm_NetShareInfo_1006 *info1006;
870 870 struct mslm_NetShareInfo_1501 *info1501;
871 871 srvsvc_netshare_getinfo_t *info;
872 872 uint8_t *netname;
873 873 uint8_t *comment;
874 874 smb_share_t si;
875 875 srvsvc_sd_t sd;
876 876 DWORD status;
877 877
878 878 status = smb_shr_get((char *)param->netname, &si);
879 879 if (status != NERR_Success) {
880 880 bzero(param, sizeof (struct mlsm_NetShareGetInfo));
881 881 param->status = status;
882 882 return (NDR_DRC_OK);
883 883 }
884 884
885 885 netname = (uint8_t *)NDR_STRDUP(mxa, si.shr_name);
886 886 comment = (uint8_t *)NDR_STRDUP(mxa, si.shr_cmnt);
887 887 info = NDR_NEW(mxa, srvsvc_netshare_getinfo_t);
888 888
889 889 if (netname == NULL || comment == NULL || info == NULL) {
890 890 bzero(param, sizeof (struct mlsm_NetShareGetInfo));
891 891 param->status = ERROR_NOT_ENOUGH_MEMORY;
892 892 return (NDR_DRC_OK);
893 893 }
894 894
895 895 switch (param->level) {
896 896 case 0:
897 897 info0 = &info->nsg_info0;
898 898 info0->shi0_netname = netname;
899 899 param->result.ru.info0 = info0;
900 900 break;
901 901
902 902 case 1:
903 903 info1 = &info->nsg_info1;
904 904 info1->shi1_netname = netname;
905 905 info1->shi1_comment = comment;
906 906 info1->shi1_type = si.shr_type;
907 907 param->result.ru.info1 = info1;
908 908 break;
909 909
910 910 case 2:
911 911 info2 = &info->nsg_info2;
912 912 info2->shi2_netname = netname;
913 913 info2->shi2_comment = comment;
914 914 info2->shi2_path =
915 915 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
916 916 info2->shi2_passwd = 0;
917 917 info2->shi2_type = si.shr_type;
918 918 info2->shi2_permissions = 0;
919 919 info2->shi2_max_uses = SHI_USES_UNLIMITED;
920 920 info2->shi2_current_uses = 0;
921 921 param->result.ru.info2 = info2;
922 922 break;
923 923
924 924 case 501:
925 925 info501 = &info->nsg_info501;
926 926 info501->shi501_netname = netname;
927 927 info501->shi501_comment = comment;
928 928 info501->shi501_type = si.shr_type;
929 929 info501->shi501_flags = srvsvc_get_share_flags(&si);
930 930 param->result.ru.info501 = info501;
931 931 break;
932 932
933 933 case 502:
934 934 info502 = &info->nsg_info502;
935 935 info502->shi502_netname = netname;
936 936 info502->shi502_comment = comment;
937 937 info502->shi502_path =
938 938 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
939 939 info502->shi502_passwd = 0;
940 940 info502->shi502_type = si.shr_type;
941 941 info502->shi502_permissions = 0;
942 942 info502->shi502_max_uses = SHI_USES_UNLIMITED;
943 943 info502->shi502_current_uses = 0;
944 944
945 945 status = srvsvc_share_getsd(mxa, &si, &sd);
946 946 if (status == ERROR_SUCCESS) {
947 947 info502->shi502_reserved = sd.sd_size;
948 948 info502->shi502_security_descriptor = sd.sd_buf;
949 949 } else {
950 950 info502->shi502_reserved = 0;
951 951 info502->shi502_security_descriptor = NULL;
952 952 }
953 953
954 954 param->result.ru.info502 = info502;
955 955 break;
956 956
957 957 case 503:
958 958 info503 = &info->nsg_info503;
959 959 info503->shi503_netname = netname;
960 960 info503->shi503_comment = comment;
961 961 info503->shi503_path =
962 962 (uint8_t *)srvsvc_share_mkpath(mxa, si.shr_path);
963 963 info503->shi503_passwd = NULL;
964 964 info503->shi503_type = si.shr_type;
965 965 info503->shi503_permissions = 0;
966 966 info503->shi503_max_uses = SHI_USES_UNLIMITED;
967 967 info503->shi503_current_uses = 0;
968 968 info503->shi503_servername = NULL;
969 969
970 970 status = srvsvc_share_getsd(mxa, &si, &sd);
971 971 if (status == ERROR_SUCCESS) {
972 972 info503->shi503_reserved = sd.sd_size;
973 973 info503->shi503_security_descriptor = sd.sd_buf;
974 974 } else {
975 975 info503->shi503_reserved = 0;
976 976 info503->shi503_security_descriptor = NULL;
977 977 }
978 978
979 979 param->result.ru.info503 = info503;
980 980 break;
981 981
982 982 case 1004:
983 983 info1004 = &info->nsg_info1004;
984 984 info1004->shi1004_comment = comment;
985 985 param->result.ru.info1004 = info1004;
986 986 break;
987 987
988 988 case 1005:
989 989 info1005 = &info->nsg_info1005;
990 990 info1005->shi1005_flags = srvsvc_get_share_flags(&si);
991 991 param->result.ru.info1005 = info1005;
992 992 break;
993 993
994 994 case 1006:
|
↓ open down ↓ |
960 lines elided |
↑ open up ↑ |
995 995 info1006 = &info->nsg_info1006;
996 996 info1006->shi1006_max_uses = SHI_USES_UNLIMITED;
997 997 param->result.ru.info1006 = info1006;
998 998 break;
999 999
1000 1000 case 1501:
1001 1001 info1501 = &info->nsg_info1501;
1002 1002
1003 1003 status = srvsvc_share_getsd(mxa, &si, &sd);
1004 1004 if (status == ERROR_SUCCESS) {
1005 - info503->shi503_reserved = sd.sd_size;
1006 - info503->shi503_security_descriptor = sd.sd_buf;
1005 + info1501->shi1501_reserved = sd.sd_size;
1006 + info1501->shi1501_security_descriptor = sd.sd_buf;
1007 1007 } else {
1008 - info503->shi503_reserved = 0;
1009 - info503->shi503_security_descriptor = NULL;
1008 + info1501->shi1501_reserved = 0;
1009 + info1501->shi1501_security_descriptor = NULL;
1010 1010 }
1011 1011
1012 1012 param->result.ru.info1501 = info1501;
1013 1013 break;
1014 1014
1015 1015 default:
1016 1016 status = ERROR_ACCESS_DENIED;
1017 1017 break;
1018 1018 }
1019 1019
1020 1020 if (status != ERROR_SUCCESS)
1021 1021 bzero(param, sizeof (struct mlsm_NetShareGetInfo));
1022 1022 else
1023 1023 param->result.switch_value = param->level;
1024 1024
1025 1025 param->status = status;
1026 1026 return (NDR_DRC_OK);
1027 1027 }
1028 1028
1029 1029 static uint32_t
1030 1030 srvsvc_share_getsd(ndr_xa_t *mxa, smb_share_t *si, srvsvc_sd_t *sd)
1031 1031 {
1032 1032 uint32_t status;
1033 1033
1034 1034 status = srvsvc_sd_get(si, NULL, &sd->sd_size);
1035 1035 if (status != ERROR_SUCCESS) {
1036 1036 if (status == ERROR_PATH_NOT_FOUND) {
1037 1037 bzero(sd, sizeof (srvsvc_sd_t));
1038 1038 status = ERROR_SUCCESS;
1039 1039 }
1040 1040
1041 1041 return (status);
1042 1042 }
1043 1043
1044 1044 if ((sd->sd_buf = NDR_MALLOC(mxa, sd->sd_size)) == NULL)
1045 1045 return (ERROR_NOT_ENOUGH_MEMORY);
1046 1046
1047 1047 status = srvsvc_sd_get(si, sd->sd_buf, NULL);
1048 1048 if (status == ERROR_PATH_NOT_FOUND) {
1049 1049 bzero(sd, sizeof (srvsvc_sd_t));
1050 1050 status = ERROR_SUCCESS;
1051 1051 }
1052 1052
1053 1053 return (status);
1054 1054 }
1055 1055
1056 1056 /*
1057 1057 * srvsvc_s_NetShareSetInfo
1058 1058 *
1059 1059 * This call is made by SrvMgr to set share information.
1060 1060 * Only power users groups can manage shares.
1061 1061 *
1062 1062 * To avoid misleading errors, we don't report an error
1063 1063 * when a FS doesn't support ACLs on shares.
1064 1064 *
1065 1065 * Returns Win32 error codes.
1066 1066 */
1067 1067 static int
1068 1068 srvsvc_s_NetShareSetInfo(void *arg, ndr_xa_t *mxa)
1069 1069 {
1070 1070 struct mlsm_NetShareSetInfo *param = arg;
1071 1071 struct mslm_NetShareInfo_0 *info0;
1072 1072 struct mslm_NetShareInfo_1 *info1;
1073 1073 struct mslm_NetShareInfo_2 *info2;
1074 1074 struct mslm_NetShareInfo_501 *info501;
1075 1075 struct mslm_NetShareInfo_502 *info502;
1076 1076 struct mslm_NetShareInfo_503 *info503;
1077 1077 struct mslm_NetShareInfo_1004 *info1004;
1078 1078 struct mslm_NetShareInfo_1005 *info1005;
1079 1079 struct mslm_NetShareInfo_1501 *info1501;
1080 1080 static DWORD parm_err = 0;
1081 1081 srvsvc_netshare_setinfo_t info;
1082 1082 smb_share_t si;
1083 1083 uint8_t *sdbuf;
1084 1084 int32_t native_os;
1085 1085 DWORD status;
1086 1086
1087 1087 native_os = ndr_native_os(mxa);
1088 1088
1089 1089 if (!ndr_is_poweruser(mxa)) {
1090 1090 status = ERROR_ACCESS_DENIED;
1091 1091 goto netsharesetinfo_exit;
1092 1092 }
1093 1093
1094 1094 if (smb_shr_get((char *)param->netname, &si) != NERR_Success) {
1095 1095 status = ERROR_INVALID_NETNAME;
1096 1096 goto netsharesetinfo_exit;
1097 1097 }
1098 1098
1099 1099 if (param->result.ru.nullptr == NULL) {
1100 1100 status = ERROR_INVALID_PARAMETER;
1101 1101 goto netsharesetinfo_exit;
1102 1102 }
1103 1103
1104 1104 bzero(&info, sizeof (srvsvc_netshare_setinfo_t));
1105 1105
1106 1106 switch (param->level) {
1107 1107 case 0:
1108 1108 info0 = (struct mslm_NetShareInfo_0 *)param->result.ru.info0;
1109 1109 info.nss_netname = (char *)info0->shi0_netname;
1110 1110 status = srvsvc_modify_share(&si, &info);
1111 1111 break;
1112 1112
1113 1113 case 1:
1114 1114 info1 = (struct mslm_NetShareInfo_1 *)param->result.ru.info1;
1115 1115 info.nss_netname = (char *)info1->shi1_netname;
1116 1116 info.nss_comment = (char *)info1->shi1_comment;
1117 1117 info.nss_type = info1->shi1_type;
1118 1118 status = srvsvc_modify_share(&si, &info);
1119 1119 break;
1120 1120
1121 1121 case 2:
1122 1122 info2 = (struct mslm_NetShareInfo_2 *)param->result.ru.info2;
1123 1123 info.nss_netname = (char *)info2->shi2_netname;
1124 1124 info.nss_comment = (char *)info2->shi2_comment;
1125 1125 info.nss_path = (char *)info2->shi2_path;
1126 1126 info.nss_type = info2->shi2_type;
1127 1127 status = srvsvc_modify_share(&si, &info);
1128 1128 break;
1129 1129
1130 1130 case 501:
1131 1131 info501 = (struct mslm_NetShareInfo_501 *)
1132 1132 param->result.ru.info501;
1133 1133 info.nss_netname = (char *)info501->shi501_netname;
1134 1134 info.nss_comment = (char *)info501->shi501_comment;
1135 1135 info.nss_type = info501->shi501_type;
1136 1136 status = srvsvc_modify_share(&si, &info);
1137 1137 if (status == ERROR_SUCCESS)
1138 1138 status = srvsvc_update_share_flags(&si,
1139 1139 info501->shi501_flags);
1140 1140 break;
1141 1141
1142 1142 case 502:
1143 1143 info502 = (struct mslm_NetShareInfo_502 *)
1144 1144 param->result.ru.info502;
1145 1145 info.nss_netname = (char *)info502->shi502_netname;
1146 1146 info.nss_comment = (char *)info502->shi502_comment;
1147 1147 info.nss_path = (char *)info502->shi502_path;
1148 1148 info.nss_type = info502->shi502_type;
1149 1149 info.nss_sd.sd_buf = info502->shi502_security_descriptor;
1150 1150 status = srvsvc_modify_share(&si, &info);
1151 1151 break;
1152 1152
1153 1153 case 503:
1154 1154 info503 = (struct mslm_NetShareInfo_503 *)
1155 1155 param->result.ru.info503;
1156 1156 info.nss_netname = (char *)info503->shi503_netname;
1157 1157 info.nss_comment = (char *)info503->shi503_comment;
1158 1158 info.nss_path = (char *)info503->shi503_path;
1159 1159 info.nss_type = info503->shi503_type;
1160 1160 info.nss_sd.sd_buf = info503->shi503_security_descriptor;
1161 1161 status = srvsvc_modify_share(&si, &info);
1162 1162 break;
1163 1163
1164 1164 case 1004:
1165 1165 info1004 = (struct mslm_NetShareInfo_1004 *)
1166 1166 param->result.ru.info1004;
1167 1167 info.nss_comment = (char *)info1004->shi1004_comment;
1168 1168 status = srvsvc_modify_share(&si, &info);
1169 1169 break;
1170 1170
1171 1171 case 1005:
1172 1172 info1005 = (struct mslm_NetShareInfo_1005 *)
1173 1173 param->result.ru.info1005;
1174 1174 status = srvsvc_update_share_flags(&si,
1175 1175 info1005->shi1005_flags);
1176 1176 break;
1177 1177
1178 1178 case 1006:
1179 1179 /*
1180 1180 * We don't limit the maximum number of concurrent
1181 1181 * connections to a share.
1182 1182 */
1183 1183 status = ERROR_SUCCESS;
1184 1184 break;
1185 1185
1186 1186 case 1501:
1187 1187 info1501 = (struct mslm_NetShareInfo_1501 *)
1188 1188 param->result.ru.info1501;
1189 1189 sdbuf = info1501->shi1501_security_descriptor;
1190 1190 status = ERROR_SUCCESS;
1191 1191
1192 1192 if (sdbuf != NULL) {
1193 1193 status = srvsvc_sd_set(&si, sdbuf);
1194 1194 if (status == ERROR_PATH_NOT_FOUND)
1195 1195 status = ERROR_SUCCESS;
1196 1196 }
1197 1197 break;
1198 1198
1199 1199 default:
1200 1200 status = ERROR_ACCESS_DENIED;
1201 1201 break;
1202 1202 }
1203 1203
1204 1204 netsharesetinfo_exit:
1205 1205 if (status != ERROR_SUCCESS)
1206 1206 bzero(param, sizeof (struct mlsm_NetShareSetInfo));
1207 1207
1208 1208 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
1209 1209 param->status = status;
1210 1210 return (NDR_DRC_OK);
1211 1211 }
1212 1212
1213 1213 static uint32_t
1214 1214 srvsvc_modify_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
1215 1215 {
1216 1216 uint32_t nerr = NERR_Success;
1217 1217
1218 1218 if (si->shr_flags & SMB_SHRF_TRANS)
1219 1219 return (srvsvc_modify_transient_share(si, info));
1220 1220
1221 1221 if (info->nss_sd.sd_buf != NULL) {
1222 1222 nerr = srvsvc_sd_set(si, info->nss_sd.sd_buf);
1223 1223 if (nerr == ERROR_PATH_NOT_FOUND)
1224 1224 nerr = NERR_Success;
1225 1225 }
1226 1226
1227 1227 if ((nerr = srvsvc_sa_modify(si, info)) == NERR_Success)
1228 1228 nerr = smb_shr_modify(si);
1229 1229
1230 1230 return (nerr);
1231 1231 }
1232 1232
1233 1233 /*
1234 1234 * Update transient shares. This includes autohome shares.
1235 1235 */
1236 1236 static uint32_t
1237 1237 srvsvc_modify_transient_share(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
1238 1238 {
1239 1239 uint32_t nerr;
1240 1240
1241 1241 if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
1242 1242 smb_strcasecmp(info->nss_netname, si->shr_name, 0) != 0) {
1243 1243 nerr = smb_shr_rename(si->shr_name, info->nss_netname);
1244 1244 if (nerr != NERR_Success)
1245 1245 return (nerr);
1246 1246
1247 1247 (void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
1248 1248 }
1249 1249
1250 1250 if ((info->nss_comment != NULL) &&
1251 1251 (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
1252 1252 (void) strlcpy(si->shr_cmnt, info->nss_comment,
1253 1253 SMB_SHARE_CMNT_MAX);
1254 1254
1255 1255 if ((nerr = smb_shr_modify(si)) != NERR_Success)
1256 1256 return (nerr);
1257 1257 }
1258 1258
1259 1259 return (NERR_Success);
1260 1260 }
1261 1261
1262 1262 /*
1263 1263 * srvsvc_update_share_flags
1264 1264 *
1265 1265 * This function updates flags for shares.
1266 1266 * Flags for Persistent shares are updated in both libshare and the local cache.
1267 1267 * Flags for Transient shares are updated only in the local cache.
1268 1268 */
1269 1269 static uint32_t
1270 1270 srvsvc_update_share_flags(smb_share_t *si, uint32_t shi_flags)
1271 1271 {
1272 1272 uint32_t nerr = NERR_Success;
1273 1273 uint32_t flag = 0;
1274 1274 char *csc_value;
1275 1275 char *abe_value = "false";
1276 1276 nvlist_t *nvl;
1277 1277 int err = 0;
1278 1278
1279 1279 if (shi_flags & SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM) {
1280 1280 flag = SMB_SHRF_ABE;
1281 1281 abe_value = "true";
1282 1282 }
1283 1283
1284 1284 si->shr_flags &= ~SMB_SHRF_ABE;
1285 1285 si->shr_flags |= flag;
1286 1286
1287 1287 switch ((shi_flags & CSC_MASK)) {
1288 1288 case CSC_CACHE_AUTO_REINT:
1289 1289 flag = SMB_SHRF_CSC_AUTO;
1290 1290 break;
1291 1291 case CSC_CACHE_VDO:
1292 1292 flag = SMB_SHRF_CSC_VDO;
1293 1293 break;
1294 1294 case CSC_CACHE_NONE:
1295 1295 flag = SMB_SHRF_CSC_DISABLED;
1296 1296 break;
1297 1297 case CSC_CACHE_MANUAL_REINT:
1298 1298 flag = SMB_SHRF_CSC_MANUAL;
1299 1299 break;
1300 1300 default:
1301 1301 return (NERR_InternalError);
1302 1302 }
1303 1303
1304 1304 si->shr_flags &= ~SMB_SHRF_CSC_MASK;
1305 1305 si->shr_flags |= flag;
1306 1306
1307 1307 if ((si->shr_flags & SMB_SHRF_TRANS) == 0) {
1308 1308 csc_value = smb_shr_sa_csc_name(si);
1309 1309
1310 1310 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1311 1311 return (NERR_InternalError);
1312 1312
1313 1313 err |= nvlist_add_string(nvl, SHOPT_CSC, csc_value);
1314 1314 err |= nvlist_add_string(nvl, SHOPT_ABE, abe_value);
1315 1315 if (err) {
1316 1316 nvlist_free(nvl);
1317 1317 return (NERR_InternalError);
1318 1318 }
1319 1319
1320 1320 nerr = srvsvc_sa_setprop(si, nvl);
1321 1321 nvlist_free(nvl);
1322 1322
1323 1323 if (nerr != NERR_Success)
1324 1324 return (nerr);
1325 1325 }
1326 1326
1327 1327 return (smb_shr_modify(si));
1328 1328 }
1329 1329
1330 1330 static uint32_t
1331 1331 srvsvc_get_share_flags(smb_share_t *si)
1332 1332 {
1333 1333 uint32_t flags = 0;
1334 1334 boolean_t shortnames = B_TRUE;
1335 1335
1336 1336 switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
1337 1337 case SMB_SHRF_CSC_DISABLED:
1338 1338 flags |= CSC_CACHE_NONE;
1339 1339 break;
1340 1340 case SMB_SHRF_CSC_AUTO:
1341 1341 flags |= CSC_CACHE_AUTO_REINT;
1342 1342 break;
1343 1343 case SMB_SHRF_CSC_VDO:
1344 1344 flags |= CSC_CACHE_VDO;
1345 1345 break;
1346 1346 case SMB_SHRF_CSC_MANUAL:
1347 1347 default:
1348 1348 /*
1349 1349 * Default to CSC_CACHE_MANUAL_REINT.
1350 1350 */
1351 1351 break;
1352 1352 }
1353 1353
1354 1354 if (si->shr_flags & SMB_SHRF_ABE)
1355 1355 flags |= SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
1356 1356
1357 1357 /* if 'smb' zfs property: shortnames=disabled */
1358 1358 if ((smb_kmod_shareinfo(si->shr_name, &shortnames) == 0) &&
1359 1359 (shortnames == B_FALSE)) {
1360 1360 flags |= SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING;
1361 1361 }
1362 1362
1363 1363 return (flags);
1364 1364 }
1365 1365
1366 1366 /*
1367 1367 * srvsvc_s_NetSessionEnum
1368 1368 *
1369 1369 * Level 1 request is made by (Server Manager (srvmgr) on NT Server when
1370 1370 * the user info icon is selected.
1371 1371 *
1372 1372 * On success, the return value is NERR_Success.
1373 1373 * On error, the return value can be one of the following error codes:
1374 1374 *
1375 1375 * ERROR_ACCESS_DENIED The user does not have access to the requested
1376 1376 * information.
1377 1377 * ERROR_INVALID_LEVEL The value specified for the level is invalid.
1378 1378 * ERROR_INVALID_PARAMETER The specified parameter is invalid.
1379 1379 * ERROR_MORE_DATA More entries are available. Specify a large
1380 1380 * enough buffer to receive all entries.
1381 1381 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
1382 1382 * NERR_ClientNameNotFound A session does not exist with the computer name.
1383 1383 * NERR_InvalidComputer The computer name is invalid.
1384 1384 * NERR_UserNotFound The user name could not be found.
1385 1385 */
1386 1386 static int
1387 1387 srvsvc_s_NetSessionEnum(void *arg, ndr_xa_t *mxa)
1388 1388 {
1389 1389 struct mslm_NetSessionEnum *param = arg;
1390 1390 srvsvc_infonres_t *info;
1391 1391 smb_netsvc_t *ns;
1392 1392 smb_svcenum_t se;
1393 1393 DWORD status = ERROR_SUCCESS;
1394 1394
1395 1395 if (!ndr_is_admin(mxa)) {
1396 1396 status = ERROR_ACCESS_DENIED;
1397 1397 goto srvsvc_netsessionenum_error;
1398 1398 }
1399 1399
1400 1400 if ((info = NDR_NEW(mxa, srvsvc_infonres_t)) == NULL) {
1401 1401 status = ERROR_NOT_ENOUGH_MEMORY;
1402 1402 goto srvsvc_netsessionenum_error;
1403 1403 }
1404 1404
1405 1405 info->entriesread = 0;
1406 1406 info->entries = NULL;
1407 1407 param->result.level = param->level;
1408 1408 param->result.bufptr.p = info;
1409 1409
1410 1410 if ((param->total_entries = srvsvc_open_sessions()) == 0) {
1411 1411 param->resume_handle = NULL;
1412 1412 param->status = ERROR_SUCCESS;
1413 1413 return (NDR_DRC_OK);
1414 1414 }
1415 1415
1416 1416 bzero(&se, sizeof (smb_svcenum_t));
1417 1417 se.se_type = SMB_SVCENUM_TYPE_USER;
1418 1418 se.se_level = param->level;
1419 1419 se.se_ntotal = param->total_entries;
1420 1420 se.se_nlimit = se.se_ntotal;
1421 1421
1422 1422 if (param->resume_handle) {
1423 1423 se.se_resume = *param->resume_handle;
1424 1424 se.se_nskip = se.se_resume;
1425 1425 *param->resume_handle = 0;
1426 1426 }
1427 1427
1428 1428 switch (param->level) {
1429 1429 case 0:
1430 1430 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_0,
1431 1431 se.se_nlimit);
1432 1432 break;
1433 1433 case 1:
1434 1434 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_1,
1435 1435 se.se_nlimit);
1436 1436 break;
1437 1437 case 2:
1438 1438 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_2,
1439 1439 se.se_nlimit);
1440 1440 break;
1441 1441 case 10:
1442 1442 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_10,
1443 1443 se.se_nlimit);
1444 1444 break;
1445 1445 case 502:
1446 1446 info->entries = NDR_NEWN(mxa, struct mslm_SESSION_INFO_502,
1447 1447 se.se_nlimit);
1448 1448 break;
1449 1449 default:
1450 1450 bzero(param, sizeof (struct mslm_NetSessionEnum));
1451 1451 param->status = ERROR_INVALID_LEVEL;
1452 1452 return (NDR_DRC_OK);
1453 1453 }
1454 1454
1455 1455 if (info->entries == NULL) {
1456 1456 status = ERROR_NOT_ENOUGH_MEMORY;
1457 1457 goto srvsvc_netsessionenum_error;
1458 1458 }
1459 1459
1460 1460 if ((ns = smb_kmod_enum_init(&se)) == NULL) {
1461 1461 status = ERROR_NOT_ENOUGH_MEMORY;
1462 1462 goto srvsvc_netsessionenum_error;
1463 1463 }
1464 1464
1465 1465 status = srvsvc_NetSessionEnumCommon(mxa, info, ns, &se);
1466 1466 smb_kmod_enum_fini(ns);
1467 1467
1468 1468 if (status != ERROR_SUCCESS)
1469 1469 goto srvsvc_netsessionenum_error;
1470 1470
1471 1471 if (param->resume_handle &&
1472 1472 param->pref_max_len != SMB_SRVSVC_MAXPREFLEN) {
1473 1473 if (se.se_resume < param->total_entries) {
1474 1474 *param->resume_handle = se.se_resume;
1475 1475 status = ERROR_MORE_DATA;
1476 1476 }
1477 1477 }
1478 1478
1479 1479 param->total_entries = info->entriesread;
1480 1480 param->status = status;
1481 1481 return (NDR_DRC_OK);
1482 1482
1483 1483 srvsvc_netsessionenum_error:
1484 1484 bzero(param, sizeof (struct mslm_NetSessionEnum));
1485 1485 param->status = status;
1486 1486 return (NDR_DRC_OK);
1487 1487 }
1488 1488
1489 1489 static uint32_t
1490 1490 srvsvc_NetSessionEnumCommon(ndr_xa_t *mxa, srvsvc_infonres_t *info,
1491 1491 smb_netsvc_t *ns, smb_svcenum_t *se)
1492 1492 {
1493 1493 struct mslm_SESSION_INFO_0 *info0 = info->entries;
1494 1494 struct mslm_SESSION_INFO_1 *info1 = info->entries;
1495 1495 struct mslm_SESSION_INFO_2 *info2 = info->entries;
1496 1496 struct mslm_SESSION_INFO_10 *info10 = info->entries;
1497 1497 struct mslm_SESSION_INFO_502 *info502 = info->entries;
1498 1498 smb_netsvcitem_t *item;
1499 1499 smb_netuserinfo_t *user;
1500 1500 char *workstation;
1501 1501 char account[MAXNAMELEN];
1502 1502 char ipaddr_buf[INET6_ADDRSTRLEN];
1503 1503 uint32_t logon_time;
1504 1504 uint32_t flags;
1505 1505 uint32_t entries_read = 0;
1506 1506
1507 1507 if (smb_kmod_enum(ns) != 0)
1508 1508 return (ERROR_INTERNAL_ERROR);
1509 1509
1510 1510 item = list_head(&ns->ns_list);
1511 1511 while (item != NULL) {
1512 1512 user = &item->nsi_un.nsi_user;
1513 1513
1514 1514 workstation = user->ui_workstation;
1515 1515 if (workstation == NULL || *workstation == '\0') {
1516 1516 (void) smb_inet_ntop(&user->ui_ipaddr, ipaddr_buf,
1517 1517 SMB_IPSTRLEN(user->ui_ipaddr.a_family));
1518 1518 workstation = ipaddr_buf;
1519 1519 }
1520 1520
1521 1521 (void) snprintf(account, MAXNAMELEN, "%s\\%s",
1522 1522 user->ui_domain, user->ui_account);
1523 1523
1524 1524 logon_time = time(0) - user->ui_logon_time;
1525 1525 flags = (user->ui_flags & SMB_ATF_GUEST) ? SESS_GUEST : 0;
1526 1526
1527 1527 switch (se->se_level) {
1528 1528 case 0:
1529 1529 info0->sesi0_cname = NDR_STRDUP(mxa, workstation);
1530 1530 if (info0->sesi0_cname == NULL)
1531 1531 return (ERROR_NOT_ENOUGH_MEMORY);
1532 1532 ++info0;
1533 1533 break;
1534 1534
1535 1535 case 1:
1536 1536 info1->sesi1_cname = NDR_STRDUP(mxa, workstation);
1537 1537 info1->sesi1_uname = NDR_STRDUP(mxa, account);
1538 1538
1539 1539 if (info1->sesi1_cname == NULL ||
1540 1540 info1->sesi1_uname == NULL)
1541 1541 return (ERROR_NOT_ENOUGH_MEMORY);
1542 1542
1543 1543 info1->sesi1_nopens = user->ui_numopens;
1544 1544 info1->sesi1_time = logon_time;
1545 1545 info1->sesi1_itime = 0;
1546 1546 info1->sesi1_uflags = flags;
1547 1547 ++info1;
1548 1548 break;
1549 1549
1550 1550 case 2:
1551 1551 info2->sesi2_cname = NDR_STRDUP(mxa, workstation);
1552 1552 info2->sesi2_uname = NDR_STRDUP(mxa, account);
1553 1553
1554 1554 if (info2->sesi2_cname == NULL ||
1555 1555 info2->sesi2_uname == NULL)
1556 1556 return (ERROR_NOT_ENOUGH_MEMORY);
1557 1557
1558 1558 info2->sesi2_nopens = user->ui_numopens;
1559 1559 info2->sesi2_time = logon_time;
1560 1560 info2->sesi2_itime = 0;
1561 1561 info2->sesi2_uflags = flags;
1562 1562 info2->sesi2_cltype_name = (uint8_t *)"";
1563 1563 ++info2;
1564 1564 break;
1565 1565
1566 1566 case 10:
1567 1567 info10->sesi10_cname = NDR_STRDUP(mxa, workstation);
1568 1568 info10->sesi10_uname = NDR_STRDUP(mxa, account);
1569 1569
1570 1570 if (info10->sesi10_cname == NULL ||
1571 1571 info10->sesi10_uname == NULL)
1572 1572 return (ERROR_NOT_ENOUGH_MEMORY);
1573 1573
1574 1574 info10->sesi10_time = logon_time;
1575 1575 info10->sesi10_itime = 0;
1576 1576 ++info10;
1577 1577 break;
1578 1578
1579 1579 case 502:
1580 1580 info502->sesi502_cname = NDR_STRDUP(mxa, workstation);
1581 1581 info502->sesi502_uname = NDR_STRDUP(mxa, account);
1582 1582
1583 1583 if (info502->sesi502_cname == NULL ||
1584 1584 info502->sesi502_uname == NULL)
1585 1585 return (ERROR_NOT_ENOUGH_MEMORY);
1586 1586
1587 1587 info502->sesi502_nopens = user->ui_numopens;
1588 1588 info502->sesi502_time = logon_time;
1589 1589 info502->sesi502_itime = 0;
1590 1590 info502->sesi502_uflags = flags;
1591 1591 info502->sesi502_cltype_name = (uint8_t *)"";
1592 1592 info502->sesi502_transport = (uint8_t *)"";
1593 1593 ++info502;
1594 1594 break;
1595 1595
1596 1596 default:
1597 1597 return (ERROR_INVALID_LEVEL);
1598 1598 }
1599 1599
1600 1600 ++entries_read;
1601 1601 item = list_next(&ns->ns_list, item);
1602 1602 }
1603 1603
1604 1604 info->entriesread = entries_read;
1605 1605 return (ERROR_SUCCESS);
1606 1606 }
1607 1607
1608 1608 /*
1609 1609 * srvsvc_s_NetSessionDel
1610 1610 *
1611 1611 * Ends a network session between a server and a workstation.
1612 1612 * On NT only members of the Administrators or Account Operators
1613 1613 * local groups are permitted to use NetSessionDel.
1614 1614 *
1615 1615 * If unc_clientname is NULL, all sessions associated with the
1616 1616 * specified user will be disconnected.
1617 1617 *
1618 1618 * If username is NULL, all sessions from the specified client
1619 1619 * will be disconnected.
1620 1620 *
1621 1621 * Return Values
1622 1622 * On success, the return value is NERR_Success/ERROR_SUCCESS.
1623 1623 * On failure, the return value can be one of the following errors:
1624 1624 *
1625 1625 * ERROR_ACCESS_DENIED The user does not have access to the
1626 1626 * requested information.
1627 1627 * ERROR_INVALID_PARAMETER The specified parameter is invalid.
1628 1628 * ERROR_NOT_ENOUGH_MEMORY Insufficient memory is available.
1629 1629 * NERR_ClientNameNotFound A session does not exist with that
1630 1630 * computer name.
1631 1631 */
1632 1632 static int
1633 1633 srvsvc_s_NetSessionDel(void *arg, ndr_xa_t *mxa)
1634 1634 {
1635 1635 static struct {
1636 1636 int errnum;
1637 1637 int nerr;
1638 1638 } errmap[] = {
1639 1639 0, ERROR_SUCCESS,
1640 1640 EACCES, ERROR_ACCESS_DENIED,
1641 1641 EPERM, ERROR_ACCESS_DENIED,
1642 1642 EINVAL, ERROR_INVALID_PARAMETER,
1643 1643 ENOMEM, ERROR_NOT_ENOUGH_MEMORY,
1644 1644 ENOENT, NERR_ClientNameNotFound
1645 1645 };
1646 1646
1647 1647 struct mslm_NetSessionDel *param = arg;
1648 1648 int i;
1649 1649 int rc;
1650 1650
1651 1651 if (!ndr_is_admin(mxa)) {
1652 1652 param->status = ERROR_ACCESS_DENIED;
1653 1653 return (NDR_DRC_OK);
1654 1654 }
1655 1655
1656 1656 rc = smb_kmod_session_close((char *)param->unc_clientname,
1657 1657 (char *)param->username);
1658 1658
1659 1659 for (i = 0; i < (sizeof (errmap) / sizeof (errmap[0])); ++i) {
1660 1660 if (rc == errmap[i].errnum) {
1661 1661 param->status = errmap[i].nerr;
1662 1662 return (NDR_DRC_OK);
1663 1663 }
1664 1664 }
1665 1665
1666 1666 param->status = ERROR_INTERNAL_ERROR;
1667 1667 return (NDR_DRC_OK);
1668 1668 }
1669 1669
1670 1670 static int
1671 1671 srvsvc_s_NetServerGetInfo(void *arg, ndr_xa_t *mxa)
1672 1672 {
1673 1673 struct mslm_NetServerGetInfo *param = arg;
1674 1674 struct mslm_SERVER_INFO_100 *info100;
1675 1675 struct mslm_SERVER_INFO_101 *info101;
1676 1676 struct mslm_SERVER_INFO_102 *info102;
1677 1677 struct mslm_SERVER_INFO_502 *info502;
1678 1678 struct mslm_SERVER_INFO_503 *info503;
1679 1679 char sys_comment[SMB_PI_MAX_COMMENT];
1680 1680 char hostname[NETBIOS_NAME_SZ];
1681 1681 smb_version_t version;
1682 1682
1683 1683 if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) {
1684 1684 netservergetinfo_no_memory:
1685 1685 bzero(param, sizeof (struct mslm_NetServerGetInfo));
1686 1686 return (ERROR_NOT_ENOUGH_MEMORY);
1687 1687 }
1688 1688
1689 1689 (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment,
1690 1690 sizeof (sys_comment));
1691 1691 if (*sys_comment == '\0')
1692 1692 (void) strcpy(sys_comment, " ");
1693 1693
1694 1694 smb_config_get_version(&version);
1695 1695
1696 1696 switch (param->level) {
1697 1697 case 100:
1698 1698 info100 = NDR_NEW(mxa, struct mslm_SERVER_INFO_100);
1699 1699 if (info100 == NULL)
1700 1700 goto netservergetinfo_no_memory;
1701 1701
1702 1702 bzero(info100, sizeof (struct mslm_SERVER_INFO_100));
1703 1703 info100->sv100_platform_id = SV_PLATFORM_ID_NT;
1704 1704 info100->sv100_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
1705 1705 if (info100->sv100_name == NULL)
1706 1706 goto netservergetinfo_no_memory;
1707 1707
1708 1708 param->result.bufptr.bufptr100 = info100;
1709 1709 break;
1710 1710
1711 1711 case 101:
1712 1712 info101 = NDR_NEW(mxa, struct mslm_SERVER_INFO_101);
1713 1713 if (info101 == NULL)
1714 1714 goto netservergetinfo_no_memory;
1715 1715
1716 1716 bzero(info101, sizeof (struct mslm_SERVER_INFO_101));
1717 1717 info101->sv101_platform_id = SV_PLATFORM_ID_NT;
1718 1718 info101->sv101_version_major = version.sv_major;
1719 1719 info101->sv101_version_minor = version.sv_minor;
1720 1720 info101->sv101_type = SV_TYPE_DEFAULT;
1721 1721 info101->sv101_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
1722 1722 info101->sv101_comment
1723 1723 = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
1724 1724
1725 1725 if (info101->sv101_name == NULL ||
1726 1726 info101->sv101_comment == NULL)
1727 1727 goto netservergetinfo_no_memory;
1728 1728
1729 1729 param->result.bufptr.bufptr101 = info101;
1730 1730 break;
1731 1731
1732 1732 case 102:
1733 1733 info102 = NDR_NEW(mxa, struct mslm_SERVER_INFO_102);
1734 1734 if (info102 == NULL)
1735 1735 goto netservergetinfo_no_memory;
1736 1736
1737 1737 bzero(info102, sizeof (struct mslm_SERVER_INFO_102));
1738 1738 info102->sv102_platform_id = SV_PLATFORM_ID_NT;
1739 1739 info102->sv102_version_major = version.sv_major;
1740 1740 info102->sv102_version_minor = version.sv_minor;
1741 1741 info102->sv102_type = SV_TYPE_DEFAULT;
1742 1742 info102->sv102_name = (uint8_t *)NDR_STRDUP(mxa, hostname);
1743 1743 info102->sv102_comment
1744 1744 = (uint8_t *)NDR_STRDUP(mxa, sys_comment);
1745 1745
1746 1746 /*
1747 1747 * The following level 102 fields are defaulted to zero
1748 1748 * by virtue of the call to bzero above.
1749 1749 *
1750 1750 * sv102_users
1751 1751 * sv102_disc
1752 1752 * sv102_hidden
1753 1753 * sv102_announce
1754 1754 * sv102_anndelta
1755 1755 * sv102_licenses
1756 1756 * sv102_userpath
1757 1757 */
1758 1758 if (info102->sv102_name == NULL ||
1759 1759 info102->sv102_comment == NULL)
1760 1760 goto netservergetinfo_no_memory;
1761 1761
1762 1762 param->result.bufptr.bufptr102 = info102;
1763 1763 break;
1764 1764
1765 1765 case 502:
1766 1766 info502 = NDR_NEW(mxa, struct mslm_SERVER_INFO_502);
1767 1767 if (info502 == NULL)
1768 1768 goto netservergetinfo_no_memory;
1769 1769
1770 1770 bzero(info502, sizeof (struct mslm_SERVER_INFO_502));
1771 1771 param->result.bufptr.bufptr502 = info502;
1772 1772 #ifdef SRVSVC_SATISFY_SMBTORTURE
1773 1773 break;
1774 1774 #else
1775 1775 param->result.level = param->level;
1776 1776 param->status = ERROR_ACCESS_DENIED;
1777 1777 return (NDR_DRC_OK);
1778 1778 #endif /* SRVSVC_SATISFY_SMBTORTURE */
1779 1779
1780 1780 case 503:
1781 1781 info503 = NDR_NEW(mxa, struct mslm_SERVER_INFO_503);
1782 1782 if (info503 == NULL)
1783 1783 goto netservergetinfo_no_memory;
1784 1784
1785 1785 bzero(info503, sizeof (struct mslm_SERVER_INFO_503));
1786 1786 param->result.bufptr.bufptr503 = info503;
1787 1787 #ifdef SRVSVC_SATISFY_SMBTORTURE
1788 1788 break;
1789 1789 #else
1790 1790 param->result.level = param->level;
1791 1791 param->status = ERROR_ACCESS_DENIED;
1792 1792 return (NDR_DRC_OK);
1793 1793 #endif /* SRVSVC_SATISFY_SMBTORTURE */
1794 1794
1795 1795 default:
1796 1796 bzero(¶m->result,
1797 1797 sizeof (struct mslm_NetServerGetInfo_result));
1798 1798 param->status = ERROR_ACCESS_DENIED;
1799 1799 return (NDR_DRC_OK);
1800 1800 }
1801 1801
1802 1802 param->result.level = param->level;
1803 1803 param->status = ERROR_SUCCESS;
1804 1804 return (NDR_DRC_OK);
1805 1805 }
1806 1806
1807 1807 /*
1808 1808 * NetRemoteTOD
1809 1809 *
1810 1810 * Returns information about the time of day on this server.
1811 1811 *
1812 1812 * typedef struct _TIME_OF_DAY_INFO {
1813 1813 * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT
1814 1814 * DWORD tod_msecs; // arbitrary milliseconds (since reset)
1815 1815 * DWORD tod_hours; // current hour [0-23]
1816 1816 * DWORD tod_mins; // current minute [0-59]
1817 1817 * DWORD tod_secs; // current second [0-59]
1818 1818 * DWORD tod_hunds; // current hundredth (0.01) second [0-99]
1819 1819 * LONG tod_timezone; // time zone of the server
1820 1820 * DWORD tod_tinterval; // clock tick time interval
1821 1821 * DWORD tod_day; // day of the month [1-31]
1822 1822 * DWORD tod_month; // month of the year [1-12]
1823 1823 * DWORD tod_year; // current year
1824 1824 * DWORD tod_weekday; // day of the week since Sunday [0-6]
1825 1825 * } TIME_OF_DAY_INFO;
1826 1826 *
1827 1827 * The time zone of the server is calculated in minutes from Greenwich
1828 1828 * Mean Time (GMT). For time zones west of Greenwich, the value is
1829 1829 * positive; for time zones east of Greenwich, the value is negative.
1830 1830 * A value of -1 indicates that the time zone is undefined.
1831 1831 *
1832 1832 * Determine offset from GMT. If daylight saving time use altzone,
1833 1833 * otherwise use timezone.
1834 1834 *
1835 1835 * The clock tick value represents a resolution of one ten-thousandth
1836 1836 * (0.0001) second.
1837 1837 */
1838 1838 static int
1839 1839 srvsvc_s_NetRemoteTOD(void *arg, ndr_xa_t *mxa)
1840 1840 {
1841 1841 struct mslm_NetRemoteTOD *param = arg;
1842 1842 struct mslm_TIME_OF_DAY_INFO *tod;
1843 1843 struct timeval time_val;
1844 1844 struct tm tm;
1845 1845 time_t gmtoff;
1846 1846
1847 1847
1848 1848 (void) gettimeofday(&time_val, 0);
1849 1849 (void) gmtime_r(&time_val.tv_sec, &tm);
1850 1850
1851 1851 tod = NDR_NEW(mxa, struct mslm_TIME_OF_DAY_INFO);
1852 1852 if (tod == NULL) {
1853 1853 bzero(param, sizeof (struct mslm_NetRemoteTOD));
1854 1854 return (ERROR_NOT_ENOUGH_MEMORY);
1855 1855 }
1856 1856
1857 1857 bzero(tod, sizeof (struct mslm_TIME_OF_DAY_INFO));
1858 1858
1859 1859 tod->tod_elapsedt = time_val.tv_sec;
1860 1860 tod->tod_msecs = time_val.tv_usec;
1861 1861 tod->tod_hours = tm.tm_hour;
1862 1862 tod->tod_mins = tm.tm_min;
1863 1863 tod->tod_secs = tm.tm_sec;
1864 1864 tod->tod_hunds = 0;
1865 1865 tod->tod_tinterval = 1000;
1866 1866 tod->tod_day = tm.tm_mday;
1867 1867 tod->tod_month = tm.tm_mon+1;
1868 1868 tod->tod_year = tm.tm_year+1900;
1869 1869 tod->tod_weekday = tm.tm_wday;
1870 1870
1871 1871 (void) localtime_r(&time_val.tv_sec, &tm);
1872 1872 gmtoff = (tm.tm_isdst) ? altzone : timezone;
1873 1873 tod->tod_timezone = gmtoff / SECSPERMIN;
1874 1874
1875 1875 param->bufptr = tod;
1876 1876 param->status = ERROR_SUCCESS;
1877 1877 return (NDR_DRC_OK);
1878 1878 }
1879 1879
1880 1880 /*
1881 1881 * srvsvc_s_NetNameValidate
1882 1882 *
1883 1883 * Perform name validation.
1884 1884 *
1885 1885 * Returns Win32 error codes.
1886 1886 */
1887 1887 /*ARGSUSED*/
1888 1888 static int
1889 1889 srvsvc_s_NetNameValidate(void *arg, ndr_xa_t *mxa)
1890 1890 {
1891 1891 struct mslm_NetNameValidate *param = arg;
1892 1892 char *name;
1893 1893 int maxlen;
1894 1894 int len;
1895 1895
1896 1896 if ((name = (char *)param->pathname) == NULL) {
1897 1897 param->status = ERROR_INVALID_PARAMETER;
1898 1898 return (NDR_DRC_OK);
1899 1899 }
1900 1900
1901 1901 switch (param->type) {
1902 1902 case NAMETYPE_SHARE:
1903 1903 len = strlen(name);
1904 1904 maxlen = (param->flags & NAMEFLAG_LM2) ?
1905 1905 SMB_SHARE_OEMNAME_MAX : SMB_SHARE_NTNAME_MAX;
1906 1906
1907 1907 if (len > maxlen) {
1908 1908 param->status = ERROR_INVALID_NAME;
1909 1909 return (NDR_DRC_OK);
1910 1910 }
1911 1911
1912 1912 param->status = smb_name_validate_share(name);
1913 1913 break;
1914 1914
1915 1915 case NAMETYPE_USER:
1916 1916 case NAMETYPE_GROUP:
1917 1917 param->status = smb_name_validate_account(name);
1918 1918 break;
1919 1919
1920 1920 case NAMETYPE_DOMAIN: /* NetBIOS domain name */
1921 1921 param->status = smb_name_validate_nbdomain(name);
1922 1922 break;
1923 1923
1924 1924 case NAMETYPE_WORKGROUP:
1925 1925 param->status = smb_name_validate_workgroup(name);
1926 1926 break;
1927 1927
1928 1928 case NAMETYPE_PASSWORD:
1929 1929 case NAMETYPE_COMPUTER:
1930 1930 case NAMETYPE_EVENT:
1931 1931 case NAMETYPE_SERVICE:
1932 1932 case NAMETYPE_NET:
1933 1933 case NAMETYPE_MESSAGE:
1934 1934 case NAMETYPE_MESSAGEDEST:
1935 1935 case NAMETYPE_SHAREPASSWORD:
1936 1936 param->status = ERROR_NOT_SUPPORTED;
1937 1937 break;
1938 1938
1939 1939 default:
1940 1940 param->status = ERROR_INVALID_PARAMETER;
1941 1941 break;
1942 1942 }
1943 1943
1944 1944 return (NDR_DRC_OK);
1945 1945 }
1946 1946
1947 1947 /*
1948 1948 * srvsvc_s_NetShareAdd
1949 1949 *
1950 1950 * Add a new share. Only power users groups can manage shares.
1951 1951 *
1952 1952 * This interface is used by the rmtshare command from the NT resource
1953 1953 * kit. Rmtshare allows a client to add or remove shares on a server
1954 1954 * from the client's command line.
1955 1955 *
1956 1956 * Returns Win32 error codes.
1957 1957 */
1958 1958 static int
1959 1959 srvsvc_s_NetShareAdd(void *arg, ndr_xa_t *mxa)
1960 1960 {
1961 1961 static DWORD parm_err = 0;
1962 1962 DWORD parm_stat;
1963 1963 struct mslm_NetShareAdd *param = arg;
1964 1964 struct mslm_NetShareInfo_2 *info2;
1965 1965 struct mslm_NetShareInfo_502 *info502;
1966 1966 char realpath[MAXPATHLEN];
1967 1967 int32_t native_os;
1968 1968 uint8_t *sdbuf = NULL;
1969 1969 uint32_t status;
1970 1970 smb_share_t si;
1971 1971
1972 1972 native_os = ndr_native_os(mxa);
1973 1973
1974 1974 if (!ndr_is_poweruser(mxa)) {
1975 1975 bzero(param, sizeof (struct mslm_NetShareAdd));
1976 1976 param->status = ERROR_ACCESS_DENIED;
1977 1977 return (NDR_DRC_OK);
1978 1978 }
1979 1979
1980 1980 switch (param->level) {
1981 1981 case 2:
1982 1982 info2 = (struct mslm_NetShareInfo_2 *)param->info.un.info2;
1983 1983 break;
1984 1984
1985 1985 case 502:
1986 1986 info502 = (struct mslm_NetShareInfo_502 *)
1987 1987 param->info.un.info502;
1988 1988 sdbuf = info502->shi502_security_descriptor;
1989 1989 info2 = (struct mslm_NetShareInfo_2 *)info502;
1990 1990 break;
1991 1991
1992 1992 default:
1993 1993 bzero(param, sizeof (struct mslm_NetShareAdd));
1994 1994 param->status = ERROR_ACCESS_DENIED;
1995 1995 return (NDR_DRC_OK);
1996 1996 }
1997 1997
1998 1998 if (info2->shi2_netname == NULL || info2->shi2_path == NULL) {
1999 1999 bzero(param, sizeof (struct mslm_NetShareAdd));
2000 2000 param->status = NERR_NetNameNotFound;
2001 2001 return (NDR_DRC_OK);
2002 2002 }
2003 2003
2004 2004 if (smb_shr_is_restricted((char *)info2->shi2_netname)) {
2005 2005 bzero(param, sizeof (struct mslm_NetShareAdd));
2006 2006 param->status = ERROR_ACCESS_DENIED;
2007 2007 return (NDR_DRC_OK);
2008 2008 }
2009 2009
2010 2010 if (info2->shi2_comment == NULL)
2011 2011 info2->shi2_comment = (uint8_t *)"";
2012 2012
2013 2013 /*
2014 2014 * Derive the real path which will be stored in the
2015 2015 * directory field of the smb_share_t structure
2016 2016 * from the path field in this RPC request.
2017 2017 */
2018 2018 parm_stat = smb_shr_get_realpath((const char *)info2->shi2_path,
2019 2019 realpath, MAXPATHLEN);
2020 2020
2021 2021 if (parm_stat != NERR_Success) {
2022 2022 bzero(param, sizeof (struct mslm_NetShareAdd));
2023 2023 param->status = parm_stat;
2024 2024 param->parm_err
2025 2025 = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
2026 2026 return (NDR_DRC_OK);
2027 2027 }
2028 2028
2029 2029 param->status = srvsvc_sa_add((char *)info2->shi2_netname, realpath,
2030 2030 (char *)info2->shi2_comment);
2031 2031 if (param->status == NERR_Success) {
2032 2032 status = smb_shr_get((char *)info2->shi2_netname, &si);
2033 2033
2034 2034 if ((sdbuf != NULL) && (status == NERR_Success))
2035 2035 (void) srvsvc_sd_set(&si, sdbuf);
2036 2036 }
2037 2037 param->parm_err = (native_os == NATIVE_OS_WIN95) ? 0 : &parm_err;
2038 2038 return (NDR_DRC_OK);
2039 2039 }
2040 2040
2041 2041 /*
2042 2042 * srvsvc_estimate_limit
2043 2043 *
2044 2044 * Estimate the number of objects that will fit in prefmaxlen.
2045 2045 * nlimit is adjusted here.
2046 2046 */
2047 2047 static void
2048 2048 srvsvc_estimate_limit(smb_svcenum_t *se, uint32_t obj_size)
2049 2049 {
2050 2050 DWORD max_cnt;
2051 2051
2052 2052 if (obj_size == 0) {
2053 2053 se->se_nlimit = 0;
2054 2054 return;
2055 2055 }
2056 2056
2057 2057 if ((max_cnt = (se->se_prefmaxlen / obj_size)) == 0) {
2058 2058 se->se_nlimit = 0;
2059 2059 return;
2060 2060 }
2061 2061
2062 2062 if (se->se_ntotal > max_cnt)
2063 2063 se->se_nlimit = max_cnt;
2064 2064 else
2065 2065 se->se_nlimit = se->se_ntotal;
2066 2066 }
2067 2067
2068 2068 /*
2069 2069 * srvsvc_s_NetShareEnum
2070 2070 *
2071 2071 * Enumerate all shares (see also NetShareEnumSticky).
2072 2072 *
2073 2073 * Request for various levels of information about our shares.
2074 2074 * Level 0: share names.
2075 2075 * Level 1: share name, share type and comment field.
2076 2076 * Level 2: everything that we know about the shares.
2077 2077 * Level 501: level 1 + flags.
2078 2078 * Level 502: level 2 + security descriptor.
2079 2079 */
2080 2080 static int
2081 2081 srvsvc_s_NetShareEnum(void *arg, ndr_xa_t *mxa)
2082 2082 {
2083 2083 struct mslm_NetShareEnum *param = arg;
2084 2084 srvsvc_infonres_t *infonres;
2085 2085 smb_svcenum_t se;
2086 2086 DWORD status;
2087 2087
2088 2088 infonres = NDR_NEW(mxa, srvsvc_infonres_t);
2089 2089 if (infonres == NULL) {
2090 2090 bzero(param, sizeof (struct mslm_NetShareEnum));
2091 2091 param->status = ERROR_NOT_ENOUGH_MEMORY;
2092 2092 return (NDR_DRC_OK);
2093 2093 }
2094 2094
2095 2095 infonres->entriesread = 0;
2096 2096 infonres->entries = NULL;
2097 2097 param->result.level = param->level;
2098 2098 param->result.bufptr.p = infonres;
2099 2099
2100 2100 bzero(&se, sizeof (smb_svcenum_t));
2101 2101 se.se_type = SMB_SVCENUM_TYPE_SHARE;
2102 2102 se.se_level = param->level;
2103 2103 se.se_ntotal = smb_shr_count();
2104 2104 se.se_nlimit = se.se_ntotal;
2105 2105
2106 2106 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
2107 2107 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
2108 2108 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
2109 2109 else
2110 2110 se.se_prefmaxlen = param->prefmaxlen;
2111 2111
2112 2112 if (param->resume_handle) {
2113 2113 se.se_resume = *param->resume_handle;
2114 2114 se.se_nskip = se.se_resume;
2115 2115 *param->resume_handle = 0;
2116 2116 }
2117 2117
2118 2118 switch (param->level) {
2119 2119 case 0:
2120 2120 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 0);
2121 2121 break;
2122 2122
2123 2123 case 1:
2124 2124 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 0);
2125 2125 break;
2126 2126
2127 2127 case 2:
2128 2128 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 0);
2129 2129 break;
2130 2130
2131 2131 case 501:
2132 2132 status = mlsvc_NetShareEnumLevel501(mxa, infonres, &se, 0);
2133 2133 break;
2134 2134
2135 2135 case 502:
2136 2136 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 0);
2137 2137 break;
2138 2138
2139 2139 default:
2140 2140 status = ERROR_INVALID_LEVEL;
2141 2141 break;
2142 2142 }
2143 2143
2144 2144 if (status != 0) {
2145 2145 bzero(param, sizeof (struct mslm_NetShareEnum));
2146 2146 param->status = status;
2147 2147 return (NDR_DRC_OK);
2148 2148 }
2149 2149
2150 2150 if (se.se_nlimit == 0) {
2151 2151 param->status = ERROR_SUCCESS;
2152 2152 return (NDR_DRC_OK);
2153 2153 }
2154 2154
2155 2155 if (param->resume_handle &&
2156 2156 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
2157 2157 if (se.se_resume < se.se_ntotal) {
2158 2158 *param->resume_handle = se.se_resume;
2159 2159 status = ERROR_MORE_DATA;
2160 2160 }
2161 2161 }
2162 2162
2163 2163 param->totalentries = se.se_ntotal;
2164 2164 param->status = status;
2165 2165 return (NDR_DRC_OK);
2166 2166 }
2167 2167
2168 2168 /*
2169 2169 * srvsvc_s_NetShareEnumSticky
2170 2170 *
2171 2171 * Enumerate sticky shares: all shares except those marked STYPE_SPECIAL.
2172 2172 * Except for excluding STYPE_SPECIAL shares, NetShareEnumSticky is the
2173 2173 * same as NetShareEnum.
2174 2174 *
2175 2175 * Request for various levels of information about our shares.
2176 2176 * Level 0: share names.
2177 2177 * Level 1: share name, share type and comment field.
2178 2178 * Level 2: everything that we know about the shares.
2179 2179 * Level 501: not valid for this request.
2180 2180 * Level 502: level 2 + security descriptor.
2181 2181 *
2182 2182 * We set n_skip to resume_handle, which is used to find the appropriate
2183 2183 * place to resume. The resume_handle is similar to the readdir cookie.
2184 2184 */
2185 2185 static int
2186 2186 srvsvc_s_NetShareEnumSticky(void *arg, ndr_xa_t *mxa)
2187 2187 {
2188 2188 struct mslm_NetShareEnum *param = arg;
2189 2189 srvsvc_infonres_t *infonres;
2190 2190 smb_svcenum_t se;
2191 2191 DWORD status;
2192 2192
2193 2193 infonres = NDR_NEW(mxa, srvsvc_infonres_t);
2194 2194 if (infonres == NULL) {
2195 2195 bzero(param, sizeof (struct mslm_NetShareEnum));
2196 2196 param->status = ERROR_NOT_ENOUGH_MEMORY;
2197 2197 return (NDR_DRC_OK);
2198 2198 }
2199 2199
2200 2200 infonres->entriesread = 0;
2201 2201 infonres->entries = NULL;
2202 2202 param->result.level = param->level;
2203 2203 param->result.bufptr.p = infonres;
2204 2204
2205 2205 bzero(&se, sizeof (smb_svcenum_t));
2206 2206 se.se_type = SMB_SVCENUM_TYPE_SHARE;
2207 2207 se.se_level = param->level;
2208 2208 se.se_ntotal = smb_shr_count();
2209 2209 se.se_nlimit = se.se_ntotal;
2210 2210
2211 2211 if (param->prefmaxlen == SMB_SRVSVC_MAXPREFLEN ||
2212 2212 param->prefmaxlen > SMB_SRVSVC_MAXBUFLEN)
2213 2213 se.se_prefmaxlen = SMB_SRVSVC_MAXBUFLEN;
2214 2214 else
2215 2215 se.se_prefmaxlen = param->prefmaxlen;
2216 2216
2217 2217 if (param->resume_handle) {
2218 2218 se.se_resume = *param->resume_handle;
2219 2219 se.se_nskip = se.se_resume;
2220 2220 *param->resume_handle = 0;
2221 2221 }
2222 2222
2223 2223 switch (param->level) {
2224 2224 case 0:
2225 2225 status = mlsvc_NetShareEnumLevel0(mxa, infonres, &se, 1);
2226 2226 break;
2227 2227
2228 2228 case 1:
2229 2229 status = mlsvc_NetShareEnumLevel1(mxa, infonres, &se, 1);
2230 2230 break;
2231 2231
2232 2232 case 2:
2233 2233 status = mlsvc_NetShareEnumLevel2(mxa, infonres, &se, 1);
2234 2234 break;
2235 2235
2236 2236 case 502:
2237 2237 status = mlsvc_NetShareEnumLevel502(mxa, infonres, &se, 1);
2238 2238 break;
2239 2239
2240 2240 case 501:
2241 2241 default:
2242 2242 status = ERROR_INVALID_LEVEL;
2243 2243 break;
2244 2244 }
2245 2245
2246 2246 if (status != ERROR_SUCCESS) {
2247 2247 bzero(param, sizeof (struct mslm_NetShareEnum));
2248 2248 param->status = status;
2249 2249 return (NDR_DRC_OK);
2250 2250 }
2251 2251
2252 2252 if (se.se_nlimit == 0) {
2253 2253 param->status = ERROR_SUCCESS;
2254 2254 return (NDR_DRC_OK);
2255 2255 }
2256 2256
2257 2257 if (param->resume_handle &&
2258 2258 param->prefmaxlen != SMB_SRVSVC_MAXPREFLEN) {
2259 2259 if (se.se_resume < se.se_ntotal) {
2260 2260 *param->resume_handle = se.se_resume;
2261 2261 status = ERROR_MORE_DATA;
2262 2262 }
2263 2263 }
2264 2264
2265 2265 param->totalentries = se.se_ntotal;
2266 2266 param->status = status;
2267 2267 return (NDR_DRC_OK);
2268 2268 }
2269 2269
2270 2270 /*
2271 2271 * NetShareEnum Level 0
2272 2272 */
2273 2273 static DWORD
2274 2274 mlsvc_NetShareEnumLevel0(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
2275 2275 smb_svcenum_t *se, int sticky)
2276 2276 {
2277 2277 struct mslm_NetShareInfo_0 *info0;
2278 2278 smb_shriter_t iterator;
2279 2279 smb_share_t *si;
2280 2280 DWORD status;
2281 2281
2282 2282 srvsvc_estimate_limit(se,
2283 2283 sizeof (struct mslm_NetShareInfo_0) + MAXNAMELEN);
2284 2284 if (se->se_nlimit == 0)
2285 2285 return (ERROR_SUCCESS);
2286 2286
2287 2287 info0 = NDR_NEWN(mxa, struct mslm_NetShareInfo_0, se->se_nlimit);
2288 2288 if (info0 == NULL)
2289 2289 return (ERROR_NOT_ENOUGH_MEMORY);
2290 2290
2291 2291 smb_shr_iterinit(&iterator);
2292 2292
2293 2293 se->se_nitems = 0;
2294 2294 while ((si = smb_shr_iterate(&iterator)) != NULL) {
2295 2295 if (se->se_nskip > 0) {
2296 2296 --se->se_nskip;
2297 2297 continue;
2298 2298 }
2299 2299
2300 2300 ++se->se_resume;
2301 2301
2302 2302 if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
2303 2303 continue;
2304 2304
2305 2305 if (si->shr_flags & SMB_SHRF_AUTOHOME)
2306 2306 continue;
2307 2307
2308 2308 if (se->se_nitems >= se->se_nlimit) {
2309 2309 se->se_nitems = se->se_nlimit;
2310 2310 break;
2311 2311 }
2312 2312
2313 2313 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info0);
2314 2314 if (status != ERROR_SUCCESS)
2315 2315 break;
2316 2316
2317 2317 ++se->se_nitems;
2318 2318 }
2319 2319
2320 2320 if (se->se_nitems < se->se_nlimit) {
2321 2321 if (srvsvc_add_autohome(mxa, se, (void *)info0))
2322 2322 ++se->se_nitems;
2323 2323 }
2324 2324
2325 2325 infonres->entriesread = se->se_nitems;
2326 2326 infonres->entries = info0;
2327 2327 return (ERROR_SUCCESS);
2328 2328 }
2329 2329
2330 2330 /*
2331 2331 * NetShareEnum Level 1
2332 2332 */
2333 2333 static DWORD
2334 2334 mlsvc_NetShareEnumLevel1(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
2335 2335 smb_svcenum_t *se, int sticky)
2336 2336 {
2337 2337 struct mslm_NetShareInfo_1 *info1;
2338 2338 smb_shriter_t iterator;
2339 2339 smb_share_t *si;
2340 2340 DWORD status;
2341 2341
2342 2342 srvsvc_estimate_limit(se,
2343 2343 sizeof (struct mslm_NetShareInfo_1) + MAXNAMELEN);
2344 2344 if (se->se_nlimit == 0)
2345 2345 return (ERROR_SUCCESS);
2346 2346
2347 2347 info1 = NDR_NEWN(mxa, struct mslm_NetShareInfo_1, se->se_nlimit);
2348 2348 if (info1 == NULL)
2349 2349 return (ERROR_NOT_ENOUGH_MEMORY);
2350 2350
2351 2351 smb_shr_iterinit(&iterator);
2352 2352
2353 2353 se->se_nitems = 0;
2354 2354 while ((si = smb_shr_iterate(&iterator)) != 0) {
2355 2355 if (se->se_nskip > 0) {
2356 2356 --se->se_nskip;
2357 2357 continue;
2358 2358 }
2359 2359
2360 2360 ++se->se_resume;
2361 2361
2362 2362 if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
2363 2363 continue;
2364 2364
2365 2365 if (si->shr_flags & SMB_SHRF_AUTOHOME)
2366 2366 continue;
2367 2367
2368 2368 if (se->se_nitems >= se->se_nlimit) {
2369 2369 se->se_nitems = se->se_nlimit;
2370 2370 break;
2371 2371 }
2372 2372
2373 2373 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info1);
2374 2374 if (status != ERROR_SUCCESS)
2375 2375 break;
2376 2376
2377 2377 ++se->se_nitems;
2378 2378 }
2379 2379
2380 2380 if (se->se_nitems < se->se_nlimit) {
2381 2381 if (srvsvc_add_autohome(mxa, se, (void *)info1))
2382 2382 ++se->se_nitems;
2383 2383 }
2384 2384
2385 2385 infonres->entriesread = se->se_nitems;
2386 2386 infonres->entries = info1;
2387 2387 return (ERROR_SUCCESS);
2388 2388 }
2389 2389
2390 2390 /*
2391 2391 * NetShareEnum Level 2
2392 2392 */
2393 2393 static DWORD
2394 2394 mlsvc_NetShareEnumLevel2(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
2395 2395 smb_svcenum_t *se, int sticky)
2396 2396 {
2397 2397 struct mslm_NetShareInfo_2 *info2;
2398 2398 smb_shriter_t iterator;
2399 2399 smb_share_t *si;
2400 2400 DWORD status;
2401 2401
2402 2402 srvsvc_estimate_limit(se,
2403 2403 sizeof (struct mslm_NetShareInfo_2) + MAXNAMELEN);
2404 2404 if (se->se_nlimit == 0)
2405 2405 return (ERROR_SUCCESS);
2406 2406
2407 2407 info2 = NDR_NEWN(mxa, struct mslm_NetShareInfo_2, se->se_nlimit);
2408 2408 if (info2 == NULL)
2409 2409 return (ERROR_NOT_ENOUGH_MEMORY);
2410 2410
2411 2411 smb_shr_iterinit(&iterator);
2412 2412
2413 2413 se->se_nitems = 0;
2414 2414 while ((si = smb_shr_iterate(&iterator)) != 0) {
2415 2415 if (se->se_nskip > 0) {
2416 2416 --se->se_nskip;
2417 2417 continue;
2418 2418 }
2419 2419
2420 2420 ++se->se_resume;
2421 2421
2422 2422 if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
2423 2423 continue;
2424 2424
2425 2425 if (si->shr_flags & SMB_SHRF_AUTOHOME)
2426 2426 continue;
2427 2427
2428 2428 if (se->se_nitems >= se->se_nlimit) {
2429 2429 se->se_nitems = se->se_nlimit;
2430 2430 break;
2431 2431 }
2432 2432
2433 2433 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info2);
2434 2434 if (status != ERROR_SUCCESS)
2435 2435 break;
2436 2436
2437 2437 ++se->se_nitems;
2438 2438 }
2439 2439
2440 2440 if (se->se_nitems < se->se_nlimit) {
2441 2441 if (srvsvc_add_autohome(mxa, se, (void *)info2))
2442 2442 ++se->se_nitems;
2443 2443 }
2444 2444
2445 2445 infonres->entriesread = se->se_nitems;
2446 2446 infonres->entries = info2;
2447 2447 return (ERROR_SUCCESS);
2448 2448 }
2449 2449
2450 2450 /*
2451 2451 * NetShareEnum Level 501
2452 2452 */
2453 2453 static DWORD
2454 2454 mlsvc_NetShareEnumLevel501(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
2455 2455 smb_svcenum_t *se, int sticky)
2456 2456 {
2457 2457 struct mslm_NetShareInfo_501 *info501;
2458 2458 smb_shriter_t iterator;
2459 2459 smb_share_t *si;
2460 2460 DWORD status;
2461 2461
2462 2462 srvsvc_estimate_limit(se,
2463 2463 sizeof (struct mslm_NetShareInfo_501) + MAXNAMELEN);
2464 2464 if (se->se_nlimit == 0)
2465 2465 return (ERROR_SUCCESS);
2466 2466
2467 2467 info501 = NDR_NEWN(mxa, struct mslm_NetShareInfo_501,
2468 2468 se->se_nlimit);
2469 2469 if (info501 == NULL)
2470 2470 return (ERROR_NOT_ENOUGH_MEMORY);
2471 2471
2472 2472 smb_shr_iterinit(&iterator);
2473 2473
2474 2474 se->se_nitems = 0;
2475 2475 while ((si = smb_shr_iterate(&iterator)) != 0) {
2476 2476 if (se->se_nskip > 0) {
2477 2477 --se->se_nskip;
2478 2478 continue;
2479 2479 }
2480 2480
2481 2481 ++se->se_resume;
2482 2482
2483 2483 if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
2484 2484 continue;
2485 2485
2486 2486 if (si->shr_flags & SMB_SHRF_AUTOHOME)
2487 2487 continue;
2488 2488
2489 2489 if (se->se_nitems >= se->se_nlimit) {
2490 2490 se->se_nitems = se->se_nlimit;
2491 2491 break;
2492 2492 }
2493 2493
2494 2494 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info501);
2495 2495 if (status != ERROR_SUCCESS)
2496 2496 break;
2497 2497
2498 2498 ++se->se_nitems;
2499 2499 }
2500 2500
2501 2501 if (se->se_nitems < se->se_nlimit) {
2502 2502 if (srvsvc_add_autohome(mxa, se, (void *)info501))
2503 2503 ++se->se_nitems;
2504 2504 }
2505 2505
2506 2506 infonres->entriesread = se->se_nitems;
2507 2507 infonres->entries = info501;
2508 2508 return (ERROR_SUCCESS);
2509 2509 }
2510 2510
2511 2511 /*
2512 2512 * NetShareEnum Level 502
2513 2513 */
2514 2514 static DWORD
2515 2515 mlsvc_NetShareEnumLevel502(ndr_xa_t *mxa, srvsvc_infonres_t *infonres,
2516 2516 smb_svcenum_t *se, int sticky)
2517 2517 {
2518 2518 struct mslm_NetShareInfo_502 *info502;
2519 2519 smb_shriter_t iterator;
2520 2520 smb_share_t *si;
2521 2521 DWORD status;
2522 2522
2523 2523 srvsvc_estimate_limit(se,
2524 2524 sizeof (struct mslm_NetShareInfo_502) + MAXNAMELEN);
2525 2525 if (se->se_nlimit == 0)
2526 2526 return (ERROR_SUCCESS);
2527 2527
2528 2528 info502 = NDR_NEWN(mxa, struct mslm_NetShareInfo_502,
2529 2529 se->se_nlimit);
2530 2530 if (info502 == NULL)
2531 2531 return (ERROR_NOT_ENOUGH_MEMORY);
2532 2532
2533 2533 smb_shr_iterinit(&iterator);
2534 2534
2535 2535 se->se_nitems = 0;
2536 2536 while ((si = smb_shr_iterate(&iterator)) != NULL) {
2537 2537 if (se->se_nskip > 0) {
2538 2538 --se->se_nskip;
2539 2539 continue;
2540 2540 }
2541 2541
2542 2542 ++se->se_resume;
2543 2543
2544 2544 if (sticky && (si->shr_flags & SMB_SHRF_TRANS))
2545 2545 continue;
2546 2546
2547 2547 if (si->shr_flags & SMB_SHRF_AUTOHOME)
2548 2548 continue;
2549 2549
2550 2550 if (se->se_nitems >= se->se_nlimit) {
2551 2551 se->se_nitems = se->se_nlimit;
2552 2552 break;
2553 2553 }
2554 2554
2555 2555 status = mlsvc_NetShareEnumCommon(mxa, se, si, (void *)info502);
2556 2556 if (status != ERROR_SUCCESS)
2557 2557 break;
2558 2558
2559 2559 ++se->se_nitems;
2560 2560 }
2561 2561
2562 2562 if (se->se_nitems < se->se_nlimit) {
2563 2563 if (srvsvc_add_autohome(mxa, se, (void *)info502))
2564 2564 ++se->se_nitems;
2565 2565 }
2566 2566
2567 2567 infonres->entriesread = se->se_nitems;
2568 2568 infonres->entries = info502;
2569 2569 return (ERROR_SUCCESS);
2570 2570 }
2571 2571
2572 2572 /*
2573 2573 * mlsvc_NetShareEnumCommon
2574 2574 *
2575 2575 * Build the levels 0, 1, 2, 501 and 502 share information. This function
2576 2576 * is called by the various NetShareEnum levels for each share. If
2577 2577 * we cannot build the share data for some reason, we return an error
2578 2578 * but the actual value of the error is not important to the caller.
2579 2579 * The caller just needs to know not to include this info in the RPC
2580 2580 * response.
2581 2581 *
2582 2582 * Returns:
2583 2583 * ERROR_SUCCESS
2584 2584 * ERROR_NOT_ENOUGH_MEMORY
2585 2585 * ERROR_INVALID_LEVEL
2586 2586 */
2587 2587 static DWORD
2588 2588 mlsvc_NetShareEnumCommon(ndr_xa_t *mxa, smb_svcenum_t *se,
2589 2589 smb_share_t *si, void *infop)
2590 2590 {
2591 2591 struct mslm_NetShareInfo_0 *info0;
2592 2592 struct mslm_NetShareInfo_1 *info1;
2593 2593 struct mslm_NetShareInfo_2 *info2;
2594 2594 struct mslm_NetShareInfo_501 *info501;
2595 2595 struct mslm_NetShareInfo_502 *info502;
2596 2596 srvsvc_sd_t sd;
2597 2597 uint8_t *netname;
2598 2598 uint8_t *comment;
2599 2599 uint8_t *passwd;
2600 2600 uint8_t *path;
2601 2601 int i = se->se_nitems;
2602 2602
2603 2603 netname = (uint8_t *)NDR_STRDUP(mxa, si->shr_name);
2604 2604 comment = (uint8_t *)NDR_STRDUP(mxa, si->shr_cmnt);
2605 2605 passwd = (uint8_t *)NDR_STRDUP(mxa, empty_string);
2606 2606 path = (uint8_t *)srvsvc_share_mkpath(mxa, si->shr_path);
2607 2607
2608 2608 if (!netname || !comment || !passwd || !path)
2609 2609 return (ERROR_NOT_ENOUGH_MEMORY);
2610 2610
2611 2611 switch (se->se_level) {
2612 2612 case 0:
2613 2613 info0 = (struct mslm_NetShareInfo_0 *)infop;
2614 2614 info0[i].shi0_netname = netname;
2615 2615 break;
2616 2616
2617 2617 case 1:
2618 2618 info1 = (struct mslm_NetShareInfo_1 *)infop;
2619 2619 info1[i].shi1_netname = netname;
2620 2620 info1[i].shi1_comment = comment;
2621 2621 info1[i].shi1_type = si->shr_type;
2622 2622 break;
2623 2623
2624 2624 case 2:
2625 2625 info2 = (struct mslm_NetShareInfo_2 *)infop;
2626 2626 info2[i].shi2_netname = netname;
2627 2627 info2[i].shi2_comment = comment;
2628 2628 info2[i].shi2_path = path;
2629 2629 info2[i].shi2_type = si->shr_type;
2630 2630 info2[i].shi2_permissions = 0;
2631 2631 info2[i].shi2_max_uses = SHI_USES_UNLIMITED;
2632 2632 info2[i].shi2_current_uses = 0;
2633 2633 info2[i].shi2_passwd = passwd;
2634 2634 break;
2635 2635
2636 2636 case 501:
2637 2637 info501 = (struct mslm_NetShareInfo_501 *)infop;
2638 2638 info501[i].shi501_netname = netname;
2639 2639 info501[i].shi501_comment = comment;
2640 2640 info501[i].shi501_type = si->shr_type;
2641 2641 info501[i].shi501_flags = srvsvc_get_share_flags(si);
2642 2642 break;
2643 2643
2644 2644 case 502:
2645 2645 info502 = (struct mslm_NetShareInfo_502 *)infop;
2646 2646 info502[i].shi502_netname = netname;
2647 2647 info502[i].shi502_comment = comment;
2648 2648 info502[i].shi502_path = path;
2649 2649 info502[i].shi502_type = si->shr_type;
2650 2650 info502[i].shi502_permissions = 0;
2651 2651 info502[i].shi502_max_uses = SHI_USES_UNLIMITED;
2652 2652 info502[i].shi502_current_uses = 0;
2653 2653 info502[i].shi502_passwd = passwd;
2654 2654
2655 2655 if (srvsvc_share_getsd(mxa, si, &sd) == ERROR_SUCCESS) {
2656 2656 info502[i].shi502_reserved = sd.sd_size;
2657 2657 info502[i].shi502_security_descriptor = sd.sd_buf;
2658 2658 } else {
2659 2659 info502[i].shi502_reserved = 0;
2660 2660 info502[i].shi502_security_descriptor = NULL;
2661 2661 }
2662 2662
2663 2663 break;
2664 2664
2665 2665 default:
2666 2666 return (ERROR_INVALID_LEVEL);
2667 2667 }
2668 2668
2669 2669 return (ERROR_SUCCESS);
2670 2670 }
2671 2671
2672 2672 /*
2673 2673 * srvsvc_add_autohome
2674 2674 *
2675 2675 * Add the autohome share for the user. The share must not be a permanent
2676 2676 * share to avoid duplicates.
2677 2677 */
2678 2678 static boolean_t
2679 2679 srvsvc_add_autohome(ndr_xa_t *mxa, smb_svcenum_t *se, void *infop)
2680 2680 {
2681 2681 smb_netuserinfo_t *user = mxa->pipe->np_user;
2682 2682 char *username;
2683 2683 smb_share_t si;
2684 2684 DWORD status;
2685 2685 struct passwd pw;
2686 2686 char buf[NSS_LINELEN_PASSWD];
2687 2687
2688 2688 if (IDMAP_ID_IS_EPHEMERAL(user->ui_posix_uid)) {
2689 2689 username = user->ui_account;
2690 2690 } else {
2691 2691 if (getpwuid_r(user->ui_posix_uid, &pw, buf, sizeof (buf)) ==
2692 2692 NULL)
2693 2693 return (B_FALSE);
2694 2694
2695 2695 username = pw.pw_name;
2696 2696 }
2697 2697
2698 2698 if (smb_shr_get(username, &si) != NERR_Success)
2699 2699 return (B_FALSE);
2700 2700
2701 2701 if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0)
2702 2702 return (B_FALSE);
2703 2703
2704 2704 status = mlsvc_NetShareEnumCommon(mxa, se, &si, infop);
2705 2705 return (status == ERROR_SUCCESS);
2706 2706 }
2707 2707
2708 2708 /*
2709 2709 * srvsvc_share_mkpath
2710 2710 *
2711 2711 * Create the share path required by the share enum calls. The path
2712 2712 * is created in a heap buffer ready for use by the caller.
2713 2713 *
2714 2714 * Some Windows over-the-wire backup applications do not work unless a
2715 2715 * drive letter is present in the share path. We don't care about the
2716 2716 * drive letter since the path is fully qualified with the volume name.
2717 2717 *
2718 2718 * Windows clients seem to be mostly okay with forward slashes in
2719 2719 * share paths but they cannot handle one immediately after the drive
2720 2720 * letter, i.e. B:/. For consistency we convert all the slashes in
2721 2721 * the path.
2722 2722 *
2723 2723 * Returns a pointer to a heap buffer containing the share path, which
2724 2724 * could be a null pointer if the heap allocation fails.
2725 2725 */
2726 2726 static char *
2727 2727 srvsvc_share_mkpath(ndr_xa_t *mxa, char *path)
2728 2728 {
2729 2729 char tmpbuf[MAXPATHLEN];
2730 2730 char *p;
2731 2731 char drive_letter;
2732 2732
2733 2733 if (strlen(path) == 0)
2734 2734 return (NDR_STRDUP(mxa, path));
2735 2735
2736 2736 drive_letter = smb_shr_drive_letter(path);
2737 2737 if (drive_letter != '\0') {
2738 2738 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:\\", drive_letter);
2739 2739 return (NDR_STRDUP(mxa, tmpbuf));
2740 2740 }
2741 2741
2742 2742 /*
2743 2743 * Strip the volume name from the path (/vol1/home -> /home).
2744 2744 */
2745 2745 p = path;
2746 2746 p += strspn(p, "/");
2747 2747 p += strcspn(p, "/");
2748 2748 p += strspn(p, "/");
2749 2749 (void) snprintf(tmpbuf, MAXPATHLEN, "%c:/%s", 'B', p);
2750 2750 (void) strsubst(tmpbuf, '/', '\\');
2751 2751
2752 2752 return (NDR_STRDUP(mxa, tmpbuf));
2753 2753 }
2754 2754
2755 2755 static int
2756 2756 srvsvc_s_NetShareCheck(void *arg, ndr_xa_t *mxa)
2757 2757 {
2758 2758 struct mslm_NetShareCheck *param = arg;
2759 2759 smb_shriter_t iterator;
2760 2760 smb_share_t *si;
2761 2761 char *path;
2762 2762
2763 2763 if (param->path == NULL) {
2764 2764 param->stype = STYPE_DISKTREE;
2765 2765 param->status = NERR_NetNameNotFound;
2766 2766 return (NDR_DRC_OK);
2767 2767 }
2768 2768
2769 2769 (void) strsubst((char *)param->path, '/', '\\');
2770 2770
2771 2771 smb_shr_iterinit(&iterator);
2772 2772
2773 2773 while ((si = smb_shr_iterate(&iterator)) != NULL) {
2774 2774 path = srvsvc_share_mkpath(mxa, si->shr_path);
2775 2775
2776 2776 if (smb_strcasecmp(path, (char *)param->path, 0) == 0) {
2777 2777 param->stype = (si->shr_type & STYPE_MASK);
2778 2778 param->status = NERR_Success;
2779 2779 return (NDR_DRC_OK);
2780 2780 }
2781 2781 }
2782 2782
2783 2783 param->stype = STYPE_DISKTREE;
2784 2784 param->status = NERR_NetNameNotFound;
2785 2785 return (NDR_DRC_OK);
2786 2786 }
2787 2787
2788 2788 /*
2789 2789 * Delete a share. Only members of the Administrators, Server Operators
2790 2790 * or Power Users local groups are allowed to delete shares.
2791 2791 *
2792 2792 * This interface is used by the rmtshare command from the NT resource
2793 2793 * kit. Rmtshare allows a client to add or remove shares on a server
2794 2794 * from the client's command line.
2795 2795 *
2796 2796 * Returns Win32 error codes.
2797 2797 */
2798 2798 static int
2799 2799 srvsvc_s_NetShareDel(void *arg, ndr_xa_t *mxa)
2800 2800 {
2801 2801 struct mslm_NetShareDel *param = arg;
2802 2802 smb_share_t si;
2803 2803
2804 2804 if (!ndr_is_poweruser(mxa) ||
2805 2805 smb_shr_is_restricted((char *)param->netname)) {
2806 2806 param->status = ERROR_ACCESS_DENIED;
2807 2807 return (NDR_DRC_OK);
2808 2808 }
2809 2809
2810 2810 if (smb_shr_get((char *)param->netname, &si) == NERR_Success) {
2811 2811 if (si.shr_flags & SMB_SHRF_DFSROOT) {
2812 2812 param->status = NERR_IsDfsShare;
2813 2813 return (NDR_DRC_OK);
2814 2814 }
2815 2815 }
2816 2816
2817 2817 param->status = srvsvc_sa_delete((char *)param->netname);
2818 2818 return (NDR_DRC_OK);
2819 2819 }
2820 2820
2821 2821 /*
2822 2822 * srvsvc_s_NetGetFileSecurity
2823 2823 *
2824 2824 * Get security descriptor of the requested file/folder
2825 2825 *
2826 2826 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
2827 2827 * get the requested SD here in RPC code.
2828 2828 */
2829 2829 /*ARGSUSED*/
2830 2830 static int
2831 2831 srvsvc_s_NetGetFileSecurity(void *arg, ndr_xa_t *mxa)
2832 2832 {
2833 2833 struct mslm_NetGetFileSecurity *param = arg;
2834 2834
2835 2835 param->length = 0;
2836 2836 param->status = ERROR_ACCESS_DENIED;
2837 2837 return (NDR_DRC_OK);
2838 2838 }
2839 2839
2840 2840 /*
2841 2841 * srvsvc_s_NetSetFileSecurity
2842 2842 *
2843 2843 * Set the given security descriptor for the requested file/folder
2844 2844 *
2845 2845 * Right now, just returns ERROR_ACCESS_DENIED, because we cannot
2846 2846 * set the requested SD here in RPC code.
2847 2847 */
2848 2848 /*ARGSUSED*/
2849 2849 static int
2850 2850 srvsvc_s_NetSetFileSecurity(void *arg, ndr_xa_t *mxa)
2851 2851 {
2852 2852 struct mslm_NetSetFileSecurity *param = arg;
2853 2853
2854 2854 param->status = ERROR_ACCESS_DENIED;
2855 2855 return (NDR_DRC_OK);
2856 2856 }
2857 2857
2858 2858 /*
2859 2859 * If the default "smb" share group exists then return the group
2860 2860 * handle, otherwise create the group and return the handle.
2861 2861 *
2862 2862 * All shares created via the srvsvc will be added to the "smb"
2863 2863 * group.
2864 2864 */
2865 2865 static sa_group_t
2866 2866 srvsvc_sa_get_smbgrp(sa_handle_t handle)
2867 2867 {
2868 2868 sa_group_t group = NULL;
2869 2869 int err;
2870 2870
2871 2871 group = sa_get_group(handle, SMB_DEFAULT_SHARE_GROUP);
2872 2872 if (group != NULL)
2873 2873 return (group);
2874 2874
2875 2875 group = sa_create_group(handle, SMB_DEFAULT_SHARE_GROUP, &err);
2876 2876 if (group == NULL)
2877 2877 return (NULL);
2878 2878
2879 2879 if (sa_create_optionset(group, SMB_DEFAULT_SHARE_GROUP) == NULL) {
2880 2880 (void) sa_remove_group(group);
2881 2881 group = NULL;
2882 2882 }
2883 2883
2884 2884 return (group);
2885 2885 }
2886 2886
2887 2887 /*
2888 2888 * Stores the given share in sharemgr
2889 2889 */
2890 2890 static uint32_t
2891 2891 srvsvc_sa_add(char *sharename, char *path, char *cmnt)
2892 2892 {
2893 2893 sa_handle_t handle;
2894 2894 sa_share_t share;
2895 2895 sa_group_t group;
2896 2896 sa_resource_t resource;
2897 2897 boolean_t new_share = B_FALSE;
2898 2898 uint32_t status = NERR_Success;
2899 2899 int err;
2900 2900
2901 2901 if ((handle = smb_shr_sa_enter()) == NULL)
2902 2902 return (NERR_InternalError);
2903 2903
2904 2904 share = sa_find_share(handle, path);
2905 2905 if (share == NULL) {
2906 2906 group = srvsvc_sa_get_smbgrp(handle);
2907 2907 if (group == NULL) {
2908 2908 smb_shr_sa_exit();
2909 2909 return (NERR_InternalError);
2910 2910 }
2911 2911
2912 2912 share = sa_add_share(group, path, SA_SHARE_PERMANENT, &err);
2913 2913 if (share == NULL) {
2914 2914 smb_shr_sa_exit();
2915 2915 return (NERR_InternalError);
2916 2916 }
2917 2917 new_share = B_TRUE;
2918 2918 }
2919 2919
2920 2920 resource = sa_get_share_resource(share, sharename);
2921 2921 if (resource == NULL) {
2922 2922 resource = sa_add_resource(share, sharename,
2923 2923 SA_SHARE_PERMANENT, &err);
2924 2924 if (resource == NULL) {
2925 2925 if (new_share)
2926 2926 (void) sa_remove_share(share);
2927 2927 smb_shr_sa_exit();
2928 2928 return (NERR_InternalError);
2929 2929 }
2930 2930 }
2931 2931
2932 2932 (void) sa_set_resource_description(resource, cmnt);
2933 2933
2934 2934 smb_shr_sa_exit();
2935 2935 return (status);
2936 2936 }
2937 2937
2938 2938 /*
2939 2939 * Removes the share from sharemgr
2940 2940 */
2941 2941 static uint32_t
2942 2942 srvsvc_sa_delete(char *sharename)
2943 2943 {
2944 2944 sa_handle_t handle;
2945 2945 sa_resource_t resource;
2946 2946 uint32_t status;
2947 2947
2948 2948 if ((handle = smb_shr_sa_enter()) == NULL)
2949 2949 return (NERR_InternalError);
2950 2950
2951 2951 status = NERR_InternalError;
2952 2952 if ((resource = sa_find_resource(handle, sharename)) != NULL) {
2953 2953 if (sa_remove_resource(resource) == SA_OK)
2954 2954 status = NERR_Success;
2955 2955 }
2956 2956
2957 2957 smb_shr_sa_exit();
2958 2958 return (status);
2959 2959 }
2960 2960
2961 2961 /*
2962 2962 * Update the share information.
2963 2963 */
2964 2964 static uint32_t
2965 2965 srvsvc_sa_modify(smb_share_t *si, srvsvc_netshare_setinfo_t *info)
2966 2966 {
2967 2967 sa_handle_t handle;
2968 2968 sa_share_t share;
2969 2969 sa_resource_t resource;
2970 2970 boolean_t renamed = B_FALSE, is_zfs = B_FALSE;
2971 2971 nvlist_t *nvl;
2972 2972 uint32_t nerr = NERR_Success;
2973 2973
2974 2974 if ((handle = smb_shr_sa_enter()) == NULL)
2975 2975 return (NERR_InternalError);
2976 2976
2977 2977 if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
2978 2978 smb_shr_sa_exit();
2979 2979 return (NERR_InternalError);
2980 2980 }
2981 2981
2982 2982 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
2983 2983 smb_shr_sa_exit();
2984 2984 return (NERR_InternalError);
2985 2985 }
2986 2986
2987 2987 if (sa_group_is_zfs(sa_get_parent_group(share))) {
2988 2988 is_zfs = B_TRUE;
2989 2989 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
2990 2990 smb_shr_sa_exit();
2991 2991 return (NERR_InternalError);
2992 2992 }
2993 2993 }
2994 2994
2995 2995 if (info->nss_netname != NULL && info->nss_netname[0] != '\0' &&
2996 2996 smb_strcasecmp(info->nss_netname, si->shr_name, 0) != 0) {
2997 2997 if (is_zfs)
2998 2998 (void) nvlist_add_string(nvl, SHOPT_NAME,
2999 2999 info->nss_netname);
3000 3000 else
3001 3001 (void) sa_set_resource_attr(resource, SHOPT_NAME,
3002 3002 info->nss_netname);
3003 3003 renamed = B_TRUE;
3004 3004 }
3005 3005
3006 3006 if ((info->nss_comment != NULL) &&
3007 3007 (strcmp(info->nss_comment, si->shr_cmnt) != 0)) {
3008 3008 if (is_zfs)
3009 3009 (void) nvlist_add_string(nvl, SHOPT_DESCRIPTION,
3010 3010 info->nss_comment);
3011 3011 else
3012 3012 (void) sa_set_resource_description(resource,
3013 3013 info->nss_comment);
3014 3014 (void) strlcpy(si->shr_cmnt, info->nss_comment,
3015 3015 SMB_SHARE_CMNT_MAX);
3016 3016 }
3017 3017
3018 3018 if (is_zfs) {
3019 3019 if (sa_zfs_setprop(handle, si->shr_path, nvl) != 0) {
3020 3020 smb_shr_sa_exit();
3021 3021 nvlist_free(nvl);
3022 3022 return (NERR_InternalError);
3023 3023 }
3024 3024 nvlist_free(nvl);
3025 3025 }
3026 3026 smb_shr_sa_exit();
3027 3027
3028 3028 if (renamed) {
3029 3029 nerr = smb_shr_rename(si->shr_name, info->nss_netname);
3030 3030 if (nerr != NERR_Success)
3031 3031 return (nerr);
3032 3032
3033 3033 (void) strlcpy(si->shr_name, info->nss_netname, MAXNAMELEN);
3034 3034 }
3035 3035
3036 3036 return (nerr);
3037 3037 }
3038 3038
3039 3039 /*
3040 3040 * Sets the share properties.
3041 3041 *
3042 3042 * This method sets share properties. If its a ZFS share, then properties
3043 3043 * are set by calling the sa_zfs_setprop method. Else the optionset properties
3044 3044 * of the share resource are set.The properties to be set are given as a list
3045 3045 * of name-value pair.
3046 3046 */
3047 3047 static uint32_t
3048 3048 srvsvc_sa_setprop(smb_share_t *si, nvlist_t *nvl)
3049 3049 {
3050 3050 sa_handle_t handle;
3051 3051 sa_share_t share;
3052 3052 sa_resource_t resource;
3053 3053 sa_property_t prop;
3054 3054 sa_optionset_t opts;
3055 3055 uint32_t nerr = NERR_Success;
3056 3056 nvpair_t *cur;
3057 3057 int err = 0;
3058 3058 char *name, *val;
3059 3059
3060 3060 if ((handle = sa_init(SA_INIT_SHARE_API)) == NULL)
3061 3061 return (NERR_InternalError);
3062 3062
3063 3063 if ((share = sa_find_share(handle, si->shr_path)) == NULL) {
3064 3064 sa_fini(handle);
3065 3065 return (NERR_InternalError);
3066 3066 }
3067 3067
3068 3068 if ((resource = sa_get_share_resource(share, si->shr_name)) == NULL) {
3069 3069 sa_fini(handle);
3070 3070 return (NERR_InternalError);
3071 3071 }
3072 3072
3073 3073 if (sa_group_is_zfs(sa_get_parent_group(share))) {
3074 3074 if (sa_zfs_setprop(handle, si->shr_path, nvl) != 0)
3075 3075 nerr = NERR_InternalError;
3076 3076 sa_fini(handle);
3077 3077 return (nerr);
3078 3078 }
3079 3079
3080 3080 if ((opts = sa_get_optionset(resource, SMB_PROTOCOL_NAME)) == NULL) {
3081 3081 opts = sa_create_optionset(resource, SMB_PROTOCOL_NAME);
3082 3082 if (opts == NULL) {
3083 3083 sa_fini(handle);
3084 3084 return (NERR_InternalError);
3085 3085 }
3086 3086 }
3087 3087
3088 3088 cur = nvlist_next_nvpair(nvl, NULL);
3089 3089 while (cur != NULL) {
3090 3090 name = nvpair_name(cur);
3091 3091 err = nvpair_value_string(cur, &val);
3092 3092 if ((err != 0) || (name == NULL) || (val == NULL)) {
3093 3093 nerr = NERR_InternalError;
3094 3094 break;
3095 3095 }
3096 3096
3097 3097 prop = NULL;
3098 3098 if ((prop = sa_get_property(opts, name)) == NULL) {
3099 3099 prop = sa_create_property(name, val);
3100 3100 if (prop != NULL) {
3101 3101 nerr = sa_valid_property(handle, opts,
3102 3102 SMB_PROTOCOL_NAME, prop);
3103 3103 if (nerr != NERR_Success) {
3104 3104 (void) sa_remove_property(prop);
3105 3105 break;
3106 3106 }
3107 3107 }
3108 3108 nerr = sa_add_property(opts, prop);
3109 3109 if (nerr != NERR_Success)
3110 3110 break;
3111 3111 } else {
3112 3112 nerr = sa_update_property(prop, val);
3113 3113 if (nerr != NERR_Success)
3114 3114 break;
3115 3115 }
3116 3116
3117 3117 cur = nvlist_next_nvpair(nvl, cur);
3118 3118 }
3119 3119
3120 3120 if (nerr == NERR_Success)
3121 3121 nerr = sa_commit_properties(opts, 0);
3122 3122
3123 3123 sa_fini(handle);
3124 3124 return (nerr);
3125 3125 }
3126 3126
3127 3127 static ndr_stub_table_t srvsvc_stub_table[] = {
3128 3128 { srvsvc_s_NetConnectEnum, SRVSVC_OPNUM_NetConnectEnum },
3129 3129 { srvsvc_s_NetFileEnum, SRVSVC_OPNUM_NetFileEnum },
3130 3130 { srvsvc_s_NetFileClose, SRVSVC_OPNUM_NetFileClose },
3131 3131 { srvsvc_s_NetShareGetInfo, SRVSVC_OPNUM_NetShareGetInfo },
3132 3132 { srvsvc_s_NetShareSetInfo, SRVSVC_OPNUM_NetShareSetInfo },
3133 3133 { srvsvc_s_NetSessionEnum, SRVSVC_OPNUM_NetSessionEnum },
3134 3134 { srvsvc_s_NetSessionDel, SRVSVC_OPNUM_NetSessionDel },
3135 3135 { srvsvc_s_NetServerGetInfo, SRVSVC_OPNUM_NetServerGetInfo },
3136 3136 { srvsvc_s_NetRemoteTOD, SRVSVC_OPNUM_NetRemoteTOD },
3137 3137 { srvsvc_s_NetNameValidate, SRVSVC_OPNUM_NetNameValidate },
3138 3138 { srvsvc_s_NetShareAdd, SRVSVC_OPNUM_NetShareAdd },
3139 3139 { srvsvc_s_NetShareDel, SRVSVC_OPNUM_NetShareDel },
3140 3140 { srvsvc_s_NetShareEnum, SRVSVC_OPNUM_NetShareEnum },
3141 3141 { srvsvc_s_NetShareEnumSticky, SRVSVC_OPNUM_NetShareEnumSticky },
3142 3142 { srvsvc_s_NetShareCheck, SRVSVC_OPNUM_NetShareCheck },
3143 3143 { srvsvc_s_NetGetFileSecurity, SRVSVC_OPNUM_NetGetFileSecurity },
3144 3144 { srvsvc_s_NetSetFileSecurity, SRVSVC_OPNUM_NetSetFileSecurity },
3145 3145 {0}
3146 3146 };
|
↓ open down ↓ |
2127 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX