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