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 "web/swat_proto.h"
32 #include "../lib/crypto/md5.h"
34 static int demo_mode
= False
;
35 static int passwd_only
= False
;
36 static bool have_write_access
= False
;
37 static bool have_read_access
= False
;
38 static int iNumNonAutoPrintServices
= 0;
41 * Password Management Globals
43 #define SWAT_USER "username"
44 #define OLD_PSWD "old_passwd"
45 #define NEW_PSWD "new_passwd"
46 #define NEW2_PSWD "new2_passwd"
47 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
48 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
49 #define ADD_USER_FLAG "add_user_flag"
50 #define DELETE_USER_FLAG "delete_user_flag"
51 #define DISABLE_USER_FLAG "disable_user_flag"
52 #define ENABLE_USER_FLAG "enable_user_flag"
53 #define RHOST "remote_host"
54 #define XSRF_TOKEN "xsrf"
56 #define _(x) lang_msg_rotate(talloc_tos(),x)
58 /****************************************************************************
59 ****************************************************************************/
60 static int enum_index(int value
, const struct enum_list
*enumlist
)
63 for (i
=0;enumlist
[i
].name
;i
++)
64 if (value
== enumlist
[i
].value
) break;
68 static char *fix_backslash(const char *str
)
70 static char newstring
[1024];
74 if (*str
== '\\') {*p
++ = '\\';*p
++ = '\\';}
82 static const char *fix_quotes(TALLOC_CTX
*ctx
, const char *str
)
84 char *newstring
= NULL
;
87 int quote_len
= strlen(""");
89 /* Count the number of quotes. */
94 newstring_len
+= quote_len
;
100 newstring
= TALLOC_ARRAY(ctx
, char, newstring_len
);
104 for (p
= newstring
; *str
; str
++) {
106 strncpy( p
, """, quote_len
);
116 static char *stripspaceupper(const char *str
)
118 static char newstring
[1024];
122 if (*str
!= ' ') *p
++ = toupper_ascii(*str
);
129 static char *make_parm_name(const char *label
)
131 static char parmname
[1024];
135 if (*label
== ' ') *p
++ = '_';
143 void get_xsrf_token(const char *username
, const char *pass
,
144 const char *formname
, char token_str
[33])
146 struct MD5Context md5_ctx
;
151 ZERO_STRUCT(md5_ctx
);
154 MD5Update(&md5_ctx
, (uint8_t *)formname
, strlen(formname
));
155 if (username
!= NULL
) {
156 MD5Update(&md5_ctx
, (uint8_t *)username
, strlen(username
));
159 MD5Update(&md5_ctx
, (uint8_t *)pass
, strlen(pass
));
162 MD5Final(token
, &md5_ctx
);
164 for(i
= 0; i
< sizeof(token
); i
++) {
167 snprintf(tmp
, sizeof(tmp
), "%02x", token
[i
]);
168 strncat(token_str
, tmp
, sizeof(tmp
));
172 void print_xsrf_token(const char *username
, const char *pass
,
173 const char *formname
)
177 get_xsrf_token(username
, pass
, formname
, token
);
178 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
183 bool verify_xsrf_token(const char *formname
)
186 const char *username
= cgi_user_name();
187 const char *pass
= cgi_user_pass();
188 const char *token
= cgi_variable_nonull(XSRF_TOKEN
);
190 get_xsrf_token(username
, pass
, formname
, expected
);
191 return (strncmp(expected
, token
, sizeof(expected
)) == 0);
195 /****************************************************************************
196 include a lump of html in a page
197 ****************************************************************************/
198 static int include_html(const char *fname
)
204 fd
= web_open(fname
, O_RDONLY
, 0);
207 printf(_("ERROR: Can't open %s"), fname
);
212 while ((ret
= read(fd
, buf
, sizeof(buf
))) > 0) {
213 if (write(1, buf
, ret
) == -1) {
222 /****************************************************************************
223 start the page with standard stuff
224 ****************************************************************************/
225 static void print_header(void)
227 if (!cgi_waspost()) {
228 printf("Expires: 0\r\n");
230 printf("Content-type: text/html\r\n\r\n");
232 if (!include_html("include/header.html")) {
233 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
234 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
238 /* *******************************************************************
239 show parameter label with translated name in the following form
240 because showing original and translated label in one line looks
241 too long, and showing translated label only is unusable for
243 -------------------------------
244 HELP security [combo box][button]
246 -------------------------------
247 (capital words are translated by gettext.)
248 if no translation is available, then same form as original is
250 "i18n_translated_parm" class is used to change the color of the
251 translated parameter with CSS.
252 **************************************************************** */
253 static const char *get_parm_translated(TALLOC_CTX
*ctx
,
254 const char* pAnchor
, const char* pHelp
, const char* pLabel
)
256 const char *pTranslated
= _(pLabel
);
258 if(strcmp(pLabel
, pTranslated
) != 0) {
259 output
= talloc_asprintf(ctx
,
260 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
261 pAnchor
, pHelp
, pLabel
, pTranslated
);
264 output
= talloc_asprintf(ctx
,
265 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
266 pAnchor
, pHelp
, pLabel
);
269 /****************************************************************************
271 ****************************************************************************/
272 static void print_footer(void)
274 if (!include_html("include/footer.html")) {
275 printf("\n</BODY>\n</HTML>\n");
279 /****************************************************************************
280 display one editable parameter in a form
281 ****************************************************************************/
282 static void show_parameter(int snum
, struct parm_struct
*parm
)
285 void *ptr
= parm
->ptr
;
286 char *utf8_s1
, *utf8_s2
;
287 size_t converted_size
;
288 TALLOC_CTX
*ctx
= talloc_stackframe();
290 if (parm
->p_class
== P_LOCAL
&& snum
>= 0) {
291 ptr
= lp_local_ptr(snum
, ptr
);
294 printf("<tr><td>%s</td><td>", get_parm_translated(ctx
,
295 stripspaceupper(parm
->label
), _("Help"), parm
->label
));
296 switch (parm
->type
) {
298 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
299 make_parm_name(parm
->label
), *(char *)ptr
);
300 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
301 _("Set Default"), make_parm_name(parm
->label
),(char)(parm
->def
.cvalue
));
305 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
306 make_parm_name(parm
->label
));
307 if ((char ***)ptr
&& *(char ***)ptr
&& **(char ***)ptr
) {
308 char **list
= *(char ***)ptr
;
309 for (;*list
;list
++) {
310 /* enclose in HTML encoded quotes if the string contains a space */
311 if ( strchr_m(*list
, ' ') ) {
312 push_utf8_allocate(&utf8_s1
, *list
, &converted_size
);
313 push_utf8_allocate(&utf8_s2
, ((*(list
+1))?", ":""), &converted_size
);
314 printf(""%s"%s", utf8_s1
, utf8_s2
);
316 push_utf8_allocate(&utf8_s1
, *list
, &converted_size
);
317 push_utf8_allocate(&utf8_s2
, ((*(list
+1))?", ":""), &converted_size
);
318 printf("%s%s", utf8_s1
, utf8_s2
);
325 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
326 _("Set Default"), make_parm_name(parm
->label
));
327 if (parm
->def
.lvalue
) {
328 char **list
= (char **)(parm
->def
.lvalue
);
329 for (; *list
; list
++) {
330 /* enclose in HTML encoded quotes if the string contains a space */
331 if ( strchr_m(*list
, ' ') )
332 printf(""%s"%s", *list
, ((*(list
+1))?", ":""));
334 printf("%s%s", *list
, ((*(list
+1))?", ":""));
342 push_utf8_allocate(&utf8_s1
, *(char **)ptr
, &converted_size
);
343 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
344 make_parm_name(parm
->label
), fix_quotes(ctx
, utf8_s1
));
346 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
347 _("Set Default"), make_parm_name(parm
->label
),fix_backslash((char *)(parm
->def
.svalue
)));
351 printf("<select name=\"parm_%s\">",make_parm_name(parm
->label
));
352 printf("<option %s>Yes", (*(bool *)ptr
)?"selected":"");
353 printf("<option %s>No", (*(bool *)ptr
)?"":"selected");
355 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
356 _("Set Default"), make_parm_name(parm
->label
),(bool)(parm
->def
.bvalue
)?0:1);
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":"");
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
)?1:0);
369 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm
->label
), *(int *)ptr
);
370 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
371 _("Set Default"), make_parm_name(parm
->label
),(int)(parm
->def
.ivalue
));
376 o
= octal_string(*(int *)ptr
);
377 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
378 make_parm_name(parm
->label
), o
);
380 o
= octal_string((int)(parm
->def
.ivalue
));
381 printf("<input type=button value=\"%s\" "
382 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
383 _("Set Default"), make_parm_name(parm
->label
), o
);
389 printf("<select name=\"parm_%s\">",make_parm_name(parm
->label
));
390 for (i
=0;parm
->enum_list
[i
].name
;i
++) {
391 if (i
== 0 || parm
->enum_list
[i
].value
!= parm
->enum_list
[i
-1].value
) {
392 printf("<option %s>%s",(*(int *)ptr
)==parm
->enum_list
[i
].value
?"selected":"",parm
->enum_list
[i
].name
);
396 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
397 _("Set Default"), make_parm_name(parm
->label
),enum_index((int)(parm
->def
.ivalue
),parm
->enum_list
));
402 printf("</td></tr>\n");
406 /****************************************************************************
407 display a set of parameters for a service
408 ****************************************************************************/
409 static void show_parameters(int snum
, int allparameters
, unsigned int parm_filter
, int printers
)
412 struct parm_struct
*parm
;
413 const char *heading
= NULL
;
414 const char *last_heading
= NULL
;
416 while ((parm
= lp_next_parameter(snum
, &i
, allparameters
))) {
417 if (snum
< 0 && parm
->p_class
== P_LOCAL
&& !(parm
->flags
& FLAG_GLOBAL
))
419 if (parm
->p_class
== P_SEPARATOR
) {
420 heading
= parm
->label
;
423 if (parm
->flags
& FLAG_HIDE
) continue;
425 if (printers
& !(parm
->flags
& FLAG_PRINT
)) continue;
426 if (!printers
& !(parm
->flags
& FLAG_SHARE
)) continue;
429 if (!( parm_filter
& FLAG_ADVANCED
)) {
430 if (!(parm
->flags
& FLAG_BASIC
)) {
431 void *ptr
= parm
->ptr
;
433 if (parm
->p_class
== P_LOCAL
&& snum
>= 0) {
434 ptr
= lp_local_ptr(snum
, ptr
);
437 switch (parm
->type
) {
439 if (*(char *)ptr
== (char)(parm
->def
.cvalue
)) continue;
443 if (!str_list_compare(*(char ***)ptr
, (char **)(parm
->def
.lvalue
))) continue;
448 if (!strcmp(*(char **)ptr
,(char *)(parm
->def
.svalue
))) continue;
453 if (*(bool *)ptr
== (bool)(parm
->def
.bvalue
)) continue;
458 if (*(int *)ptr
== (int)(parm
->def
.ivalue
)) continue;
463 if (*(int *)ptr
== (int)(parm
->def
.ivalue
)) continue;
469 if (printers
&& !(parm
->flags
& FLAG_PRINT
)) continue;
472 if ((parm_filter
& FLAG_WIZARD
) && !(parm
->flags
& FLAG_WIZARD
)) continue;
474 if ((parm_filter
& FLAG_ADVANCED
) && !(parm
->flags
& FLAG_ADVANCED
)) continue;
476 if (heading
&& heading
!= last_heading
) {
477 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading
));
478 last_heading
= heading
;
480 show_parameter(snum
, parm
);
484 /****************************************************************************
485 load the smb.conf file into loadparm.
486 ****************************************************************************/
487 static bool load_config(bool save_def
)
489 return lp_load(get_dyn_CONFIGFILE(),False
,save_def
,False
,True
);
492 /****************************************************************************
494 ****************************************************************************/
495 static void write_config(FILE *f
, bool show_defaults
)
497 TALLOC_CTX
*ctx
= talloc_stackframe();
499 fprintf(f
, "# Samba config file created using SWAT\n");
500 fprintf(f
, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
501 fprintf(f
, "# Date: %s\n\n", current_timestring(ctx
, False
));
503 lp_dump(f
, show_defaults
, iNumNonAutoPrintServices
);
508 /****************************************************************************
509 save and reload the smb.conf config file
510 ****************************************************************************/
511 static int save_reload(int snum
)
516 f
= sys_fopen(get_dyn_CONFIGFILE(),"w");
518 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
523 /* just in case they have used the buggy xinetd to create the file */
524 if (fstat(fileno(f
), &st
) == 0 &&
525 (st
.st_mode
& S_IWOTH
)) {
526 #if defined HAVE_FCHMOD
527 fchmod(fileno(f
), S_IWUSR
| S_IRUSR
| S_IRGRP
| S_IROTH
);
529 chmod(get_dyn_CONFIGFILE(), S_IWUSR
| S_IRUSR
| S_IRGRP
| S_IROTH
);
533 write_config(f
, False
);
535 lp_dump_one(f
, False
, snum
);
538 lp_kill_all_services();
540 if (!load_config(False
)) {
541 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
545 iNumNonAutoPrintServices
= lp_numservices();
551 /****************************************************************************
553 ****************************************************************************/
554 static void commit_parameter(int snum
, struct parm_struct
*parm
, const char *v
)
559 if (snum
< 0 && parm
->p_class
== P_LOCAL
) {
560 /* this handles the case where we are changing a local
561 variable globally. We need to change the parameter in
562 all shares where it is currently set to the default */
563 for (i
=0;i
<lp_numservices();i
++) {
564 s
= lp_servicename(i
);
565 if (s
&& (*s
) && lp_is_default(i
, parm
)) {
566 lp_do_parameter(i
, parm
->label
, v
);
571 lp_do_parameter(snum
, parm
->label
, v
);
574 /****************************************************************************
575 commit a set of parameters for a service
576 ****************************************************************************/
577 static void commit_parameters(int snum
)
580 struct parm_struct
*parm
;
584 while ((parm
= lp_next_parameter(snum
, &i
, 1))) {
585 if (asprintf(&label
, "parm_%s", make_parm_name(parm
->label
)) > 0) {
586 if ((v
= cgi_variable(label
)) != NULL
) {
587 if (parm
->flags
& FLAG_HIDE
)
589 commit_parameter(snum
, parm
, v
);
596 /****************************************************************************
597 spit out the html for a link with an image
598 ****************************************************************************/
599 static void image_link(const char *name
, const char *hlink
, const char *src
)
601 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
602 cgi_baseurl(), hlink
, src
, name
);
605 /****************************************************************************
606 display the main navigation controls at the top of each page along
608 ****************************************************************************/
609 static void show_main_buttons(void)
613 if ((p
= cgi_user_name()) && strcmp(p
, "root")) {
614 printf(_("Logged in as <b>%s</b>"), p
);
618 image_link(_("Home"), "", "images/home.gif");
619 if (have_write_access
) {
620 image_link(_("Globals"), "globals", "images/globals.gif");
621 image_link(_("Shares"), "shares", "images/shares.gif");
622 image_link(_("Printers"), "printers", "images/printers.gif");
623 image_link(_("Wizard"), "wizard", "images/wizard.gif");
625 /* root always gets all buttons, otherwise look for -P */
626 if ( have_write_access
|| (!passwd_only
&& have_read_access
) ) {
627 image_link(_("Status"), "status", "images/status.gif");
628 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
630 image_link(_("Password Management"), "passwd", "images/passwd.gif");
635 /****************************************************************************
636 * Handle Display/Edit Mode CGI
637 ****************************************************************************/
638 static void ViewModeBoxes(int mode
)
640 printf("<p>%s: \n", _("Current View Is"));
641 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode
== 0) ? "checked" : ""), _("Basic"));
642 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode
== 1) ? "checked" : ""), _("Advanced"));
643 printf("<br>%s: \n", _("Change View To"));
644 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
645 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
646 printf("</p><br>\n");
649 /****************************************************************************
650 display a welcome page
651 ****************************************************************************/
652 static void welcome_page(void)
654 if (file_exist("help/welcome.html", NULL
)) {
655 include_html("help/welcome.html");
657 include_html("help/welcome-no-samba-doc.html");
661 /****************************************************************************
662 display the current smb.conf
663 ****************************************************************************/
664 static void viewconfig_page(void)
667 const char form_name
[] = "viewconfig";
669 if (!verify_xsrf_token(form_name
)) {
673 if (cgi_variable("full_view")) {
678 printf("<H2>%s</H2>\n", _("Current Config"));
679 printf("<form method=post>\n");
680 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name
);
683 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
685 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
689 write_config(stdout
, full_view
);
694 /****************************************************************************
695 second screen of the wizard ... Fetch Configuration Parameters
696 ****************************************************************************/
697 static void wizard_params_page(void)
699 unsigned int parm_filter
= FLAG_WIZARD
;
700 const char form_name
[] = "wizard_params";
702 /* Here we first set and commit all the parameters that were selected
703 in the previous screen. */
705 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
707 if (!verify_xsrf_token(form_name
)) {
711 if (cgi_variable("Commit")) {
712 commit_parameters(GLOBAL_SECTION_SNUM
);
717 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
718 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name
);
720 if (have_write_access
) {
721 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
724 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
728 show_parameters(GLOBAL_SECTION_SNUM
, 1, parm_filter
, 0);
729 printf("</table>\n");
733 /****************************************************************************
734 Utility to just rewrite the smb.conf file - effectively just cleans it up
735 ****************************************************************************/
736 static void rewritecfg_file(void)
738 commit_parameters(GLOBAL_SECTION_SNUM
);
740 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
743 /****************************************************************************
744 wizard to create/modify the smb.conf file
745 ****************************************************************************/
746 static void wizard_page(void)
748 /* Set some variables to collect data from smb.conf */
754 const char form_name
[] = "wizard";
756 if (!verify_xsrf_token(form_name
)) {
760 if (cgi_variable("Rewrite")) {
761 (void) rewritecfg_file();
765 if (cgi_variable("GetWizardParams")){
766 (void) wizard_params_page();
770 if (cgi_variable("Commit")){
771 SerType
= atoi(cgi_variable_nonull("ServerType"));
772 winstype
= atoi(cgi_variable_nonull("WINSType"));
773 have_home
= lp_servicenumber(HOMES_NAME
);
774 HomeExpo
= atoi(cgi_variable_nonull("HomeExpo"));
776 /* Plain text passwords are too badly broken - use encrypted passwords only */
777 lp_do_parameter( GLOBAL_SECTION_SNUM
, "encrypt passwords", "Yes");
781 /* Stand-alone Server */
782 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "USER" );
783 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "No" );
787 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "DOMAIN" );
788 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "No" );
791 /* Domain Controller */
792 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "USER" );
793 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "Yes" );
796 switch ( winstype
) {
798 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "No" );
799 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", "" );
802 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "Yes" );
803 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", "" );
806 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "No" );
807 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", cgi_variable_nonull("WINSAddr"));
811 /* Have to create Homes share? */
812 if ((HomeExpo
== 1) && (have_home
== -1)) {
813 const char *unix_share
= HOMES_NAME
;
816 lp_copy_service(GLOBAL_SECTION_SNUM
, unix_share
);
817 have_home
= lp_servicenumber(HOMES_NAME
);
818 lp_do_parameter( have_home
, "read only", "No");
819 lp_do_parameter( have_home
, "valid users", "%S");
820 lp_do_parameter( have_home
, "browseable", "No");
821 commit_parameters(have_home
);
822 save_reload(have_home
);
825 /* Need to Delete Homes share? */
826 if ((HomeExpo
== 0) && (have_home
!= -1)) {
827 lp_remove_service(have_home
);
831 commit_parameters(GLOBAL_SECTION_SNUM
);
836 /* Now determine smb.conf WINS settings */
837 if (lp_wins_support())
839 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
842 /* Do we have a homes share? */
843 have_home
= lp_servicenumber(HOMES_NAME
);
845 if ((winstype
== 2) && lp_wins_support())
848 role
= lp_server_role();
852 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
853 printf("<form method=post action=wizard>\n");
854 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name
);
856 if (have_write_access
) {
857 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
858 printf("%s", _("The same will happen if you press the commit button."));
859 printf("<br><br>\n");
861 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
862 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
863 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
864 printf("</center>\n");
868 printf("<center><table border=0>");
869 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
870 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role
== ROLE_STANDALONE
) ? "checked" : ""), _("Stand Alone"));
871 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role
== ROLE_DOMAIN_MEMBER
) ? "checked" : ""), _("Domain Member"));
872 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role
== ROLE_DOMAIN_PDC
) ? "checked" : ""), _("Domain Controller"));
874 if (role
== ROLE_DOMAIN_BDC
) {
875 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
877 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
878 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype
== 0) ? "checked" : ""), _("Not Used"));
879 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype
== 1) ? "checked" : ""), _("Server for client use"));
880 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype
== 2) ? "checked" : ""), _("Client of another WINS server"));
882 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
884 /* Print out the list of wins servers */
885 if(lp_wins_server_list()) {
887 const char **wins_servers
= lp_wins_server_list();
888 for(i
= 0; wins_servers
[i
]; i
++) printf("%s ", wins_servers
[i
]);
891 printf("\"></td></tr>\n");
893 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"));
894 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
896 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
897 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home
== -1) ? "" : "checked ");
898 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home
== -1 ) ? "checked" : "");
899 printf("<td></td></tr>\n");
901 /* Enable this when we are ready ....
902 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
903 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
904 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
905 * printf("<td></td></tr>\n");
908 printf("</table></center>");
911 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
916 /****************************************************************************
917 display a globals editing page
918 ****************************************************************************/
919 static void globals_page(void)
921 unsigned int parm_filter
= FLAG_BASIC
;
923 const char form_name
[] = "globals";
925 printf("<H2>%s</H2>\n", _("Global Parameters"));
927 if (!verify_xsrf_token(form_name
)) {
931 if (cgi_variable("Commit")) {
932 commit_parameters(GLOBAL_SECTION_SNUM
);
936 if ( cgi_variable("ViewMode") )
937 mode
= atoi(cgi_variable_nonull("ViewMode"));
938 if ( cgi_variable("BasicMode"))
940 if ( cgi_variable("AdvMode"))
944 printf("<form name=\"swatform\" method=post action=globals>\n");
945 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name
);
947 ViewModeBoxes( mode
);
950 parm_filter
= FLAG_BASIC
;
953 parm_filter
= FLAG_ADVANCED
;
957 if (have_write_access
) {
958 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
959 _("Commit Changes"));
962 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
967 show_parameters(GLOBAL_SECTION_SNUM
, 1, parm_filter
, 0);
968 printf("</table>\n");
972 /****************************************************************************
973 display a shares editing page. share is in unix codepage,
974 ****************************************************************************/
975 static void shares_page(void)
977 const char *share
= cgi_variable("share");
983 unsigned int parm_filter
= FLAG_BASIC
;
984 size_t converted_size
;
985 const char form_name
[] = "shares";
987 printf("<H2>%s</H2>\n", _("Share Parameters"));
989 if (!verify_xsrf_token(form_name
)) {
994 snum
= lp_servicenumber(share
);
997 if (cgi_variable("Commit") && snum
>= 0) {
998 commit_parameters(snum
);
1000 snum
= lp_servicenumber(share
);
1003 if (cgi_variable("Delete") && snum
>= 0) {
1004 lp_remove_service(snum
);
1010 if (cgi_variable("createshare") && (share
=cgi_variable("newshare"))) {
1011 snum
= lp_servicenumber(share
);
1014 lp_copy_service(GLOBAL_SECTION_SNUM
, share
);
1015 snum
= lp_servicenumber(share
);
1017 snum
= lp_servicenumber(share
);
1021 if ( cgi_variable("ViewMode") )
1022 mode
= atoi(cgi_variable_nonull("ViewMode"));
1023 if ( cgi_variable("BasicMode"))
1025 if ( cgi_variable("AdvMode"))
1029 printf("<FORM name=\"swatform\" method=post>\n");
1030 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name
);
1032 printf("<table>\n");
1034 ViewModeBoxes( mode
);
1037 parm_filter
= FLAG_BASIC
;
1040 parm_filter
= FLAG_ADVANCED
;
1043 printf("<br><tr>\n");
1044 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1045 printf("<td><select name=share>\n");
1047 printf("<option value=\" \"> \n");
1048 for (i
=0;i
<lp_numservices();i
++) {
1049 s
= lp_servicename(i
);
1050 if (s
&& (*s
) && strcmp(s
,"IPC$") && !lp_print_ok(i
)) {
1051 push_utf8_allocate(&utf8_s
, s
, &converted_size
);
1052 printf("<option %s value=\"%s\">%s\n",
1053 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
1058 printf("</select></td>\n");
1059 if (have_write_access
) {
1060 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1065 if (have_write_access
) {
1067 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1068 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1074 if (have_write_access
) {
1075 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1078 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1083 printf("<table>\n");
1084 show_parameters(snum
, 1, parm_filter
, 0);
1085 printf("</table>\n");
1088 printf("</FORM>\n");
1091 /*************************************************************
1092 change a password either locally or remotely
1093 *************************************************************/
1094 static bool change_password(const char *remote_machine
, const char *user_name
,
1095 const char *old_passwd
, const char *new_passwd
,
1099 char *err_str
= NULL
;
1100 char *msg_str
= NULL
;
1103 printf("%s\n<p>", _("password change in demo mode rejected"));
1107 if (remote_machine
!= NULL
) {
1108 ret
= remote_password_change(remote_machine
, user_name
,
1109 old_passwd
, new_passwd
, &err_str
);
1110 if (err_str
!= NULL
)
1111 printf("%s\n<p>", err_str
);
1113 return NT_STATUS_IS_OK(ret
);
1116 if(!initialize_password_db(True
, NULL
)) {
1117 printf("%s\n<p>", _("Can't setup password database vectors."));
1121 ret
= local_password_change(user_name
, local_flags
, new_passwd
,
1122 &err_str
, &msg_str
);
1125 printf("%s\n<p>", msg_str
);
1127 printf("%s\n<p>", err_str
);
1131 return NT_STATUS_IS_OK(ret
);
1134 /****************************************************************************
1135 do the stuff required to add or change a password
1136 ****************************************************************************/
1137 static void chg_passwd(void)
1141 int local_flags
= 0;
1143 /* Make sure users name has been specified */
1144 if (strlen(cgi_variable_nonull(SWAT_USER
)) == 0) {
1145 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1150 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1151 * so if that's what we're doing, skip the rest of the checks
1153 if (!cgi_variable(DISABLE_USER_FLAG
) && !cgi_variable(ENABLE_USER_FLAG
) && !cgi_variable(DELETE_USER_FLAG
)) {
1156 * If current user is not root, make sure old password has been specified
1157 * If REMOTE change, even root must provide old password
1159 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD
)) <= 0)) ||
1160 ((cgi_variable(CHG_R_PASSWD_FLAG
)) && (strlen( cgi_variable_nonull(OLD_PSWD
)) <= 0))) {
1161 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1165 /* If changing a users password on a remote hosts we have to know what host */
1166 if ((cgi_variable(CHG_R_PASSWD_FLAG
)) && (strlen( cgi_variable_nonull(RHOST
)) <= 0)) {
1167 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1171 /* Make sure new passwords have been specified */
1172 if ((strlen( cgi_variable_nonull(NEW_PSWD
)) <= 0) ||
1173 (strlen( cgi_variable_nonull(NEW2_PSWD
)) <= 0)) {
1174 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1178 /* Make sure new passwords was typed correctly twice */
1179 if (strcmp(cgi_variable_nonull(NEW_PSWD
), cgi_variable_nonull(NEW2_PSWD
)) != 0) {
1180 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1185 if (cgi_variable(CHG_R_PASSWD_FLAG
)) {
1186 host
= cgi_variable(RHOST
);
1187 } else if (am_root()) {
1194 * Set up the local flags.
1197 local_flags
|= (cgi_variable(ADD_USER_FLAG
) ? LOCAL_ADD_USER
: 0);
1198 local_flags
|= (cgi_variable(ADD_USER_FLAG
) ? LOCAL_SET_PASSWORD
: 0);
1199 local_flags
|= (cgi_variable(CHG_S_PASSWD_FLAG
) ? LOCAL_SET_PASSWORD
: 0);
1200 local_flags
|= (cgi_variable(DELETE_USER_FLAG
) ? LOCAL_DELETE_USER
: 0);
1201 local_flags
|= (cgi_variable(ENABLE_USER_FLAG
) ? LOCAL_ENABLE_USER
: 0);
1202 local_flags
|= (cgi_variable(DISABLE_USER_FLAG
) ? LOCAL_DISABLE_USER
: 0);
1205 rslt
= change_password(host
,
1206 cgi_variable_nonull(SWAT_USER
),
1207 cgi_variable_nonull(OLD_PSWD
), cgi_variable_nonull(NEW_PSWD
),
1210 if(cgi_variable(CHG_S_PASSWD_FLAG
)) {
1213 printf("%s\n", _(" The passwd has been changed."));
1215 printf("%s\n", _(" The passwd for has NOT been changed."));
1222 /****************************************************************************
1223 display a password editing page
1224 ****************************************************************************/
1225 static void passwd_page(void)
1227 const char *new_name
= cgi_user_name();
1229 if (!new_name
) new_name
= "";
1231 printf("<H2>%s</H2>\n", _("Server Password Management"));
1233 printf("<FORM name=\"swatform\" method=post>\n");
1235 printf("<table>\n");
1238 * Create all the dialog boxes for data collection
1240 printf("<tr><td> %s : </td>\n", _("User Name"));
1241 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER
, new_name
);
1243 printf("<tr><td> %s : </td>\n", _("Old Password"));
1244 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD
);
1246 printf("<tr><td> %s : </td>\n", _("New Password"));
1247 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD
);
1248 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1249 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD
);
1250 printf("</table>\n");
1253 * Create all the control buttons for requesting action
1255 printf("<input type=submit name=%s value=\"%s\">\n",
1256 CHG_S_PASSWD_FLAG
, _("Change Password"));
1257 if (demo_mode
|| am_root()) {
1258 printf("<input type=submit name=%s value=\"%s\">\n",
1259 ADD_USER_FLAG
, _("Add New User"));
1260 printf("<input type=submit name=%s value=\"%s\">\n",
1261 DELETE_USER_FLAG
, _("Delete User"));
1262 printf("<input type=submit name=%s value=\"%s\">\n",
1263 DISABLE_USER_FLAG
, _("Disable User"));
1264 printf("<input type=submit name=%s value=\"%s\">\n",
1265 ENABLE_USER_FLAG
, _("Enable User"));
1267 printf("<p></FORM>\n");
1270 * Do some work if change, add, disable or enable was
1271 * requested. It could be this is the first time through this
1272 * code, so there isn't anything to do. */
1273 if ((cgi_variable(CHG_S_PASSWD_FLAG
)) || (cgi_variable(ADD_USER_FLAG
)) || (cgi_variable(DELETE_USER_FLAG
)) ||
1274 (cgi_variable(DISABLE_USER_FLAG
)) || (cgi_variable(ENABLE_USER_FLAG
))) {
1278 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1280 printf("<FORM name=\"swatform\" method=post>\n");
1282 printf("<table>\n");
1285 * Create all the dialog boxes for data collection
1287 printf("<tr><td> %s : </td>\n", _("User Name"));
1288 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER
, new_name
);
1289 printf("<tr><td> %s : </td>\n", _("Old Password"));
1290 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD
);
1291 printf("<tr><td> %s : </td>\n", _("New Password"));
1292 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD
);
1293 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1294 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD
);
1295 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1296 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST
);
1301 * Create all the control buttons for requesting action
1303 printf("<input type=submit name=%s value=\"%s\">",
1304 CHG_R_PASSWD_FLAG
, _("Change Password"));
1306 printf("<p></FORM>\n");
1309 * Do some work if a request has been made to change the
1310 * password somewhere other than the server. It could be this
1311 * is the first time through this code, so there isn't
1312 * anything to do. */
1313 if (cgi_variable(CHG_R_PASSWD_FLAG
)) {
1319 /****************************************************************************
1320 display a printers editing page
1321 ****************************************************************************/
1322 static void printers_page(void)
1324 const char *share
= cgi_variable("share");
1329 unsigned int parm_filter
= FLAG_BASIC
;
1332 snum
= lp_servicenumber(share
);
1334 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1336 printf("<H3>%s</H3>\n", _("Important Note:"));
1337 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1338 printf("%s",_("are autoloaded printers from "));
1339 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1340 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1342 if (cgi_variable("Commit") && snum
>= 0) {
1343 commit_parameters(snum
);
1344 if (snum
>= iNumNonAutoPrintServices
)
1348 snum
= lp_servicenumber(share
);
1351 if (cgi_variable("Delete") && snum
>= 0) {
1352 lp_remove_service(snum
);
1358 if (cgi_variable("createshare") && (share
=cgi_variable("newshare"))) {
1359 snum
= lp_servicenumber(share
);
1360 if (snum
< 0 || snum
>= iNumNonAutoPrintServices
) {
1362 lp_copy_service(GLOBAL_SECTION_SNUM
, share
);
1363 snum
= lp_servicenumber(share
);
1364 lp_do_parameter(snum
, "print ok", "Yes");
1366 snum
= lp_servicenumber(share
);
1370 printf("<FORM name=\"swatform\" method=post>\n");
1372 if ( cgi_variable("ViewMode") )
1373 mode
= atoi(cgi_variable_nonull("ViewMode"));
1374 if ( cgi_variable("BasicMode"))
1376 if ( cgi_variable("AdvMode"))
1379 ViewModeBoxes( mode
);
1382 parm_filter
= FLAG_BASIC
;
1385 parm_filter
= FLAG_ADVANCED
;
1388 printf("<table>\n");
1389 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1390 printf("<td><select name=\"share\">\n");
1391 if (snum
< 0 || !lp_print_ok(snum
))
1392 printf("<option value=\" \"> \n");
1393 for (i
=0;i
<lp_numservices();i
++) {
1394 s
= lp_servicename(i
);
1395 if (s
&& (*s
) && strcmp(s
,"IPC$") && lp_print_ok(i
)) {
1396 if (i
>= iNumNonAutoPrintServices
)
1397 printf("<option %s value=\"%s\">[*]%s\n",
1398 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
1401 printf("<option %s value=\"%s\">%s\n",
1402 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
1406 printf("</select></td>");
1407 if (have_write_access
) {
1408 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1411 printf("</table>\n");
1413 if (have_write_access
) {
1414 printf("<table>\n");
1415 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1416 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1422 if (have_write_access
) {
1423 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1425 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1430 printf("<table>\n");
1431 show_parameters(snum
, 1, parm_filter
, 1);
1432 printf("</table>\n");
1434 printf("</FORM>\n");
1438 when the _() translation macro is used there is no obvious place to free
1439 the resulting string and there is no easy way to give a static pointer.
1440 All we can do is rotate between some static buffers and hope a single d_printf()
1441 doesn't have more calls to _() than the number of buffers
1444 const char *lang_msg_rotate(TALLOC_CTX
*ctx
, const char *msgid
)
1449 msgstr
= lang_msg(msgid
);
1454 ret
= talloc_strdup(ctx
, msgstr
);
1456 lang_msg_free(msgstr
);
1465 * main function for SWAT.
1467 int main(int argc
, char *argv
[])
1471 struct poptOption long_options
[] = {
1473 { "disable-authentication", 'a', POPT_ARG_VAL
, &demo_mode
, True
, "Disable authentication (demo mode)" },
1474 { "password-menu-only", 'P', POPT_ARG_VAL
, &passwd_only
, True
, "Show only change password menu" },
1478 TALLOC_CTX
*frame
= talloc_stackframe();
1481 umask(S_IWGRP
| S_IWOTH
);
1483 #if defined(HAVE_SET_AUTH_PARAMETERS)
1484 set_auth_parameters(argc
, argv
);
1485 #endif /* HAVE_SET_AUTH_PARAMETERS */
1487 /* just in case it goes wild ... */
1492 /* we don't want any SIGPIPE messages */
1493 BlockSignals(True
,SIGPIPE
);
1495 dbf
= x_fopen("/dev/null", O_WRONLY
, 0);
1496 if (!dbf
) dbf
= x_stderr
;
1498 /* we don't want stderr screwing us up */
1500 open("/dev/null", O_WRONLY
);
1502 pc
= poptGetContext("swat", argc
, (const char **) argv
, long_options
, 0);
1504 /* Parse command line options */
1506 while(poptGetNextOpt(pc
) != -1) { }
1508 poptFreeContext(pc
);
1512 setup_logging(argv
[0],False
);
1515 iNumNonAutoPrintServices
= lp_numservices();
1518 cgi_setup(get_dyn_SWATDIR(), !demo_mode
);
1522 cgi_load_variables();
1524 if (!file_exist(get_dyn_CONFIGFILE(), NULL
)) {
1525 have_read_access
= True
;
1526 have_write_access
= True
;
1528 /* check if the authenticated user has write access - if not then
1529 don't show write options */
1530 have_write_access
= (access(get_dyn_CONFIGFILE(),W_OK
) == 0);
1532 /* if the user doesn't have read access to smb.conf then
1533 don't let them view it */
1534 have_read_access
= (access(get_dyn_CONFIGFILE(),R_OK
) == 0);
1537 show_main_buttons();
1539 page
= cgi_pathinfo();
1541 /* Root gets full functionality */
1542 if (have_read_access
&& strcmp(page
, "globals")==0) {
1544 } else if (have_read_access
&& strcmp(page
,"shares")==0) {
1546 } else if (have_read_access
&& strcmp(page
,"printers")==0) {
1548 } else if (have_read_access
&& strcmp(page
,"status")==0) {
1550 } else if (have_read_access
&& strcmp(page
,"viewconfig")==0) {
1552 } else if (strcmp(page
,"passwd")==0) {
1554 } else if (have_read_access
&& strcmp(page
,"wizard")==0) {
1556 } else if (have_read_access
&& strcmp(page
,"wizard_params")==0) {
1557 wizard_params_page();
1558 } else if (have_read_access
&& strcmp(page
,"rewritecfg")==0) {