make swat recover from previously bad umask from xinetd
[samba.git] / source3 / web / swat.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba Web Administration Tool
5    Copyright (C) Andrew Tridgell 1997-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27 #include "smb.h"
28
29 #define GLOBALS_SNUM -1
30
31 static pstring servicesf = CONFIGFILE;
32 static BOOL demo_mode = False;
33 static BOOL have_write_access = False;
34 static BOOL have_read_access = False;
35 static int iNumNonAutoPrintServices = 0;
36
37 /*
38  * Password Management Globals
39  */
40 #define SWAT_USER "username"
41 #define OLD_PSWD "old_passwd"
42 #define NEW_PSWD "new_passwd"
43 #define NEW2_PSWD "new2_passwd"
44 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
45 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
46 #define ADD_USER_FLAG "add_user_flag"
47 #define DELETE_USER_FLAG "delete_user_flag"
48 #define DISABLE_USER_FLAG "disable_user_flag"
49 #define ENABLE_USER_FLAG "enable_user_flag"
50 #define RHOST "remote_host"
51
52 /* we need these because we link to locking*.o */
53  void become_root(void) {}
54  void unbecome_root(void) {}
55
56 /****************************************************************************
57 ****************************************************************************/
58 static int enum_index(int value, struct enum_list *enumlist)
59 {
60         int i;
61         for (i=0;enumlist[i].name;i++)
62                 if (value == enumlist[i].value) break;
63         return(i);
64 }
65
66 static char *fix_backslash(char *str)
67 {
68         static char newstring[1024];
69         char *p = newstring;
70
71         while (*str) {
72                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
73                 else *p++ = *str;
74                 ++str;
75         }
76         *p = '\0';
77         return newstring;
78 }
79
80 static char *stripspace(char *str)
81 {
82 static char newstring[1024];
83 char *p = newstring;
84
85         while (*str) {
86                 if (*str != ' ') *p++ = *str;
87                 ++str;
88         }
89         *p = '\0';
90         return newstring;
91 }
92
93 static char *make_parm_name(char *label)
94 {
95         static char parmname[1024];
96         char *p = parmname;
97
98         while (*label) {
99                 if (*label == ' ') *p++ = '_';
100                 else *p++ = *label;
101                 ++label;
102         }
103         *p = '\0';
104         return parmname;
105 }
106
107 /****************************************************************************
108   include a lump of html in a page 
109 ****************************************************************************/
110 static int include_html(char *fname)
111 {
112         FILE *f = sys_fopen(fname,"r");
113         char buf[1024];
114         int ret;
115
116         if (!f) {
117                 printf("ERROR: Can't open %s\n", fname);
118                 return 0;
119         }
120
121         while (!feof(f)) {
122                 ret = fread(buf, 1, sizeof(buf), f);
123                 if (ret <= 0) break;
124                 fwrite(buf, 1, ret, stdout);
125         }
126
127         fclose(f);
128         return 1;
129 }
130
131 /****************************************************************************
132   start the page with standard stuff 
133 ****************************************************************************/
134 static void print_header(void)
135 {
136         if (!cgi_waspost()) {
137                 printf("Expires: 0\r\n");
138         }
139         printf("Content-type: text/html\r\n\r\n");
140
141         if (!include_html("include/header.html")) {
142                 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
143                 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
144         }
145 }
146
147 /****************************************************************************
148  finish off the page 
149 ****************************************************************************/
150 static void print_footer(void)
151 {
152         if (!include_html("include/footer.html")) {
153                 printf("\n</BODY>\n</HTML>\n");
154         }
155 }
156
157 /****************************************************************************
158   display one editable parameter in a form 
159 ****************************************************************************/
160 static void show_parameter(int snum, struct parm_struct *parm)
161 {
162         int i;
163         void *ptr = parm->ptr;
164         char* str;
165
166         if (parm->class == P_LOCAL && snum >= 0) {
167                 ptr = lp_local_ptr(snum, ptr);
168         }
169
170         str = stripspace(parm->label);
171         strupper (str);
172         printf("<tr><td><A HREF=\"/swat/help/smb.conf.5.html#%s\" target=\"docs\">Help</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s</td><td>", 
173                str, parm->label);
174
175         switch (parm->type) {
176         case P_CHAR:
177                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
178                        make_parm_name(parm->label), *(char *)ptr);
179                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
180                         make_parm_name(parm->label),(char)(parm->def.cvalue));
181                 break;
182
183         case P_STRING:
184         case P_USTRING:
185                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
186                        make_parm_name(parm->label), *(char **)ptr);
187                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
188                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
189                 break;
190
191         case P_GSTRING:
192         case P_UGSTRING:
193                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
194                        make_parm_name(parm->label), (char *)ptr);
195                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
196                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
197                 break;
198
199         case P_BOOL:
200                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
201                 printf("<option %s>Yes", (*(BOOL *)ptr)?"selected":"");
202                 printf("<option %s>No", (*(BOOL *)ptr)?"":"selected");
203                 printf("</select>");
204                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
205                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?0:1);
206                 break;
207
208         case P_BOOLREV:
209                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
210                 printf("<option %s>Yes", (*(BOOL *)ptr)?"":"selected");
211                 printf("<option %s>No", (*(BOOL *)ptr)?"selected":"");
212                 printf("</select>");
213                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
214                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?1:0);
215                 break;
216
217         case P_INTEGER:
218                 printf("<input type=text size=8 name=\"parm_%s\" value=%d>", make_parm_name(parm->label), *(int *)ptr);
219                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
220                         make_parm_name(parm->label),(int)(parm->def.ivalue));
221                 break;
222
223         case P_OCTAL:
224                 printf("<input type=text size=8 name=\"parm_%s\" value=%s>", make_parm_name(parm->label), octal_string(*(int *)ptr));
225                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
226                        make_parm_name(parm->label),
227                        octal_string((int)(parm->def.ivalue)));
228                 break;
229
230         case P_ENUM:
231                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
232                 for (i=0;parm->enum_list[i].name;i++) {
233                         if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
234                                 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
235                         }
236                 }
237                 printf("</select>");
238                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
239                         make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
240                 break;
241         case P_SEP:
242                 break;
243         }
244         printf("</td></tr>\n");
245 }
246
247 /****************************************************************************
248   display a set of parameters for a service 
249 ****************************************************************************/
250 static void show_parameters(int snum, int allparameters, int advanced, int printers)
251 {
252         int i = 0;
253         struct parm_struct *parm;
254         char *heading = NULL;
255         char *last_heading = NULL;
256
257         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
258                 if (snum < 0 && parm->class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
259                         continue;
260                 if (parm->class == P_SEPARATOR) {
261                         heading = parm->label;
262                         continue;
263                 }
264                 if (parm->flags & FLAG_HIDE) continue;
265                 if (snum >= 0) {
266                         if (printers & !(parm->flags & FLAG_PRINT)) continue;
267                         if (!printers & !(parm->flags & FLAG_SHARE)) continue;
268                 }
269                 if (!advanced) {
270                         if (!(parm->flags & FLAG_BASIC)) {
271                                 void *ptr = parm->ptr;
272
273                                 if (parm->class == P_LOCAL && snum >= 0) {
274                                         ptr = lp_local_ptr(snum, ptr);
275                                 }
276
277                                 switch (parm->type) {
278                                 case P_CHAR:
279                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
280                                         break;
281
282                                 case P_STRING:
283                                 case P_USTRING:
284                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
285                                         break;
286
287                                 case P_GSTRING:
288                                 case P_UGSTRING:
289                                         if (!strcmp((char *)ptr,(char *)(parm->def.svalue))) continue;
290                                         break;
291
292                                 case P_BOOL:
293                                 case P_BOOLREV:
294                                         if (*(BOOL *)ptr == (BOOL)(parm->def.bvalue)) continue;
295                                         break;
296
297                                 case P_INTEGER:
298                                 case P_OCTAL:
299                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
300                                         break;
301
302
303                                 case P_ENUM:
304                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
305                                         break;
306                                 case P_SEP:
307                                         continue;
308                                 }
309                         }
310                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
311                 }
312                 if (heading && heading != last_heading) {
313                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", heading);
314                         last_heading = heading;
315                 }
316                 show_parameter(snum, parm);
317         }
318 }
319
320 /****************************************************************************
321   load the smb.conf file into loadparm.
322 ****************************************************************************/
323 static BOOL load_config(BOOL save_def)
324 {
325         lp_resetnumservices();
326         return lp_load(servicesf,False,save_def,False);
327 }
328
329 /****************************************************************************
330   write a config file 
331 ****************************************************************************/
332 static void write_config(FILE *f, BOOL show_defaults, char *(*dos_to_ext)(char *, BOOL))
333 {
334         fprintf(f, "# Samba config file created using SWAT\n");
335         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
336         fprintf(f, "# Date: %s\n\n", timestring(False));
337         
338         lp_dump(f, show_defaults, iNumNonAutoPrintServices, dos_to_ext);        
339 }
340
341 /****************************************************************************
342   save and reoad the smb.conf config file 
343 ****************************************************************************/
344 static int save_reload(int snum)
345 {
346         FILE *f;
347         struct stat st;
348
349         f = sys_fopen(servicesf,"w");
350         if (!f) {
351                 printf("failed to open %s for writing\n", servicesf);
352                 return 0;
353         }
354
355         /* just in case they have used the buggy xinetd to create the file */
356         if (fstat(fileno(f), &st) == 0 &&
357             (st.st_mode & S_IWOTH)) {
358                 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
359         }
360
361         write_config(f, False, _dos_to_unix);
362         if (snum)
363                 lp_dump_one(f, False, snum, _dos_to_unix);
364         fclose(f);
365
366         lp_killunused(NULL);
367
368         if (!load_config(False)) {
369                 printf("Can't reload %s\n", servicesf);
370                 return 0;
371         }
372         iNumNonAutoPrintServices = lp_numservices();
373         load_printers();
374
375         return 1;
376 }
377
378 /****************************************************************************
379   commit one parameter 
380 ****************************************************************************/
381 static void commit_parameter(int snum, struct parm_struct *parm, char *v)
382 {
383         int i;
384         char *s;
385
386         /* lp_do_parameter() will do unix_to_dos(v). */
387         if(parm->flags & FLAG_DOS_STRING)
388                 dos_to_unix(v, True);
389
390         if (snum < 0 && parm->class == P_LOCAL) {
391                 /* this handles the case where we are changing a local
392                    variable globally. We need to change the parameter in 
393                    all shares where it is currently set to the default */
394                 for (i=0;i<lp_numservices();i++) {
395                         s = lp_servicename(i);
396                         if (s && (*s) && lp_is_default(i, parm)) {
397                                 lp_do_parameter(i, parm->label, v);
398                         }
399                 }
400         }
401
402         lp_do_parameter(snum, parm->label, v);
403 }
404
405 /****************************************************************************
406   commit a set of parameters for a service 
407 ****************************************************************************/
408 static void commit_parameters(int snum)
409 {
410         int i = 0;
411         struct parm_struct *parm;
412         pstring label;
413         char *v;
414
415         while ((parm = lp_next_parameter(snum, &i, 1))) {
416                 slprintf(label, sizeof(label)-1, "parm_%s", make_parm_name(parm->label));
417                 if ((v = cgi_variable(label))) {
418                         if (parm->flags & FLAG_HIDE) continue;
419                         commit_parameter(snum, parm, v); 
420                 }
421         }
422 }
423
424 /****************************************************************************
425   spit out the html for a link with an image 
426 ****************************************************************************/
427 static void image_link(char *name,char *hlink, char *src)
428 {
429         printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", 
430                cgi_baseurl(), hlink, src, name);
431 }
432
433 /****************************************************************************
434   display the main navigation controls at the top of each page along
435   with a title 
436 ****************************************************************************/
437 static void show_main_buttons(void)
438 {
439         char *p;
440         
441         if ((p = cgi_user_name()) && strcmp(p, "root")) {
442                 printf("Logged in as <b>%s</b><p>\n", p);
443         }
444
445         image_link("Home", "", "images/home.gif");
446         if (have_write_access) {
447                 image_link("Globals", "globals", "images/globals.gif");
448                 image_link("Shares", "shares", "images/shares.gif");
449                 image_link("Printers", "printers", "images/printers.gif");
450         }
451         if (have_read_access) {
452                 image_link("Status", "status", "images/status.gif");
453                 image_link("View Config", "viewconfig","images/viewconfig.gif");
454         }
455         image_link("Password Management", "passwd", "images/passwd.gif");
456
457         printf("<HR>\n");
458 }
459
460 /****************************************************************************
461   display a welcome page  
462 ****************************************************************************/
463 static void welcome_page(void)
464 {
465         include_html("help/welcome.html");
466 }
467
468 /****************************************************************************
469   display the current smb.conf  
470 ****************************************************************************/
471 static void viewconfig_page(void)
472 {
473         int full_view=0;
474
475         if (cgi_variable("full_view")) {
476                 full_view = 1;
477         }
478
479         printf("<H2>Current Config</H2>\n");
480         printf("<form method=post>\n");
481
482         if (full_view) {
483                 printf("<input type=submit name=\"normal_view\" value=\"Normal View\">\n");
484         } else {
485                 printf("<input type=submit name=\"full_view\" value=\"Full View\">\n");
486         }
487
488         printf("<p><pre>");
489         write_config(stdout, full_view, _dos_to_dos);
490         printf("</pre>");
491         printf("</form>\n");
492 }
493
494 /****************************************************************************
495   display a globals editing page  
496 ****************************************************************************/
497 static void globals_page(void)
498 {
499         int advanced = 0;
500
501         printf("<H2>Global Variables</H2>\n");
502
503         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
504                 advanced = 1;
505
506         if (cgi_variable("Commit")) {
507                 commit_parameters(GLOBALS_SNUM);
508                 save_reload(0);
509         }
510
511         printf("<FORM name=\"swatform\" method=post>\n");
512
513         if (have_write_access) {
514                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
515         }
516
517         printf("<input type=reset name=\"Reset Values\" value=\"Reset Values\">\n");
518         if (advanced == 0) {
519                 printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
520         } else {
521                 printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
522         }
523         printf("<p>\n");
524         
525         printf("<table>\n");
526         show_parameters(GLOBALS_SNUM, 1, advanced, 0);
527         printf("</table>\n");
528
529         if (advanced) {
530                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
531         }
532
533         printf("</FORM>\n");
534 }
535
536 /****************************************************************************
537   display a shares editing page. share is in unix codepage, and must be in
538   dos codepage. FIXME !!! JRA.
539 ****************************************************************************/
540 static void shares_page(void)
541 {
542         char *share = cgi_variable("share");
543         char *s;
544         int snum=-1;
545         int i;
546         int advanced = 0;
547
548         if (share)
549                 snum = lp_servicenumber(share);
550
551         printf("<H2>Share Parameters</H2>\n");
552
553         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
554                 advanced = 1;
555
556         if (cgi_variable("Commit") && snum >= 0) {
557                 commit_parameters(snum);
558                 save_reload(0);
559         }
560
561         if (cgi_variable("Delete") && snum >= 0) {
562                 lp_remove_service(snum);
563                 save_reload(0);
564                 share = NULL;
565                 snum = -1;
566         }
567
568         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
569                 /* add_a_service() which is called by lp_copy_service()
570                         will do unix_to_dos() conversion, so we need dos_to_unix() before the lp_copy_service(). */
571                 pstring unix_share;
572                 pstrcpy(unix_share, dos_to_unix(share, False));
573                 load_config(False);
574                 lp_copy_service(GLOBALS_SNUM, unix_share);
575                 iNumNonAutoPrintServices = lp_numservices();
576                 save_reload(0);
577                 snum = lp_servicenumber(share);
578         }
579
580         printf("<FORM name=\"swatform\" method=post>\n");
581
582         printf("<table>\n");
583         printf("<tr>\n");
584         printf("<td><input type=submit name=selectshare value=\"Choose Share\"></td>\n");
585         printf("<td><select name=share>\n");
586         if (snum < 0)
587                 printf("<option value=\" \"> \n");
588         for (i=0;i<lp_numservices();i++) {
589                 s = lp_servicename(i);
590                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
591                         printf("<option %s value=\"%s\">%s\n", 
592                                (share && strcmp(share,s)==0)?"SELECTED":"",
593                                s, s);
594                 }
595         }
596         printf("</select></td>\n");
597         if (have_write_access) {
598                 printf("<td><input type=submit name=\"Delete\" value=\"Delete Share\"></td>\n");
599         }
600         printf("</tr>\n");
601         printf("</table>");
602         printf("<table>");
603         if (have_write_access) {
604                 printf("<tr>\n");
605                 printf("<td><input type=submit name=createshare value=\"Create Share\"></td>\n");
606                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
607         }
608         printf("</table>");
609
610
611         if (snum >= 0) {
612                 if (have_write_access) {
613                         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
614                 }
615
616                 printf("<input type=reset name=\"Reset Values\" value=\"Reset Values\">\n");
617                 if (advanced == 0) {
618                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
619                 } else {
620                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
621                 }
622                 printf("<p>\n");
623         }
624
625         if (snum >= 0) {
626                 printf("<table>\n");
627                 show_parameters(snum, 1, advanced, 0);
628                 printf("</table>\n");
629         }
630
631         if (advanced) {
632                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
633         }
634
635         printf("</FORM>\n");
636 }
637
638 /*************************************************************
639 change a password either locally or remotely
640 *************************************************************/
641 static BOOL change_password(const char *remote_machine, char *user_name, 
642                             char *old_passwd, char *new_passwd, 
643                                 int local_flags)
644 {
645         BOOL ret = False;
646         pstring err_str;
647         pstring msg_str;
648
649         if (demo_mode) {
650                 printf("password change in demo mode rejected\n<p>");
651                 return False;
652         }
653         
654         if (remote_machine != NULL) {
655                 ret = remote_password_change(remote_machine, user_name, old_passwd, 
656                                                                          new_passwd, err_str, sizeof(err_str));
657                 if(*err_str)
658                         printf("%s\n<p>", err_str);
659                 return ret;
660         }
661
662         if(!initialize_password_db(True)) {
663                 printf("Can't setup password database vectors.\n<p>");
664                 return False;
665         }
666         
667         ret = local_password_change(user_name, local_flags, new_passwd, err_str, sizeof(err_str),
668                                          msg_str, sizeof(msg_str));
669
670         if(*msg_str)
671                 printf("%s\n<p>", msg_str);
672         if(*err_str)
673                 printf("%s\n<p>", err_str);
674
675         return ret;
676 }
677
678 /****************************************************************************
679   do the stuff required to add or change a password 
680 ****************************************************************************/
681 static void chg_passwd(void)
682 {
683         char *host;
684         BOOL rslt;
685         int local_flags = 0;
686
687         /* Make sure users name has been specified */
688         if (strlen(cgi_variable(SWAT_USER)) == 0) {
689                 printf("<p> Must specify \"User Name\" \n");
690                 return;
691         }
692
693         /*
694          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
695          * so if that's what we're doing, skip the rest of the checks
696          */
697         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
698
699                 /*
700                  * If current user is not root, make sure old password has been specified 
701                  * If REMOTE change, even root must provide old password 
702                  */
703                 if (((!am_root()) && (strlen( cgi_variable(OLD_PSWD)) <= 0)) ||
704                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable(OLD_PSWD)) <= 0))) {
705                         printf("<p> Must specify \"Old Password\" \n");
706                         return;
707                 }
708
709                 /* If changing a users password on a remote hosts we have to know what host */
710                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable(RHOST)) <= 0)) {
711                         printf("<p> Must specify \"Remote Machine\" \n");
712                         return;
713                 }
714
715                 /* Make sure new passwords have been specified */
716                 if ((strlen( cgi_variable(NEW_PSWD)) <= 0) ||
717                     (strlen( cgi_variable(NEW2_PSWD)) <= 0)) {
718                         printf("<p> Must specify \"New, and Re-typed Passwords\" \n");
719                         return;
720                 }
721
722                 /* Make sure new passwords was typed correctly twice */
723                 if (strcmp(cgi_variable(NEW_PSWD), cgi_variable(NEW2_PSWD)) != 0) {
724                         printf("<p> Re-typed password didn't match new password\n");
725                         return;
726                 }
727         }
728
729         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
730                 host = cgi_variable(RHOST);
731         } else if (am_root()) {
732                 host = NULL;
733         } else {
734                 host = "127.0.0.1";
735         }
736
737         /*
738          * Set up the local flags.
739          */
740
741         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
742         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
743         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
744         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
745
746         rslt = change_password(host,
747                                cgi_variable(SWAT_USER),
748                                cgi_variable(OLD_PSWD), cgi_variable(NEW_PSWD),
749                                    local_flags);
750
751         if(local_flags == 0) {
752                 if (rslt == True) {
753                         printf("<p> The passwd for '%s' has been changed. \n", cgi_variable(SWAT_USER));
754                 } else {
755                         printf("<p> The passwd for '%s' has NOT been changed. \n",cgi_variable(SWAT_USER));
756                 }
757         }
758         
759         return;
760 }
761
762 /****************************************************************************
763   display a password editing page  
764 ****************************************************************************/
765 static void passwd_page(void)
766 {
767         char *new_name = cgi_user_name();
768
769         /* 
770          * After the first time through here be nice. If the user
771          * changed the User box text to another users name, remember it.
772          */
773         if (cgi_variable(SWAT_USER)) {
774                 new_name = cgi_variable(SWAT_USER);
775         } 
776
777         if (!new_name) new_name = "";
778
779         printf("<H2>Server Password Management</H2>\n");
780
781         printf("<FORM name=\"swatform\" method=post>\n");
782
783         printf("<table>\n");
784
785         /* 
786          * Create all the dialog boxes for data collection
787          */
788         printf("<tr><td> User Name : </td>\n");
789         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
790         if (!am_root()) {
791                 printf("<tr><td> Old Password : </td>\n");
792                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
793         }
794         printf("<tr><td> New Password : </td>\n");
795         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
796         printf("<tr><td> Re-type New Password : </td>\n");
797         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
798         printf("</table>\n");
799
800         /*
801          * Create all the control buttons for requesting action
802          */
803         printf("<input type=submit name=%s value=\"Change Password\">\n", 
804                CHG_S_PASSWD_FLAG);
805         if (demo_mode || am_root()) {
806                 printf("<input type=submit name=%s value=\"Add New User\">\n",
807                        ADD_USER_FLAG);
808                 printf("<input type=submit name=%s value=\"Delete User\">\n",
809                        DELETE_USER_FLAG);
810                 printf("<input type=submit name=%s value=\"Disable User\">\n", 
811                        DISABLE_USER_FLAG);
812                 printf("<input type=submit name=%s value=\"Enable User\">\n", 
813                        ENABLE_USER_FLAG);
814         }
815         printf("<p></FORM>\n");
816
817         /*
818          * Do some work if change, add, disable or enable was
819          * requested. It could be this is the first time through this
820          * code, so there isn't anything to do.  */
821         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
822             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
823                 chg_passwd();           
824         }
825
826         printf("<H2>Client/Server Password Management</H2>\n");
827
828         printf("<FORM name=\"swatform\" method=post>\n");
829
830         printf("<table>\n");
831
832         /* 
833          * Create all the dialog boxes for data collection
834          */
835         printf("<tr><td> User Name : </td>\n");
836         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
837         printf("<tr><td> Old Password : </td>\n");
838         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
839         printf("<tr><td> New Password : </td>\n");
840         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
841         printf("<tr><td> Re-type New Password : </td>\n");
842         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
843         printf("<tr><td> Remote Machine : </td>\n");
844         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
845
846         printf("</table>");
847
848         /*
849          * Create all the control buttons for requesting action
850          */
851         printf("<input type=submit name=%s value=\"Change Password\">", 
852                CHG_R_PASSWD_FLAG);
853
854         printf("<p></FORM>\n");
855
856         /*
857          * Do some work if a request has been made to change the
858          * password somewhere other than the server. It could be this
859          * is the first time through this code, so there isn't
860          * anything to do.  */
861         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
862                 chg_passwd();           
863         }
864
865 }
866
867 /****************************************************************************
868   display a printers editing page  
869 ****************************************************************************/
870 static void printers_page(void)
871 {
872         char *share = cgi_variable("share");
873         char *s;
874         int snum=-1;
875         int i;
876         int advanced = 0;
877
878         if (share)
879                 snum = lp_servicenumber(share);
880
881         printf("<H2>Printer Parameters</H2>\n");
882
883         printf("<H3>Important Note:</H3>\n");
884         printf("Printer names marked with [*] in the Choose Printer drop-down box ");
885         printf("are autoloaded printers from ");
886         printf("<A HREF=\"/swat/help/smb.conf.5.html#PRINTCAPNAME\" target=\"docs\">Printcap Name</A>.\n");
887         printf("Attempting to delete these printers from SWAT will have no effect.\n");
888
889         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
890                 advanced = 1;
891
892         if (cgi_variable("Commit") && snum >= 0) {
893                 commit_parameters(snum);
894                 if (snum >= iNumNonAutoPrintServices)
895                     save_reload(snum);
896                 else
897                     save_reload(0);
898         }
899
900         if (cgi_variable("Delete") && snum >= 0) {
901                 lp_remove_service(snum);
902                 save_reload(0);
903                 share = NULL;
904                 snum = -1;
905         }
906
907         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
908                 /* add_a_service() which is called by lp_copy_service()
909                         will do unix_to_dos() conversion, so we need dos_to_unix() before the lp_copy_service(). */
910                 pstring unix_share;
911                 pstrcpy(unix_share, dos_to_unix(share, False));
912                 load_config(False);
913                 lp_copy_service(GLOBALS_SNUM, unix_share);
914                 iNumNonAutoPrintServices = lp_numservices();
915                 snum = lp_servicenumber(share);
916                 lp_do_parameter(snum, "print ok", "Yes");
917                 save_reload(0);
918                 snum = lp_servicenumber(share);
919         }
920
921         printf("<FORM name=\"swatform\" method=post>\n");
922
923         printf("<table>\n");
924         printf("<tr><td><input type=submit name=selectshare value=\"Choose Printer\"></td>\n");
925         printf("<td><select name=share>\n");
926         if (snum < 0 || !lp_print_ok(snum))
927                 printf("<option value=\" \"> \n");
928         for (i=0;i<lp_numservices();i++) {
929                 s = lp_servicename(i);
930                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
931                     if (i >= iNumNonAutoPrintServices)
932                         printf("<option %s value=\"%s\">[*]%s\n",
933                                (share && strcmp(share,s)==0)?"SELECTED":"",
934                                s, s);
935                     else
936                         printf("<option %s value=\"%s\">%s\n", 
937                                (share && strcmp(share,s)==0)?"SELECTED":"",
938                                s, s);
939                 }
940         }
941         printf("</select></td>");
942         if (have_write_access) {
943                 printf("<td><input type=submit name=\"Delete\" value=\"Delete Printer\"></td>\n");
944         }
945         printf("</tr>");
946         printf("</table>\n");
947
948         if (have_write_access) {
949                 printf("<table>\n");
950                 printf("<tr><td><input type=submit name=createshare value=\"Create Printer\"></td>\n");
951                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
952                 printf("</table>");
953         }
954
955
956         if (snum >= 0) {
957                 if (have_write_access) {
958                         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
959                 }
960                 printf("<input type=reset name=\"Reset Values\" value=\"Reset Values\">\n");
961                 if (advanced == 0) {
962                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
963                 } else {
964                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
965                 }
966                 printf("<p>\n");
967         }
968
969         if (snum >= 0) {
970                 printf("<table>\n");
971                 show_parameters(snum, 1, advanced, 1);
972                 printf("</table>\n");
973         }
974
975         if (advanced) {
976                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
977         }
978
979         printf("</FORM>\n");
980 }
981
982 /****************************************************************************
983   MAIN()
984 ****************************************************************************/
985  int main(int argc, char *argv[])
986 {
987         extern char *optarg;
988         extern int optind;
989         extern FILE *dbf;
990         int opt;
991         char *page;
992
993         fault_setup(NULL);
994         umask(S_IWGRP | S_IWOTH);
995
996 #if defined(HAVE_SET_AUTH_PARAMETERS)
997         set_auth_parameters(argc, argv);
998 #endif /* HAVE_SET_AUTH_PARAMETERS */
999
1000         /* just in case it goes wild ... */
1001         alarm(300);
1002
1003         /* we don't want any SIGPIPE messages */
1004         BlockSignals(True,SIGPIPE);
1005
1006         dbf = sys_fopen("/dev/null", "w");
1007         if (!dbf) dbf = stderr;
1008
1009         /* we don't want stderr screwing us up */
1010         close(2);
1011         open("/dev/null", O_WRONLY);
1012
1013         while ((opt = getopt(argc, argv,"s:a")) != EOF) {
1014                 switch (opt) {
1015                 case 's':
1016                         pstrcpy(servicesf,optarg);
1017                         break;    
1018                 case 'a':
1019                         demo_mode = True;
1020                         break;    
1021                 }
1022         }
1023
1024         setup_logging(argv[0],False);
1025         charset_initialise();
1026         load_config(True);
1027         iNumNonAutoPrintServices = lp_numservices();
1028         load_printers();
1029
1030         cgi_setup(SWATDIR, !demo_mode);
1031
1032         print_header();
1033         
1034         cgi_load_variables(NULL);
1035
1036         if (!file_exist(servicesf, NULL)) {
1037                 have_read_access = True;
1038                 have_write_access = True;
1039         } else {
1040                 /* check if the authenticated user has write access - if not then
1041                    don't show write options */
1042                 have_write_access = (access(servicesf,W_OK) == 0);
1043
1044                 /* if the user doesn't have read access to smb.conf then
1045                    don't let them view it */
1046                 have_read_access = (access(servicesf,R_OK) == 0);
1047         }
1048
1049
1050         show_main_buttons();
1051
1052         page = cgi_pathinfo();
1053
1054         /* Root gets full functionality */
1055         if (have_read_access && strcmp(page, "globals")==0) {
1056                 globals_page();
1057         } else if (have_read_access && strcmp(page,"shares")==0) {
1058                 shares_page();
1059         } else if (have_read_access && strcmp(page,"printers")==0) {
1060                 printers_page();
1061         } else if (have_read_access && strcmp(page,"status")==0) {
1062                 status_page();
1063         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1064                 viewconfig_page();
1065         } else if (strcmp(page,"passwd")==0) {
1066                 passwd_page();
1067         } else {
1068                 welcome_page();
1069         }
1070
1071         print_footer();
1072         return 0;
1073 }