this is the bug change to using connection_struct* instead of cnum.
[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
33
34 /* we need these because we link to locking*.o */
35  void become_root(BOOL save_dir) {}
36  void unbecome_root(BOOL restore_dir) {}
37 /* We need this because we link to password.o */
38 BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) {return False;}
39 files_struct Files[MAX_OPEN_FILES];
40
41 static int enum_index(int value, struct enum_list *enumlist)
42 {
43 int i;
44         for (i=0;enumlist[i].name;i++)
45                 if (value == enumlist[i].value) break;
46         return(i);
47 }
48
49 static char *fix_backslash(char *str)
50 {
51 static char newstring[1024];
52 char *p = newstring;
53
54         *p = '\0';
55         while (*str) {
56                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
57                 else *p++ = *str;
58                 ++str;
59                 *p = '\0';
60         }
61         return newstring;
62 }
63
64 static char *make_parm_name(char *label)
65 {
66 static char parmname[1024];
67 char *p = parmname;
68
69         while (*label) {
70                 if (*label == ' ') *p++ = '_';
71                 else *p++ = *label;
72                 ++label;
73                 *p = '\0';
74         }
75         return parmname;
76 }
77
78 /* start the page with standard stuff */
79 static void print_header(void)
80 {
81         if (!cgi_waspost()) {
82                 printf("Expires: 0\r\n");
83         }
84         printf("Content-type: text/html\r\n\r\n");
85         printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
86         printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"%simages/background.jpg\">\n\n", cgi_rooturl());
87 }
88
89
90 /* finish off the page */
91 static void print_footer(void)
92 {
93         printf("\n</BODY>\n</HTML>\n");
94 }
95
96 /* include a lump of html in a page */
97 static void include_html(char *fname)
98 {
99         FILE *f = fopen(fname,"r");
100         char buf[1024];
101         int ret;
102
103         if (!f) {
104                 printf("ERROR: Can't open %s\n", fname);
105                 return;
106         }
107
108         while (!feof(f)) {
109                 ret = fread(buf, 1, sizeof(buf), f);
110                 if (ret <= 0) break;
111                 fwrite(buf, 1, ret, stdout);
112         }
113
114         fclose(f);
115 }
116
117
118 /* display one editable parameter in a form */
119 static void show_parameter(int snum, struct parm_struct *parm)
120 {
121         int i;
122         void *ptr = parm->ptr;
123
124         if (parm->class == P_LOCAL && snum >= 0) {
125                 ptr = lp_local_ptr(snum, ptr);
126         }
127
128         printf("<tr><td><A HREF=\"%shelp/parameters.html#%s\">?</A> %s</td><td>", 
129                cgi_rooturl(), parm->label, parm->label);
130
131         switch (parm->type) {
132         case P_CHAR:
133                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
134                        make_parm_name(parm->label), *(char *)ptr);
135                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
136                         make_parm_name(parm->label),(char)(parm->def.cvalue));
137                 break;
138
139         case P_STRING:
140         case P_USTRING:
141                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
142                        make_parm_name(parm->label), *(char **)ptr);
143                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
144                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
145                 break;
146
147         case P_GSTRING:
148         case P_UGSTRING:
149                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
150                        make_parm_name(parm->label), (char *)ptr);
151                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
152                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
153                 break;
154
155         case P_BOOL:
156                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
157                 printf("<option %s>Yes", (*(BOOL *)ptr)?"selected":"");
158                 printf("<option %s>No", (*(BOOL *)ptr)?"":"selected");
159                 printf("</select>");
160                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
161                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?0:1);
162                 break;
163
164         case P_BOOLREV:
165                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
166                 printf("<option %s>Yes", (*(BOOL *)ptr)?"":"selected");
167                 printf("<option %s>No", (*(BOOL *)ptr)?"selected":"");
168                 printf("</select>");
169                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
170                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?1:0);
171                 break;
172
173         case P_INTEGER:
174                 printf("<input type=text size=8 name=\"parm_%s\" value=%d>", make_parm_name(parm->label), *(int *)ptr);
175                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
176                         make_parm_name(parm->label),(int)(parm->def.ivalue));
177                 break;
178
179         case P_OCTAL:
180                 printf("<input type=text size=8 name=\"parm_%s\" value=0%o>", make_parm_name(parm->label), *(int *)ptr);
181                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'0%o\'\">",
182                         make_parm_name(parm->label),(int)(parm->def.ivalue));
183                 break;
184
185         case P_ENUM:
186                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
187                 for (i=0;parm->enum_list[i].name;i++)
188                         printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
189                 printf("</select>");
190                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
191                         make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
192                 break;
193         case P_SEP:
194                 break;
195         }
196         printf("</td></tr>\n");
197 }
198
199 /* display a set of parameters for a service */
200 static void show_parameters(int snum, int allparameters, int advanced, int printers)
201 {
202         int i = 0;
203         struct parm_struct *parm;
204         char *heading = NULL;
205         char *last_heading = NULL;
206
207         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
208                 if (snum < 0 && parm->class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
209                         continue;
210                 if (parm->class == P_SEPARATOR) {
211                         heading = parm->label;
212                         continue;
213                 }
214                 if (parm->flags & FLAG_HIDE) continue;
215                 if (!advanced) {
216                         if (!printers && !(parm->flags & FLAG_BASIC)) {
217                                 void *ptr = parm->ptr;
218
219                                 switch (parm->type) {
220                                 case P_CHAR:
221                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
222                                         break;
223
224                                 case P_STRING:
225                                 case P_USTRING:
226                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
227                                         break;
228
229                                 case P_GSTRING:
230                                 case P_UGSTRING:
231                                         if (!strcmp((char *)ptr,(char *)(parm->def.svalue))) continue;
232                                         break;
233
234                                 case P_BOOL:
235                                 case P_BOOLREV:
236                                         if (*(BOOL *)ptr == (BOOL)(parm->def.bvalue)) continue;
237                                         break;
238
239                                 case P_INTEGER:
240                                 case P_OCTAL:
241                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
242                                         break;
243
244
245                                 case P_ENUM:
246                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
247                                         break;
248                                 case P_SEP:
249                                         continue;
250                                 }
251                         }
252                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
253                 }
254                 if (heading && heading != last_heading) {
255                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", heading);
256                         last_heading = heading;
257                 }
258                 show_parameter(snum, parm);
259         }
260 }
261
262
263 /* write a config file */
264 static void write_config(FILE *f, BOOL show_defaults)
265 {
266         fprintf(f, "# Samba config file created using SWAT\n");
267         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
268         fprintf(f, "# Date: %s\n\n", timestring());
269         
270         lp_dump(f, show_defaults);      
271 }
272
273
274 /* save and reoad the smb.conf config file */
275 static int save_reload(void)
276 {
277         FILE *f;
278
279         f = fopen(servicesf,"w");
280         if (!f) {
281                 printf("failed to open %s for writing\n", servicesf);
282                 return 0;
283         }
284
285         write_config(f, False);
286         fclose(f);
287
288         lp_killunused(NULL);
289
290         if (!lp_load(servicesf,False,False,False)) {
291                 printf("Can't reload %s\n", servicesf);
292                 return 0;
293         }
294
295         return 1;
296 }
297
298
299
300 /* commit one parameter */
301 static void commit_parameter(int snum, struct parm_struct *parm, char *v)
302 {
303         int i;
304         char *s;
305
306         if (snum < 0 && parm->class == P_LOCAL) {
307                 /* this handles the case where we are changing a local
308                    variable globally. We need to change the parameter in 
309                    all shares where it is currently set to the default */
310                 for (i=0;i<lp_numservices();i++) {
311                         s = lp_servicename(i);
312                         if (s && (*s) && lp_is_default(i, parm)) {
313                                 lp_do_parameter(i, parm->label, v);
314                         }
315                 }
316         }
317
318         lp_do_parameter(snum, parm->label, v);
319 }
320
321 /* commit a set of parameters for a service */
322 static void commit_parameters(int snum)
323 {
324         int i = 0;
325         struct parm_struct *parm;
326         pstring label;
327         char *v;
328
329         while ((parm = lp_next_parameter(snum, &i, 1))) {
330                 slprintf(label, sizeof(label)-1, "parm_%s", make_parm_name(parm->label));
331                 if ((v = cgi_variable(label))) {
332                         if (parm->flags & FLAG_HIDE) continue;
333                         commit_parameter(snum, parm, v); 
334                 }
335         }
336 }
337
338
339 /* load the smb.conf file into loadparm. */
340 static void load_config(void)
341 {
342         if (!lp_load(servicesf,False,True,False)) {
343                 printf("<b>Can't load %s - using defaults</b><p>\n", 
344                        servicesf);
345         }
346 }
347
348 /* spit out the html for a link with an image */
349 static void image_link(char *name,char *hlink, char *src, int width, int height)
350 {
351         printf("<A HREF=\"%s/%s\"><img width=%d height=%d src=\"%s%s\" alt=\"%s\"></A>\n", 
352                cgi_baseurl(),
353                hlink, width, height, 
354                cgi_rooturl(),
355                src, name);
356 }
357
358 /* display the main navigation controls at the top of each page along
359    with a title */
360 static void show_main_buttons(void)
361 {
362         printf("<H2 align=center>Samba Web Administration Tool</H2>\n");
363
364         image_link("Home", "", "images/home.gif", 50, 50);
365         image_link("Globals", "globals", "images/globals.gif", 50, 50);
366         image_link("Shares", "shares", "images/shares.gif", 50, 50);
367         image_link("Printers", "printers", "images/printers.gif", 50, 50);
368         image_link("Status", "status", "images/status.gif", 50, 50);
369         image_link("View Config", "viewconfig", "images/viewconfig.gif", 50, 50);
370
371         printf("<HR>\n");
372 }
373
374 /* display a welcome page  */
375 static void welcome_page(void)
376 {
377         include_html("help/welcome.html");
378 }
379
380
381 /* display the current smb.conf  */
382 static void viewconfig_page(void)
383 {
384         int full_view=0;
385
386         if (cgi_variable("full_view")) {
387                 full_view = 1;
388         }
389
390         printf("<H2>Current Config</H2>\n");
391         printf("<form method=post>\n");
392
393         if (full_view) {
394                 printf("<input type=submit name=\"normal_view\" value=\"Normal View\">\n");
395         } else {
396                 printf("<input type=submit name=\"full_view\" value=\"Full View\">\n");
397         }
398
399         printf("<p><pre>");
400         write_config(stdout, full_view);
401         printf("</pre>");
402         printf("</form>\n");
403 }
404
405
406 /* display a globals editing page  */
407 static void globals_page(void)
408 {
409         int advanced = 0;
410
411         printf("<H2>Global Variables</H2>\n");
412
413         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
414                 advanced = 1;
415
416         if (cgi_variable("Commit")) {
417                 commit_parameters(GLOBALS_SNUM);
418                 save_reload();
419         }
420
421         printf("<FORM name=\"swatform\" method=post>\n");
422
423         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
424         printf("<input type=reset name=\"Reset Values\" value=\"Reset Values\">\n");
425         if (advanced == 0) {
426                 printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
427         } else {
428                 printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
429         }
430         printf("<p>\n");
431         
432         printf("<table>\n");
433         show_parameters(GLOBALS_SNUM, 1, advanced, 0);
434         printf("</table>\n");
435
436         if (advanced) {
437                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
438         }
439
440         printf("</FORM>\n");
441 }
442
443 /* display a shares editing page  */
444 static void shares_page(void)
445 {
446         char *share = cgi_variable("share");
447         char *s;
448         int snum=-1;
449         int i;
450         int advanced = 0;
451
452         if (share)
453                 snum = lp_servicenumber(share);
454
455         printf("<H2>Share Parameters</H2>\n");
456
457         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
458                 advanced = 1;
459
460         if (cgi_variable("Commit") && snum >= 0) {
461                 commit_parameters(snum);
462                 save_reload();
463         }
464
465         if (cgi_variable("Delete") && snum >= 0) {
466                 lp_remove_service(snum);
467                 save_reload();
468                 share = NULL;
469                 snum = -1;
470         }
471
472         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
473                 lp_copy_service(GLOBALS_SNUM, share);
474                 save_reload();
475                 snum = lp_servicenumber(share);
476         }
477
478         printf("<FORM name=\"swatform\" method=post>\n");
479
480         printf("<table>\n");
481         printf("<tr><td><input type=submit name=selectshare value=\"Choose Share\"></td>\n");
482         printf("<td><select name=share>\n");
483         if (snum < 0)
484                 printf("<option value=\" \"> \n");
485         for (i=0;i<lp_numservices();i++) {
486                 s = lp_servicename(i);
487                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
488                         printf("<option %s value=\"%s\">%s\n", 
489                                (share && strcmp(share,s)==0)?"SELECTED":"",
490                                s, s);
491                 }
492         }
493         printf("</select></td></tr><p>");
494
495         printf("<tr><td><input type=submit name=createshare value=\"Create Share\"></td>\n");
496         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
497         printf("</table>");
498
499
500         if (snum >= 0) {
501                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
502                 printf("<input type=submit name=\"Delete\" value=\"Delete Share\">\n");
503                 if (advanced == 0) {
504                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
505                 } else {
506                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
507                 }
508                 printf("<p>\n");
509         }
510
511         if (snum >= 0) {
512                 printf("<table>\n");
513                 show_parameters(snum, 1, advanced, 0);
514                 printf("</table>\n");
515         }
516
517         if (advanced) {
518                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
519         }
520
521         printf("</FORM>\n");
522 }
523
524
525 /* display a printers editing page  */
526 static void printers_page(void)
527 {
528         char *share = cgi_variable("share");
529         char *s;
530         int snum=-1;
531         int i;
532         int advanced = 0;
533
534         if (share)
535                 snum = lp_servicenumber(share);
536
537         printf("<H2>Printer Parameters</H2>\n");
538
539         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
540                 advanced = 1;
541
542         if (cgi_variable("Commit") && snum >= 0) {
543                 commit_parameters(snum);
544                 save_reload();
545         }
546
547         if (cgi_variable("Delete") && snum >= 0) {
548                 lp_remove_service(snum);
549                 save_reload();
550                 share = NULL;
551                 snum = -1;
552         }
553
554         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
555                 lp_copy_service(GLOBALS_SNUM, share);
556                 snum = lp_servicenumber(share);
557                 lp_do_parameter(snum, "print ok", "Yes");
558                 save_reload();
559                 snum = lp_servicenumber(share);
560         }
561
562         printf("<FORM name=\"swatform\" method=post>\n");
563
564         printf("<table>\n");
565         printf("<tr><td><input type=submit name=selectshare value=\"Choose Printer\"></td>\n");
566         printf("<td><select name=share>\n");
567         if (snum < 0 || !lp_print_ok(snum))
568                 printf("<option value=\" \"> \n");
569         for (i=0;i<lp_numservices();i++) {
570                 s = lp_servicename(i);
571                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
572                         printf("<option %s value=\"%s\">%s\n", 
573                                (share && strcmp(share,s)==0)?"SELECTED":"",
574                                s, s);
575                 }
576         }
577         printf("</select></td></tr><p>");
578
579         printf("<tr><td><input type=submit name=createshare value=\"Create Printer\"></td>\n");
580         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
581         printf("</table>");
582
583
584         if (snum >= 0) {
585                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
586                 printf("<input type=submit name=\"Delete\" value=\"Delete Printer\">\n");
587                 if (advanced == 0) {
588                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
589                 } else {
590                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
591                 }
592                 printf("<p>\n");
593         }
594
595         if (snum >= 0) {
596                 printf("<table>\n");
597                 show_parameters(snum, 1, advanced, 1);
598                 printf("</table>\n");
599         }
600
601         if (advanced) {
602                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
603         }
604
605         printf("</FORM>\n");
606 }
607
608
609
610 int main(int argc, char *argv[])
611 {
612         extern char *optarg;
613         extern int optind;
614         extern FILE *dbf;
615         int opt;
616         char *page;
617         int auth_required = 1;
618
619         /* just in case it goes wild ... */
620         alarm(300);
621
622         dbf = fopen("/dev/null", "w");
623
624         if (!dbf) dbf = stderr;
625
626         while ((opt = getopt(argc, argv,"s:a")) != EOF) {
627                 switch (opt) {
628                 case 's':
629                         pstrcpy(servicesf,optarg);
630                         break;    
631                 case 'a':
632                         auth_required = 0;
633                         break;    
634                 }
635         }
636
637         cgi_setup(SWATDIR, auth_required);
638
639         print_header();
640         
641         charset_initialise();
642
643         /* if this binary is setuid then run completely as root */
644         setuid(0);
645
646         load_config();
647
648         cgi_load_variables(NULL);
649
650         show_main_buttons();
651
652         page = cgi_pathinfo();
653
654         if (strcmp(page, "globals")==0) {
655                 globals_page();
656         } else if (strcmp(page,"shares")==0) {
657                 shares_page();
658         } else if (strcmp(page,"printers")==0) {
659                 printers_page();
660         } else if (strcmp(page,"status")==0) {
661                 status_page();
662         } else if (strcmp(page,"viewconfig")==0) {
663                 viewconfig_page();
664         } else {
665                 welcome_page();
666         }
667         
668         print_footer();
669         return 0;
670 }
671
672