s3 swat: Add XSRF protection to wizard_params 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
769         if (cgi_variable("Rewrite")) {
770                 (void) rewritecfg_file();
771                 return;
772         }
773
774         if (cgi_variable("GetWizardParams")){
775                 (void) wizard_params_page();
776                 return;
777         }
778
779         if (cgi_variable("Commit")){
780                 SerType = atoi(cgi_variable_nonull("ServerType"));
781                 winstype = atoi(cgi_variable_nonull("WINSType"));
782                 have_home = lp_servicenumber(HOMES_NAME);
783                 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
784
785                 /* Plain text passwords are too badly broken - use encrypted passwords only */
786                 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
787
788                 switch ( SerType ){
789                         case 0:
790                                 /* Stand-alone Server */
791                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
792                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
793                                 break;
794                         case 1:
795                                 /* Domain Member */
796                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
797                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
798                                 break;
799                         case 2:
800                                 /* Domain Controller */
801                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
802                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
803                                 break;
804                 }
805                 switch ( winstype ) {
806                         case 0:
807                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
808                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
809                                 break;
810                         case 1:
811                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
812                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
813                                 break;
814                         case 2:
815                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
816                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
817                                 break;
818                 }
819
820                 /* Have to create Homes share? */
821                 if ((HomeExpo == 1) && (have_home == -1)) {
822                         const char *unix_share = HOMES_NAME;
823
824                         load_config(False);
825                         lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
826                         have_home = lp_servicenumber(HOMES_NAME);
827                         lp_do_parameter( have_home, "read only", "No");
828                         lp_do_parameter( have_home, "valid users", "%S");
829                         lp_do_parameter( have_home, "browseable", "No");
830                         commit_parameters(have_home);
831                         save_reload(have_home);
832                 }
833
834                 /* Need to Delete Homes share? */
835                 if ((HomeExpo == 0) && (have_home != -1)) {
836                         lp_remove_service(have_home);
837                         have_home = -1;
838                 }
839
840                 commit_parameters(GLOBAL_SECTION_SNUM);
841                 save_reload(-1);
842         }
843         else
844         {
845                 /* Now determine smb.conf WINS settings */
846                 if (lp_we_are_a_wins_server())
847                         winstype = 1;
848                 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
849                         winstype = 2;
850
851                 /* Do we have a homes share? */
852                 have_home = lp_servicenumber(HOMES_NAME);
853         }
854         if ((winstype == 2) && lp_we_are_a_wins_server())
855                 winstype = 3;
856
857         role = lp_server_role();
858
859         /* Here we go ... */
860         printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
861         printf("<form method=post action=wizard>\n");
862
863         if (have_write_access) {
864                 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
865                 printf("%s", _("The same will happen if you press the commit button."));
866                 printf("<br><br>\n");
867                 printf("<center>");
868                 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
869                 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
870                 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
871                 printf("</center>\n");
872         }
873
874         printf("<hr>");
875         printf("<center><table border=0>");
876         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
877         printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
878         printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member")); 
879         printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
880         printf("</tr>\n");
881         if (role == ROLE_DOMAIN_BDC) {
882                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
883         }
884         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
885         printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
886         printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
887         printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
888         printf("</tr>\n");
889         printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
890
891         /* Print out the list of wins servers */
892         if(lp_wins_server_list()) {
893                 int i;
894                 const char **wins_servers = lp_wins_server_list();
895                 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
896         }
897
898         printf("\"></td></tr>\n");
899         if (winstype == 3) {
900                 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"));
901                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
902         }
903         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
904         printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
905         printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
906         printf("<td></td></tr>\n");
907
908         /* Enable this when we are ready ....
909          * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
910          * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
911          * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
912          * printf("<td></td></tr>\n");
913          */
914
915         printf("</table></center>");
916         printf("<hr>");
917
918         printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
919         printf("</form>\n");
920 }
921
922
923 /****************************************************************************
924   display a globals editing page  
925 ****************************************************************************/
926 static void globals_page(void)
927 {
928         unsigned int parm_filter = FLAG_BASIC;
929         int mode = 0;
930
931         printf("<H2>%s</H2>\n", _("Global Parameters"));
932
933         if (cgi_variable("Commit")) {
934                 commit_parameters(GLOBAL_SECTION_SNUM);
935                 save_reload(-1);
936         }
937
938         if ( cgi_variable("ViewMode") )
939                 mode = atoi(cgi_variable_nonull("ViewMode"));
940         if ( cgi_variable("BasicMode"))
941                 mode = 0;
942         if ( cgi_variable("AdvMode"))
943                 mode = 1;
944
945         printf("<form name=\"swatform\" method=post action=globals>\n");
946
947         ViewModeBoxes( mode );
948         switch ( mode ) {
949                 case 0:
950                         parm_filter = FLAG_BASIC;
951                         break;
952                 case 1:
953                         parm_filter = FLAG_ADVANCED;
954                         break;
955         }
956         printf("<br>\n");
957         if (have_write_access) {
958                 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
959                         _("Commit Changes"));
960         }
961
962         printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
963                  _("Reset Values"));
964
965         printf("<p>\n");
966         printf("<table>\n");
967         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
968         printf("</table>\n");
969         printf("</form>\n");
970 }
971
972 /****************************************************************************
973   display a shares editing page. share is in unix codepage, 
974 ****************************************************************************/
975 static void shares_page(void)
976 {
977         const char *share = cgi_variable("share");
978         char *s;
979         char *utf8_s;
980         int snum = -1;
981         int i;
982         int mode = 0;
983         unsigned int parm_filter = FLAG_BASIC;
984         size_t converted_size;
985
986         if (share)
987                 snum = lp_servicenumber(share);
988
989         printf("<H2>%s</H2>\n", _("Share Parameters"));
990
991         if (cgi_variable("Commit") && snum >= 0) {
992                 commit_parameters(snum);
993                 save_reload(-1);
994                 snum = lp_servicenumber(share);
995         }
996
997         if (cgi_variable("Delete") && snum >= 0) {
998                 lp_remove_service(snum);
999                 save_reload(-1);
1000                 share = NULL;
1001                 snum = -1;
1002         }
1003
1004         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1005                 snum = lp_servicenumber(share);
1006                 if (snum < 0) {
1007                         load_config(False);
1008                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1009                         snum = lp_servicenumber(share);
1010                         save_reload(snum);
1011                         snum = lp_servicenumber(share);
1012                 }
1013         }
1014
1015         printf("<FORM name=\"swatform\" method=post>\n");
1016
1017         printf("<table>\n");
1018
1019         if ( cgi_variable("ViewMode") )
1020                 mode = atoi(cgi_variable_nonull("ViewMode"));
1021         if ( cgi_variable("BasicMode"))
1022                 mode = 0;
1023         if ( cgi_variable("AdvMode"))
1024                 mode = 1;
1025
1026         ViewModeBoxes( mode );
1027         switch ( mode ) {
1028                 case 0:
1029                         parm_filter = FLAG_BASIC;
1030                         break;
1031                 case 1:
1032                         parm_filter = FLAG_ADVANCED;
1033                         break;
1034         }
1035         printf("<br><tr>\n");
1036         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1037         printf("<td><select name=share>\n");
1038         if (snum < 0)
1039                 printf("<option value=\" \"> \n");
1040         for (i=0;i<lp_numservices();i++) {
1041                 s = lp_servicename(i);
1042                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1043                         push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1044                         printf("<option %s value=\"%s\">%s\n", 
1045                                (share && strcmp(share,s)==0)?"SELECTED":"",
1046                                utf8_s, utf8_s);
1047                         TALLOC_FREE(utf8_s);
1048                 }
1049         }
1050         printf("</select></td>\n");
1051         if (have_write_access) {
1052                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1053         }
1054         printf("</tr>\n");
1055         printf("</table>");
1056         printf("<table>");
1057         if (have_write_access) {
1058                 printf("<tr>\n");
1059                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1060                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1061         }
1062         printf("</table>");
1063
1064
1065         if (snum >= 0) {
1066                 if (have_write_access) {
1067                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1068                 }
1069
1070                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1071                 printf("<p>\n");
1072         }
1073
1074         if (snum >= 0) {
1075                 printf("<table>\n");
1076                 show_parameters(snum, 1, parm_filter, 0);
1077                 printf("</table>\n");
1078         }
1079
1080         printf("</FORM>\n");
1081 }
1082
1083 /*************************************************************
1084 change a password either locally or remotely
1085 *************************************************************/
1086 static bool change_password(const char *remote_machine, const char *user_name, 
1087                             const char *old_passwd, const char *new_passwd, 
1088                                 int local_flags)
1089 {
1090         NTSTATUS ret;
1091         char *err_str = NULL;
1092         char *msg_str = NULL;
1093
1094         if (demo_mode) {
1095                 printf("%s\n<p>", _("password change in demo mode rejected"));
1096                 return False;
1097         }
1098
1099         if (remote_machine != NULL) {
1100                 ret = remote_password_change(remote_machine, user_name,
1101                                              old_passwd, new_passwd, &err_str);
1102                 if (err_str != NULL)
1103                         printf("%s\n<p>", err_str);
1104                 SAFE_FREE(err_str);
1105                 return NT_STATUS_IS_OK(ret);
1106         }
1107
1108         if(!initialize_password_db(True, NULL)) {
1109                 printf("%s\n<p>", _("Can't setup password database vectors."));
1110                 return False;
1111         }
1112
1113         ret = local_password_change(user_name, local_flags, new_passwd,
1114                                         &err_str, &msg_str);
1115
1116         if(msg_str)
1117                 printf("%s\n<p>", msg_str);
1118         if(err_str)
1119                 printf("%s\n<p>", err_str);
1120
1121         SAFE_FREE(msg_str);
1122         SAFE_FREE(err_str);
1123         return NT_STATUS_IS_OK(ret);
1124 }
1125
1126 /****************************************************************************
1127   do the stuff required to add or change a password 
1128 ****************************************************************************/
1129 static void chg_passwd(void)
1130 {
1131         const char *host;
1132         bool rslt;
1133         int local_flags = 0;
1134
1135         /* Make sure users name has been specified */
1136         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1137                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1138                 return;
1139         }
1140
1141         /*
1142          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1143          * so if that's what we're doing, skip the rest of the checks
1144          */
1145         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1146
1147                 /*
1148                  * If current user is not root, make sure old password has been specified 
1149                  * If REMOTE change, even root must provide old password 
1150                  */
1151                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1152                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1153                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1154                         return;
1155                 }
1156
1157                 /* If changing a users password on a remote hosts we have to know what host */
1158                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1159                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1160                         return;
1161                 }
1162
1163                 /* Make sure new passwords have been specified */
1164                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1165                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1166                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1167                         return;
1168                 }
1169
1170                 /* Make sure new passwords was typed correctly twice */
1171                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1172                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1173                         return;
1174                 }
1175         }
1176
1177         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1178                 host = cgi_variable(RHOST);
1179         } else if (am_root()) {
1180                 host = NULL;
1181         } else {
1182                 host = "127.0.0.1";
1183         }
1184
1185         /*
1186          * Set up the local flags.
1187          */
1188
1189         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1190         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1191         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1192         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1193         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1194         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1195
1196         rslt = change_password(host,
1197                                cgi_variable_nonull(SWAT_USER),
1198                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1199                                    local_flags);
1200
1201         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1202                 printf("<p>");
1203                 if (rslt == True) {
1204                         printf("%s\n", _(" The passwd has been changed."));
1205                 } else {
1206                         printf("%s\n", _(" The passwd has NOT been changed."));
1207                 }
1208         }
1209
1210         return;
1211 }
1212
1213 /****************************************************************************
1214   display a password editing page  
1215 ****************************************************************************/
1216 static void passwd_page(void)
1217 {
1218         const char *new_name = cgi_user_name();
1219
1220         if (!new_name) new_name = "";
1221
1222         printf("<H2>%s</H2>\n", _("Server Password Management"));
1223
1224         printf("<FORM name=\"swatform\" method=post>\n");
1225
1226         printf("<table>\n");
1227
1228         /* 
1229          * Create all the dialog boxes for data collection
1230          */
1231         printf("<tr><td> %s : </td>\n", _("User Name"));
1232         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1233         if (!am_root()) {
1234                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1235                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1236         }
1237         printf("<tr><td> %s : </td>\n", _("New Password"));
1238         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1239         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1240         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1241         printf("</table>\n");
1242
1243         /*
1244          * Create all the control buttons for requesting action
1245          */
1246         printf("<input type=submit name=%s value=\"%s\">\n", 
1247                CHG_S_PASSWD_FLAG, _("Change Password"));
1248         if (demo_mode || am_root()) {
1249                 printf("<input type=submit name=%s value=\"%s\">\n",
1250                        ADD_USER_FLAG, _("Add New User"));
1251                 printf("<input type=submit name=%s value=\"%s\">\n",
1252                        DELETE_USER_FLAG, _("Delete User"));
1253                 printf("<input type=submit name=%s value=\"%s\">\n", 
1254                        DISABLE_USER_FLAG, _("Disable User"));
1255                 printf("<input type=submit name=%s value=\"%s\">\n", 
1256                        ENABLE_USER_FLAG, _("Enable User"));
1257         }
1258         printf("<p></FORM>\n");
1259
1260         /*
1261          * Do some work if change, add, disable or enable was
1262          * requested. It could be this is the first time through this
1263          * code, so there isn't anything to do.  */
1264         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1265             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1266                 chg_passwd();           
1267         }
1268
1269         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1270
1271         printf("<FORM name=\"swatform\" method=post>\n");
1272
1273         printf("<table>\n");
1274
1275         /* 
1276          * Create all the dialog boxes for data collection
1277          */
1278         printf("<tr><td> %s : </td>\n", _("User Name"));
1279         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1280         printf("<tr><td> %s : </td>\n", _("Old Password"));
1281         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1282         printf("<tr><td> %s : </td>\n", _("New Password"));
1283         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1284         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1285         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1286         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1287         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1288
1289         printf("</table>");
1290
1291         /*
1292          * Create all the control buttons for requesting action
1293          */
1294         printf("<input type=submit name=%s value=\"%s\">", 
1295                CHG_R_PASSWD_FLAG, _("Change Password"));
1296
1297         printf("<p></FORM>\n");
1298
1299         /*
1300          * Do some work if a request has been made to change the
1301          * password somewhere other than the server. It could be this
1302          * is the first time through this code, so there isn't
1303          * anything to do.  */
1304         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1305                 chg_passwd();           
1306         }
1307
1308 }
1309
1310 /****************************************************************************
1311   display a printers editing page  
1312 ****************************************************************************/
1313 static void printers_page(void)
1314 {
1315         const char *share = cgi_variable("share");
1316         char *s;
1317         int snum=-1;
1318         int i;
1319         int mode = 0;
1320         unsigned int parm_filter = FLAG_BASIC;
1321
1322         if (share)
1323                 snum = lp_servicenumber(share);
1324
1325         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1326  
1327         printf("<H3>%s</H3>\n", _("Important Note:"));
1328         printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1329         printf("%s",_("are autoloaded printers from "));
1330         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1331         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1332
1333         if (cgi_variable("Commit") && snum >= 0) {
1334                 commit_parameters(snum);
1335                 if (snum >= iNumNonAutoPrintServices)
1336                     save_reload(snum);
1337                 else
1338                     save_reload(-1);
1339                 snum = lp_servicenumber(share);
1340         }
1341
1342         if (cgi_variable("Delete") && snum >= 0) {
1343                 lp_remove_service(snum);
1344                 save_reload(-1);
1345                 share = NULL;
1346                 snum = -1;
1347         }
1348
1349         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1350                 snum = lp_servicenumber(share);
1351                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1352                         load_config(False);
1353                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1354                         snum = lp_servicenumber(share);
1355                         lp_do_parameter(snum, "print ok", "Yes");
1356                         save_reload(snum);
1357                         snum = lp_servicenumber(share);
1358                 }
1359         }
1360
1361         printf("<FORM name=\"swatform\" method=post>\n");
1362
1363         if ( cgi_variable("ViewMode") )
1364                 mode = atoi(cgi_variable_nonull("ViewMode"));
1365         if ( cgi_variable("BasicMode"))
1366                 mode = 0;
1367         if ( cgi_variable("AdvMode"))
1368                 mode = 1;
1369
1370         ViewModeBoxes( mode );
1371         switch ( mode ) {
1372                 case 0:
1373                         parm_filter = FLAG_BASIC;
1374                         break;
1375                 case 1:
1376                         parm_filter = FLAG_ADVANCED;
1377                         break;
1378         }
1379         printf("<table>\n");
1380         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1381         printf("<td><select name=\"share\">\n");
1382         if (snum < 0 || !lp_print_ok(snum))
1383                 printf("<option value=\" \"> \n");
1384         for (i=0;i<lp_numservices();i++) {
1385                 s = lp_servicename(i);
1386                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1387                     if (i >= iNumNonAutoPrintServices)
1388                         printf("<option %s value=\"%s\">[*]%s\n",
1389                                (share && strcmp(share,s)==0)?"SELECTED":"",
1390                                s, s);
1391                     else
1392                         printf("<option %s value=\"%s\">%s\n", 
1393                                (share && strcmp(share,s)==0)?"SELECTED":"",
1394                                s, s);
1395                 }
1396         }
1397         printf("</select></td>");
1398         if (have_write_access) {
1399                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1400         }
1401         printf("</tr>");
1402         printf("</table>\n");
1403
1404         if (have_write_access) {
1405                 printf("<table>\n");
1406                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1407                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1408                 printf("</table>");
1409         }
1410
1411
1412         if (snum >= 0) {
1413                 if (have_write_access) {
1414                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1415                 }
1416                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1417                 printf("<p>\n");
1418         }
1419
1420         if (snum >= 0) {
1421                 printf("<table>\n");
1422                 show_parameters(snum, 1, parm_filter, 1);
1423                 printf("</table>\n");
1424         }
1425         printf("</FORM>\n");
1426 }
1427
1428 /*
1429   when the _() translation macro is used there is no obvious place to free
1430   the resulting string and there is no easy way to give a static pointer.
1431   All we can do is rotate between some static buffers and hope a single d_printf()
1432   doesn't have more calls to _() than the number of buffers
1433 */
1434
1435 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1436 {
1437         const char *msgstr;
1438         const char *ret;
1439
1440         msgstr = lang_msg(msgid);
1441         if (!msgstr) {
1442                 return msgid;
1443         }
1444
1445         ret = talloc_strdup(ctx, msgstr);
1446
1447         lang_msg_free(msgstr);
1448         if (!ret) {
1449                 return msgid;
1450         }
1451
1452         return ret;
1453 }
1454
1455 /**
1456  * main function for SWAT.
1457  **/
1458  int main(int argc, char *argv[])
1459 {
1460         const char *page;
1461         poptContext pc;
1462         struct poptOption long_options[] = {
1463                 POPT_AUTOHELP
1464                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1465                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1466                 POPT_COMMON_SAMBA
1467                 POPT_TABLEEND
1468         };
1469         TALLOC_CTX *frame = talloc_stackframe();
1470
1471         fault_setup();
1472         umask(S_IWGRP | S_IWOTH);
1473
1474 #if defined(HAVE_SET_AUTH_PARAMETERS)
1475         set_auth_parameters(argc, argv);
1476 #endif /* HAVE_SET_AUTH_PARAMETERS */
1477
1478         /* just in case it goes wild ... */
1479         alarm(300);
1480
1481         setlinebuf(stdout);
1482
1483         /* we don't want any SIGPIPE messages */
1484         BlockSignals(True,SIGPIPE);
1485
1486         debug_set_logfile("/dev/null");
1487
1488         /* we don't want stderr screwing us up */
1489         close(2);
1490         open("/dev/null", O_WRONLY);
1491         setup_logging("swat", DEBUG_FILE);
1492
1493         load_case_tables();
1494         
1495         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1496
1497         /* Parse command line options */
1498
1499         while(poptGetNextOpt(pc) != -1) { }
1500
1501         poptFreeContext(pc);
1502
1503         /* This should set a more apporiate log file */
1504         load_config(True);
1505         reopen_logs();
1506         load_interfaces();
1507         iNumNonAutoPrintServices = lp_numservices();
1508         if (pcap_cache_loaded()) {
1509                 load_printers(server_event_context(),
1510                               server_messaging_context());
1511         }
1512
1513         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1514
1515         print_header();
1516
1517         cgi_load_variables();
1518
1519         if (!file_exist(get_dyn_CONFIGFILE())) {
1520                 have_read_access = True;
1521                 have_write_access = True;
1522         } else {
1523                 /* check if the authenticated user has write access - if not then
1524                    don't show write options */
1525                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1526
1527                 /* if the user doesn't have read access to smb.conf then
1528                    don't let them view it */
1529                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1530         }
1531
1532         show_main_buttons();
1533
1534         page = cgi_pathinfo();
1535
1536         /* Root gets full functionality */
1537         if (have_read_access && strcmp(page, "globals")==0) {
1538                 globals_page();
1539         } else if (have_read_access && strcmp(page,"shares")==0) {
1540                 shares_page();
1541         } else if (have_read_access && strcmp(page,"printers")==0) {
1542                 printers_page();
1543         } else if (have_read_access && strcmp(page,"status")==0) {
1544                 status_page();
1545         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1546                 viewconfig_page();
1547         } else if (strcmp(page,"passwd")==0) {
1548                 passwd_page();
1549         } else if (have_read_access && strcmp(page,"wizard")==0) {
1550                 wizard_page();
1551         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1552                 wizard_params_page();
1553         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1554                 rewritecfg_file();
1555         } else {
1556                 welcome_page();
1557         }
1558
1559         print_footer();
1560
1561         TALLOC_FREE(frame);
1562         return 0;
1563 }
1564
1565 /** @} **/