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