Removed version number from file header.
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_srvsvc_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Paul Ashton                       1997.
7  *  Copyright (C) Jeremy Allison                                        2001.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 /* This is the implementation of the srvsvc pipe. */
25
26 #include "includes.h"
27
28 extern pstring global_myname;
29
30 /*******************************************************************
31  Fill in a share info level 1 structure.
32  ********************************************************************/
33
34 static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int snum)
35 {
36         int len_net_name;
37         pstring net_name;
38         pstring remark;
39         uint32 type;
40
41         pstrcpy(net_name, lp_servicename(snum));
42         pstrcpy(remark, lp_comment(snum));
43         standard_sub_conn(p->conn, remark);
44         len_net_name = strlen(net_name);
45
46         /* work out the share type */
47         type = STYPE_DISKTREE;
48                 
49         if (lp_print_ok(snum))
50                 type = STYPE_PRINTQ;
51         if (strequal("IPC$", net_name) || strequal("ADMIN$", net_name))
52                 type = STYPE_IPC;
53         if (net_name[len_net_name] == '$')
54                 type |= STYPE_HIDDEN;
55
56         init_srv_share_info1(&sh1->info_1, net_name, type, remark);
57         init_srv_share_info1_str(&sh1->info_1_str, net_name, remark);
58 }
59
60 /*******************************************************************
61  Fill in a share info level 2 structure.
62  ********************************************************************/
63
64 static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int snum)
65 {
66         int len_net_name;
67         pstring net_name;
68         pstring remark;
69         pstring path;
70         pstring passwd;
71         uint32 type;
72
73         pstrcpy(net_name, lp_servicename(snum));
74         pstrcpy(remark, lp_comment(snum));
75         standard_sub_conn(p->conn, remark);
76         pstrcpy(path, "C:");
77         pstrcat(path, lp_pathname(snum));
78
79         /*
80          * Change / to \\ so that win2k will see it as a valid path.  This was added to
81          * enable use of browsing in win2k add share dialog.
82          */ 
83
84         string_replace(path, '/', '\\');
85
86         pstrcpy(passwd, "");
87         len_net_name = strlen(net_name);
88
89         /* work out the share type */
90         type = STYPE_DISKTREE;
91                 
92         if (lp_print_ok(snum))
93                 type = STYPE_PRINTQ;
94         if (strequal("IPC$", net_name) || strequal("ADMIN$", net_name))
95                 type = STYPE_IPC;
96         if (net_name[len_net_name] == '$')
97                 type |= STYPE_HIDDEN;
98
99         init_srv_share_info2(&sh2->info_2, net_name, type, remark, 0, 0xffffffff, 1, path, passwd);
100         init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
101 }
102
103 /*******************************************************************
104  What to do when smb.conf is updated.
105  ********************************************************************/
106
107 static void smb_conf_updated(int msg_type, pid_t src, void *buf, size_t len)
108 {
109         DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
110         reload_services(False);
111 }
112
113 /*******************************************************************
114  Create the share security tdb.
115  ********************************************************************/
116
117 static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
118 #define SHARE_DATABASE_VERSION_V1 1
119 #define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
120
121 BOOL share_info_db_init(void)
122 {
123         static pid_t local_pid;
124         char *vstring = "INFO/version";
125         int32 vers_id;
126  
127         if (share_tdb && local_pid == sys_getpid())
128                 return True;
129         share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
130         if (!share_tdb) {
131                 DEBUG(0,("Failed to open share info database %s (%s)\n",
132                         lock_path("share_info.tdb"), strerror(errno) ));
133                 return False;
134         }
135  
136         local_pid = sys_getpid();
137  
138         /* handle a Samba upgrade */
139         tdb_lock_bystring(share_tdb, vstring);
140
141         /* Cope with byte-reversed older versions of the db. */
142         vers_id = tdb_fetch_int32(share_tdb, vstring);
143         if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) {
144                 /* Written on a bigendian machine with old fetch_int code. Save as le. */
145                 tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
146                 vers_id = SHARE_DATABASE_VERSION_V2;
147         }
148
149         if (vers_id != SHARE_DATABASE_VERSION_V2) {
150                 tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL);
151                 tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
152         }
153         tdb_unlock_bystring(share_tdb, vstring);
154
155         message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated);
156  
157         return True;
158 }
159
160 /*******************************************************************
161  Fake up a Everyone, full access as a default.
162  ********************************************************************/
163
164 static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *psize)
165 {
166         extern DOM_SID global_sid_World;
167         extern struct generic_mapping file_generic_mapping;
168         SEC_ACCESS sa;
169         SEC_ACE ace;
170         SEC_ACL *psa = NULL;
171         SEC_DESC *psd = NULL;
172         uint32 def_access = GENERIC_ALL_ACCESS;
173
174         se_map_generic(&def_access, &file_generic_mapping);
175
176     init_sec_access(&sa, GENERIC_ALL_ACCESS | def_access );
177     init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
178
179         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
180                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, psize);
181         }
182
183         if (!psd) {
184                 DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
185                 return NULL;
186         }
187
188         return psd;
189 }
190
191 /*******************************************************************
192  Pull a security descriptor from the share tdb.
193  ********************************************************************/
194
195 static SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
196 {
197         prs_struct ps;
198         fstring key;
199         SEC_DESC *psd = NULL;
200
201         *psize = 0;
202
203         /* Fetch security descriptor from tdb */
204  
205         slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
206  
207     if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 ||
208         !sec_io_desc("get_share_security", &psd, &ps, 1)) {
209  
210         DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) ));
211  
212         return get_share_security_default(ctx, snum, psize);
213     }
214
215         if (psd)
216                 *psize = sec_desc_size(psd);
217
218         prs_mem_free(&ps);
219         return psd;
220 }
221
222 /*******************************************************************
223  Store a security descriptor in the share db.
224  ********************************************************************/
225
226 static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
227 {
228         prs_struct ps;
229         TALLOC_CTX *mem_ctx = NULL;
230         fstring key;
231         BOOL ret = False;
232
233         mem_ctx = talloc_init();
234         if (mem_ctx == NULL)
235                 return False;
236
237         prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL);
238  
239     if (!sec_io_desc("share_security", &psd, &ps, 1)) {
240         goto out;
241     }
242  
243         slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
244  
245     if (tdb_prs_store(share_tdb, key, &ps)==0) {
246         ret = True;
247         DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
248     } else {
249         DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
250     }
251
252     /* Free malloc'ed memory */
253  
254  out:
255  
256     prs_mem_free(&ps);
257     if (mem_ctx)
258         talloc_destroy(mem_ctx);
259     return ret;
260 }
261
262 /*******************************************************************
263  Delete a security descriptor.
264 ********************************************************************/
265
266 static BOOL delete_share_security(int snum)
267 {
268         TDB_DATA kbuf;
269         fstring key;
270
271         slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
272         kbuf.dptr = key;
273         kbuf.dsize = strlen(key)+1;
274
275         if (tdb_delete(share_tdb, kbuf) != 0) {
276                 DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
277                                 lp_servicename(snum) ));
278                 return False;
279         }
280
281         return True;
282 }
283
284 /*******************************************************************
285  Map any generic bits to file specific bits.
286 ********************************************************************/
287
288 void map_generic_share_sd_bits(SEC_DESC *psd)
289 {
290         extern struct generic_mapping file_generic_mapping;
291         int i;
292         SEC_ACL *ps_dacl = NULL;
293
294         if (!psd)
295                 return;
296
297         ps_dacl = psd->dacl;
298         if (!ps_dacl)
299                 return;
300
301         for (i = 0; i < ps_dacl->num_aces; i++) {
302                 SEC_ACE *psa = &ps_dacl->ace[i];
303                 uint32 orig_mask = psa->info.mask;
304
305                 se_map_generic(&psa->info.mask, &file_generic_mapping);
306                 psa->info.mask |= orig_mask;
307         }       
308 }
309
310 /*******************************************************************
311  Can this user access with share with the required permissions ?
312 ********************************************************************/
313
314 BOOL share_access_check(connection_struct *conn, int snum, uint16 vuid, uint32 desired_access)
315 {
316         uint32 granted;
317         NTSTATUS status;
318         TALLOC_CTX *mem_ctx = NULL;
319         SEC_DESC *psd = NULL;
320         size_t sd_size;
321         NT_USER_TOKEN *token = NULL;
322         user_struct *vuser = get_valid_user_struct(vuid);
323         BOOL ret = True;
324
325         mem_ctx = talloc_init();
326         if (mem_ctx == NULL)
327                 return False;
328
329         psd = get_share_security(mem_ctx, snum, &sd_size);
330
331         if (!psd)
332                 goto out;
333
334         if (vuser)
335                 token = vuser->nt_user_token;
336         else
337                 token = conn->nt_user_token;
338
339         ret = se_access_check(psd, token, desired_access, &granted, &status);
340
341   out:
342
343         talloc_destroy(mem_ctx);
344
345         return ret;
346 }
347
348 /*******************************************************************
349  Fill in a share info level 502 structure.
350  ********************************************************************/
351
352 static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, int snum)
353 {
354         int len_net_name;
355         pstring net_name;
356         pstring remark;
357         pstring path;
358         pstring passwd;
359         uint32 type;
360         SEC_DESC *sd;
361         size_t sd_size;
362         TALLOC_CTX *ctx = p->mem_ctx;
363
364
365         ZERO_STRUCTP(sh502);
366
367         pstrcpy(net_name, lp_servicename(snum));
368         pstrcpy(remark, lp_comment(snum));
369         standard_sub_conn(p->conn, remark);
370         pstrcpy(path, "C:");
371         pstrcat(path, lp_pathname(snum));
372
373         /*
374          * Change / to \\ so that win2k will see it as a valid path.  This was added to
375          * enable use of browsing in win2k add share dialog.
376          */ 
377
378         string_replace(path, '/', '\\');
379
380         pstrcpy(passwd, "");
381         len_net_name = strlen(net_name);
382
383         /* work out the share type */
384         type = STYPE_DISKTREE;
385                 
386         if (lp_print_ok(snum))
387                 type = STYPE_PRINTQ;
388         if (strequal("IPC$", net_name))
389                 type = STYPE_IPC;
390         if (net_name[len_net_name] == '$')
391                 type |= STYPE_HIDDEN;
392
393         sd = get_share_security(ctx, snum, &sd_size);
394
395         init_srv_share_info502(&sh502->info_502, net_name, type, remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
396         init_srv_share_info502_str(&sh502->info_502_str, &sh502->info_502, net_name, remark, path, passwd, sd, sd_size);
397 }
398
399 /***************************************************************************
400  Fill in a share info level 1005 structure.
401  ***************************************************************************/
402
403 static void init_srv_share_info_1005(SRV_SHARE_INFO_1005* sh1005, int snum)
404 {
405         sh1005->dfs_root_flag = 0;
406
407         if(lp_host_msdfs() && lp_msdfs_root(snum))
408                 sh1005->dfs_root_flag = 3;
409 }
410
411 /*******************************************************************
412  True if it ends in '$'.
413  ********************************************************************/
414
415 static BOOL is_admin_share(int snum)
416 {
417         pstring net_name;
418
419         pstrcpy(net_name, lp_servicename(snum));
420         return (net_name[strlen(net_name)] == '$') ? True : False;
421 }
422
423 /*******************************************************************
424  Fill in a share info structure.
425  ********************************************************************/
426
427 static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
428                uint32 info_level, uint32 *resume_hnd, uint32 *total_entries, BOOL all_shares)
429 {
430         int num_entries = 0;
431         int num_services = lp_numservices();
432         int snum;
433         TALLOC_CTX *ctx = p->mem_ctx;
434
435         DEBUG(5,("init_srv_share_info_ctr\n"));
436
437         ZERO_STRUCTPN(ctr);
438
439         ctr->info_level = ctr->switch_value = info_level;
440         *resume_hnd = 0;
441
442         /* Count the number of entries. */
443         for (snum = 0; snum < num_services; snum++) {
444                 if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) )
445                         num_entries++;
446         }
447
448         *total_entries = num_entries;
449         ctr->num_entries2 = ctr->num_entries = num_entries;
450         ctr->ptr_share_info = ctr->ptr_entries = 1;
451
452         if (!num_entries)
453                 return True;
454
455         switch (info_level) {
456         case 1:
457         {
458                 SRV_SHARE_INFO_1 *info1;
459                 int i = 0;
460
461                 info1 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1));
462
463                 for (snum = *resume_hnd; snum < num_services; snum++) {
464                         if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
465                                 init_srv_share_info_1(p, &info1[i++], snum);
466                         }
467                 }
468
469                 ctr->share.info1 = info1;
470                 break;
471         }
472
473         case 2:
474         {
475                 SRV_SHARE_INFO_2 *info2;
476                 int i = 0;
477
478                 info2 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_2));
479
480                 for (snum = *resume_hnd; snum < num_services; snum++) {
481                         if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
482                                 init_srv_share_info_2(p, &info2[i++], snum);
483                         }
484                 }
485
486                 ctr->share.info2 = info2;
487                 break;
488         }
489
490         case 502:
491         {
492                 SRV_SHARE_INFO_502 *info502;
493                 int i = 0;
494
495                 info502 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_502));
496
497                 for (snum = *resume_hnd; snum < num_services; snum++) {
498                         if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
499                                 init_srv_share_info_502(p, &info502[i++], snum);
500                         }
501                 }
502
503                 ctr->share.info502 = info502;
504                 break;
505         }
506
507         default:
508                 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n", info_level));
509                 return False;
510         }
511
512         return True;
513 }
514
515 /*******************************************************************
516  Inits a SRV_R_NET_SHARE_ENUM structure.
517 ********************************************************************/
518
519 static void init_srv_r_net_share_enum(pipes_struct *p, SRV_R_NET_SHARE_ENUM *r_n,
520                                       uint32 info_level, uint32 resume_hnd, BOOL all)  
521 {
522         DEBUG(5,("init_srv_r_net_share_enum: %d\n", __LINE__));
523
524         if (init_srv_share_info_ctr(p, &r_n->ctr, info_level,
525                                     &resume_hnd, &r_n->total_entries, all)) {
526                 r_n->status = NT_STATUS_OK;
527         } else {
528                 r_n->status = NT_STATUS_INVALID_INFO_CLASS;
529         }
530
531         init_enum_hnd(&r_n->enum_hnd, resume_hnd);
532 }
533
534 /*******************************************************************
535  Inits a SRV_R_NET_SHARE_GET_INFO structure.
536 ********************************************************************/
537
538 static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_INFO *r_n,
539                                   char *share_name, uint32 info_level)
540 {
541         NTSTATUS status = NT_STATUS_OK;
542         int snum;
543
544         DEBUG(5,("init_srv_r_net_share_get_info: %d\n", __LINE__));
545
546         r_n->info.switch_value = info_level;
547
548         snum = find_service(share_name);
549
550         if (snum >= 0) {
551                 switch (info_level) {
552                 case 1:
553                         init_srv_share_info_1(p, &r_n->info.share.info1, snum);
554                         break;
555                 case 2:
556                         init_srv_share_info_2(p, &r_n->info.share.info2, snum);
557                         break;
558                 case 502:
559                         init_srv_share_info_502(p, &r_n->info.share.info502, snum);
560                         break;
561                 case 1005:
562                         init_srv_share_info_1005(&r_n->info.share.info1005, snum);
563                         break;
564                 default:
565                         DEBUG(5,("init_srv_net_share_get_info: unsupported switch value %d\n", info_level));
566                         status = NT_STATUS_INVALID_INFO_CLASS;
567                         break;
568                 }
569         } else {
570                 status = NT_STATUS_BAD_NETWORK_NAME;
571         }
572
573         r_n->info.ptr_share_ctr = NT_STATUS_IS_OK(status) ? 1 : 0;
574         r_n->status = status;
575 }
576
577 /*******************************************************************
578  fill in a sess info level 1 structure.
579  ********************************************************************/
580
581 static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name)
582 {
583         init_srv_sess_info0(se0, name);
584         init_srv_sess_info0_str(str0, name);
585 }
586
587 /*******************************************************************
588  fill in a sess info level 0 structure.
589  ********************************************************************/
590
591 static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot)
592 {
593         uint32 num_entries = 0;
594         (*stot) = 1;
595
596         if (ss0 == NULL) {
597                 (*snum) = 0;
598                 return;
599         }
600
601         DEBUG(5,("init_srv_sess_0_ss0\n"));
602
603         if (snum) {
604                 for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
605                         init_srv_sess_0_info(&ss0->info_0[num_entries],
606                                                                  &ss0->info_0_str[num_entries], "MACHINE");
607
608                         /* move on to creating next session */
609                         /* move on to creating next sess */
610                         num_entries++;
611                 }
612
613                 ss0->num_entries_read  = num_entries;
614                 ss0->ptr_sess_info     = num_entries > 0 ? 1 : 0;
615                 ss0->num_entries_read2 = num_entries;
616                 
617                 if ((*snum) >= (*stot)) {
618                         (*snum) = 0;
619                 }
620
621         } else {
622                 ss0->num_entries_read = 0;
623                 ss0->ptr_sess_info = 0;
624                 ss0->num_entries_read2 = 0;
625         }
626 }
627
628 /*******************************************************************
629  fill in a sess info level 1 structure.
630  ********************************************************************/
631
632 static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1,
633                                 char *name, char *user,
634                                 uint32 num_opens,
635                                 uint32 open_time, uint32 idle_time,
636                                 uint32 usr_flgs)
637 {
638         init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
639         init_srv_sess_info1_str(str1, name, user);
640 }
641
642 /*******************************************************************
643  fill in a sess info level 1 structure.
644  ********************************************************************/
645
646 static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot)
647 {
648         uint32 num_entries = 0;
649         (*stot) = 1;
650
651         if (ss1 == NULL) {
652                 (*snum) = 0;
653                 return;
654         }
655
656         DEBUG(5,("init_srv_sess_1_ss1\n"));
657
658         if (snum) {
659                 for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
660                         init_srv_sess_1_info(&ss1->info_1[num_entries],
661                                                                  &ss1->info_1_str[num_entries],
662                                              "MACHINE", "dummy_user", 1, 10, 5, 0);
663
664                         /* move on to creating next session */
665                         /* move on to creating next sess */
666                         num_entries++;
667                 }
668
669                 ss1->num_entries_read  = num_entries;
670                 ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
671                 ss1->num_entries_read2 = num_entries;
672                 
673                 if ((*snum) >= (*stot)) {
674                         (*snum) = 0;
675                 }
676
677         } else {
678                 ss1->num_entries_read = 0;
679                 ss1->ptr_sess_info = 0;
680                 ss1->num_entries_read2 = 0;
681                 
682                 (*stot) = 0;
683         }
684 }
685
686 /*******************************************************************
687  makes a SRV_R_NET_SESS_ENUM structure.
688 ********************************************************************/
689
690 static NTSTATUS init_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr,
691                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
692 {
693         NTSTATUS status = NT_STATUS_OK;
694         DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__));
695
696         ctr->switch_value = switch_value;
697
698         switch (switch_value) {
699         case 0:
700                 init_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries);
701                 ctr->ptr_sess_ctr = 1;
702                 break;
703         case 1:
704                 init_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries);
705                 ctr->ptr_sess_ctr = 1;
706                 break;
707         default:
708                 DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n", switch_value));
709                 (*resume_hnd) = 0;
710                 (*total_entries) = 0;
711                 ctr->ptr_sess_ctr = 0;
712                 status = NT_STATUS_INVALID_INFO_CLASS;
713                 break;
714         }
715
716         return status;
717 }
718
719 /*******************************************************************
720  makes a SRV_R_NET_SESS_ENUM structure.
721 ********************************************************************/
722
723 static void init_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n,
724                                 uint32 resume_hnd, int sess_level, int switch_value)  
725 {
726         DEBUG(5,("init_srv_r_net_sess_enum: %d\n", __LINE__));
727
728         r_n->sess_level  = sess_level;
729
730         if (sess_level == -1)
731                 r_n->status = NT_STATUS_INVALID_INFO_CLASS;
732         else
733                 r_n->status = init_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
734
735         if (NT_STATUS_IS_ERR(r_n->status))
736                 resume_hnd = 0;
737
738         init_enum_hnd(&r_n->enum_hnd, resume_hnd);
739 }
740
741 /*******************************************************************
742  fill in a conn info level 0 structure.
743  ********************************************************************/
744
745 static void init_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot)
746 {
747         uint32 num_entries = 0;
748         (*stot) = 1;
749
750         if (ss0 == NULL) {
751                 (*snum) = 0;
752                 return;
753         }
754
755         DEBUG(5,("init_srv_conn_0_ss0\n"));
756
757         if (snum) {
758                 for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) {
759
760                         init_srv_conn_info0(&ss0->info_0[num_entries], (*stot));
761
762                         /* move on to creating next connection */
763                         /* move on to creating next conn */
764                         num_entries++;
765                 }
766
767                 ss0->num_entries_read  = num_entries;
768                 ss0->ptr_conn_info     = num_entries > 0 ? 1 : 0;
769                 ss0->num_entries_read2 = num_entries;
770                 
771                 if ((*snum) >= (*stot)) {
772                         (*snum) = 0;
773                 }
774
775         } else {
776                 ss0->num_entries_read = 0;
777                 ss0->ptr_conn_info = 0;
778                 ss0->num_entries_read2 = 0;
779
780                 (*stot) = 0;
781         }
782 }
783
784 /*******************************************************************
785  fill in a conn info level 1 structure.
786  ********************************************************************/
787
788 static void init_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1,
789                                 uint32 id, uint32 type,
790                                 uint32 num_opens, uint32 num_users, uint32 open_time,
791                                 char *usr_name, char *net_name)
792 {
793         init_srv_conn_info1(se1 , id, type, num_opens, num_users, open_time, usr_name, net_name);
794         init_srv_conn_info1_str(str1, usr_name, net_name);
795 }
796
797 /*******************************************************************
798  fill in a conn info level 1 structure.
799  ********************************************************************/
800
801 static void init_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot)
802 {
803         uint32 num_entries = 0;
804         (*stot) = 1;
805
806         if (ss1 == NULL) {
807                 (*snum) = 0;
808                 return;
809         }
810
811         DEBUG(5,("init_srv_conn_1_ss1\n"));
812
813         if (snum) {
814                 for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) {
815                         init_srv_conn_1_info(&ss1->info_1[num_entries],
816                                                                  &ss1->info_1_str[num_entries],
817                                              (*stot), 0x3, 1, 1, 3,"dummy_user", "IPC$");
818
819                         /* move on to creating next connection */
820                         /* move on to creating next conn */
821                         num_entries++;
822                 }
823
824                 ss1->num_entries_read  = num_entries;
825                 ss1->ptr_conn_info     = num_entries > 0 ? 1 : 0;
826                 ss1->num_entries_read2 = num_entries;
827                 
828
829                 if ((*snum) >= (*stot)) {
830                         (*snum) = 0;
831                 }
832
833         } else {
834                 ss1->num_entries_read = 0;
835                 ss1->ptr_conn_info = 0;
836                 ss1->num_entries_read2 = 0;
837                 
838                 (*stot) = 0;
839         }
840 }
841
842 /*******************************************************************
843  makes a SRV_R_NET_CONN_ENUM structure.
844 ********************************************************************/
845
846 static NTSTATUS init_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr,
847                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
848 {
849         NTSTATUS status = NT_STATUS_OK;
850         DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__));
851
852         ctr->switch_value = switch_value;
853
854         switch (switch_value) {
855         case 0:
856                 init_srv_conn_info_0(&ctr->conn.info0, resume_hnd, total_entries);
857                 ctr->ptr_conn_ctr = 1;
858                 break;
859         case 1:
860                 init_srv_conn_info_1(&ctr->conn.info1, resume_hnd, total_entries);
861                 ctr->ptr_conn_ctr = 1;
862                 break;
863         default:
864                 DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n", switch_value));
865                 (*resume_hnd = 0);
866                 (*total_entries) = 0;
867                 ctr->ptr_conn_ctr = 0;
868                 status = NT_STATUS_INVALID_INFO_CLASS;
869                 break;
870         }
871
872         return status;
873 }
874
875 /*******************************************************************
876  makes a SRV_R_NET_CONN_ENUM structure.
877 ********************************************************************/
878
879 static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
880                                 uint32 resume_hnd, int conn_level, int switch_value)  
881 {
882         DEBUG(5,("init_srv_r_net_conn_enum: %d\n", __LINE__));
883
884         r_n->conn_level  = conn_level;
885         if (conn_level == -1)
886                 r_n->status = NT_STATUS_INVALID_INFO_CLASS;
887         else
888                 r_n->status = init_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
889
890         if (NT_STATUS_IS_ERR(r_n->status))
891                 resume_hnd = 0;
892
893         init_enum_hnd(&r_n->enum_hnd, resume_hnd);
894 }
895
896 /*******************************************************************
897  fill in a file info level 3 structure.
898  ********************************************************************/
899
900 static void init_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3,
901                                 uint32 fnum, uint32 perms, uint32 num_locks,
902                                 char *path_name, char *user_name)
903 {
904         init_srv_file_info3(fl3 , fnum, perms, num_locks, path_name, user_name);
905         init_srv_file_info3_str(str3, path_name, user_name);
906 }
907
908 /*******************************************************************
909  fill in a file info level 3 structure.
910  ********************************************************************/
911
912 static void init_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot)
913 {
914         uint32 num_entries = 0;
915         (*ftot) = 1;
916
917         if (fl3 == NULL) {
918                 (*fnum) = 0;
919                 return;
920         }
921
922         DEBUG(5,("init_srv_file_3_fl3\n"));
923
924         for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++) {
925                 init_srv_file_3_info(&fl3->info_3[num_entries],
926                                          &fl3->info_3_str[num_entries],
927                                      (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user");
928
929                 /* move on to creating next file */
930                 num_entries++;
931         }
932
933         fl3->num_entries_read  = num_entries;
934         fl3->ptr_file_info     = num_entries > 0 ? 1 : 0;
935         fl3->num_entries_read2 = num_entries;
936         
937         if ((*fnum) >= (*ftot)) {
938                 (*fnum) = 0;
939         }
940 }
941
942 /*******************************************************************
943  makes a SRV_R_NET_FILE_ENUM structure.
944 ********************************************************************/
945
946 static NTSTATUS init_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr,
947                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)  
948 {
949         NTSTATUS status = NT_STATUS_OK;
950         DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
951
952         ctr->switch_value = switch_value;
953
954         switch (switch_value) {
955         case 3:
956                 init_srv_file_info_3(&ctr->file.info3, resume_hnd, total_entries);
957                 ctr->ptr_file_ctr = 1;
958                 break;
959         default:
960                 DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value));
961                 (*resume_hnd = 0);
962                 (*total_entries) = 0;
963                 ctr->ptr_file_ctr = 0;
964                 status = NT_STATUS_INVALID_INFO_CLASS;
965                 break;
966         }
967
968         return status;
969 }
970
971 /*******************************************************************
972  makes a SRV_R_NET_FILE_ENUM structure.
973 ********************************************************************/
974
975 static void init_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n,
976                                 uint32 resume_hnd, int file_level, int switch_value)  
977 {
978         DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
979
980         r_n->file_level  = file_level;
981         if (file_level == 0)
982                 r_n->status = NT_STATUS_INVALID_INFO_CLASS;
983         else
984                 r_n->status = init_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
985
986         if (NT_STATUS_IS_ERR(r_n->status))
987                 resume_hnd = 0;
988
989         init_enum_hnd(&r_n->enum_hnd, resume_hnd);
990 }
991
992 /*******************************************************************
993 net server get info
994 ********************************************************************/
995
996 NTSTATUS _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R_NET_SRV_GET_INFO *r_u)
997 {
998         NTSTATUS status = NT_STATUS_OK;
999         SRV_INFO_CTR *ctr = (SRV_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_INFO_CTR));
1000
1001         if (!ctr)
1002                 return NT_STATUS_NO_MEMORY;
1003
1004         ZERO_STRUCTP(ctr);
1005
1006         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1007
1008         switch (q_u->switch_value) {
1009         case 102:
1010                 init_srv_info_102(&ctr->srv.sv102,
1011                                   500, global_myname, 
1012                                                 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
1013                                   lp_major_announce_version(), lp_minor_announce_version(),
1014                                   lp_default_server_announce(),
1015                                   0xffffffff, /* users */
1016                                   0xf, /* disc */
1017                                   0, /* hidden */
1018                                   240, /* announce */
1019                                   3000, /* announce delta */
1020                                   100000, /* licenses */
1021                                   "c:\\"); /* user path */
1022                 break;
1023         case 101:
1024                 init_srv_info_101(&ctr->srv.sv101,
1025                                   500, global_myname,
1026                                   lp_major_announce_version(), lp_minor_announce_version(),
1027                                   lp_default_server_announce(),
1028                                   string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1029                 break;
1030         case 100:
1031                 init_srv_info_100(&ctr->srv.sv100, 500, global_myname);
1032                 break;
1033         default:
1034                 status = NT_STATUS_INVALID_INFO_CLASS;
1035                 break;
1036         }
1037
1038         /* set up the net server get info structure */
1039         init_srv_r_net_srv_get_info(r_u, q_u->switch_value, ctr, status);
1040
1041         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
1042
1043         return r_u->status;
1044 }
1045
1046 /*******************************************************************
1047 net server set info
1048 ********************************************************************/
1049
1050 NTSTATUS _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R_NET_SRV_SET_INFO *r_u)
1051 {
1052         /* NT gives "Windows NT error 0xc00000022" if we return
1053            NT_STATUS_ACCESS_DENIED here so just pretend everything is OK. */
1054
1055         NTSTATUS status = NT_STATUS_OK;
1056
1057         DEBUG(5,("srv_net_srv_set_info: %d\n", __LINE__));
1058
1059         /* Set up the net server set info structure. */
1060
1061         init_srv_r_net_srv_set_info(r_u, 0x0, status);
1062
1063         DEBUG(5,("srv_net_srv_set_info: %d\n", __LINE__));
1064
1065         return r_u->status;
1066 }
1067
1068 /*******************************************************************
1069 net file enum
1070 ********************************************************************/
1071
1072 NTSTATUS _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
1073 {
1074         r_u->ctr = (SRV_FILE_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_FILE_INFO_CTR));
1075         if (!r_u->ctr)
1076                 return NT_STATUS_NO_MEMORY;
1077
1078         ZERO_STRUCTP(r_u->ctr);
1079
1080         DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
1081
1082         /* set up the */
1083         init_srv_r_net_file_enum(r_u,
1084                                 get_enum_hnd(&q_u->enum_hnd),
1085                                 q_u->file_level,
1086                                 q_u->ctr->switch_value);
1087
1088         DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
1089
1090         return r_u->status;
1091 }
1092
1093 /*******************************************************************
1094 net conn enum
1095 ********************************************************************/
1096
1097 NTSTATUS _srv_net_conn_enum(pipes_struct *p, SRV_Q_NET_CONN_ENUM *q_u, SRV_R_NET_CONN_ENUM *r_u)
1098 {
1099         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1100
1101         r_u->ctr = (SRV_CONN_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_CONN_INFO_CTR));
1102         if (!r_u->ctr)
1103                 return NT_STATUS_NO_MEMORY;
1104
1105         ZERO_STRUCTP(r_u->ctr);
1106
1107         /* set up the */
1108         init_srv_r_net_conn_enum(r_u,
1109                                 get_enum_hnd(&q_u->enum_hnd),
1110                                 q_u->conn_level,
1111                                 q_u->ctr->switch_value);
1112
1113         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
1114
1115         return r_u->status;
1116 }
1117
1118 /*******************************************************************
1119 net sess enum
1120 ********************************************************************/
1121
1122 NTSTATUS _srv_net_sess_enum(pipes_struct *p, SRV_Q_NET_SESS_ENUM *q_u, SRV_R_NET_SESS_ENUM *r_u)
1123 {
1124         DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1125
1126         r_u->ctr = (SRV_SESS_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_SESS_INFO_CTR));
1127         if (!r_u->ctr)
1128                 return NT_STATUS_NO_MEMORY;
1129
1130         ZERO_STRUCTP(r_u->ctr);
1131
1132         /* set up the */
1133         init_srv_r_net_sess_enum(r_u,
1134                                 get_enum_hnd(&q_u->enum_hnd),
1135                                 q_u->sess_level,
1136                                 q_u->ctr->switch_value);
1137
1138         DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
1139
1140         return r_u->status;
1141 }
1142
1143 /*******************************************************************
1144  Net share enum all.
1145 ********************************************************************/
1146
1147 NTSTATUS _srv_net_share_enum_all(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R_NET_SHARE_ENUM *r_u)
1148 {
1149         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1150
1151         /* Create the list of shares for the response. */
1152         init_srv_r_net_share_enum(p, r_u,
1153                                 q_u->ctr.info_level,
1154                                 get_enum_hnd(&q_u->enum_hnd), True);
1155
1156         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1157
1158         return r_u->status;
1159 }
1160
1161 /*******************************************************************
1162  Net share enum.
1163 ********************************************************************/
1164
1165 NTSTATUS _srv_net_share_enum(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R_NET_SHARE_ENUM *r_u)
1166 {
1167         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1168
1169         /* Create the list of shares for the response. */
1170         init_srv_r_net_share_enum(p, r_u,
1171                                 q_u->ctr.info_level,
1172                                 get_enum_hnd(&q_u->enum_hnd), False);
1173
1174         DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
1175
1176         return r_u->status;
1177 }
1178
1179 /*******************************************************************
1180  Net share get info.
1181 ********************************************************************/
1182
1183 NTSTATUS _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, SRV_R_NET_SHARE_GET_INFO *r_u)
1184 {
1185         fstring share_name;
1186
1187         DEBUG(5,("_srv_net_share_get_info: %d\n", __LINE__));
1188
1189         /* Create the list of shares for the response. */
1190         unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
1191         init_srv_r_net_share_get_info(p, r_u, share_name, q_u->info_level);
1192
1193         DEBUG(5,("_srv_net_share_get_info: %d\n", __LINE__));
1194
1195         return r_u->status;
1196 }
1197
1198 /*******************************************************************
1199  Check a given DOS pathname is valid for a share.
1200 ********************************************************************/
1201
1202 static char *valid_share_pathname(char *dos_pathname)
1203 {
1204         pstring saved_pathname;
1205         pstring unix_pathname;
1206         char *ptr;
1207         int ret;
1208
1209         /* Convert any '\' paths to '/' */
1210         unix_format(dos_pathname);
1211         unix_clean_name(dos_pathname);
1212
1213         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1214         ptr = dos_pathname;
1215         if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
1216                 ptr += 2;
1217
1218         /* Only abolute paths allowed. */
1219         if (*ptr != '/')
1220                 return NULL;
1221
1222         /* Can we cd to it ? */
1223
1224         /* First save our current directory. */
1225         if (getcwd(saved_pathname, sizeof(saved_pathname)) == NULL)
1226                 return False;
1227
1228         pstrcpy(unix_pathname, ptr);
1229         
1230         ret = chdir(unix_pathname);
1231
1232         /* We *MUST* be able to chdir back. Abort if we can't. */
1233         if (chdir(saved_pathname) == -1)
1234                 smb_panic("valid_share_pathname: Unable to restore current directory.\n");
1235
1236         return (ret != -1) ? ptr : NULL;
1237 }
1238
1239 /*******************************************************************
1240  Net share set info. Modify share details.
1241 ********************************************************************/
1242
1243 NTSTATUS _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u)
1244 {
1245         struct current_user user;
1246         pstring command;
1247         fstring share_name;
1248         fstring comment;
1249         pstring pathname;
1250         int type;
1251         int snum;
1252         int ret;
1253         char *ptr;
1254         SEC_DESC *psd = NULL;
1255
1256         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1257
1258         unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
1259
1260         r_u->switch_value = 0;
1261
1262         if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
1263                 return NT_STATUS_ACCESS_DENIED;
1264
1265         snum = find_service(share_name);
1266
1267         /* Does this share exist ? */
1268         if (snum < 0)
1269                 return NT_STATUS_BAD_NETWORK_NAME;
1270
1271         /* No change to printer shares. */
1272         if (lp_print_ok(snum))
1273                 return NT_STATUS_ACCESS_DENIED;
1274
1275         get_current_user(&user,p);
1276
1277         if (user.uid != 0)
1278                 return NT_STATUS_ACCESS_DENIED;
1279
1280         switch (q_u->info_level) {
1281         case 1:
1282                 /* Not enough info in a level 1 to do anything. */
1283                 return NT_STATUS_ACCESS_DENIED;
1284         case 2:
1285                 unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(share_name));
1286                 unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(share_name));
1287                 type = q_u->info.share.info2.info_2.type;
1288                 psd = NULL;
1289                 break;
1290         case 502:
1291                 unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
1292                 unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(share_name));
1293                 type = q_u->info.share.info502.info_502.type;
1294                 psd = q_u->info.share.info502.info_502_str.sd;
1295                 map_generic_share_sd_bits(psd);
1296                 break;
1297         case 1005:
1298                 return NT_STATUS_ACCESS_DENIED;
1299         case 1501:
1300                 fstrcpy(pathname, lp_pathname(snum));
1301                 fstrcpy(comment, lp_comment(snum));
1302                 psd = q_u->info.share.info1501.sdb->sec;
1303                 map_generic_share_sd_bits(psd);
1304                 type = STYPE_DISKTREE;
1305                 break;
1306         default:
1307                 DEBUG(5,("_srv_net_share_set_info: unsupported switch value %d\n", q_u->info_level));
1308                 return NT_STATUS_INVALID_INFO_CLASS;
1309         }
1310
1311         /* We can only modify disk shares. */
1312         if (type != STYPE_DISKTREE)
1313                 return NT_STATUS_ACCESS_DENIED;
1314                 
1315         /* Check if the pathname is valid. */
1316         if (!(ptr = valid_share_pathname( pathname )))
1317                 return NT_STATUS_OBJECT_PATH_INVALID;
1318
1319         /* Ensure share name, pathname and comment don't contain '"' characters. */
1320         string_replace(share_name, '"', ' ');
1321         string_replace(ptr, '"', ' ');
1322         string_replace(comment, '"', ' ');
1323
1324         DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
1325                 lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
1326
1327         /* Only call modify function if something changed. */
1328
1329         if (strcmp(ptr, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) {
1330                 if (!lp_change_share_cmd() || !*lp_change_share_cmd())
1331                         return NT_STATUS_ACCESS_DENIED;
1332
1333                 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1334                                 lp_change_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment);
1335
1336                 DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command ));
1337                 if ((ret = smbrun(command, NULL)) != 0) {
1338                         DEBUG(0,("_srv_net_share_set_info: Running [%s] returned (%d)\n", command, ret ));
1339                         return NT_STATUS_ACCESS_DENIED;
1340                 }
1341
1342                 /* Tell everyone we updated smb.conf. */
1343                 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL,
1344                                  0, False, NULL);
1345
1346         } else {
1347                 DEBUG(10,("_srv_net_share_set_info: No change to share name (%s)\n", share_name ));
1348         }
1349
1350         /* Replace SD if changed. */
1351         if (psd) {
1352                 SEC_DESC *old_sd;
1353                 size_t sd_size;
1354
1355                 old_sd = get_share_security(p->mem_ctx, snum, &sd_size);
1356
1357                 if (old_sd && !sec_desc_equal(old_sd, psd)) {
1358                         if (!set_share_security(p->mem_ctx, share_name, psd))
1359                                 DEBUG(0,("_srv_net_share_set_info: Failed to change security info in share %s.\n",
1360                                         share_name ));
1361                 }
1362         }
1363
1364         DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
1365
1366         return NT_STATUS_OK;
1367 }
1368
1369 /*******************************************************************
1370  Net share add. Call 'add_share_command "sharename" "pathname" "comment" "read only = xxx"'
1371 ********************************************************************/
1372
1373 NTSTATUS _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u)
1374 {
1375         struct current_user user;
1376         pstring command;
1377         fstring share_name;
1378         fstring comment;
1379         pstring pathname;
1380         int type;
1381         int snum;
1382         int ret;
1383         char *ptr;
1384         SEC_DESC *psd = NULL;
1385
1386         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1387
1388         r_u->switch_value = 0;
1389
1390         get_current_user(&user,p);
1391
1392         if (user.uid != 0) {
1393                 DEBUG(10,("_srv_net_share_add: uid != 0. Access denied.\n"));
1394                 return NT_STATUS_ACCESS_DENIED;
1395         }
1396
1397         if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
1398                 DEBUG(10,("_srv_net_share_add: No add share command\n"));
1399                 return NT_STATUS_ACCESS_DENIED;
1400         }
1401
1402         switch (q_u->info_level) {
1403         case 1:
1404                 /* Not enough info in a level 1 to do anything. */
1405                 return NT_STATUS_ACCESS_DENIED;
1406         case 2:
1407                 unistr2_to_ascii(share_name, &q_u->info.share.info2.info_2_str.uni_netname, sizeof(share_name));
1408                 unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(share_name));
1409                 unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(share_name));
1410                 type = q_u->info.share.info2.info_2.type;
1411                 break;
1412         case 502:
1413                 unistr2_to_ascii(share_name, &q_u->info.share.info502.info_502_str.uni_netname, sizeof(share_name));
1414                 unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
1415                 unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(share_name));
1416                 type = q_u->info.share.info502.info_502.type;
1417                 psd = q_u->info.share.info502.info_502_str.sd;
1418                 map_generic_share_sd_bits(psd);
1419                 break;
1420         case 1005:
1421                 /* DFS only level. */
1422                 return NT_STATUS_ACCESS_DENIED;
1423         default:
1424                 DEBUG(5,("_srv_net_share_add: unsupported switch value %d\n", q_u->info_level));
1425                 return NT_STATUS_INVALID_INFO_CLASS;
1426         }
1427
1428         if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
1429                 return NT_STATUS_ACCESS_DENIED;
1430
1431         snum = find_service(share_name);
1432
1433         /* Share already exists. */
1434         if (snum >= 0)
1435                 return NT_STATUS_OBJECT_NAME_COLLISION;
1436
1437         /* We can only add disk shares. */
1438         if (type != STYPE_DISKTREE)
1439                 return NT_STATUS_ACCESS_DENIED;
1440                 
1441         /* Check if the pathname is valid. */
1442         if (!(ptr = valid_share_pathname( pathname )))
1443                 return NT_STATUS_OBJECT_PATH_INVALID;
1444
1445         /* Ensure share name, pathname and comment don't contain '"' characters. */
1446         string_replace(share_name, '"', ' ');
1447         string_replace(ptr, '"', ' ');
1448         string_replace(comment, '"', ' ');
1449
1450         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1451                         lp_add_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment);
1452
1453         DEBUG(10,("_srv_net_share_add: Running [%s]\n", command ));
1454         if ((ret = smbrun(command, NULL)) != 0) {
1455                 DEBUG(0,("_srv_net_share_add: Running [%s] returned (%d)\n", command, ret ));
1456                 return NT_STATUS_ACCESS_DENIED;
1457         }
1458
1459         if (psd) {
1460                 if (!set_share_security(p->mem_ctx, share_name, psd))
1461                         DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n",
1462                                 share_name ));
1463         }
1464
1465         /* Tell everyone we updated smb.conf. */
1466         message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False,
1467                          NULL);
1468
1469         /*
1470          * We don't call reload_services() here, the message will
1471          * cause this to be done before the next packet is read
1472          * from the client. JRA.
1473          */
1474
1475         DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
1476
1477         return NT_STATUS_OK;
1478 }
1479
1480 /*******************************************************************
1481  Net share delete. Call "delete share command" with the share name as
1482  a parameter.
1483 ********************************************************************/
1484
1485 NTSTATUS _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u)
1486 {
1487         struct current_user user;
1488         pstring command;
1489         fstring share_name;
1490         int ret;
1491         int snum;
1492
1493         DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
1494
1495         unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
1496
1497         if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
1498                 return NT_STATUS_ACCESS_DENIED;
1499
1500         snum = find_service(share_name);
1501
1502         if (snum < 0)
1503                 return NT_STATUS_BAD_NETWORK_NAME;
1504
1505         /* No change to printer shares. */
1506         if (lp_print_ok(snum))
1507                 return NT_STATUS_ACCESS_DENIED;
1508
1509         get_current_user(&user,p);
1510
1511         if (user.uid != 0)
1512                 return NT_STATUS_ACCESS_DENIED;
1513
1514         if (!lp_delete_share_cmd() || !*lp_delete_share_cmd())
1515                 return NT_STATUS_ACCESS_DENIED;
1516
1517         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
1518                         lp_delete_share_cmd(), dyn_CONFIGFILE, lp_servicename(snum));
1519
1520         DEBUG(10,("_srv_net_share_del: Running [%s]\n", command ));
1521         if ((ret = smbrun(command, NULL)) != 0) {
1522                 DEBUG(0,("_srv_net_share_del: Running [%s] returned (%d)\n", command, ret ));
1523                 return NT_STATUS_ACCESS_DENIED;
1524         }
1525
1526         /* Delete the SD in the database. */
1527         delete_share_security(snum);
1528
1529         /* Tell everyone we updated smb.conf. */
1530         message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False,
1531                          NULL);
1532
1533         lp_killservice(snum);
1534
1535         return NT_STATUS_OK;
1536 }
1537
1538 /*******************************************************************
1539 time of day
1540 ********************************************************************/
1541
1542 NTSTATUS _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET_REMOTE_TOD *r_u)
1543 {
1544         TIME_OF_DAY_INFO *tod;
1545         struct tm *t;
1546         time_t unixdate = time(NULL);
1547
1548         tod = (TIME_OF_DAY_INFO *)talloc(p->mem_ctx, sizeof(TIME_OF_DAY_INFO));
1549         if (!tod)
1550                 return NT_STATUS_NO_MEMORY;
1551
1552         ZERO_STRUCTP(tod);
1553  
1554         r_u->tod = tod;
1555         r_u->ptr_srv_tod = 0x1;
1556         r_u->status = NT_STATUS_OK;
1557
1558         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
1559
1560         t = gmtime(&unixdate);
1561
1562         /* set up the */
1563         init_time_of_day_info(tod,
1564                               unixdate,
1565                               0,
1566                               t->tm_hour,
1567                               t->tm_min,
1568                               t->tm_sec,
1569                               0,
1570                               TimeDiff(unixdate)/60,
1571                               10000,
1572                               t->tm_mday,
1573                               t->tm_mon + 1,
1574                               1900+t->tm_year,
1575                               t->tm_wday);
1576         
1577         DEBUG(5,("_srv_net_remote_tod: %d\n", __LINE__));
1578
1579         return r_u->status;
1580 }
1581
1582 /***********************************************************************************
1583  Win9x NT tools get security descriptor.
1584 ***********************************************************************************/
1585
1586 NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC *q_u,
1587                         SRV_R_NET_FILE_QUERY_SECDESC *r_u)
1588 {
1589         SEC_DESC *psd = NULL;
1590         size_t sd_size;
1591         DATA_BLOB null_pw;
1592         pstring filename;
1593         pstring qualname;
1594         files_struct *fsp = NULL;
1595         SMB_STRUCT_STAT st;
1596         BOOL bad_path;
1597         int access_mode;
1598         int action;
1599         NTSTATUS nt_status;
1600         struct current_user user;
1601         connection_struct *conn = NULL;
1602         BOOL became_user = False;
1603
1604         ZERO_STRUCT(st);
1605
1606         r_u->status = NT_STATUS_OK;
1607
1608         unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname));
1609
1610         /* Null password is ok - we are already an authenticated user... */
1611         null_pw = data_blob(NULL, 0);
1612
1613         get_current_user(&user, p);     
1614         
1615         become_root();
1616         conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
1617         unbecome_root();
1618
1619         if (conn == NULL) {
1620                 DEBUG(3,("_srv_net_file_query_secdesc: Unable to connect to %s\n", qualname));
1621                 r_u->status = nt_status;
1622                 goto error_exit;
1623         }
1624
1625         if (!become_user(conn, conn->vuid)) {
1626                 DEBUG(0,("_srv_net_file_query_secdesc: Can't become connected user!\n"));
1627                 r_u->status = NT_STATUS_ACCESS_DENIED;
1628                 goto error_exit;
1629         }
1630         became_user = True;
1631
1632         unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
1633         unix_convert(filename, conn, NULL, &bad_path, &st);
1634
1635         fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDONLY),
1636                                (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
1637
1638         if (!fsp) {
1639                 /* Perhaps it is a directory */
1640                 if (errno == EISDIR)
1641                         fsp = open_directory(conn, filename, &st,0,
1642                                              (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
1643
1644                 if (!fsp) {
1645                         DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
1646                         r_u->status = NT_STATUS_ACCESS_DENIED;
1647                         goto error_exit;
1648                 }
1649         }
1650
1651         sd_size = conn->vfs_ops.get_nt_acl(fsp, fsp->fsp_name, &psd);
1652
1653         if (sd_size == 0) {
1654                 DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", filename));
1655                 r_u->status = NT_STATUS_ACCESS_DENIED;
1656                 goto error_exit;
1657         }
1658
1659         r_u->ptr_response = 1;
1660         r_u->size_response = sd_size;
1661         r_u->ptr_secdesc = 1;
1662         r_u->size_secdesc = sd_size;
1663         r_u->sec_desc = psd;
1664
1665         psd->dacl->revision = (uint16) NT4_ACL_REVISION;
1666
1667         close_file(fsp, True);
1668         unbecome_user();
1669         close_cnum(conn, user.vuid);
1670         return r_u->status;
1671
1672   error_exit:
1673
1674         if(fsp) {
1675                 close_file(fsp, True);
1676         }
1677
1678         if (became_user)
1679                 unbecome_user();
1680
1681         if (conn) 
1682                 close_cnum(conn, user.vuid);
1683
1684         return r_u->status;
1685 }
1686
1687 /***********************************************************************************
1688  Win9x NT tools set security descriptor.
1689 ***********************************************************************************/
1690
1691 NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_u,
1692                                                                         SRV_R_NET_FILE_SET_SECDESC *r_u)
1693 {
1694         BOOL ret;
1695         DATA_BLOB null_pw;
1696         pstring filename;
1697         pstring qualname;
1698         files_struct *fsp = NULL;
1699         SMB_STRUCT_STAT st;
1700         BOOL bad_path;
1701         int access_mode;
1702         int action;
1703         NTSTATUS nt_status;
1704         struct current_user user;
1705         connection_struct *conn = NULL;
1706         BOOL became_user = False;
1707
1708         ZERO_STRUCT(st);
1709
1710         r_u->status = NT_STATUS_OK;
1711
1712         unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname));
1713
1714         /* Null password is ok - we are already an authenticated user... */
1715         null_pw = data_blob(NULL, 0);
1716
1717         get_current_user(&user, p);     
1718         
1719         become_root();
1720         conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
1721         unbecome_root();
1722
1723         if (conn == NULL) {
1724                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", qualname));
1725                 r_u->status = nt_status;
1726                 goto error_exit;
1727         }
1728
1729         if (!become_user(conn, conn->vuid)) {
1730                 DEBUG(0,("_srv_net_file_set_secdesc: Can't become connected user!\n"));
1731                 r_u->status = NT_STATUS_ACCESS_DENIED;
1732                 goto error_exit;
1733         }
1734         became_user = True;
1735
1736         unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
1737         unix_convert(filename, conn, NULL, &bad_path, &st);
1738
1739         fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDWR),
1740                                (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
1741
1742         if (!fsp) {
1743                 /* Perhaps it is a directory */
1744                 if (errno == EISDIR)
1745                         fsp = open_directory(conn, filename, &st,0,
1746                                              (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
1747
1748                 if (!fsp) {
1749                         DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
1750                         r_u->status = NT_STATUS_ACCESS_DENIED;
1751                         goto error_exit;
1752                 }
1753         }
1754
1755         ret = conn->vfs_ops.set_nt_acl(fsp, fsp->fsp_name, q_u->sec_info, q_u->sec_desc);
1756
1757         if (ret == False) {
1758                 DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", filename));
1759                 r_u->status = NT_STATUS_ACCESS_DENIED;
1760                 goto error_exit;
1761         }
1762
1763         close_file(fsp, True);
1764         unbecome_user();
1765         close_cnum(conn, user.vuid);
1766         return r_u->status;
1767
1768   error_exit:
1769
1770         if(fsp) {
1771                 close_file(fsp, True);
1772         }
1773
1774         if (became_user)
1775                 unbecome_user();
1776
1777         if (conn) 
1778                 close_cnum(conn, user.vuid);
1779
1780         return r_u->status;
1781 }
1782
1783 /***********************************************************************************
1784  It may be that we want to limit users to creating shares on certain areas of the UNIX file area.
1785  We could define areas by mapping Windows style disks to points on the UNIX directory hierarchy.
1786  These disks would the disks listed by this function.
1787  Users could then create shares relative to these disks.  Watch out for moving these disks around.
1788  "Nigel Williams" <nigel@veritas.com>.
1789 ***********************************************************************************/
1790
1791 const char *server_disks[] = {"C:"};
1792
1793 static uint32 get_server_disk_count(void)
1794 {
1795         return sizeof(server_disks)/sizeof(server_disks[0]);
1796 }
1797
1798 static uint32 init_server_disk_enum(uint32 *resume)
1799 {
1800         uint32 server_disk_count = get_server_disk_count();
1801
1802         /*resume can be an offset into the list for now*/
1803
1804         if(*resume & 0x80000000)
1805                 *resume = 0;
1806
1807         if(*resume > server_disk_count)
1808                 *resume = server_disk_count;
1809
1810         return server_disk_count - *resume;
1811 }
1812
1813 static const char *next_server_disk_enum(uint32 *resume)
1814 {
1815         const char *disk;
1816
1817         if(init_server_disk_enum(resume) == 0)
1818                 return NULL;
1819
1820         disk = server_disks[*resume];
1821
1822         (*resume)++;
1823
1824         DEBUG(10, ("next_server_disk_enum: reporting disk %s. resume handle %d.\n", disk, *resume));
1825
1826         return disk;
1827 }
1828
1829 NTSTATUS _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_DISK_ENUM *r_u)
1830 {
1831         uint32 i;
1832         const char *disk_name;
1833         uint32 resume=get_enum_hnd(&q_u->enum_hnd);
1834
1835         r_u->status=NT_STATUS_OK;
1836
1837         r_u->total_entries = init_server_disk_enum(&resume);
1838
1839         r_u->disk_enum_ctr.unknown = 0; 
1840
1841         r_u->disk_enum_ctr.disk_info_ptr = r_u->disk_enum_ctr.disk_info? 1 : 0;
1842
1843         /*allow one DISK_INFO for null terminator*/
1844
1845         for(i = 0; i < MAX_SERVER_DISK_ENTRIES -1 && (disk_name = next_server_disk_enum(&resume)); i++) {
1846
1847                 r_u->disk_enum_ctr.entries_read++;
1848
1849                 /*copy disk name into a unicode string*/
1850
1851                 init_unistr3(&r_u->disk_enum_ctr.disk_info[i].disk_name, disk_name);    
1852         }
1853
1854         /*add a terminating null string.  Is this there if there is more data to come?*/
1855
1856         r_u->disk_enum_ctr.entries_read++;
1857
1858         init_unistr3(&r_u->disk_enum_ctr.disk_info[i].disk_name, "");
1859
1860         init_enum_hnd(&r_u->enum_hnd, resume);
1861
1862         return r_u->status;
1863 }
1864
1865 NTSTATUS _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV_R_NET_NAME_VALIDATE *r_u)
1866 {
1867         int snum;
1868         fstring share_name;
1869
1870         r_u->status=NT_STATUS_OK;
1871
1872         switch(q_u->type) {
1873
1874         case 0x9:
1875
1876                 /*check if share name is ok*/
1877                 /*also check if we already have a share with this name*/
1878
1879                 unistr2_to_ascii(share_name, &q_u->uni_name, sizeof(share_name));
1880                 snum = find_service(share_name);
1881
1882                 /* Share already exists. */
1883                 if (snum >= 0)
1884                         r_u->status = NT_STATUS_OBJECT_NAME_INVALID;
1885                 break;
1886
1887         default:
1888                 /*unsupported type*/
1889                 r_u->status = NT_STATUS_INVALID_LEVEL;
1890                 break;
1891         }
1892
1893         return r_u->status;
1894 }