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"
33 static int demo_mode
= False
;
34 static int passwd_only
= False
;
35 static bool have_write_access
= False
;
36 static bool have_read_access
= False
;
37 static int iNumNonAutoPrintServices
= 0;
40 * Password Management Globals
42 #define SWAT_USER "username"
43 #define OLD_PSWD "old_passwd"
44 #define NEW_PSWD "new_passwd"
45 #define NEW2_PSWD "new2_passwd"
46 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
47 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
48 #define ADD_USER_FLAG "add_user_flag"
49 #define DELETE_USER_FLAG "delete_user_flag"
50 #define DISABLE_USER_FLAG "disable_user_flag"
51 #define ENABLE_USER_FLAG "enable_user_flag"
52 #define RHOST "remote_host"
54 #define _(x) lang_msg_rotate(talloc_tos(),x)
56 /****************************************************************************
57 ****************************************************************************/
58 static int enum_index(int value
, const struct enum_list
*enumlist
)
61 for (i
=0;enumlist
[i
].name
;i
++)
62 if (value
== enumlist
[i
].value
) break;
66 static char *fix_backslash(const char *str
)
68 static char newstring
[1024];
72 if (*str
== '\\') {*p
++ = '\\';*p
++ = '\\';}
80 static const char *fix_quotes(TALLOC_CTX
*ctx
, const char *str
)
82 char *newstring
= NULL
;
85 int quote_len
= strlen(""");
87 /* Count the number of quotes. */
91 newstring_len
+= quote_len
;
97 newstring
= TALLOC_ARRAY(ctx
, char, newstring_len
);
101 for (p
= newstring
; *str
; str
++) {
103 strncpy( p
, """, quote_len
);
114 static char *stripspaceupper(const char *str
)
116 static char newstring
[1024];
120 if (*str
!= ' ') *p
++ = toupper_ascii(*str
);
127 static char *make_parm_name(const char *label
)
129 static char parmname
[1024];
133 if (*label
== ' ') *p
++ = '_';
141 /****************************************************************************
142 include a lump of html in a page
143 ****************************************************************************/
144 static int include_html(const char *fname
)
150 fd
= web_open(fname
, O_RDONLY
, 0);
153 printf(_("ERROR: Can't open %s"), fname
);
158 while ((ret
= read(fd
, buf
, sizeof(buf
))) > 0) {
166 /****************************************************************************
167 start the page with standard stuff
168 ****************************************************************************/
169 static void print_header(void)
171 if (!cgi_waspost()) {
172 printf("Expires: 0\r\n");
174 printf("Content-type: text/html\r\n\r\n");
176 if (!include_html("include/header.html")) {
177 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
178 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
182 /* *******************************************************************
183 show parameter label with translated name in the following form
184 because showing original and translated label in one line looks
185 too long, and showing translated label only is unusable for
187 -------------------------------
188 HELP security [combo box][button]
190 -------------------------------
191 (capital words are translated by gettext.)
192 if no translation is available, then same form as original is
194 "i18n_translated_parm" class is used to change the color of the
195 translated parameter with CSS.
196 **************************************************************** */
197 static const char *get_parm_translated(TALLOC_CTX
*ctx
,
198 const char* pAnchor
, const char* pHelp
, const char* pLabel
)
200 const char *pTranslated
= _(pLabel
);
202 if(strcmp(pLabel
, pTranslated
) != 0) {
203 output
= talloc_asprintf(ctx
,
204 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
205 pAnchor
, pHelp
, pLabel
, pTranslated
);
208 output
= talloc_asprintf(ctx
,
209 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
210 pAnchor
, pHelp
, pLabel
);
213 /****************************************************************************
215 ****************************************************************************/
216 static void print_footer(void)
218 if (!include_html("include/footer.html")) {
219 printf("\n</BODY>\n</HTML>\n");
223 /****************************************************************************
224 display one editable parameter in a form
225 ****************************************************************************/
226 static void show_parameter(int snum
, struct parm_struct
*parm
)
229 void *ptr
= parm
->ptr
;
230 char *utf8_s1
, *utf8_s2
;
231 TALLOC_CTX
*ctx
= talloc_stackframe();
233 if (parm
->p_class
== P_LOCAL
&& snum
>= 0) {
234 ptr
= lp_local_ptr(snum
, ptr
);
237 printf("<tr><td>%s</td><td>", get_parm_translated(ctx
,
238 stripspaceupper(parm
->label
), _("Help"), parm
->label
));
239 switch (parm
->type
) {
241 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
242 make_parm_name(parm
->label
), *(char *)ptr
);
243 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
244 _("Set Default"), make_parm_name(parm
->label
),(char)(parm
->def
.cvalue
));
248 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
249 make_parm_name(parm
->label
));
250 if ((char ***)ptr
&& *(char ***)ptr
&& **(char ***)ptr
) {
251 char **list
= *(char ***)ptr
;
252 for (;*list
;list
++) {
253 /* enclose in HTML encoded quotes if the string contains a space */
254 if ( strchr_m(*list
, ' ') ) {
255 push_utf8_allocate(&utf8_s1
, *list
);
256 push_utf8_allocate(&utf8_s2
, ((*(list
+1))?", ":""));
257 printf(""%s"%s", utf8_s1
, utf8_s2
);
259 push_utf8_allocate(&utf8_s1
, *list
);
260 push_utf8_allocate(&utf8_s2
, ((*(list
+1))?", ":""));
261 printf("%s%s", utf8_s1
, utf8_s2
);
268 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
269 _("Set Default"), make_parm_name(parm
->label
));
270 if (parm
->def
.lvalue
) {
271 char **list
= (char **)(parm
->def
.lvalue
);
272 for (; *list
; list
++) {
273 /* enclose in HTML encoded quotes if the string contains a space */
274 if ( strchr_m(*list
, ' ') )
275 printf(""%s"%s", *list
, ((*(list
+1))?", ":""));
277 printf("%s%s", *list
, ((*(list
+1))?", ":""));
285 push_utf8_allocate(&utf8_s1
, *(char **)ptr
);
286 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
287 make_parm_name(parm
->label
), fix_quotes(ctx
, utf8_s1
));
289 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
290 _("Set Default"), make_parm_name(parm
->label
),fix_backslash((char *)(parm
->def
.svalue
)));
294 printf("<select name=\"parm_%s\">",make_parm_name(parm
->label
));
295 printf("<option %s>Yes", (*(bool *)ptr
)?"selected":"");
296 printf("<option %s>No", (*(bool *)ptr
)?"":"selected");
298 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
299 _("Set Default"), make_parm_name(parm
->label
),(bool)(parm
->def
.bvalue
)?0:1);
303 printf("<select name=\"parm_%s\">",make_parm_name(parm
->label
));
304 printf("<option %s>Yes", (*(bool *)ptr
)?"":"selected");
305 printf("<option %s>No", (*(bool *)ptr
)?"selected":"");
307 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
308 _("Set Default"), make_parm_name(parm
->label
),(bool)(parm
->def
.bvalue
)?1:0);
312 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm
->label
), *(int *)ptr
);
313 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
314 _("Set Default"), make_parm_name(parm
->label
),(int)(parm
->def
.ivalue
));
319 o
= octal_string(*(int *)ptr
);
320 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
321 make_parm_name(parm
->label
), o
);
323 o
= octal_string((int)(parm
->def
.ivalue
));
324 printf("<input type=button value=\"%s\" "
325 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
326 _("Set Default"), make_parm_name(parm
->label
), o
);
332 printf("<select name=\"parm_%s\">",make_parm_name(parm
->label
));
333 for (i
=0;parm
->enum_list
[i
].name
;i
++) {
334 if (i
== 0 || parm
->enum_list
[i
].value
!= parm
->enum_list
[i
-1].value
) {
335 printf("<option %s>%s",(*(int *)ptr
)==parm
->enum_list
[i
].value
?"selected":"",parm
->enum_list
[i
].name
);
339 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
340 _("Set Default"), make_parm_name(parm
->label
),enum_index((int)(parm
->def
.ivalue
),parm
->enum_list
));
345 printf("</td></tr>\n");
349 /****************************************************************************
350 display a set of parameters for a service
351 ****************************************************************************/
352 static void show_parameters(int snum
, int allparameters
, unsigned int parm_filter
, int printers
)
355 struct parm_struct
*parm
;
356 const char *heading
= NULL
;
357 const char *last_heading
= NULL
;
359 while ((parm
= lp_next_parameter(snum
, &i
, allparameters
))) {
360 if (snum
< 0 && parm
->p_class
== P_LOCAL
&& !(parm
->flags
& FLAG_GLOBAL
))
362 if (parm
->p_class
== P_SEPARATOR
) {
363 heading
= parm
->label
;
366 if (parm
->flags
& FLAG_HIDE
) continue;
368 if (printers
& !(parm
->flags
& FLAG_PRINT
)) continue;
369 if (!printers
& !(parm
->flags
& FLAG_SHARE
)) continue;
372 if (!( parm_filter
& FLAG_ADVANCED
)) {
373 if (!(parm
->flags
& FLAG_BASIC
)) {
374 void *ptr
= parm
->ptr
;
376 if (parm
->p_class
== P_LOCAL
&& snum
>= 0) {
377 ptr
= lp_local_ptr(snum
, ptr
);
380 switch (parm
->type
) {
382 if (*(char *)ptr
== (char)(parm
->def
.cvalue
)) continue;
386 if (!str_list_compare(*(char ***)ptr
, (char **)(parm
->def
.lvalue
))) continue;
391 if (!strcmp(*(char **)ptr
,(char *)(parm
->def
.svalue
))) continue;
396 if (*(bool *)ptr
== (bool)(parm
->def
.bvalue
)) continue;
401 if (*(int *)ptr
== (int)(parm
->def
.ivalue
)) continue;
406 if (*(int *)ptr
== (int)(parm
->def
.ivalue
)) continue;
412 if (printers
&& !(parm
->flags
& FLAG_PRINT
)) continue;
415 if ((parm_filter
& FLAG_WIZARD
) && !(parm
->flags
& FLAG_WIZARD
)) continue;
417 if ((parm_filter
& FLAG_ADVANCED
) && !(parm
->flags
& FLAG_ADVANCED
)) continue;
419 if (heading
&& heading
!= last_heading
) {
420 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading
));
421 last_heading
= heading
;
423 show_parameter(snum
, parm
);
427 /****************************************************************************
428 load the smb.conf file into loadparm.
429 ****************************************************************************/
430 static bool load_config(bool save_def
)
432 lp_resetnumservices();
433 return lp_load(get_dyn_CONFIGFILE(),False
,save_def
,False
,True
);
436 /****************************************************************************
438 ****************************************************************************/
439 static void write_config(FILE *f
, bool show_defaults
)
441 TALLOC_CTX
*ctx
= talloc_stackframe();
443 fprintf(f
, "# Samba config file created using SWAT\n");
444 fprintf(f
, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
445 fprintf(f
, "# Date: %s\n\n", current_timestring(ctx
, False
));
447 lp_dump(f
, show_defaults
, iNumNonAutoPrintServices
);
452 /****************************************************************************
453 save and reload the smb.conf config file
454 ****************************************************************************/
455 static int save_reload(int snum
)
460 f
= sys_fopen(get_dyn_CONFIGFILE(),"w");
462 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
467 /* just in case they have used the buggy xinetd to create the file */
468 if (fstat(fileno(f
), &st
) == 0 &&
469 (st
.st_mode
& S_IWOTH
)) {
470 #if defined HAVE_FCHMOD
471 fchmod(fileno(f
), S_IWUSR
| S_IRUSR
| S_IRGRP
| S_IROTH
);
473 chmod(get_dyn_CONFIGFILE(), S_IWUSR
| S_IRUSR
| S_IRGRP
| S_IROTH
);
477 write_config(f
, False
);
479 lp_dump_one(f
, False
, snum
);
482 lp_kill_all_services();
484 if (!load_config(False
)) {
485 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
489 iNumNonAutoPrintServices
= lp_numservices();
495 /****************************************************************************
497 ****************************************************************************/
498 static void commit_parameter(int snum
, struct parm_struct
*parm
, const char *v
)
503 if (snum
< 0 && parm
->p_class
== P_LOCAL
) {
504 /* this handles the case where we are changing a local
505 variable globally. We need to change the parameter in
506 all shares where it is currently set to the default */
507 for (i
=0;i
<lp_numservices();i
++) {
508 s
= lp_servicename(i
);
509 if (s
&& (*s
) && lp_is_default(i
, parm
)) {
510 lp_do_parameter(i
, parm
->label
, v
);
515 lp_do_parameter(snum
, parm
->label
, v
);
518 /****************************************************************************
519 commit a set of parameters for a service
520 ****************************************************************************/
521 static void commit_parameters(int snum
)
524 struct parm_struct
*parm
;
528 while ((parm
= lp_next_parameter(snum
, &i
, 1))) {
529 if (asprintf(&label
, "parm_%s", make_parm_name(parm
->label
)) > 0) {
530 if ((v
= cgi_variable(label
)) != NULL
) {
531 if (parm
->flags
& FLAG_HIDE
)
533 commit_parameter(snum
, parm
, v
);
540 /****************************************************************************
541 spit out the html for a link with an image
542 ****************************************************************************/
543 static void image_link(const char *name
, const char *hlink
, const char *src
)
545 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
546 cgi_baseurl(), hlink
, src
, name
);
549 /****************************************************************************
550 display the main navigation controls at the top of each page along
552 ****************************************************************************/
553 static void show_main_buttons(void)
557 if ((p
= cgi_user_name()) && strcmp(p
, "root")) {
558 printf(_("Logged in as <b>%s</b>"), p
);
562 image_link(_("Home"), "", "images/home.gif");
563 if (have_write_access
) {
564 image_link(_("Globals"), "globals", "images/globals.gif");
565 image_link(_("Shares"), "shares", "images/shares.gif");
566 image_link(_("Printers"), "printers", "images/printers.gif");
567 image_link(_("Wizard"), "wizard", "images/wizard.gif");
569 /* root always gets all buttons, otherwise look for -P */
570 if ( have_write_access
|| (!passwd_only
&& have_read_access
) ) {
571 image_link(_("Status"), "status", "images/status.gif");
572 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
574 image_link(_("Password Management"), "passwd", "images/passwd.gif");
579 /****************************************************************************
580 * Handle Display/Edit Mode CGI
581 ****************************************************************************/
582 static void ViewModeBoxes(int mode
)
584 printf("<p>%s: \n", _("Current View Is"));
585 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode
== 0) ? "checked" : ""), _("Basic"));
586 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode
== 1) ? "checked" : ""), _("Advanced"));
587 printf("<br>%s: \n", _("Change View To"));
588 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
589 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
590 printf("</p><br>\n");
593 /****************************************************************************
594 display a welcome page
595 ****************************************************************************/
596 static void welcome_page(void)
598 if (file_exist("help/welcome.html", NULL
)) {
599 include_html("help/welcome.html");
601 include_html("help/welcome-no-samba-doc.html");
605 /****************************************************************************
606 display the current smb.conf
607 ****************************************************************************/
608 static void viewconfig_page(void)
612 if (cgi_variable("full_view")) {
616 printf("<H2>%s</H2>\n", _("Current Config"));
617 printf("<form method=post>\n");
620 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
622 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
626 write_config(stdout
, full_view
);
631 /****************************************************************************
632 second screen of the wizard ... Fetch Configuration Parameters
633 ****************************************************************************/
634 static void wizard_params_page(void)
636 unsigned int parm_filter
= FLAG_WIZARD
;
638 /* Here we first set and commit all the parameters that were selected
639 in the previous screen. */
641 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
643 if (cgi_variable("Commit")) {
644 commit_parameters(GLOBAL_SECTION_SNUM
);
648 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
650 if (have_write_access
) {
651 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
654 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
658 show_parameters(GLOBAL_SECTION_SNUM
, 1, parm_filter
, 0);
659 printf("</table>\n");
663 /****************************************************************************
664 Utility to just rewrite the smb.conf file - effectively just cleans it up
665 ****************************************************************************/
666 static void rewritecfg_file(void)
668 commit_parameters(GLOBAL_SECTION_SNUM
);
670 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
673 /****************************************************************************
674 wizard to create/modify the smb.conf file
675 ****************************************************************************/
676 static void wizard_page(void)
678 /* Set some variables to collect data from smb.conf */
685 if (cgi_variable("Rewrite")) {
686 (void) rewritecfg_file();
690 if (cgi_variable("GetWizardParams")){
691 (void) wizard_params_page();
695 if (cgi_variable("Commit")){
696 SerType
= atoi(cgi_variable_nonull("ServerType"));
697 winstype
= atoi(cgi_variable_nonull("WINSType"));
698 have_home
= lp_servicenumber(HOMES_NAME
);
699 HomeExpo
= atoi(cgi_variable_nonull("HomeExpo"));
701 /* Plain text passwords are too badly broken - use encrypted passwords only */
702 lp_do_parameter( GLOBAL_SECTION_SNUM
, "encrypt passwords", "Yes");
706 /* Stand-alone Server */
707 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "USER" );
708 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "No" );
712 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "DOMAIN" );
713 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "No" );
716 /* Domain Controller */
717 lp_do_parameter( GLOBAL_SECTION_SNUM
, "security", "USER" );
718 lp_do_parameter( GLOBAL_SECTION_SNUM
, "domain logons", "Yes" );
721 switch ( winstype
) {
723 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "No" );
724 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", "" );
727 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "Yes" );
728 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", "" );
731 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins support", "No" );
732 lp_do_parameter( GLOBAL_SECTION_SNUM
, "wins server", cgi_variable_nonull("WINSAddr"));
736 /* Have to create Homes share? */
737 if ((HomeExpo
== 1) && (have_home
== -1)) {
738 const char *unix_share
= HOMES_NAME
;
741 lp_copy_service(GLOBAL_SECTION_SNUM
, unix_share
);
742 iNumNonAutoPrintServices
= lp_numservices();
743 have_home
= lp_servicenumber(HOMES_NAME
);
744 lp_do_parameter( have_home
, "read only", "No");
745 lp_do_parameter( have_home
, "valid users", "%S");
746 lp_do_parameter( have_home
, "browseable", "No");
747 commit_parameters(have_home
);
750 /* Need to Delete Homes share? */
751 if ((HomeExpo
== 0) && (have_home
!= -1)) {
752 lp_remove_service(have_home
);
756 commit_parameters(GLOBAL_SECTION_SNUM
);
761 /* Now determine smb.conf WINS settings */
762 if (lp_wins_support())
764 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
767 /* Do we have a homes share? */
768 have_home
= lp_servicenumber(HOMES_NAME
);
770 if ((winstype
== 2) && lp_wins_support())
773 role
= lp_server_role();
776 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
777 printf("<form method=post action=wizard>\n");
779 if (have_write_access
) {
780 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
781 printf("%s", _("The same will happen if you press the commit button."));
782 printf("<br><br>\n");
784 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
785 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
786 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
787 printf("</center>\n");
791 printf("<center><table border=0>");
792 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
793 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role
== ROLE_STANDALONE
) ? "checked" : ""), _("Stand Alone"));
794 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role
== ROLE_DOMAIN_MEMBER
) ? "checked" : ""), _("Domain Member"));
795 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role
== ROLE_DOMAIN_PDC
) ? "checked" : ""), _("Domain Controller"));
797 if (role
== ROLE_DOMAIN_BDC
) {
798 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
800 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
801 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype
== 0) ? "checked" : ""), _("Not Used"));
802 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype
== 1) ? "checked" : ""), _("Server for client use"));
803 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype
== 2) ? "checked" : ""), _("Client of another WINS server"));
805 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
807 /* Print out the list of wins servers */
808 if(lp_wins_server_list()) {
810 const char **wins_servers
= lp_wins_server_list();
811 for(i
= 0; wins_servers
[i
]; i
++) printf("%s ", wins_servers
[i
]);
814 printf("\"></td></tr>\n");
816 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"));
817 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
819 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
820 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home
== -1) ? "" : "checked ");
821 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home
== -1 ) ? "checked" : "");
822 printf("<td></td></tr>\n");
824 /* Enable this when we are ready ....
825 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
826 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
827 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
828 * printf("<td></td></tr>\n");
831 printf("</table></center>");
834 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
839 /****************************************************************************
840 display a globals editing page
841 ****************************************************************************/
842 static void globals_page(void)
844 unsigned int parm_filter
= FLAG_BASIC
;
847 printf("<H2>%s</H2>\n", _("Global Parameters"));
849 if (cgi_variable("Commit")) {
850 commit_parameters(GLOBAL_SECTION_SNUM
);
854 if ( cgi_variable("ViewMode") )
855 mode
= atoi(cgi_variable_nonull("ViewMode"));
856 if ( cgi_variable("BasicMode"))
858 if ( cgi_variable("AdvMode"))
861 printf("<form name=\"swatform\" method=post action=globals>\n");
863 ViewModeBoxes( mode
);
866 parm_filter
= FLAG_BASIC
;
869 parm_filter
= FLAG_ADVANCED
;
873 if (have_write_access
) {
874 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
875 _("Commit Changes"));
878 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
883 show_parameters(GLOBAL_SECTION_SNUM
, 1, parm_filter
, 0);
884 printf("</table>\n");
888 /****************************************************************************
889 display a shares editing page. share is in unix codepage,
890 ****************************************************************************/
891 static void shares_page(void)
893 const char *share
= cgi_variable("share");
899 unsigned int parm_filter
= FLAG_BASIC
;
902 snum
= lp_servicenumber(share
);
904 printf("<H2>%s</H2>\n", _("Share Parameters"));
906 if (cgi_variable("Commit") && snum
>= 0) {
907 commit_parameters(snum
);
911 if (cgi_variable("Delete") && snum
>= 0) {
912 lp_remove_service(snum
);
918 if (cgi_variable("createshare") && (share
=cgi_variable("newshare"))) {
920 lp_copy_service(GLOBAL_SECTION_SNUM
, share
);
921 iNumNonAutoPrintServices
= lp_numservices();
923 snum
= lp_servicenumber(share
);
926 printf("<FORM name=\"swatform\" method=post>\n");
930 if ( cgi_variable("ViewMode") )
931 mode
= atoi(cgi_variable_nonull("ViewMode"));
932 if ( cgi_variable("BasicMode"))
934 if ( cgi_variable("AdvMode"))
937 ViewModeBoxes( mode
);
940 parm_filter
= FLAG_BASIC
;
943 parm_filter
= FLAG_ADVANCED
;
946 printf("<br><tr>\n");
947 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
948 printf("<td><select name=share>\n");
950 printf("<option value=\" \"> \n");
951 for (i
=0;i
<lp_numservices();i
++) {
952 s
= lp_servicename(i
);
953 if (s
&& (*s
) && strcmp(s
,"IPC$") && !lp_print_ok(i
)) {
954 push_utf8_allocate(&utf8_s
, s
);
955 printf("<option %s value=\"%s\">%s\n",
956 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
962 printf("</select></td>\n");
963 if (have_write_access
) {
964 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
969 if (have_write_access
) {
971 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
972 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
978 if (have_write_access
) {
979 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
982 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
988 show_parameters(snum
, 1, parm_filter
, 0);
989 printf("</table>\n");
995 /*************************************************************
996 change a password either locally or remotely
997 *************************************************************/
998 static bool change_password(const char *remote_machine
, const char *user_name
,
999 const char *old_passwd
, const char *new_passwd
,
1003 char *err_str
= NULL
;
1004 char *msg_str
= NULL
;
1007 printf("%s\n<p>", _("password change in demo mode rejected"));
1011 if (remote_machine
!= NULL
) {
1012 ret
= remote_password_change(remote_machine
, user_name
,
1013 old_passwd
, new_passwd
, &err_str
);
1014 if (err_str
!= NULL
)
1015 printf("%s\n<p>", err_str
);
1017 return NT_STATUS_IS_OK(ret
);
1020 if(!initialize_password_db(True
, NULL
)) {
1021 printf("%s\n<p>", _("Can't setup password database vectors."));
1025 ret
= local_password_change(user_name
, local_flags
, new_passwd
,
1026 &err_str
, &msg_str
);
1029 printf("%s\n<p>", msg_str
);
1031 printf("%s\n<p>", err_str
);
1035 return NT_STATUS_IS_OK(ret
);
1038 /****************************************************************************
1039 do the stuff required to add or change a password
1040 ****************************************************************************/
1041 static void chg_passwd(void)
1045 int local_flags
= 0;
1047 /* Make sure users name has been specified */
1048 if (strlen(cgi_variable_nonull(SWAT_USER
)) == 0) {
1049 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1054 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1055 * so if that's what we're doing, skip the rest of the checks
1057 if (!cgi_variable(DISABLE_USER_FLAG
) && !cgi_variable(ENABLE_USER_FLAG
) && !cgi_variable(DELETE_USER_FLAG
)) {
1060 * If current user is not root, make sure old password has been specified
1061 * If REMOTE change, even root must provide old password
1063 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD
)) <= 0)) ||
1064 ((cgi_variable(CHG_R_PASSWD_FLAG
)) && (strlen( cgi_variable_nonull(OLD_PSWD
)) <= 0))) {
1065 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1069 /* If changing a users password on a remote hosts we have to know what host */
1070 if ((cgi_variable(CHG_R_PASSWD_FLAG
)) && (strlen( cgi_variable_nonull(RHOST
)) <= 0)) {
1071 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1075 /* Make sure new passwords have been specified */
1076 if ((strlen( cgi_variable_nonull(NEW_PSWD
)) <= 0) ||
1077 (strlen( cgi_variable_nonull(NEW2_PSWD
)) <= 0)) {
1078 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1082 /* Make sure new passwords was typed correctly twice */
1083 if (strcmp(cgi_variable_nonull(NEW_PSWD
), cgi_variable_nonull(NEW2_PSWD
)) != 0) {
1084 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1089 if (cgi_variable(CHG_R_PASSWD_FLAG
)) {
1090 host
= cgi_variable(RHOST
);
1091 } else if (am_root()) {
1098 * Set up the local flags.
1101 local_flags
|= (cgi_variable(ADD_USER_FLAG
) ? LOCAL_ADD_USER
: 0);
1102 local_flags
|= (cgi_variable(ADD_USER_FLAG
) ? LOCAL_SET_PASSWORD
: 0);
1103 local_flags
|= (cgi_variable(CHG_S_PASSWD_FLAG
) ? LOCAL_SET_PASSWORD
: 0);
1104 local_flags
|= (cgi_variable(DELETE_USER_FLAG
) ? LOCAL_DELETE_USER
: 0);
1105 local_flags
|= (cgi_variable(ENABLE_USER_FLAG
) ? LOCAL_ENABLE_USER
: 0);
1106 local_flags
|= (cgi_variable(DISABLE_USER_FLAG
) ? LOCAL_DISABLE_USER
: 0);
1109 rslt
= change_password(host
,
1110 cgi_variable_nonull(SWAT_USER
),
1111 cgi_variable_nonull(OLD_PSWD
), cgi_variable_nonull(NEW_PSWD
),
1114 if(cgi_variable(CHG_S_PASSWD_FLAG
)) {
1117 printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER
));
1120 printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER
));
1128 /****************************************************************************
1129 display a password editing page
1130 ****************************************************************************/
1131 static void passwd_page(void)
1133 const char *new_name
= cgi_user_name();
1136 * After the first time through here be nice. If the user
1137 * changed the User box text to another users name, remember it.
1139 if (cgi_variable(SWAT_USER
)) {
1140 new_name
= cgi_variable_nonull(SWAT_USER
);
1143 if (!new_name
) new_name
= "";
1145 printf("<H2>%s</H2>\n", _("Server Password Management"));
1147 printf("<FORM name=\"swatform\" method=post>\n");
1149 printf("<table>\n");
1152 * Create all the dialog boxes for data collection
1154 printf("<tr><td> %s : </td>\n", _("User Name"));
1155 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER
, new_name
);
1157 printf("<tr><td> %s : </td>\n", _("Old Password"));
1158 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD
);
1160 printf("<tr><td> %s : </td>\n", _("New Password"));
1161 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD
);
1162 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1163 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD
);
1164 printf("</table>\n");
1167 * Create all the control buttons for requesting action
1169 printf("<input type=submit name=%s value=\"%s\">\n",
1170 CHG_S_PASSWD_FLAG
, _("Change Password"));
1171 if (demo_mode
|| am_root()) {
1172 printf("<input type=submit name=%s value=\"%s\">\n",
1173 ADD_USER_FLAG
, _("Add New User"));
1174 printf("<input type=submit name=%s value=\"%s\">\n",
1175 DELETE_USER_FLAG
, _("Delete User"));
1176 printf("<input type=submit name=%s value=\"%s\">\n",
1177 DISABLE_USER_FLAG
, _("Disable User"));
1178 printf("<input type=submit name=%s value=\"%s\">\n",
1179 ENABLE_USER_FLAG
, _("Enable User"));
1181 printf("<p></FORM>\n");
1184 * Do some work if change, add, disable or enable was
1185 * requested. It could be this is the first time through this
1186 * code, so there isn't anything to do. */
1187 if ((cgi_variable(CHG_S_PASSWD_FLAG
)) || (cgi_variable(ADD_USER_FLAG
)) || (cgi_variable(DELETE_USER_FLAG
)) ||
1188 (cgi_variable(DISABLE_USER_FLAG
)) || (cgi_variable(ENABLE_USER_FLAG
))) {
1192 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1194 printf("<FORM name=\"swatform\" method=post>\n");
1196 printf("<table>\n");
1199 * Create all the dialog boxes for data collection
1201 printf("<tr><td> %s : </td>\n", _("User Name"));
1202 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER
, new_name
);
1203 printf("<tr><td> %s : </td>\n", _("Old Password"));
1204 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD
);
1205 printf("<tr><td> %s : </td>\n", _("New Password"));
1206 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD
);
1207 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1208 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD
);
1209 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1210 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST
);
1215 * Create all the control buttons for requesting action
1217 printf("<input type=submit name=%s value=\"%s\">",
1218 CHG_R_PASSWD_FLAG
, _("Change Password"));
1220 printf("<p></FORM>\n");
1223 * Do some work if a request has been made to change the
1224 * password somewhere other than the server. It could be this
1225 * is the first time through this code, so there isn't
1226 * anything to do. */
1227 if (cgi_variable(CHG_R_PASSWD_FLAG
)) {
1233 /****************************************************************************
1234 display a printers editing page
1235 ****************************************************************************/
1236 static void printers_page(void)
1238 const char *share
= cgi_variable("share");
1243 unsigned int parm_filter
= FLAG_BASIC
;
1246 snum
= lp_servicenumber(share
);
1248 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1250 printf("<H3>%s</H3>\n", _("Important Note:"));
1251 printf(_("Printer names marked with [*] in the Choose Printer drop-down box "));
1252 printf(_("are autoloaded printers from "));
1253 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1254 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1256 if (cgi_variable("Commit") && snum
>= 0) {
1257 commit_parameters(snum
);
1258 if (snum
>= iNumNonAutoPrintServices
)
1264 if (cgi_variable("Delete") && snum
>= 0) {
1265 lp_remove_service(snum
);
1271 if (cgi_variable("createshare") && (share
=cgi_variable("newshare"))) {
1273 lp_copy_service(GLOBAL_SECTION_SNUM
, share
);
1274 iNumNonAutoPrintServices
= lp_numservices();
1275 snum
= lp_servicenumber(share
);
1276 lp_do_parameter(snum
, "print ok", "Yes");
1278 snum
= lp_servicenumber(share
);
1281 printf("<FORM name=\"swatform\" method=post>\n");
1283 if ( cgi_variable("ViewMode") )
1284 mode
= atoi(cgi_variable_nonull("ViewMode"));
1285 if ( cgi_variable("BasicMode"))
1287 if ( cgi_variable("AdvMode"))
1290 ViewModeBoxes( mode
);
1293 parm_filter
= FLAG_BASIC
;
1296 parm_filter
= FLAG_ADVANCED
;
1299 printf("<table>\n");
1300 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1301 printf("<td><select name=\"share\">\n");
1302 if (snum
< 0 || !lp_print_ok(snum
))
1303 printf("<option value=\" \"> \n");
1304 for (i
=0;i
<lp_numservices();i
++) {
1305 s
= lp_servicename(i
);
1306 if (s
&& (*s
) && strcmp(s
,"IPC$") && lp_print_ok(i
)) {
1307 if (i
>= iNumNonAutoPrintServices
)
1308 printf("<option %s value=\"%s\">[*]%s\n",
1309 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
1312 printf("<option %s value=\"%s\">%s\n",
1313 (share
&& strcmp(share
,s
)==0)?"SELECTED":"",
1317 printf("</select></td>");
1318 if (have_write_access
) {
1319 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1322 printf("</table>\n");
1324 if (have_write_access
) {
1325 printf("<table>\n");
1326 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1327 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1333 if (have_write_access
) {
1334 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1336 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1341 printf("<table>\n");
1342 show_parameters(snum
, 1, parm_filter
, 1);
1343 printf("</table>\n");
1345 printf("</FORM>\n");
1349 when the _() translation macro is used there is no obvious place to free
1350 the resulting string and there is no easy way to give a static pointer.
1351 All we can do is rotate between some static buffers and hope a single d_printf()
1352 doesn't have more calls to _() than the number of buffers
1355 const char *lang_msg_rotate(TALLOC_CTX
*ctx
, const char *msgid
)
1360 msgstr
= lang_msg(msgid
);
1365 ret
= talloc_strdup(ctx
, msgstr
);
1367 lang_msg_free(msgstr
);
1376 * main function for SWAT.
1378 int main(int argc
, char *argv
[])
1382 struct poptOption long_options
[] = {
1384 { "disable-authentication", 'a', POPT_ARG_VAL
, &demo_mode
, True
, "Disable authentication (demo mode)" },
1385 { "password-menu-only", 'P', POPT_ARG_VAL
, &passwd_only
, True
, "Show only change password menu" },
1389 TALLOC_CTX
*frame
= talloc_stackframe();
1392 umask(S_IWGRP
| S_IWOTH
);
1394 #if defined(HAVE_SET_AUTH_PARAMETERS)
1395 set_auth_parameters(argc
, argv
);
1396 #endif /* HAVE_SET_AUTH_PARAMETERS */
1398 /* just in case it goes wild ... */
1403 /* we don't want any SIGPIPE messages */
1404 BlockSignals(True
,SIGPIPE
);
1406 dbf
= x_fopen("/dev/null", O_WRONLY
, 0);
1407 if (!dbf
) dbf
= x_stderr
;
1409 /* we don't want stderr screwing us up */
1411 open("/dev/null", O_WRONLY
);
1413 pc
= poptGetContext("swat", argc
, (const char **) argv
, long_options
, 0);
1415 /* Parse command line options */
1417 while(poptGetNextOpt(pc
) != -1) { }
1419 poptFreeContext(pc
);
1423 setup_logging(argv
[0],False
);
1426 iNumNonAutoPrintServices
= lp_numservices();
1429 cgi_setup(get_dyn_SWATDIR(), !demo_mode
);
1433 cgi_load_variables();
1435 if (!file_exist(get_dyn_CONFIGFILE(), NULL
)) {
1436 have_read_access
= True
;
1437 have_write_access
= True
;
1439 /* check if the authenticated user has write access - if not then
1440 don't show write options */
1441 have_write_access
= (access(get_dyn_CONFIGFILE(),W_OK
) == 0);
1443 /* if the user doesn't have read access to smb.conf then
1444 don't let them view it */
1445 have_read_access
= (access(get_dyn_CONFIGFILE(),R_OK
) == 0);
1448 show_main_buttons();
1450 page
= cgi_pathinfo();
1452 /* Root gets full functionality */
1453 if (have_read_access
&& strcmp(page
, "globals")==0) {
1455 } else if (have_read_access
&& strcmp(page
,"shares")==0) {
1457 } else if (have_read_access
&& strcmp(page
,"printers")==0) {
1459 } else if (have_read_access
&& strcmp(page
,"status")==0) {
1461 } else if (have_read_access
&& strcmp(page
,"viewconfig")==0) {
1463 } else if (strcmp(page
,"passwd")==0) {
1465 } else if (have_read_access
&& strcmp(page
,"wizard")==0) {
1467 } else if (have_read_access
&& strcmp(page
,"wizard_params")==0) {
1468 wizard_params_page();
1469 } else if (have_read_access
&& strcmp(page
,"rewritecfg")==0) {