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