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"
63 #define _(x) lang_msg_rotate(talloc_tos(),x)
65 /****************************************************************************
66 ****************************************************************************/
67 static int enum_index(int value, const struct enum_list *enumlist)
70 for (i=0;enumlist[i].name;i++)
71 if (value == enumlist[i].value) break;
75 static char *fix_backslash(const char *str)
77 static char newstring[1024];
81 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
89 static const char *fix_quotes(TALLOC_CTX *ctx, char *str)
91 char *newstring = NULL;
94 int quote_len = strlen(""");
96 /* Count the number of quotes. */
101 newstring_len += quote_len;
107 newstring = talloc_array(ctx, char, newstring_len);
111 for (p = newstring; *str; str++) {
113 strncpy( p, """, quote_len);
123 static char *stripspaceupper(const char *str)
125 static char newstring[1024];
129 if (*str != ' ') *p++ = toupper_m(*str);
136 static char *make_parm_name(const char *label)
138 static char parmname[1024];
142 if (*label == ' ') *p++ = '_';
150 void get_xsrf_token(const char *username, const char *pass,
151 const char *formname, char token_str[33])
153 struct MD5Context md5_ctx;
158 ZERO_STRUCT(md5_ctx);
161 MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
162 if (username != NULL) {
163 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
166 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
169 MD5Final(token, &md5_ctx);
171 for(i = 0; i < sizeof(token); i++) {
174 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
175 strncat(token_str, tmp, sizeof(tmp));
179 void print_xsrf_token(const char *username, const char *pass,
180 const char *formname)
184 get_xsrf_token(username, pass, formname, token);
185 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
190 bool verify_xsrf_token(const char *formname)
193 const char *username = cgi_user_name();
194 const char *pass = cgi_user_pass();
195 const char *token = cgi_variable_nonull(XSRF_TOKEN);
197 get_xsrf_token(username, pass, formname, expected);
198 return (strncmp(expected, token, sizeof(expected)) == 0);
202 /****************************************************************************
203 include a lump of html in a page
204 ****************************************************************************/
205 static int include_html(const char *fname)
211 fd = web_open(fname, O_RDONLY, 0);
214 printf(_("ERROR: Can't open %s"), fname);
219 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
220 if (write(1, buf, ret) == -1) {
229 /****************************************************************************
230 start the page with standard stuff
231 ****************************************************************************/
232 static void print_header(void)
234 if (!cgi_waspost()) {
235 printf("Expires: 0\r\n");
237 printf("Content-type: text/html\r\n\r\n");
239 if (!include_html("include/header.html")) {
240 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
241 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
245 /* *******************************************************************
246 show parameter label with translated name in the following form
247 because showing original and translated label in one line looks
248 too long, and showing translated label only is unusable for
250 -------------------------------
251 HELP security [combo box][button]
253 -------------------------------
254 (capital words are translated by gettext.)
255 if no translation is available, then same form as original is
257 "i18n_translated_parm" class is used to change the color of the
258 translated parameter with CSS.
259 **************************************************************** */
260 static const char *get_parm_translated(TALLOC_CTX *ctx,
261 const char* pAnchor, const char* pHelp, const char* pLabel)
263 const char *pTranslated = _(pLabel);
265 if(strcmp(pLabel, pTranslated) != 0) {
266 output = talloc_asprintf(ctx,
267 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
268 pAnchor, pHelp, pLabel, pTranslated);
271 output = talloc_asprintf(ctx,
272 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
273 pAnchor, pHelp, pLabel);
276 /****************************************************************************
278 ****************************************************************************/
279 static void print_footer(void)
281 if (!include_html("include/footer.html")) {
282 printf("\n</BODY>\n</HTML>\n");
286 /****************************************************************************
287 display one editable parameter in a form
288 ****************************************************************************/
289 static void show_parameter(int snum, struct parm_struct *parm)
293 char *utf8_s1, *utf8_s2;
294 size_t converted_size;
295 TALLOC_CTX *ctx = talloc_stackframe();
297 if (parm->p_class == P_LOCAL && snum >= 0) {
298 ptr = lp_local_ptr_by_snum(snum, parm);
300 ptr = lp_parm_ptr(NULL, parm);
303 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
304 stripspaceupper(parm->label), _("Help"), parm->label));
305 switch (parm->type) {
307 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
308 make_parm_name(parm->label), *(char *)ptr);
309 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
310 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
314 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
315 make_parm_name(parm->label));
316 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
317 char **list = *(char ***)ptr;
318 for (;*list;list++) {
319 /* enclose in HTML encoded quotes if the string contains a space */
320 if ( strchr_m(*list, ' ') ) {
321 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
322 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
323 printf(""%s"%s", utf8_s1, utf8_s2);
325 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
326 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
327 printf("%s%s", utf8_s1, utf8_s2);
329 TALLOC_FREE(utf8_s1);
330 TALLOC_FREE(utf8_s2);
334 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
335 _("Set Default"), make_parm_name(parm->label));
336 if (parm->def.lvalue) {
337 char **list = (char **)(parm->def.lvalue);
338 for (; *list; list++) {
339 /* enclose in HTML encoded quotes if the string contains a space */
340 if ( strchr_m(*list, ' ') )
341 printf(""%s"%s", *list, ((*(list+1))?", ":""));
343 printf("%s%s", *list, ((*(list+1))?", ":""));
351 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
352 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
353 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
354 TALLOC_FREE(utf8_s1);
355 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
356 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
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)?0:1);
369 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
370 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
371 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
373 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
374 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
378 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
379 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
380 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
385 o = octal_string(*(int *)ptr);
386 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
387 make_parm_name(parm->label), o);
389 o = octal_string((int)(parm->def.ivalue));
390 printf("<input type=button value=\"%s\" "
391 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
392 _("Set Default"), make_parm_name(parm->label), o);
398 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
399 for (i=0;parm->enum_list[i].name;i++) {
400 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
401 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
405 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
406 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
411 printf("</td></tr>\n");
415 /****************************************************************************
416 display a set of parameters for a service
417 ****************************************************************************/
418 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
421 struct parm_struct *parm;
422 const char *heading = NULL;
423 const char *last_heading = NULL;
425 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
426 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
428 if (parm->p_class == P_SEPARATOR) {
429 heading = parm->label;
432 if (parm->flags & FLAG_HIDE) continue;
434 if (printers & !(parm->flags & FLAG_PRINT)) continue;
435 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
438 if (!( parm_filter & FLAG_ADVANCED )) {
439 if (!(parm->flags & FLAG_BASIC)) {
441 if (parm->p_class == P_LOCAL && snum >= 0) {
442 ptr = lp_local_ptr_by_snum(snum, parm);
444 ptr = lp_parm_ptr(NULL, parm);
447 switch (parm->type) {
449 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
453 if (!str_list_equal(*(const char ***)ptr,
454 (const char **)(parm->def.lvalue))) continue;
459 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
464 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
469 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
474 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
480 if (printers && !(parm->flags & FLAG_PRINT)) continue;
483 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
485 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
487 if (heading && heading != last_heading) {
488 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
489 last_heading = heading;
491 show_parameter(snum, parm);
495 /****************************************************************************
496 load the smb.conf file into loadparm.
497 ****************************************************************************/
498 static bool load_config(bool save_def)
500 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
503 /****************************************************************************
505 ****************************************************************************/
506 static void write_config(FILE *f, bool show_defaults)
508 TALLOC_CTX *ctx = talloc_stackframe();
510 fprintf(f, "# Samba config file created using SWAT\n");
511 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
512 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
514 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
519 /****************************************************************************
520 save and reload the smb.conf config file
521 ****************************************************************************/
522 static int save_reload(int snum)
527 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
529 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
534 /* just in case they have used the buggy xinetd to create the file */
535 if (fstat(fileno(f), &st) == 0 &&
536 (st.st_mode & S_IWOTH)) {
537 #if defined HAVE_FCHMOD
538 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
540 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
544 write_config(f, False);
546 lp_dump_one(f, False, snum);
549 lp_kill_all_services();
551 if (!load_config(False)) {
552 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
556 iNumNonAutoPrintServices = lp_numservices();
557 if (pcap_cache_loaded()) {
558 load_printers(server_event_context(),
559 server_messaging_context());
565 /****************************************************************************
567 ****************************************************************************/
568 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
573 if (snum < 0 && parm->p_class == P_LOCAL) {
574 /* this handles the case where we are changing a local
575 variable globally. We need to change the parameter in
576 all shares where it is currently set to the default */
577 for (i=0;i<lp_numservices();i++) {
578 s = lp_servicename(i);
579 if (s && (*s) && lp_is_default(i, parm)) {
580 lp_do_parameter(i, parm->label, v);
585 lp_do_parameter(snum, parm->label, v);
588 /****************************************************************************
589 commit a set of parameters for a service
590 ****************************************************************************/
591 static void commit_parameters(int snum)
594 struct parm_struct *parm;
598 while ((parm = lp_next_parameter(snum, &i, 1))) {
599 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
600 if ((v = cgi_variable(label)) != NULL) {
601 if (parm->flags & FLAG_HIDE)
603 commit_parameter(snum, parm, v);
610 /****************************************************************************
611 spit out the html for a link with an image
612 ****************************************************************************/
613 static void image_link(const char *name, const char *hlink, const char *src)
615 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
616 cgi_baseurl(), hlink, src, name);
619 /****************************************************************************
620 display the main navigation controls at the top of each page along
622 ****************************************************************************/
623 static void show_main_buttons(void)
627 if ((p = cgi_user_name()) && strcmp(p, "root")) {
628 printf(_("Logged in as <b>%s</b>"), p);
632 image_link(_("Home"), "", "images/home.gif");
633 if (have_write_access) {
634 image_link(_("Globals"), "globals", "images/globals.gif");
635 image_link(_("Shares"), "shares", "images/shares.gif");
636 image_link(_("Printers"), "printers", "images/printers.gif");
637 image_link(_("Wizard"), "wizard", "images/wizard.gif");
639 /* root always gets all buttons, otherwise look for -P */
640 if ( have_write_access || (!passwd_only && have_read_access) ) {
641 image_link(_("Status"), "status", "images/status.gif");
642 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
644 image_link(_("Password Management"), "passwd", "images/passwd.gif");
649 /****************************************************************************
650 * Handle Display/Edit Mode CGI
651 ****************************************************************************/
652 static void ViewModeBoxes(int mode)
654 printf("<p>%s: \n", _("Current View Is"));
655 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
656 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
657 printf("<br>%s: \n", _("Change View To"));
658 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
659 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
660 printf("</p><br>\n");
663 /****************************************************************************
664 display a welcome page
665 ****************************************************************************/
666 static void welcome_page(void)
668 if (file_exist("help/welcome.html")) {
669 include_html("help/welcome.html");
671 include_html("help/welcome-no-samba-doc.html");
675 /****************************************************************************
676 display the current smb.conf
677 ****************************************************************************/
678 static void viewconfig_page(void)
681 const char form_name[] = "viewconfig";
683 if (!verify_xsrf_token(form_name)) {
687 if (cgi_variable("full_view")) {
692 printf("<H2>%s</H2>\n", _("Current Config"));
693 printf("<form method=post>\n");
694 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
697 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
699 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
703 write_config(stdout, full_view);
708 /****************************************************************************
709 second screen of the wizard ... Fetch Configuration Parameters
710 ****************************************************************************/
711 static void wizard_params_page(void)
713 unsigned int parm_filter = FLAG_WIZARD;
714 const char form_name[] = "wizard_params";
716 /* Here we first set and commit all the parameters that were selected
717 in the previous screen. */
719 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
721 if (!verify_xsrf_token(form_name)) {
725 if (cgi_variable("Commit")) {
726 commit_parameters(GLOBAL_SECTION_SNUM);
731 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
732 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
734 if (have_write_access) {
735 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
738 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
742 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
743 printf("</table>\n");
747 /****************************************************************************
748 Utility to just rewrite the smb.conf file - effectively just cleans it up
749 ****************************************************************************/
750 static void rewritecfg_file(void)
752 commit_parameters(GLOBAL_SECTION_SNUM);
754 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
757 /****************************************************************************
758 wizard to create/modify the smb.conf file
759 ****************************************************************************/
760 static void wizard_page(void)
762 /* Set some variables to collect data from smb.conf */
768 const char form_name[] = "wizard";
770 if (!verify_xsrf_token(form_name)) {
774 if (cgi_variable("Rewrite")) {
775 (void) rewritecfg_file();
779 if (cgi_variable("GetWizardParams")){
780 (void) wizard_params_page();
784 if (cgi_variable("Commit")){
785 SerType = atoi(cgi_variable_nonull("ServerType"));
786 winstype = atoi(cgi_variable_nonull("WINSType"));
787 have_home = lp_servicenumber(HOMES_NAME);
788 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
790 /* Plain text passwords are too badly broken - use encrypted passwords only */
791 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
795 /* Stand-alone Server */
796 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
797 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
801 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
802 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
805 /* Domain Controller */
806 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
807 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
810 switch ( winstype ) {
812 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
813 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
816 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
817 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
820 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
821 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
825 /* Have to create Homes share? */
826 if ((HomeExpo == 1) && (have_home == -1)) {
827 const char *unix_share = HOMES_NAME;
830 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
831 have_home = lp_servicenumber(HOMES_NAME);
832 lp_do_parameter( have_home, "read only", "No");
833 lp_do_parameter( have_home, "valid users", "%S");
834 lp_do_parameter( have_home, "browseable", "No");
835 commit_parameters(have_home);
836 save_reload(have_home);
839 /* Need to Delete Homes share? */
840 if ((HomeExpo == 0) && (have_home != -1)) {
841 lp_remove_service(have_home);
845 commit_parameters(GLOBAL_SECTION_SNUM);
850 /* Now determine smb.conf WINS settings */
851 if (lp_we_are_a_wins_server())
853 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
856 /* Do we have a homes share? */
857 have_home = lp_servicenumber(HOMES_NAME);
859 if ((winstype == 2) && lp_we_are_a_wins_server())
862 role = lp_server_role();
866 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
867 printf("<form method=post action=wizard>\n");
868 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
870 if (have_write_access) {
871 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
872 printf("%s", _("The same will happen if you press the commit button."));
873 printf("<br><br>\n");
875 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
876 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
877 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
878 printf("</center>\n");
882 printf("<center><table border=0>");
883 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
884 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
885 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
886 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
888 if (role == ROLE_DOMAIN_BDC) {
889 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
891 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
892 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
893 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
894 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
896 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
898 /* Print out the list of wins servers */
899 if(lp_wins_server_list()) {
901 const char **wins_servers = lp_wins_server_list();
902 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
905 printf("\"></td></tr>\n");
907 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Error: WINS Server Mode and WINS Support both set in smb.conf"));
908 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
910 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
911 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
912 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
913 printf("<td></td></tr>\n");
915 /* Enable this when we are ready ....
916 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
917 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
918 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
919 * printf("<td></td></tr>\n");
922 printf("</table></center>");
925 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
930 /****************************************************************************
931 display a globals editing page
932 ****************************************************************************/
933 static void globals_page(void)
935 unsigned int parm_filter = FLAG_BASIC;
938 printf("<H2>%s</H2>\n", _("Global Parameters"));
940 if (cgi_variable("Commit")) {
941 commit_parameters(GLOBAL_SECTION_SNUM);
945 if ( cgi_variable("ViewMode") )
946 mode = atoi(cgi_variable_nonull("ViewMode"));
947 if ( cgi_variable("BasicMode"))
949 if ( cgi_variable("AdvMode"))
952 printf("<form name=\"swatform\" method=post action=globals>\n");
954 ViewModeBoxes( mode );
957 parm_filter = FLAG_BASIC;
960 parm_filter = FLAG_ADVANCED;
964 if (have_write_access) {
965 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
966 _("Commit Changes"));
969 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
974 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
975 printf("</table>\n");
979 /****************************************************************************
980 display a shares editing page. share is in unix codepage,
981 ****************************************************************************/
982 static void shares_page(void)
984 const char *share = cgi_variable("share");
990 unsigned int parm_filter = FLAG_BASIC;
991 size_t converted_size;
994 snum = lp_servicenumber(share);
996 printf("<H2>%s</H2>\n", _("Share Parameters"));
998 if (cgi_variable("Commit") && snum >= 0) {
999 commit_parameters(snum);
1001 snum = lp_servicenumber(share);
1004 if (cgi_variable("Delete") && snum >= 0) {
1005 lp_remove_service(snum);
1011 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1012 snum = lp_servicenumber(share);
1015 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1016 snum = lp_servicenumber(share);
1018 snum = lp_servicenumber(share);
1022 printf("<FORM name=\"swatform\" method=post>\n");
1024 printf("<table>\n");
1026 if ( cgi_variable("ViewMode") )
1027 mode = atoi(cgi_variable_nonull("ViewMode"));
1028 if ( cgi_variable("BasicMode"))
1030 if ( cgi_variable("AdvMode"))
1033 ViewModeBoxes( mode );
1036 parm_filter = FLAG_BASIC;
1039 parm_filter = FLAG_ADVANCED;
1042 printf("<br><tr>\n");
1043 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1044 printf("<td><select name=share>\n");
1046 printf("<option value=\" \"> \n");
1047 for (i=0;i<lp_numservices();i++) {
1048 s = lp_servicename(i);
1049 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1050 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1051 printf("<option %s value=\"%s\">%s\n",
1052 (share && strcmp(share,s)==0)?"SELECTED":"",
1054 TALLOC_FREE(utf8_s);
1057 printf("</select></td>\n");
1058 if (have_write_access) {
1059 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1064 if (have_write_access) {
1066 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1067 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1073 if (have_write_access) {
1074 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1077 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1082 printf("<table>\n");
1083 show_parameters(snum, 1, parm_filter, 0);
1084 printf("</table>\n");
1087 printf("</FORM>\n");
1090 /*************************************************************
1091 change a password either locally or remotely
1092 *************************************************************/
1093 static bool change_password(const char *remote_machine, const char *user_name,
1094 const char *old_passwd, const char *new_passwd,
1098 char *err_str = NULL;
1099 char *msg_str = NULL;
1102 printf("%s\n<p>", _("password change in demo mode rejected"));
1106 if (remote_machine != NULL) {
1107 ret = remote_password_change(remote_machine, user_name,
1108 old_passwd, new_passwd, &err_str);
1109 if (err_str != NULL)
1110 printf("%s\n<p>", err_str);
1112 return NT_STATUS_IS_OK(ret);
1115 if(!initialize_password_db(True, NULL)) {
1116 printf("%s\n<p>", _("Can't setup password database vectors."));
1120 ret = local_password_change(user_name, local_flags, new_passwd,
1121 &err_str, &msg_str);
1124 printf("%s\n<p>", msg_str);
1126 printf("%s\n<p>", err_str);
1130 return NT_STATUS_IS_OK(ret);
1133 /****************************************************************************
1134 do the stuff required to add or change a password
1135 ****************************************************************************/
1136 static void chg_passwd(void)
1140 int local_flags = 0;
1142 /* Make sure users name has been specified */
1143 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1144 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1149 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1150 * so if that's what we're doing, skip the rest of the checks
1152 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1155 * If current user is not root, make sure old password has been specified
1156 * If REMOTE change, even root must provide old password
1158 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1159 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1160 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1164 /* If changing a users password on a remote hosts we have to know what host */
1165 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1166 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1170 /* Make sure new passwords have been specified */
1171 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1172 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1173 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1177 /* Make sure new passwords was typed correctly twice */
1178 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1179 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1184 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1185 host = cgi_variable(RHOST);
1186 } else if (am_root()) {
1193 * Set up the local flags.
1196 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1197 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1198 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1199 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1200 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1201 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1203 rslt = change_password(host,
1204 cgi_variable_nonull(SWAT_USER),
1205 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1208 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1211 printf("%s\n", _(" The passwd has been changed."));
1213 printf("%s\n", _(" The passwd has NOT been changed."));
1220 /****************************************************************************
1221 display a password editing page
1222 ****************************************************************************/
1223 static void passwd_page(void)
1225 const char *new_name = cgi_user_name();
1227 if (!new_name) new_name = "";
1229 printf("<H2>%s</H2>\n", _("Server Password Management"));
1231 printf("<FORM name=\"swatform\" method=post>\n");
1233 printf("<table>\n");
1236 * Create all the dialog boxes for data collection
1238 printf("<tr><td> %s : </td>\n", _("User Name"));
1239 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1241 printf("<tr><td> %s : </td>\n", _("Old Password"));
1242 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1244 printf("<tr><td> %s : </td>\n", _("New Password"));
1245 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1246 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1247 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1248 printf("</table>\n");
1251 * Create all the control buttons for requesting action
1253 printf("<input type=submit name=%s value=\"%s\">\n",
1254 CHG_S_PASSWD_FLAG, _("Change Password"));
1255 if (demo_mode || am_root()) {
1256 printf("<input type=submit name=%s value=\"%s\">\n",
1257 ADD_USER_FLAG, _("Add New User"));
1258 printf("<input type=submit name=%s value=\"%s\">\n",
1259 DELETE_USER_FLAG, _("Delete User"));
1260 printf("<input type=submit name=%s value=\"%s\">\n",
1261 DISABLE_USER_FLAG, _("Disable User"));
1262 printf("<input type=submit name=%s value=\"%s\">\n",
1263 ENABLE_USER_FLAG, _("Enable User"));
1265 printf("<p></FORM>\n");
1268 * Do some work if change, add, disable or enable was
1269 * requested. It could be this is the first time through this
1270 * code, so there isn't anything to do. */
1271 if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1272 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1276 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1278 printf("<FORM name=\"swatform\" method=post>\n");
1280 printf("<table>\n");
1283 * Create all the dialog boxes for data collection
1285 printf("<tr><td> %s : </td>\n", _("User Name"));
1286 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1287 printf("<tr><td> %s : </td>\n", _("Old Password"));
1288 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1289 printf("<tr><td> %s : </td>\n", _("New Password"));
1290 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1291 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1292 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1293 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1294 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1299 * Create all the control buttons for requesting action
1301 printf("<input type=submit name=%s value=\"%s\">",
1302 CHG_R_PASSWD_FLAG, _("Change Password"));
1304 printf("<p></FORM>\n");
1307 * Do some work if a request has been made to change the
1308 * password somewhere other than the server. It could be this
1309 * is the first time through this code, so there isn't
1310 * anything to do. */
1311 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1317 /****************************************************************************
1318 display a printers editing page
1319 ****************************************************************************/
1320 static void printers_page(void)
1322 const char *share = cgi_variable("share");
1327 unsigned int parm_filter = FLAG_BASIC;
1330 snum = lp_servicenumber(share);
1332 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1334 printf("<H3>%s</H3>\n", _("Important Note:"));
1335 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1336 printf("%s",_("are autoloaded printers from "));
1337 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1338 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1340 if (cgi_variable("Commit") && snum >= 0) {
1341 commit_parameters(snum);
1342 if (snum >= iNumNonAutoPrintServices)
1346 snum = lp_servicenumber(share);
1349 if (cgi_variable("Delete") && snum >= 0) {
1350 lp_remove_service(snum);
1356 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1357 snum = lp_servicenumber(share);
1358 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1360 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1361 snum = lp_servicenumber(share);
1362 lp_do_parameter(snum, "print ok", "Yes");
1364 snum = lp_servicenumber(share);
1368 printf("<FORM name=\"swatform\" method=post>\n");
1370 if ( cgi_variable("ViewMode") )
1371 mode = atoi(cgi_variable_nonull("ViewMode"));
1372 if ( cgi_variable("BasicMode"))
1374 if ( cgi_variable("AdvMode"))
1377 ViewModeBoxes( mode );
1380 parm_filter = FLAG_BASIC;
1383 parm_filter = FLAG_ADVANCED;
1386 printf("<table>\n");
1387 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1388 printf("<td><select name=\"share\">\n");
1389 if (snum < 0 || !lp_print_ok(snum))
1390 printf("<option value=\" \"> \n");
1391 for (i=0;i<lp_numservices();i++) {
1392 s = lp_servicename(i);
1393 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1394 if (i >= iNumNonAutoPrintServices)
1395 printf("<option %s value=\"%s\">[*]%s\n",
1396 (share && strcmp(share,s)==0)?"SELECTED":"",
1399 printf("<option %s value=\"%s\">%s\n",
1400 (share && strcmp(share,s)==0)?"SELECTED":"",
1404 printf("</select></td>");
1405 if (have_write_access) {
1406 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1409 printf("</table>\n");
1411 if (have_write_access) {
1412 printf("<table>\n");
1413 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1414 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1420 if (have_write_access) {
1421 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1423 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1428 printf("<table>\n");
1429 show_parameters(snum, 1, parm_filter, 1);
1430 printf("</table>\n");
1432 printf("</FORM>\n");
1436 when the _() translation macro is used there is no obvious place to free
1437 the resulting string and there is no easy way to give a static pointer.
1438 All we can do is rotate between some static buffers and hope a single d_printf()
1439 doesn't have more calls to _() than the number of buffers
1442 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1447 msgstr = lang_msg(msgid);
1452 ret = talloc_strdup(ctx, msgstr);
1454 lang_msg_free(msgstr);
1463 * main function for SWAT.
1465 int main(int argc, char *argv[])
1469 struct poptOption long_options[] = {
1471 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1472 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1476 TALLOC_CTX *frame = talloc_stackframe();
1479 umask(S_IWGRP | S_IWOTH);
1481 #if defined(HAVE_SET_AUTH_PARAMETERS)
1482 set_auth_parameters(argc, argv);
1483 #endif /* HAVE_SET_AUTH_PARAMETERS */
1485 /* just in case it goes wild ... */
1490 /* we don't want any SIGPIPE messages */
1491 BlockSignals(True,SIGPIPE);
1493 debug_set_logfile("/dev/null");
1495 /* we don't want stderr screwing us up */
1497 open("/dev/null", O_WRONLY);
1498 setup_logging("swat", DEBUG_FILE);
1502 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1504 /* Parse command line options */
1506 while(poptGetNextOpt(pc) != -1) { }
1508 poptFreeContext(pc);
1510 /* This should set a more apporiate log file */
1514 iNumNonAutoPrintServices = lp_numservices();
1515 if (pcap_cache_loaded()) {
1516 load_printers(server_event_context(),
1517 server_messaging_context());
1520 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1524 cgi_load_variables();
1526 if (!file_exist(get_dyn_CONFIGFILE())) {
1527 have_read_access = True;
1528 have_write_access = True;
1530 /* check if the authenticated user has write access - if not then
1531 don't show write options */
1532 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1534 /* if the user doesn't have read access to smb.conf then
1535 don't let them view it */
1536 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1539 show_main_buttons();
1541 page = cgi_pathinfo();
1543 /* Root gets full functionality */
1544 if (have_read_access && strcmp(page, "globals")==0) {
1546 } else if (have_read_access && strcmp(page,"shares")==0) {
1548 } else if (have_read_access && strcmp(page,"printers")==0) {
1550 } else if (have_read_access && strcmp(page,"status")==0) {
1552 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1554 } else if (strcmp(page,"passwd")==0) {
1556 } else if (have_read_access && strcmp(page,"wizard")==0) {
1558 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1559 wizard_params_page();
1560 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {