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