s3 swat: Add XSRF protection to wizard page
[samba.git] / source3 / web / swat.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba Web Administration Tool
4    Version 3.0.0
5    Copyright (C) Andrew Tridgell 1997-2002
6    Copyright (C) John H Terpstra 2002
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /**
23  * @defgroup swat SWAT - Samba Web Administration Tool
24  * @{ 
25  * @file swat.c
26  *
27  * @brief Samba Web Administration Tool.
28  **/
29
30 #include "includes.h"
31 #include "system/filesys.h"
32 #include "popt_common.h"
33 #include "web/swat_proto.h"
34 #include "printing/pcap.h"
35 #include "printing/load.h"
36 #include "passdb.h"
37 #include "intl/lang_tdb.h"
38 #include "../lib/crypto/md5.h"
39 #include "lib/param/loadparm.h"
40
41 static int demo_mode = False;
42 static int passwd_only = False;
43 static bool have_write_access = False;
44 static bool have_read_access = False;
45 static int iNumNonAutoPrintServices = 0;
46
47 /*
48  * Password Management Globals
49  */
50 #define SWAT_USER "username"
51 #define OLD_PSWD "old_passwd"
52 #define NEW_PSWD "new_passwd"
53 #define NEW2_PSWD "new2_passwd"
54 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
55 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
56 #define ADD_USER_FLAG "add_user_flag"
57 #define DELETE_USER_FLAG "delete_user_flag"
58 #define DISABLE_USER_FLAG "disable_user_flag"
59 #define ENABLE_USER_FLAG "enable_user_flag"
60 #define RHOST "remote_host"
61 #define XSRF_TOKEN "xsrf"
62
63 #define _(x) lang_msg_rotate(talloc_tos(),x)
64
65 /****************************************************************************
66 ****************************************************************************/
67 static int enum_index(int value, const struct enum_list *enumlist)
68 {
69         int i;
70         for (i=0;enumlist[i].name;i++)
71                 if (value == enumlist[i].value) break;
72         return(i);
73 }
74
75 static char *fix_backslash(const char *str)
76 {
77         static char newstring[1024];
78         char *p = newstring;
79
80         while (*str) {
81                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
82                 else *p++ = *str;
83                 ++str;
84         }
85         *p = '\0';
86         return newstring;
87 }
88
89 static const char *fix_quotes(TALLOC_CTX *ctx, char *str)
90 {
91         char *newstring = NULL;
92         char *p = NULL;
93         size_t newstring_len;
94         int quote_len = strlen("&quot;");
95
96         /* Count the number of quotes. */
97         newstring_len = 1;
98         p = (char *) str;
99         while (*p) {
100                 if ( *p == '\"') {
101                         newstring_len += quote_len;
102                 } else {
103                         newstring_len++;
104                 }
105                 ++p;
106         }
107         newstring = talloc_array(ctx, char, newstring_len);
108         if (!newstring) {
109                 return "";
110         }
111         for (p = newstring; *str; str++) {
112                 if ( *str == '\"') {
113                         strncpy( p, "&quot;", quote_len);
114                         p += quote_len;
115                 } else {
116                         *p++ = *str;
117                 }
118         }
119         *p = '\0';
120         return newstring;
121 }
122
123 static char *stripspaceupper(const char *str)
124 {
125         static char newstring[1024];
126         char *p = newstring;
127
128         while (*str) {
129                 if (*str != ' ') *p++ = toupper_m(*str);
130                 ++str;
131         }
132         *p = '\0';
133         return newstring;
134 }
135
136 static char *make_parm_name(const char *label)
137 {
138         static char parmname[1024];
139         char *p = parmname;
140
141         while (*label) {
142                 if (*label == ' ') *p++ = '_';
143                 else *p++ = *label;
144                 ++label;
145         }
146         *p = '\0';
147         return parmname;
148 }
149
150 void get_xsrf_token(const char *username, const char *pass,
151                     const char *formname, char token_str[33])
152 {
153         struct MD5Context md5_ctx;
154         uint8_t token[16];
155         int i;
156
157         token_str[0] = '\0';
158         ZERO_STRUCT(md5_ctx);
159         MD5Init(&md5_ctx);
160
161         MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
162         if (username != NULL) {
163                 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
164         }
165         if (pass != NULL) {
166                 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
167         }
168
169         MD5Final(token, &md5_ctx);
170
171         for(i = 0; i < sizeof(token); i++) {
172                 char tmp[3];
173
174                 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
175                 strncat(token_str, tmp, sizeof(tmp));
176         }
177 }
178
179 void print_xsrf_token(const char *username, const char *pass,
180                       const char *formname)
181 {
182         char token[33];
183
184         get_xsrf_token(username, pass, formname, token);
185         printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
186                XSRF_TOKEN, token);
187
188 }
189
190 bool verify_xsrf_token(const char *formname)
191 {
192         char expected[33];
193         const char *username = cgi_user_name();
194         const char *pass = cgi_user_pass();
195         const char *token = cgi_variable_nonull(XSRF_TOKEN);
196
197         get_xsrf_token(username, pass, formname, expected);
198         return (strncmp(expected, token, sizeof(expected)) == 0);
199 }
200
201
202 /****************************************************************************
203   include a lump of html in a page 
204 ****************************************************************************/
205 static int include_html(const char *fname)
206 {
207         int fd;
208         char buf[1024];
209         int ret;
210
211         fd = web_open(fname, O_RDONLY, 0);
212
213         if (fd == -1) {
214                 printf(_("ERROR: Can't open %s"), fname);
215                 printf("\n");
216                 return 0;
217         }
218
219         while ((ret = read(fd, buf, sizeof(buf))) > 0) {
220                 if (write(1, buf, ret) == -1) {
221                         break;
222                 }
223         }
224
225         close(fd);
226         return 1;
227 }
228
229 /****************************************************************************
230   start the page with standard stuff 
231 ****************************************************************************/
232 static void print_header(void)
233 {
234         if (!cgi_waspost()) {
235                 printf("Expires: 0\r\n");
236         }
237         printf("Content-type: text/html\r\n\r\n");
238
239         if (!include_html("include/header.html")) {
240                 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
241                 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
242         }
243 }
244
245 /* *******************************************************************
246    show parameter label with translated name in the following form
247    because showing original and translated label in one line looks
248    too long, and showing translated label only is unusable for
249    heavy users.
250    -------------------------------
251    HELP       security   [combo box][button]
252    SECURITY
253    -------------------------------
254    (capital words are translated by gettext.)
255    if no translation is available, then same form as original is
256    used.
257    "i18n_translated_parm" class is used to change the color of the
258    translated parameter with CSS.
259    **************************************************************** */
260 static const char *get_parm_translated(TALLOC_CTX *ctx,
261         const char* pAnchor, const char* pHelp, const char* pLabel)
262 {
263         const char *pTranslated = _(pLabel);
264         char *output;
265         if(strcmp(pLabel, pTranslated) != 0) {
266                 output = talloc_asprintf(ctx,
267                   "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s <br><span class=\"i18n_translated_parm\">%s</span>",
268                    pAnchor, pHelp, pLabel, pTranslated);
269                 return output;
270         }
271         output = talloc_asprintf(ctx,
272           "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
273           pAnchor, pHelp, pLabel);
274         return output;
275 }
276 /****************************************************************************
277  finish off the page
278 ****************************************************************************/
279 static void print_footer(void)
280 {
281         if (!include_html("include/footer.html")) {
282                 printf("\n</BODY>\n</HTML>\n");
283         }
284 }
285
286 /****************************************************************************
287   display one editable parameter in a form
288 ****************************************************************************/
289 static void show_parameter(int snum, struct parm_struct *parm)
290 {
291         int i;
292         void *ptr;
293         char *utf8_s1, *utf8_s2;
294         size_t converted_size;
295         TALLOC_CTX *ctx = talloc_stackframe();
296
297         if (parm->p_class == P_LOCAL && snum >= 0) {
298                 ptr = lp_local_ptr_by_snum(snum, parm);
299         } else {
300                 ptr = lp_parm_ptr(NULL, parm);
301         }
302
303         printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
304                                 stripspaceupper(parm->label), _("Help"), parm->label));
305         switch (parm->type) {
306         case P_CHAR:
307                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
308                        make_parm_name(parm->label), *(char *)ptr);
309                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
310                         _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
311                 break;
312
313         case P_LIST:
314                 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
315                         make_parm_name(parm->label));
316                 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
317                         char **list = *(char ***)ptr;
318                         for (;*list;list++) {
319                                 /* enclose in HTML encoded quotes if the string contains a space */
320                                 if ( strchr_m(*list, ' ') ) {
321                                         push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
322                                         push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
323                                         printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
324                                 } else {
325                                         push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
326                                         push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
327                                         printf("%s%s", utf8_s1, utf8_s2);
328                                 }
329                                 TALLOC_FREE(utf8_s1);
330                                 TALLOC_FREE(utf8_s2);
331                         }
332                 }
333                 printf("\">");
334                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
335                         _("Set Default"), make_parm_name(parm->label));
336                 if (parm->def.lvalue) {
337                         char **list = (char **)(parm->def.lvalue);
338                         for (; *list; list++) {
339                                 /* enclose in HTML encoded quotes if the string contains a space */
340                                 if ( strchr_m(*list, ' ') )
341                                         printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
342                                 else
343                                         printf("%s%s", *list, ((*(list+1))?", ":""));
344                         }
345                 }
346                 printf("\'\">");
347                 break;
348
349         case P_STRING:
350         case P_USTRING:
351                 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
352                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
353                        make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
354                 TALLOC_FREE(utf8_s1);
355                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
356                         _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
357                 break;
358
359         case P_BOOL:
360                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
361                 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
362                 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
363                 printf("</select>");
364                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
365                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
366                 break;
367
368         case P_BOOLREV:
369                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
370                 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
371                 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
372                 printf("</select>");
373                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
374                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
375                 break;
376
377         case P_INTEGER:
378                 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
379                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
380                         _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
381                 break;
382
383         case P_OCTAL: {
384                 char *o;
385                 o = octal_string(*(int *)ptr);
386                 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
387                        make_parm_name(parm->label), o);
388                 TALLOC_FREE(o);
389                 o = octal_string((int)(parm->def.ivalue));
390                 printf("<input type=button value=\"%s\" "
391                        "onClick=\"swatform.parm_%s.value=\'%s\'\">",
392                        _("Set Default"), make_parm_name(parm->label), o);
393                 TALLOC_FREE(o);
394                 break;
395         }
396
397         case P_ENUM:
398                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
399                 for (i=0;parm->enum_list[i].name;i++) {
400                         if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
401                                 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
402                         }
403                 }
404                 printf("</select>");
405                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
406                         _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
407                 break;
408         case P_SEP:
409                 break;
410         }
411         printf("</td></tr>\n");
412         TALLOC_FREE(ctx);
413 }
414
415 /****************************************************************************
416   display a set of parameters for a service 
417 ****************************************************************************/
418 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
419 {
420         int i = 0;
421         struct parm_struct *parm;
422         const char *heading = NULL;
423         const char *last_heading = NULL;
424
425         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
426                 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
427                         continue;
428                 if (parm->p_class == P_SEPARATOR) {
429                         heading = parm->label;
430                         continue;
431                 }
432                 if (parm->flags & FLAG_HIDE) continue;
433                 if (snum >= 0) {
434                         if (printers & !(parm->flags & FLAG_PRINT)) continue;
435                         if (!printers & !(parm->flags & FLAG_SHARE)) continue;
436                 }
437
438                 if (!( parm_filter & FLAG_ADVANCED )) {
439                         if (!(parm->flags & FLAG_BASIC)) {
440                                 void *ptr;
441                                 if (parm->p_class == P_LOCAL && snum >= 0) {
442                                         ptr = lp_local_ptr_by_snum(snum, parm);
443                                 } else {
444                                         ptr = lp_parm_ptr(NULL, parm);
445                                 }
446
447                                 switch (parm->type) {
448                                 case P_CHAR:
449                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
450                                         break;
451
452                                 case P_LIST:
453                                         if (!str_list_equal(*(const char ***)ptr, 
454                                                             (const char **)(parm->def.lvalue))) continue;
455                                         break;
456
457                                 case P_STRING:
458                                 case P_USTRING:
459                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
460                                         break;
461
462                                 case P_BOOL:
463                                 case P_BOOLREV:
464                                         if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
465                                         break;
466
467                                 case P_INTEGER:
468                                 case P_OCTAL:
469                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
470                                         break;
471
472
473                                 case P_ENUM:
474                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
475                                         break;
476                                 case P_SEP:
477                                         continue;
478                                         }
479                         }
480                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
481                 }
482
483                 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
484
485                 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
486
487                 if (heading && heading != last_heading) {
488                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
489                         last_heading = heading;
490                 }
491                 show_parameter(snum, parm);
492         }
493 }
494
495 /****************************************************************************
496   load the smb.conf file into loadparm.
497 ****************************************************************************/
498 static bool load_config(bool save_def)
499 {
500         return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
501 }
502
503 /****************************************************************************
504   write a config file 
505 ****************************************************************************/
506 static void write_config(FILE *f, bool show_defaults)
507 {
508         TALLOC_CTX *ctx = talloc_stackframe();
509
510         fprintf(f, "# Samba config file created using SWAT\n");
511         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
512         fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
513
514         lp_dump(f, show_defaults, iNumNonAutoPrintServices);
515
516         TALLOC_FREE(ctx);
517 }
518
519 /****************************************************************************
520   save and reload the smb.conf config file 
521 ****************************************************************************/
522 static int save_reload(int snum)
523 {
524         FILE *f;
525         struct stat st;
526
527         f = sys_fopen(get_dyn_CONFIGFILE(),"w");
528         if (!f) {
529                 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
530                 printf("\n");
531                 return 0;
532         }
533
534         /* just in case they have used the buggy xinetd to create the file */
535         if (fstat(fileno(f), &st) == 0 &&
536             (st.st_mode & S_IWOTH)) {
537 #if defined HAVE_FCHMOD
538                 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
539 #else
540                 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
541 #endif
542         }
543
544         write_config(f, False);
545         if (snum >= 0)
546                 lp_dump_one(f, False, snum);
547         fclose(f);
548
549         lp_kill_all_services();
550
551         if (!load_config(False)) {
552                 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
553                 printf("\n");
554                 return 0;
555         }
556         iNumNonAutoPrintServices = lp_numservices();
557         if (pcap_cache_loaded()) {
558                 load_printers(server_event_context(),
559                               server_messaging_context());
560         }
561
562         return 1;
563 }
564
565 /****************************************************************************
566   commit one parameter 
567 ****************************************************************************/
568 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
569 {
570         int i;
571         char *s;
572
573         if (snum < 0 && parm->p_class == P_LOCAL) {
574                 /* this handles the case where we are changing a local
575                    variable globally. We need to change the parameter in 
576                    all shares where it is currently set to the default */
577                 for (i=0;i<lp_numservices();i++) {
578                         s = lp_servicename(i);
579                         if (s && (*s) && lp_is_default(i, parm)) {
580                                 lp_do_parameter(i, parm->label, v);
581                         }
582                 }
583         }
584
585         lp_do_parameter(snum, parm->label, v);
586 }
587
588 /****************************************************************************
589   commit a set of parameters for a service 
590 ****************************************************************************/
591 static void commit_parameters(int snum)
592 {
593         int i = 0;
594         struct parm_struct *parm;
595         char *label;
596         const char *v;
597
598         while ((parm = lp_next_parameter(snum, &i, 1))) {
599                 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
600                         if ((v = cgi_variable(label)) != NULL) {
601                                 if (parm->flags & FLAG_HIDE)
602                                         continue;
603                                 commit_parameter(snum, parm, v);
604                         }
605                         SAFE_FREE(label);
606                 }
607         }
608 }
609
610 /****************************************************************************
611   spit out the html for a link with an image 
612 ****************************************************************************/
613 static void image_link(const char *name, const char *hlink, const char *src)
614 {
615         printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", 
616                cgi_baseurl(), hlink, src, name);
617 }
618
619 /****************************************************************************
620   display the main navigation controls at the top of each page along
621   with a title 
622 ****************************************************************************/
623 static void show_main_buttons(void)
624 {
625         char *p;
626
627         if ((p = cgi_user_name()) && strcmp(p, "root")) {
628                 printf(_("Logged in as <b>%s</b>"), p);
629                 printf("<p>\n");
630         }
631
632         image_link(_("Home"), "", "images/home.gif");
633         if (have_write_access) {
634                 image_link(_("Globals"), "globals", "images/globals.gif");
635                 image_link(_("Shares"), "shares", "images/shares.gif");
636                 image_link(_("Printers"), "printers", "images/printers.gif");
637                 image_link(_("Wizard"), "wizard", "images/wizard.gif");
638         }
639    /* root always gets all buttons, otherwise look for -P */
640         if ( have_write_access || (!passwd_only && have_read_access) ) {
641                 image_link(_("Status"), "status", "images/status.gif");
642                 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
643         }
644         image_link(_("Password Management"), "passwd", "images/passwd.gif");
645
646         printf("<HR>\n");
647 }
648
649 /****************************************************************************
650  * Handle Display/Edit Mode CGI
651  ****************************************************************************/
652 static void ViewModeBoxes(int mode)
653 {
654         printf("<p>%s:&nbsp;\n", _("Current View Is"));
655         printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
656         printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
657         printf("<br>%s:&nbsp;\n", _("Change View To"));
658         printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
659         printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
660         printf("</p><br>\n");
661 }
662
663 /****************************************************************************
664   display a welcome page  
665 ****************************************************************************/
666 static void welcome_page(void)
667 {
668         if (file_exist("help/welcome.html")) {
669                 include_html("help/welcome.html");
670         } else {
671                 include_html("help/welcome-no-samba-doc.html");
672         }
673 }
674
675 /****************************************************************************
676   display the current smb.conf  
677 ****************************************************************************/
678 static void viewconfig_page(void)
679 {
680         int full_view=0;
681         const char form_name[] = "viewconfig";
682
683         if (!verify_xsrf_token(form_name)) {
684                 goto output_page;
685         }
686
687         if (cgi_variable("full_view")) {
688                 full_view = 1;
689         }
690
691 output_page:
692         printf("<H2>%s</H2>\n", _("Current Config"));
693         printf("<form method=post>\n");
694         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
695
696         if (full_view) {
697                 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
698         } else {
699                 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
700         }
701
702         printf("<p><pre>");
703         write_config(stdout, full_view);
704         printf("</pre>");
705         printf("</form>\n");
706 }
707
708 /****************************************************************************
709   second screen of the wizard ... Fetch Configuration Parameters
710 ****************************************************************************/
711 static void wizard_params_page(void)
712 {
713         unsigned int parm_filter = FLAG_WIZARD;
714         const char form_name[] = "wizard_params";
715
716         /* Here we first set and commit all the parameters that were selected
717            in the previous screen. */
718
719         printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
720
721         if (!verify_xsrf_token(form_name)) {
722                 goto output_page;
723         }
724
725         if (cgi_variable("Commit")) {
726                 commit_parameters(GLOBAL_SECTION_SNUM);
727                 save_reload(-1);
728         }
729
730 output_page:
731         printf("<form name=\"swatform\" method=post action=wizard_params>\n");
732         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
733
734         if (have_write_access) {
735                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
736         }
737
738         printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
739         printf("<p>\n");
740
741         printf("<table>\n");
742         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
743         printf("</table>\n");
744         printf("</form>\n");
745 }
746
747 /****************************************************************************
748   Utility to just rewrite the smb.conf file - effectively just cleans it up
749 ****************************************************************************/
750 static void rewritecfg_file(void)
751 {
752         commit_parameters(GLOBAL_SECTION_SNUM);
753         save_reload(-1);
754         printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
755 }
756
757 /****************************************************************************
758   wizard to create/modify the smb.conf file
759 ****************************************************************************/
760 static void wizard_page(void)
761 {
762         /* Set some variables to collect data from smb.conf */
763         int role = 0;
764         int winstype = 0;
765         int have_home = -1;
766         int HomeExpo = 0;
767         int SerType = 0;
768         const char form_name[] = "wizard";
769
770         if (!verify_xsrf_token(form_name)) {
771                 goto output_page;
772         }
773
774         if (cgi_variable("Rewrite")) {
775                 (void) rewritecfg_file();
776                 return;
777         }
778
779         if (cgi_variable("GetWizardParams")){
780                 (void) wizard_params_page();
781                 return;
782         }
783
784         if (cgi_variable("Commit")){
785                 SerType = atoi(cgi_variable_nonull("ServerType"));
786                 winstype = atoi(cgi_variable_nonull("WINSType"));
787                 have_home = lp_servicenumber(HOMES_NAME);
788                 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
789
790                 /* Plain text passwords are too badly broken - use encrypted passwords only */
791                 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
792
793                 switch ( SerType ){
794                         case 0:
795                                 /* Stand-alone Server */
796                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
797                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
798                                 break;
799                         case 1:
800                                 /* Domain Member */
801                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
802                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
803                                 break;
804                         case 2:
805                                 /* Domain Controller */
806                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
807                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
808                                 break;
809                 }
810                 switch ( winstype ) {
811                         case 0:
812                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
813                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
814                                 break;
815                         case 1:
816                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
817                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
818                                 break;
819                         case 2:
820                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
821                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
822                                 break;
823                 }
824
825                 /* Have to create Homes share? */
826                 if ((HomeExpo == 1) && (have_home == -1)) {
827                         const char *unix_share = HOMES_NAME;
828
829                         load_config(False);
830                         lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
831                         have_home = lp_servicenumber(HOMES_NAME);
832                         lp_do_parameter( have_home, "read only", "No");
833                         lp_do_parameter( have_home, "valid users", "%S");
834                         lp_do_parameter( have_home, "browseable", "No");
835                         commit_parameters(have_home);
836                         save_reload(have_home);
837                 }
838
839                 /* Need to Delete Homes share? */
840                 if ((HomeExpo == 0) && (have_home != -1)) {
841                         lp_remove_service(have_home);
842                         have_home = -1;
843                 }
844
845                 commit_parameters(GLOBAL_SECTION_SNUM);
846                 save_reload(-1);
847         }
848         else
849         {
850                 /* Now determine smb.conf WINS settings */
851                 if (lp_we_are_a_wins_server())
852                         winstype = 1;
853                 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
854                         winstype = 2;
855
856                 /* Do we have a homes share? */
857                 have_home = lp_servicenumber(HOMES_NAME);
858         }
859         if ((winstype == 2) && lp_we_are_a_wins_server())
860                 winstype = 3;
861
862         role = lp_server_role();
863
864 output_page:
865         /* Here we go ... */
866         printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
867         printf("<form method=post action=wizard>\n");
868         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
869
870         if (have_write_access) {
871                 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
872                 printf("%s", _("The same will happen if you press the commit button."));
873                 printf("<br><br>\n");
874                 printf("<center>");
875                 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
876                 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
877                 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
878                 printf("</center>\n");
879         }
880
881         printf("<hr>");
882         printf("<center><table border=0>");
883         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
884         printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
885         printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member")); 
886         printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
887         printf("</tr>\n");
888         if (role == ROLE_DOMAIN_BDC) {
889                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
890         }
891         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
892         printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
893         printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
894         printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
895         printf("</tr>\n");
896         printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
897
898         /* Print out the list of wins servers */
899         if(lp_wins_server_list()) {
900                 int i;
901                 const char **wins_servers = lp_wins_server_list();
902                 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
903         }
904
905         printf("\"></td></tr>\n");
906         if (winstype == 3) {
907                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Error: WINS Server Mode and WINS Support both set in smb.conf"));
908                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
909         }
910         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
911         printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
912         printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
913         printf("<td></td></tr>\n");
914
915         /* Enable this when we are ready ....
916          * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
917          * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
918          * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
919          * printf("<td></td></tr>\n");
920          */
921
922         printf("</table></center>");
923         printf("<hr>");
924
925         printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
926         printf("</form>\n");
927 }
928
929
930 /****************************************************************************
931   display a globals editing page  
932 ****************************************************************************/
933 static void globals_page(void)
934 {
935         unsigned int parm_filter = FLAG_BASIC;
936         int mode = 0;
937
938         printf("<H2>%s</H2>\n", _("Global Parameters"));
939
940         if (cgi_variable("Commit")) {
941                 commit_parameters(GLOBAL_SECTION_SNUM);
942                 save_reload(-1);
943         }
944
945         if ( cgi_variable("ViewMode") )
946                 mode = atoi(cgi_variable_nonull("ViewMode"));
947         if ( cgi_variable("BasicMode"))
948                 mode = 0;
949         if ( cgi_variable("AdvMode"))
950                 mode = 1;
951
952         printf("<form name=\"swatform\" method=post action=globals>\n");
953
954         ViewModeBoxes( mode );
955         switch ( mode ) {
956                 case 0:
957                         parm_filter = FLAG_BASIC;
958                         break;
959                 case 1:
960                         parm_filter = FLAG_ADVANCED;
961                         break;
962         }
963         printf("<br>\n");
964         if (have_write_access) {
965                 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
966                         _("Commit Changes"));
967         }
968
969         printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
970                  _("Reset Values"));
971
972         printf("<p>\n");
973         printf("<table>\n");
974         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
975         printf("</table>\n");
976         printf("</form>\n");
977 }
978
979 /****************************************************************************
980   display a shares editing page. share is in unix codepage, 
981 ****************************************************************************/
982 static void shares_page(void)
983 {
984         const char *share = cgi_variable("share");
985         char *s;
986         char *utf8_s;
987         int snum = -1;
988         int i;
989         int mode = 0;
990         unsigned int parm_filter = FLAG_BASIC;
991         size_t converted_size;
992
993         if (share)
994                 snum = lp_servicenumber(share);
995
996         printf("<H2>%s</H2>\n", _("Share Parameters"));
997
998         if (cgi_variable("Commit") && snum >= 0) {
999                 commit_parameters(snum);
1000                 save_reload(-1);
1001                 snum = lp_servicenumber(share);
1002         }
1003
1004         if (cgi_variable("Delete") && snum >= 0) {
1005                 lp_remove_service(snum);
1006                 save_reload(-1);
1007                 share = NULL;
1008                 snum = -1;
1009         }
1010
1011         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1012                 snum = lp_servicenumber(share);
1013                 if (snum < 0) {
1014                         load_config(False);
1015                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1016                         snum = lp_servicenumber(share);
1017                         save_reload(snum);
1018                         snum = lp_servicenumber(share);
1019                 }
1020         }
1021
1022         printf("<FORM name=\"swatform\" method=post>\n");
1023
1024         printf("<table>\n");
1025
1026         if ( cgi_variable("ViewMode") )
1027                 mode = atoi(cgi_variable_nonull("ViewMode"));
1028         if ( cgi_variable("BasicMode"))
1029                 mode = 0;
1030         if ( cgi_variable("AdvMode"))
1031                 mode = 1;
1032
1033         ViewModeBoxes( mode );
1034         switch ( mode ) {
1035                 case 0:
1036                         parm_filter = FLAG_BASIC;
1037                         break;
1038                 case 1:
1039                         parm_filter = FLAG_ADVANCED;
1040                         break;
1041         }
1042         printf("<br><tr>\n");
1043         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1044         printf("<td><select name=share>\n");
1045         if (snum < 0)
1046                 printf("<option value=\" \"> \n");
1047         for (i=0;i<lp_numservices();i++) {
1048                 s = lp_servicename(i);
1049                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1050                         push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1051                         printf("<option %s value=\"%s\">%s\n", 
1052                                (share && strcmp(share,s)==0)?"SELECTED":"",
1053                                utf8_s, utf8_s);
1054                         TALLOC_FREE(utf8_s);
1055                 }
1056         }
1057         printf("</select></td>\n");
1058         if (have_write_access) {
1059                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1060         }
1061         printf("</tr>\n");
1062         printf("</table>");
1063         printf("<table>");
1064         if (have_write_access) {
1065                 printf("<tr>\n");
1066                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1067                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1068         }
1069         printf("</table>");
1070
1071
1072         if (snum >= 0) {
1073                 if (have_write_access) {
1074                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1075                 }
1076
1077                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1078                 printf("<p>\n");
1079         }
1080
1081         if (snum >= 0) {
1082                 printf("<table>\n");
1083                 show_parameters(snum, 1, parm_filter, 0);
1084                 printf("</table>\n");
1085         }
1086
1087         printf("</FORM>\n");
1088 }
1089
1090 /*************************************************************
1091 change a password either locally or remotely
1092 *************************************************************/
1093 static bool change_password(const char *remote_machine, const char *user_name, 
1094                             const char *old_passwd, const char *new_passwd, 
1095                                 int local_flags)
1096 {
1097         NTSTATUS ret;
1098         char *err_str = NULL;
1099         char *msg_str = NULL;
1100
1101         if (demo_mode) {
1102                 printf("%s\n<p>", _("password change in demo mode rejected"));
1103                 return False;
1104         }
1105
1106         if (remote_machine != NULL) {
1107                 ret = remote_password_change(remote_machine, user_name,
1108                                              old_passwd, new_passwd, &err_str);
1109                 if (err_str != NULL)
1110                         printf("%s\n<p>", err_str);
1111                 SAFE_FREE(err_str);
1112                 return NT_STATUS_IS_OK(ret);
1113         }
1114
1115         if(!initialize_password_db(True, NULL)) {
1116                 printf("%s\n<p>", _("Can't setup password database vectors."));
1117                 return False;
1118         }
1119
1120         ret = local_password_change(user_name, local_flags, new_passwd,
1121                                         &err_str, &msg_str);
1122
1123         if(msg_str)
1124                 printf("%s\n<p>", msg_str);
1125         if(err_str)
1126                 printf("%s\n<p>", err_str);
1127
1128         SAFE_FREE(msg_str);
1129         SAFE_FREE(err_str);
1130         return NT_STATUS_IS_OK(ret);
1131 }
1132
1133 /****************************************************************************
1134   do the stuff required to add or change a password 
1135 ****************************************************************************/
1136 static void chg_passwd(void)
1137 {
1138         const char *host;
1139         bool rslt;
1140         int local_flags = 0;
1141
1142         /* Make sure users name has been specified */
1143         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1144                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1145                 return;
1146         }
1147
1148         /*
1149          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1150          * so if that's what we're doing, skip the rest of the checks
1151          */
1152         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1153
1154                 /*
1155                  * If current user is not root, make sure old password has been specified 
1156                  * If REMOTE change, even root must provide old password 
1157                  */
1158                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1159                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1160                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1161                         return;
1162                 }
1163
1164                 /* If changing a users password on a remote hosts we have to know what host */
1165                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1166                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1167                         return;
1168                 }
1169
1170                 /* Make sure new passwords have been specified */
1171                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1172                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1173                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1174                         return;
1175                 }
1176
1177                 /* Make sure new passwords was typed correctly twice */
1178                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1179                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1180                         return;
1181                 }
1182         }
1183
1184         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1185                 host = cgi_variable(RHOST);
1186         } else if (am_root()) {
1187                 host = NULL;
1188         } else {
1189                 host = "127.0.0.1";
1190         }
1191
1192         /*
1193          * Set up the local flags.
1194          */
1195
1196         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1197         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1198         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1199         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1200         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1201         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1202
1203         rslt = change_password(host,
1204                                cgi_variable_nonull(SWAT_USER),
1205                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1206                                    local_flags);
1207
1208         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1209                 printf("<p>");
1210                 if (rslt == True) {
1211                         printf("%s\n", _(" The passwd has been changed."));
1212                 } else {
1213                         printf("%s\n", _(" The passwd has NOT been changed."));
1214                 }
1215         }
1216
1217         return;
1218 }
1219
1220 /****************************************************************************
1221   display a password editing page  
1222 ****************************************************************************/
1223 static void passwd_page(void)
1224 {
1225         const char *new_name = cgi_user_name();
1226
1227         if (!new_name) new_name = "";
1228
1229         printf("<H2>%s</H2>\n", _("Server Password Management"));
1230
1231         printf("<FORM name=\"swatform\" method=post>\n");
1232
1233         printf("<table>\n");
1234
1235         /* 
1236          * Create all the dialog boxes for data collection
1237          */
1238         printf("<tr><td> %s : </td>\n", _("User Name"));
1239         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1240         if (!am_root()) {
1241                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1242                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1243         }
1244         printf("<tr><td> %s : </td>\n", _("New Password"));
1245         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1246         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1247         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1248         printf("</table>\n");
1249
1250         /*
1251          * Create all the control buttons for requesting action
1252          */
1253         printf("<input type=submit name=%s value=\"%s\">\n", 
1254                CHG_S_PASSWD_FLAG, _("Change Password"));
1255         if (demo_mode || am_root()) {
1256                 printf("<input type=submit name=%s value=\"%s\">\n",
1257                        ADD_USER_FLAG, _("Add New User"));
1258                 printf("<input type=submit name=%s value=\"%s\">\n",
1259                        DELETE_USER_FLAG, _("Delete User"));
1260                 printf("<input type=submit name=%s value=\"%s\">\n", 
1261                        DISABLE_USER_FLAG, _("Disable User"));
1262                 printf("<input type=submit name=%s value=\"%s\">\n", 
1263                        ENABLE_USER_FLAG, _("Enable User"));
1264         }
1265         printf("<p></FORM>\n");
1266
1267         /*
1268          * Do some work if change, add, disable or enable was
1269          * requested. It could be this is the first time through this
1270          * code, so there isn't anything to do.  */
1271         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1272             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1273                 chg_passwd();           
1274         }
1275
1276         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1277
1278         printf("<FORM name=\"swatform\" method=post>\n");
1279
1280         printf("<table>\n");
1281
1282         /* 
1283          * Create all the dialog boxes for data collection
1284          */
1285         printf("<tr><td> %s : </td>\n", _("User Name"));
1286         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1287         printf("<tr><td> %s : </td>\n", _("Old Password"));
1288         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1289         printf("<tr><td> %s : </td>\n", _("New Password"));
1290         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1291         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1292         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1293         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1294         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1295
1296         printf("</table>");
1297
1298         /*
1299          * Create all the control buttons for requesting action
1300          */
1301         printf("<input type=submit name=%s value=\"%s\">", 
1302                CHG_R_PASSWD_FLAG, _("Change Password"));
1303
1304         printf("<p></FORM>\n");
1305
1306         /*
1307          * Do some work if a request has been made to change the
1308          * password somewhere other than the server. It could be this
1309          * is the first time through this code, so there isn't
1310          * anything to do.  */
1311         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1312                 chg_passwd();           
1313         }
1314
1315 }
1316
1317 /****************************************************************************
1318   display a printers editing page  
1319 ****************************************************************************/
1320 static void printers_page(void)
1321 {
1322         const char *share = cgi_variable("share");
1323         char *s;
1324         int snum=-1;
1325         int i;
1326         int mode = 0;
1327         unsigned int parm_filter = FLAG_BASIC;
1328
1329         if (share)
1330                 snum = lp_servicenumber(share);
1331
1332         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1333  
1334         printf("<H3>%s</H3>\n", _("Important Note:"));
1335         printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1336         printf("%s",_("are autoloaded printers from "));
1337         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1338         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1339
1340         if (cgi_variable("Commit") && snum >= 0) {
1341                 commit_parameters(snum);
1342                 if (snum >= iNumNonAutoPrintServices)
1343                     save_reload(snum);
1344                 else
1345                     save_reload(-1);
1346                 snum = lp_servicenumber(share);
1347         }
1348
1349         if (cgi_variable("Delete") && snum >= 0) {
1350                 lp_remove_service(snum);
1351                 save_reload(-1);
1352                 share = NULL;
1353                 snum = -1;
1354         }
1355
1356         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1357                 snum = lp_servicenumber(share);
1358                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1359                         load_config(False);
1360                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1361                         snum = lp_servicenumber(share);
1362                         lp_do_parameter(snum, "print ok", "Yes");
1363                         save_reload(snum);
1364                         snum = lp_servicenumber(share);
1365                 }
1366         }
1367
1368         printf("<FORM name=\"swatform\" method=post>\n");
1369
1370         if ( cgi_variable("ViewMode") )
1371                 mode = atoi(cgi_variable_nonull("ViewMode"));
1372         if ( cgi_variable("BasicMode"))
1373                 mode = 0;
1374         if ( cgi_variable("AdvMode"))
1375                 mode = 1;
1376
1377         ViewModeBoxes( mode );
1378         switch ( mode ) {
1379                 case 0:
1380                         parm_filter = FLAG_BASIC;
1381                         break;
1382                 case 1:
1383                         parm_filter = FLAG_ADVANCED;
1384                         break;
1385         }
1386         printf("<table>\n");
1387         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1388         printf("<td><select name=\"share\">\n");
1389         if (snum < 0 || !lp_print_ok(snum))
1390                 printf("<option value=\" \"> \n");
1391         for (i=0;i<lp_numservices();i++) {
1392                 s = lp_servicename(i);
1393                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1394                     if (i >= iNumNonAutoPrintServices)
1395                         printf("<option %s value=\"%s\">[*]%s\n",
1396                                (share && strcmp(share,s)==0)?"SELECTED":"",
1397                                s, s);
1398                     else
1399                         printf("<option %s value=\"%s\">%s\n", 
1400                                (share && strcmp(share,s)==0)?"SELECTED":"",
1401                                s, s);
1402                 }
1403         }
1404         printf("</select></td>");
1405         if (have_write_access) {
1406                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1407         }
1408         printf("</tr>");
1409         printf("</table>\n");
1410
1411         if (have_write_access) {
1412                 printf("<table>\n");
1413                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1414                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1415                 printf("</table>");
1416         }
1417
1418
1419         if (snum >= 0) {
1420                 if (have_write_access) {
1421                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1422                 }
1423                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1424                 printf("<p>\n");
1425         }
1426
1427         if (snum >= 0) {
1428                 printf("<table>\n");
1429                 show_parameters(snum, 1, parm_filter, 1);
1430                 printf("</table>\n");
1431         }
1432         printf("</FORM>\n");
1433 }
1434
1435 /*
1436   when the _() translation macro is used there is no obvious place to free
1437   the resulting string and there is no easy way to give a static pointer.
1438   All we can do is rotate between some static buffers and hope a single d_printf()
1439   doesn't have more calls to _() than the number of buffers
1440 */
1441
1442 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1443 {
1444         const char *msgstr;
1445         const char *ret;
1446
1447         msgstr = lang_msg(msgid);
1448         if (!msgstr) {
1449                 return msgid;
1450         }
1451
1452         ret = talloc_strdup(ctx, msgstr);
1453
1454         lang_msg_free(msgstr);
1455         if (!ret) {
1456                 return msgid;
1457         }
1458
1459         return ret;
1460 }
1461
1462 /**
1463  * main function for SWAT.
1464  **/
1465  int main(int argc, char *argv[])
1466 {
1467         const char *page;
1468         poptContext pc;
1469         struct poptOption long_options[] = {
1470                 POPT_AUTOHELP
1471                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1472                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1473                 POPT_COMMON_SAMBA
1474                 POPT_TABLEEND
1475         };
1476         TALLOC_CTX *frame = talloc_stackframe();
1477
1478         fault_setup();
1479         umask(S_IWGRP | S_IWOTH);
1480
1481 #if defined(HAVE_SET_AUTH_PARAMETERS)
1482         set_auth_parameters(argc, argv);
1483 #endif /* HAVE_SET_AUTH_PARAMETERS */
1484
1485         /* just in case it goes wild ... */
1486         alarm(300);
1487
1488         setlinebuf(stdout);
1489
1490         /* we don't want any SIGPIPE messages */
1491         BlockSignals(True,SIGPIPE);
1492
1493         debug_set_logfile("/dev/null");
1494
1495         /* we don't want stderr screwing us up */
1496         close(2);
1497         open("/dev/null", O_WRONLY);
1498         setup_logging("swat", DEBUG_FILE);
1499
1500         load_case_tables();
1501         
1502         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1503
1504         /* Parse command line options */
1505
1506         while(poptGetNextOpt(pc) != -1) { }
1507
1508         poptFreeContext(pc);
1509
1510         /* This should set a more apporiate log file */
1511         load_config(True);
1512         reopen_logs();
1513         load_interfaces();
1514         iNumNonAutoPrintServices = lp_numservices();
1515         if (pcap_cache_loaded()) {
1516                 load_printers(server_event_context(),
1517                               server_messaging_context());
1518         }
1519
1520         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1521
1522         print_header();
1523
1524         cgi_load_variables();
1525
1526         if (!file_exist(get_dyn_CONFIGFILE())) {
1527                 have_read_access = True;
1528                 have_write_access = True;
1529         } else {
1530                 /* check if the authenticated user has write access - if not then
1531                    don't show write options */
1532                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1533
1534                 /* if the user doesn't have read access to smb.conf then
1535                    don't let them view it */
1536                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1537         }
1538
1539         show_main_buttons();
1540
1541         page = cgi_pathinfo();
1542
1543         /* Root gets full functionality */
1544         if (have_read_access && strcmp(page, "globals")==0) {
1545                 globals_page();
1546         } else if (have_read_access && strcmp(page,"shares")==0) {
1547                 shares_page();
1548         } else if (have_read_access && strcmp(page,"printers")==0) {
1549                 printers_page();
1550         } else if (have_read_access && strcmp(page,"status")==0) {
1551                 status_page();
1552         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1553                 viewconfig_page();
1554         } else if (strcmp(page,"passwd")==0) {
1555                 passwd_page();
1556         } else if (have_read_access && strcmp(page,"wizard")==0) {
1557                 wizard_page();
1558         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1559                 wizard_params_page();
1560         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1561                 rewritecfg_file();
1562         } else {
1563                 welcome_page();
1564         }
1565
1566         print_footer();
1567
1568         TALLOC_FREE(frame);
1569         return 0;
1570 }
1571
1572 /** @} **/