2 Unix SMB/CIFS implementation.
3 Samba Web Administration Tool
5 Copyright (C) Andrew Tridgell 1997-2002
6 Copyright (C) John H Terpstra 2002
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.
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.
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/>.
23 * @defgroup swat SWAT - Samba Web Administration Tool
27 * @brief Samba Web Administration Tool.
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"
37 #include "intl/lang_tdb.h"
38 #include "../lib/crypto/md5.h"
39 #include "lib/param/loadparm.h"
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;
48 * Password Management Globals
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
65 #define _(x) lang_msg_rotate(talloc_tos(),x)
67 /****************************************************************************
68 ****************************************************************************/
69 static int enum_index(int value, const struct enum_list *enumlist)
72 for (i=0;enumlist[i].name;i++)
73 if (value == enumlist[i].value) break;
77 static char *fix_backslash(const char *str)
79 static char newstring[1024];
83 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
91 static const char *fix_quotes(TALLOC_CTX *ctx, char *str)
93 char *newstring = NULL;
96 int quote_len = strlen(""");
98 /* Count the number of quotes. */
103 newstring_len += quote_len;
109 newstring = talloc_array(ctx, char, newstring_len);
113 for (p = newstring; *str; str++) {
115 strncpy( p, """, quote_len);
125 static char *stripspaceupper(const char *str)
127 static char newstring[1024];
131 if (*str != ' ') *p++ = toupper_m(*str);
138 static char *make_parm_name(const char *label)
140 static char parmname[1024];
144 if (*label == ' ') *p++ = '_';
152 void get_xsrf_token(const char *username, const char *pass,
153 const char *formname, time_t xsrf_time, char token_str[33])
155 struct MD5Context md5_ctx;
160 ZERO_STRUCT(md5_ctx);
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));
169 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
172 MD5Final(token, &md5_ctx);
174 for(i = 0; i < sizeof(token); i++) {
177 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
178 strncat(token_str, tmp, sizeof(tmp));
182 void print_xsrf_token(const char *username, const char *pass,
183 const char *formname)
186 time_t xsrf_time = time(NULL);
188 get_xsrf_token(username, pass, formname, xsrf_time, token);
189 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
191 printf("<input type=\"hidden\" name=\"%s\" value=\"%lld\">\n",
192 XSRF_TIME, (long long int)xsrf_time);
195 bool verify_xsrf_token(const char *formname)
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);
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);
213 if (abs(now - xsrf_time) > XSRF_TIMEOUT) {
217 get_xsrf_token(username, pass, formname, xsrf_time, expected);
218 return (strncmp(expected, token, sizeof(expected)) == 0);
222 /****************************************************************************
223 include a lump of html in a page
224 ****************************************************************************/
225 static int include_html(const char *fname)
231 fd = web_open(fname, O_RDONLY, 0);
234 printf(_("ERROR: Can't open %s"), fname);
239 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
240 if (write(1, buf, ret) == -1) {
249 /****************************************************************************
250 start the page with standard stuff
251 ****************************************************************************/
252 static void print_header(void)
254 if (!cgi_waspost()) {
255 printf("Expires: 0\r\n");
257 printf("Content-type: text/html\r\n\r\n");
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");
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
270 -------------------------------
271 HELP security [combo box][button]
273 -------------------------------
274 (capital words are translated by gettext.)
275 if no translation is available, then same form as original is
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)
283 const char *pTranslated = _(pLabel);
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> %s <br><span class=\"i18n_translated_parm\">%s</span>",
288 pAnchor, pHelp, pLabel, pTranslated);
291 output = talloc_asprintf(ctx,
292 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
293 pAnchor, pHelp, pLabel);
296 /****************************************************************************
298 ****************************************************************************/
299 static void print_footer(void)
301 if (!include_html("include/footer.html")) {
302 printf("\n</BODY>\n</HTML>\n");
306 /****************************************************************************
307 display one editable parameter in a form
308 ****************************************************************************/
309 static void show_parameter(int snum, struct parm_struct *parm)
313 char *utf8_s1, *utf8_s2;
314 size_t converted_size;
315 TALLOC_CTX *ctx = talloc_stackframe();
317 if (parm->p_class == P_LOCAL && snum >= 0) {
318 ptr = lp_local_ptr_by_snum(snum, parm);
320 ptr = lp_parm_ptr(NULL, parm);
323 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
324 stripspaceupper(parm->label), _("Help"), parm->label));
325 switch (parm->type) {
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));
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(""%s"%s", utf8_s1, utf8_s2);
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);
349 TALLOC_FREE(utf8_s1);
350 TALLOC_FREE(utf8_s2);
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(""%s"%s", *list, ((*(list+1))?", ":""));
363 printf("%s%s", *list, ((*(list+1))?", ":""));
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)));
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");
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);
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":"");
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);
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));
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);
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);
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);
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));
431 printf("</td></tr>\n");
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)
441 struct parm_struct *parm;
442 const char *heading = NULL;
443 const char *last_heading = NULL;
445 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
446 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
448 if (parm->p_class == P_SEPARATOR) {
449 heading = parm->label;
452 if (parm->flags & FLAG_HIDE) continue;
454 if (printers & !(parm->flags & FLAG_PRINT)) continue;
455 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
458 if (!( parm_filter & FLAG_ADVANCED )) {
459 if (!(parm->flags & FLAG_BASIC)) {
461 if (parm->p_class == P_LOCAL && snum >= 0) {
462 ptr = lp_local_ptr_by_snum(snum, parm);
464 ptr = lp_parm_ptr(NULL, parm);
467 switch (parm->type) {
469 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
473 if (!str_list_equal(*(const char ***)ptr,
474 (const char **)(parm->def.lvalue))) continue;
479 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
484 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
489 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
494 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
500 if (printers && !(parm->flags & FLAG_PRINT)) continue;
503 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
505 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
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;
511 show_parameter(snum, parm);
515 /****************************************************************************
516 load the smb.conf file into loadparm.
517 ****************************************************************************/
518 static bool load_config(bool save_def)
520 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
523 /****************************************************************************
525 ****************************************************************************/
526 static void write_config(FILE *f, bool show_defaults)
528 TALLOC_CTX *ctx = talloc_stackframe();
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));
534 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
539 /****************************************************************************
540 save and reload the smb.conf config file
541 ****************************************************************************/
542 static int save_reload(int snum)
547 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
549 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
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);
560 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
564 write_config(f, False);
566 lp_dump_one(f, False, snum);
569 lp_kill_all_services();
571 if (!load_config(False)) {
572 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
576 iNumNonAutoPrintServices = lp_numservices();
577 if (pcap_cache_loaded()) {
578 load_printers(server_event_context(),
579 server_messaging_context());
585 /****************************************************************************
587 ****************************************************************************/
588 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
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);
605 lp_do_parameter(snum, parm->label, v);
608 /****************************************************************************
609 commit a set of parameters for a service
610 ****************************************************************************/
611 static void commit_parameters(int snum)
614 struct parm_struct *parm;
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)
623 commit_parameter(snum, parm, v);
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)
635 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
636 cgi_baseurl(), hlink, src, name);
639 /****************************************************************************
640 display the main navigation controls at the top of each page along
642 ****************************************************************************/
643 static void show_main_buttons(void)
647 if ((p = cgi_user_name()) && strcmp(p, "root")) {
648 printf(_("Logged in as <b>%s</b>"), p);
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");
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");
664 image_link(_("Password Management"), "passwd", "images/passwd.gif");
669 /****************************************************************************
670 * Handle Display/Edit Mode CGI
671 ****************************************************************************/
672 static void ViewModeBoxes(int mode)
674 printf("<p>%s: \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: \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");
683 /****************************************************************************
684 display a welcome page
685 ****************************************************************************/
686 static void welcome_page(void)
688 if (file_exist("help/welcome.html")) {
689 include_html("help/welcome.html");
691 include_html("help/welcome-no-samba-doc.html");
695 /****************************************************************************
696 display the current smb.conf
697 ****************************************************************************/
698 static void viewconfig_page(void)
701 const char form_name[] = "viewconfig";
703 if (!verify_xsrf_token(form_name)) {
707 if (cgi_variable("full_view")) {
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);
717 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
719 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
723 write_config(stdout, full_view);
728 /****************************************************************************
729 second screen of the wizard ... Fetch Configuration Parameters
730 ****************************************************************************/
731 static void wizard_params_page(void)
733 unsigned int parm_filter = FLAG_WIZARD;
734 const char form_name[] = "wizard_params";
736 /* Here we first set and commit all the parameters that were selected
737 in the previous screen. */
739 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
741 if (!verify_xsrf_token(form_name)) {
745 if (cgi_variable("Commit")) {
746 commit_parameters(GLOBAL_SECTION_SNUM);
751 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
752 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
754 if (have_write_access) {
755 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
758 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
762 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
763 printf("</table>\n");
767 /****************************************************************************
768 Utility to just rewrite the smb.conf file - effectively just cleans it up
769 ****************************************************************************/
770 static void rewritecfg_file(void)
772 commit_parameters(GLOBAL_SECTION_SNUM);
774 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
777 /****************************************************************************
778 wizard to create/modify the smb.conf file
779 ****************************************************************************/
780 static void wizard_page(void)
782 /* Set some variables to collect data from smb.conf */
788 const char form_name[] = "wizard";
790 if (!verify_xsrf_token(form_name)) {
794 if (cgi_variable("Rewrite")) {
795 (void) rewritecfg_file();
799 if (cgi_variable("GetWizardParams")){
800 (void) wizard_params_page();
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"));
810 /* Plain text passwords are too badly broken - use encrypted passwords only */
811 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
815 /* Stand-alone Server */
816 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
817 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
821 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
822 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
825 /* Domain Controller */
826 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
827 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
830 switch ( winstype ) {
832 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
833 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
836 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
837 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
840 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
841 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
845 /* Have to create Homes share? */
846 if ((HomeExpo == 1) && (have_home == -1)) {
847 const char *unix_share = HOMES_NAME;
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);
859 /* Need to Delete Homes share? */
860 if ((HomeExpo == 0) && (have_home != -1)) {
861 lp_remove_service(have_home);
865 commit_parameters(GLOBAL_SECTION_SNUM);
870 /* Now determine smb.conf WINS settings */
871 if (lp_we_are_a_wins_server())
873 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
876 /* Do we have a homes share? */
877 have_home = lp_servicenumber(HOMES_NAME);
879 if ((winstype == 2) && lp_we_are_a_wins_server())
882 role = lp_server_role();
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);
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");
895 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
896 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
897 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
898 printf("</center>\n");
902 printf("<center><table border=0>");
903 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
904 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
905 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
906 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
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"));
911 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
912 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
913 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
914 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
916 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
918 /* Print out the list of wins servers */
919 if(lp_wins_server_list()) {
921 const char **wins_servers = lp_wins_server_list();
922 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
925 printf("\"></td></tr>\n");
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."));
930 printf("<tr><td><b>%s: </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");
935 /* Enable this when we are ready ....
936 * printf("<tr><td><b>%s: </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");
942 printf("</table></center>");
945 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
950 /****************************************************************************
951 display a globals editing page
952 ****************************************************************************/
953 static void globals_page(void)
955 unsigned int parm_filter = FLAG_BASIC;
957 const char form_name[] = "globals";
959 printf("<H2>%s</H2>\n", _("Global Parameters"));
961 if (!verify_xsrf_token(form_name)) {
965 if (cgi_variable("Commit")) {
966 commit_parameters(GLOBAL_SECTION_SNUM);
970 if ( cgi_variable("ViewMode") )
971 mode = atoi(cgi_variable_nonull("ViewMode"));
972 if ( cgi_variable("BasicMode"))
974 if ( cgi_variable("AdvMode"))
978 printf("<form name=\"swatform\" method=post action=globals>\n");
979 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
981 ViewModeBoxes( mode );
984 parm_filter = FLAG_BASIC;
987 parm_filter = FLAG_ADVANCED;
991 if (have_write_access) {
992 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
993 _("Commit Changes"));
996 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
1000 printf("<table>\n");
1001 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
1002 printf("</table>\n");
1003 printf("</form>\n");
1006 /****************************************************************************
1007 display a shares editing page. share is in unix codepage,
1008 ****************************************************************************/
1009 static void shares_page(void)
1011 const char *share = cgi_variable("share");
1017 unsigned int parm_filter = FLAG_BASIC;
1018 size_t converted_size;
1019 const char form_name[] = "shares";
1021 printf("<H2>%s</H2>\n", _("Share Parameters"));
1023 if (!verify_xsrf_token(form_name)) {
1028 snum = lp_servicenumber(share);
1031 if (cgi_variable("Commit") && snum >= 0) {
1032 commit_parameters(snum);
1034 snum = lp_servicenumber(share);
1037 if (cgi_variable("Delete") && snum >= 0) {
1038 lp_remove_service(snum);
1044 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1045 snum = lp_servicenumber(share);
1048 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1049 snum = lp_servicenumber(share);
1051 snum = lp_servicenumber(share);
1055 if ( cgi_variable("ViewMode") )
1056 mode = atoi(cgi_variable_nonull("ViewMode"));
1057 if ( cgi_variable("BasicMode"))
1059 if ( cgi_variable("AdvMode"))
1063 printf("<FORM name=\"swatform\" method=post>\n");
1064 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1066 printf("<table>\n");
1068 ViewModeBoxes( mode );
1071 parm_filter = FLAG_BASIC;
1074 parm_filter = FLAG_ADVANCED;
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");
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":"",
1089 TALLOC_FREE(utf8_s);
1092 printf("</select></td>\n");
1093 if (have_write_access) {
1094 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1099 if (have_write_access) {
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");
1108 if (have_write_access) {
1109 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1112 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1117 printf("<table>\n");
1118 show_parameters(snum, 1, parm_filter, 0);
1119 printf("</table>\n");
1122 printf("</FORM>\n");
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,
1133 char *err_str = NULL;
1134 char *msg_str = NULL;
1137 printf("%s\n<p>", _("password change in demo mode rejected"));
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);
1147 return NT_STATUS_IS_OK(ret);
1150 if(!initialize_password_db(True, NULL)) {
1151 printf("%s\n<p>", _("Can't setup password database vectors."));
1155 ret = local_password_change(user_name, local_flags, new_passwd,
1156 &err_str, &msg_str);
1159 printf("%s\n<p>", msg_str);
1161 printf("%s\n<p>", err_str);
1165 return NT_STATUS_IS_OK(ret);
1168 /****************************************************************************
1169 do the stuff required to add or change a password
1170 ****************************************************************************/
1171 static void chg_passwd(void)
1175 int local_flags = 0;
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\" "));
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
1187 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1190 * If current user is not root, make sure old password has been specified
1191 * If REMOTE change, even root must provide old password
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\" "));
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\" "));
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\" "));
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 "));
1219 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1220 host = cgi_variable(RHOST);
1221 } else if (am_root()) {
1228 * Set up the local flags.
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);
1238 rslt = change_password(host,
1239 cgi_variable_nonull(SWAT_USER),
1240 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1243 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1246 printf("%s\n", _(" The passwd has been changed."));
1248 printf("%s\n", _(" The passwd has NOT been changed."));
1255 /****************************************************************************
1256 display a password editing page
1257 ****************************************************************************/
1258 static void passwd_page(void)
1260 const char *new_name = cgi_user_name();
1261 const char passwd_form[] = "passwd";
1262 const char rpasswd_form[] = "rpasswd";
1264 if (!new_name) new_name = "";
1266 printf("<H2>%s</H2>\n", _("Server Password Management"));
1268 printf("<FORM name=\"swatform\" method=post>\n");
1269 print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
1271 printf("<table>\n");
1274 * Create all the dialog boxes for data collection
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);
1279 printf("<tr><td> %s : </td>\n", _("Old Password"));
1280 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1282 printf("<tr><td> %s : </td>\n", _("New Password"));
1283 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1284 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1285 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1286 printf("</table>\n");
1289 * Create all the control buttons for requesting action
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"));
1303 printf("<p></FORM>\n");
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)))) {
1315 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1317 printf("<FORM name=\"swatform\" method=post>\n");
1318 print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
1320 printf("<table>\n");
1323 * Create all the dialog boxes for data collection
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);
1339 * Create all the control buttons for requesting action
1341 printf("<input type=submit name=%s value=\"%s\">",
1342 CHG_R_PASSWD_FLAG, _("Change Password"));
1344 printf("<p></FORM>\n");
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)) {
1357 /****************************************************************************
1358 display a printers editing page
1359 ****************************************************************************/
1360 static void printers_page(void)
1362 const char *share = cgi_variable("share");
1367 unsigned int parm_filter = FLAG_BASIC;
1368 const char form_name[] = "printers";
1370 if (!verify_xsrf_token(form_name)) {
1375 snum = lp_servicenumber(share);
1377 if (cgi_variable("Commit") && snum >= 0) {
1378 commit_parameters(snum);
1379 if (snum >= iNumNonAutoPrintServices)
1383 snum = lp_servicenumber(share);
1386 if (cgi_variable("Delete") && snum >= 0) {
1387 lp_remove_service(snum);
1393 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1394 snum = lp_servicenumber(share);
1395 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1397 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1398 snum = lp_servicenumber(share);
1399 lp_do_parameter(snum, "print ok", "Yes");
1401 snum = lp_servicenumber(share);
1405 if ( cgi_variable("ViewMode") )
1406 mode = atoi(cgi_variable_nonull("ViewMode"));
1407 if ( cgi_variable("BasicMode"))
1409 if ( cgi_variable("AdvMode"))
1413 printf("<H2>%s</H2>\n", _("Printer Parameters"));
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."));
1422 printf("<FORM name=\"swatform\" method=post>\n");
1423 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1425 ViewModeBoxes( mode );
1428 parm_filter = FLAG_BASIC;
1431 parm_filter = FLAG_ADVANCED;
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":"",
1447 printf("<option %s value=\"%s\">%s\n",
1448 (share && strcmp(share,s)==0)?"SELECTED":"",
1452 printf("</select></td>");
1453 if (have_write_access) {
1454 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1457 printf("</table>\n");
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");
1468 if (have_write_access) {
1469 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1471 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1476 printf("<table>\n");
1477 show_parameters(snum, 1, parm_filter, 1);
1478 printf("</table>\n");
1480 printf("</FORM>\n");
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
1490 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1495 msgstr = lang_msg(msgid);
1500 ret = talloc_strdup(ctx, msgstr);
1502 lang_msg_free(msgstr);
1511 * main function for SWAT.
1513 int main(int argc, char *argv[])
1517 struct poptOption long_options[] = {
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" },
1524 TALLOC_CTX *frame = talloc_stackframe();
1527 umask(S_IWGRP | S_IWOTH);
1529 #if defined(HAVE_SET_AUTH_PARAMETERS)
1530 set_auth_parameters(argc, argv);
1531 #endif /* HAVE_SET_AUTH_PARAMETERS */
1533 /* just in case it goes wild ... */
1538 /* we don't want any SIGPIPE messages */
1539 BlockSignals(True,SIGPIPE);
1541 debug_set_logfile("/dev/null");
1543 /* we don't want stderr screwing us up */
1545 open("/dev/null", O_WRONLY);
1546 setup_logging("swat", DEBUG_FILE);
1550 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1552 /* Parse command line options */
1554 while(poptGetNextOpt(pc) != -1) { }
1556 poptFreeContext(pc);
1558 /* This should set a more apporiate log file */
1562 iNumNonAutoPrintServices = lp_numservices();
1563 if (pcap_cache_loaded()) {
1564 load_printers(server_event_context(),
1565 server_messaging_context());
1568 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1572 cgi_load_variables();
1574 if (!file_exist(get_dyn_CONFIGFILE())) {
1575 have_read_access = True;
1576 have_write_access = True;
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);
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);
1587 show_main_buttons();
1589 page = cgi_pathinfo();
1591 /* Root gets full functionality */
1592 if (have_read_access && strcmp(page, "globals")==0) {
1594 } else if (have_read_access && strcmp(page,"shares")==0) {
1596 } else if (have_read_access && strcmp(page,"printers")==0) {
1598 } else if (have_read_access && strcmp(page,"status")==0) {
1600 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1602 } else if (strcmp(page,"passwd")==0) {
1604 } else if (have_read_access && strcmp(page,"wizard")==0) {
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) {