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