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