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