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 "popt_common.h"
32 #include "web/swat_proto.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"
55 #define _(x) lang_msg_rotate(talloc_tos(),x)
57 /****************************************************************************
58 ****************************************************************************/
59 static int enum_index(int value, const struct enum_list *enumlist)
62 for (i=0;enumlist[i].name;i++)
63 if (value == enumlist[i].value) break;
67 static char *fix_backslash(const char *str)
69 static char newstring[1024];
73 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
81 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
83 char *newstring = NULL;
86 int quote_len = strlen(""");
88 /* Count the number of quotes. */
93 newstring_len += quote_len;
99 newstring = TALLOC_ARRAY(ctx, char, newstring_len);
103 for (p = newstring; *str; str++) {
105 strncpy( p, """, quote_len);
115 static char *stripspaceupper(const char *str)
117 static char newstring[1024];
121 if (*str != ' ') *p++ = toupper_ascii(*str);
128 static char *make_parm_name(const char *label)
130 static char parmname[1024];
134 if (*label == ' ') *p++ = '_';
142 /****************************************************************************
143 include a lump of html in a page
144 ****************************************************************************/
145 static int include_html(const char *fname)
151 fd = web_open(fname, O_RDONLY, 0);
154 printf(_("ERROR: Can't open %s"), fname);
159 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
160 if (write(1, buf, ret) == -1) {
169 /****************************************************************************
170 start the page with standard stuff
171 ****************************************************************************/
172 static void print_header(void)
174 if (!cgi_waspost()) {
175 printf("Expires: 0\r\n");
177 printf("Content-type: text/html\r\n\r\n");
179 if (!include_html("include/header.html")) {
180 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
181 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
185 /* *******************************************************************
186 show parameter label with translated name in the following form
187 because showing original and translated label in one line looks
188 too long, and showing translated label only is unusable for
190 -------------------------------
191 HELP security [combo box][button]
193 -------------------------------
194 (capital words are translated by gettext.)
195 if no translation is available, then same form as original is
197 "i18n_translated_parm" class is used to change the color of the
198 translated parameter with CSS.
199 **************************************************************** */
200 static const char *get_parm_translated(TALLOC_CTX *ctx,
201 const char* pAnchor, const char* pHelp, const char* pLabel)
203 const char *pTranslated = _(pLabel);
205 if(strcmp(pLabel, pTranslated) != 0) {
206 output = talloc_asprintf(ctx,
207 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
208 pAnchor, pHelp, pLabel, pTranslated);
211 output = talloc_asprintf(ctx,
212 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
213 pAnchor, pHelp, pLabel);
216 /****************************************************************************
218 ****************************************************************************/
219 static void print_footer(void)
221 if (!include_html("include/footer.html")) {
222 printf("\n</BODY>\n</HTML>\n");
226 /****************************************************************************
227 display one editable parameter in a form
228 ****************************************************************************/
229 static void show_parameter(int snum, struct parm_struct *parm)
232 void *ptr = parm->ptr;
233 char *utf8_s1, *utf8_s2;
234 size_t converted_size;
235 TALLOC_CTX *ctx = talloc_stackframe();
237 if (parm->p_class == P_LOCAL && snum >= 0) {
238 ptr = lp_local_ptr_by_snum(snum, ptr);
241 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
242 stripspaceupper(parm->label), _("Help"), parm->label));
243 switch (parm->type) {
245 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
246 make_parm_name(parm->label), *(char *)ptr);
247 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
248 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
252 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
253 make_parm_name(parm->label));
254 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
255 char **list = *(char ***)ptr;
256 for (;*list;list++) {
257 /* enclose in HTML encoded quotes if the string contains a space */
258 if ( strchr_m(*list, ' ') ) {
259 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
260 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
261 printf(""%s"%s", utf8_s1, utf8_s2);
263 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
264 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
265 printf("%s%s", utf8_s1, utf8_s2);
267 TALLOC_FREE(utf8_s1);
268 TALLOC_FREE(utf8_s2);
272 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
273 _("Set Default"), make_parm_name(parm->label));
274 if (parm->def.lvalue) {
275 char **list = (char **)(parm->def.lvalue);
276 for (; *list; list++) {
277 /* enclose in HTML encoded quotes if the string contains a space */
278 if ( strchr_m(*list, ' ') )
279 printf(""%s"%s", *list, ((*(list+1))?", ":""));
281 printf("%s%s", *list, ((*(list+1))?", ":""));
289 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
290 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
291 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
292 TALLOC_FREE(utf8_s1);
293 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
294 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
298 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
299 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
300 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
302 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
303 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
307 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
308 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
309 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
311 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
312 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
316 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
317 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
318 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
323 o = octal_string(*(int *)ptr);
324 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
325 make_parm_name(parm->label), o);
327 o = octal_string((int)(parm->def.ivalue));
328 printf("<input type=button value=\"%s\" "
329 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
330 _("Set Default"), make_parm_name(parm->label), o);
336 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
337 for (i=0;parm->enum_list[i].name;i++) {
338 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
339 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
343 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
344 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
349 printf("</td></tr>\n");
353 /****************************************************************************
354 display a set of parameters for a service
355 ****************************************************************************/
356 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
359 struct parm_struct *parm;
360 const char *heading = NULL;
361 const char *last_heading = NULL;
363 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
364 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
366 if (parm->p_class == P_SEPARATOR) {
367 heading = parm->label;
370 if (parm->flags & FLAG_HIDE) continue;
372 if (printers & !(parm->flags & FLAG_PRINT)) continue;
373 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
376 if (!( parm_filter & FLAG_ADVANCED )) {
377 if (!(parm->flags & FLAG_BASIC)) {
378 void *ptr = parm->ptr;
380 if (parm->p_class == P_LOCAL && snum >= 0) {
381 ptr = lp_local_ptr_by_snum(snum, ptr);
384 switch (parm->type) {
386 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
390 if (!str_list_equal(*(const char ***)ptr,
391 (const char **)(parm->def.lvalue))) continue;
396 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
401 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
406 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
411 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
417 if (printers && !(parm->flags & FLAG_PRINT)) continue;
420 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
422 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
424 if (heading && heading != last_heading) {
425 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
426 last_heading = heading;
428 show_parameter(snum, parm);
432 /****************************************************************************
433 load the smb.conf file into loadparm.
434 ****************************************************************************/
435 static bool load_config(bool save_def)
437 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
440 /****************************************************************************
442 ****************************************************************************/
443 static void write_config(FILE *f, bool show_defaults)
445 TALLOC_CTX *ctx = talloc_stackframe();
447 fprintf(f, "# Samba config file created using SWAT\n");
448 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
449 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
451 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
456 /****************************************************************************
457 save and reload the smb.conf config file
458 ****************************************************************************/
459 static int save_reload(int snum)
464 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
466 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
471 /* just in case they have used the buggy xinetd to create the file */
472 if (fstat(fileno(f), &st) == 0 &&
473 (st.st_mode & S_IWOTH)) {
474 #if defined HAVE_FCHMOD
475 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
477 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
481 write_config(f, False);
483 lp_dump_one(f, False, snum);
486 lp_kill_all_services();
488 if (!load_config(False)) {
489 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
493 iNumNonAutoPrintServices = lp_numservices();
494 pcap_cache_reload(server_event_context(), server_messaging_context(),
500 /****************************************************************************
502 ****************************************************************************/
503 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
508 if (snum < 0 && parm->p_class == P_LOCAL) {
509 /* this handles the case where we are changing a local
510 variable globally. We need to change the parameter in
511 all shares where it is currently set to the default */
512 for (i=0;i<lp_numservices();i++) {
513 s = lp_servicename(i);
514 if (s && (*s) && lp_is_default(i, parm)) {
515 lp_do_parameter(i, parm->label, v);
520 lp_do_parameter(snum, parm->label, v);
523 /****************************************************************************
524 commit a set of parameters for a service
525 ****************************************************************************/
526 static void commit_parameters(int snum)
529 struct parm_struct *parm;
533 while ((parm = lp_next_parameter(snum, &i, 1))) {
534 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
535 if ((v = cgi_variable(label)) != NULL) {
536 if (parm->flags & FLAG_HIDE)
538 commit_parameter(snum, parm, v);
545 /****************************************************************************
546 spit out the html for a link with an image
547 ****************************************************************************/
548 static void image_link(const char *name, const char *hlink, const char *src)
550 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
551 cgi_baseurl(), hlink, src, name);
554 /****************************************************************************
555 display the main navigation controls at the top of each page along
557 ****************************************************************************/
558 static void show_main_buttons(void)
562 if ((p = cgi_user_name()) && strcmp(p, "root")) {
563 printf(_("Logged in as <b>%s</b>"), p);
567 image_link(_("Home"), "", "images/home.gif");
568 if (have_write_access) {
569 image_link(_("Globals"), "globals", "images/globals.gif");
570 image_link(_("Shares"), "shares", "images/shares.gif");
571 image_link(_("Printers"), "printers", "images/printers.gif");
572 image_link(_("Wizard"), "wizard", "images/wizard.gif");
574 /* root always gets all buttons, otherwise look for -P */
575 if ( have_write_access || (!passwd_only && have_read_access) ) {
576 image_link(_("Status"), "status", "images/status.gif");
577 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
579 image_link(_("Password Management"), "passwd", "images/passwd.gif");
584 /****************************************************************************
585 * Handle Display/Edit Mode CGI
586 ****************************************************************************/
587 static void ViewModeBoxes(int mode)
589 printf("<p>%s: \n", _("Current View Is"));
590 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
591 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
592 printf("<br>%s: \n", _("Change View To"));
593 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
594 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
595 printf("</p><br>\n");
598 /****************************************************************************
599 display a welcome page
600 ****************************************************************************/
601 static void welcome_page(void)
603 if (file_exist("help/welcome.html")) {
604 include_html("help/welcome.html");
606 include_html("help/welcome-no-samba-doc.html");
610 /****************************************************************************
611 display the current smb.conf
612 ****************************************************************************/
613 static void viewconfig_page(void)
617 if (cgi_variable("full_view")) {
621 printf("<H2>%s</H2>\n", _("Current Config"));
622 printf("<form method=post>\n");
625 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
627 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
631 write_config(stdout, full_view);
636 /****************************************************************************
637 second screen of the wizard ... Fetch Configuration Parameters
638 ****************************************************************************/
639 static void wizard_params_page(void)
641 unsigned int parm_filter = FLAG_WIZARD;
643 /* Here we first set and commit all the parameters that were selected
644 in the previous screen. */
646 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
648 if (cgi_variable("Commit")) {
649 commit_parameters(GLOBAL_SECTION_SNUM);
653 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
655 if (have_write_access) {
656 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
659 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
663 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
664 printf("</table>\n");
668 /****************************************************************************
669 Utility to just rewrite the smb.conf file - effectively just cleans it up
670 ****************************************************************************/
671 static void rewritecfg_file(void)
673 commit_parameters(GLOBAL_SECTION_SNUM);
675 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
678 /****************************************************************************
679 wizard to create/modify the smb.conf file
680 ****************************************************************************/
681 static void wizard_page(void)
683 /* Set some variables to collect data from smb.conf */
690 if (cgi_variable("Rewrite")) {
691 (void) rewritecfg_file();
695 if (cgi_variable("GetWizardParams")){
696 (void) wizard_params_page();
700 if (cgi_variable("Commit")){
701 SerType = atoi(cgi_variable_nonull("ServerType"));
702 winstype = atoi(cgi_variable_nonull("WINSType"));
703 have_home = lp_servicenumber(HOMES_NAME);
704 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
706 /* Plain text passwords are too badly broken - use encrypted passwords only */
707 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
711 /* Stand-alone Server */
712 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
713 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
717 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
718 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
721 /* Domain Controller */
722 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
723 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
726 switch ( winstype ) {
728 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
729 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
732 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
733 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
736 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
737 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
741 /* Have to create Homes share? */
742 if ((HomeExpo == 1) && (have_home == -1)) {
743 const char *unix_share = HOMES_NAME;
746 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
747 have_home = lp_servicenumber(HOMES_NAME);
748 lp_do_parameter( have_home, "read only", "No");
749 lp_do_parameter( have_home, "valid users", "%S");
750 lp_do_parameter( have_home, "browseable", "No");
751 commit_parameters(have_home);
752 save_reload(have_home);
755 /* Need to Delete Homes share? */
756 if ((HomeExpo == 0) && (have_home != -1)) {
757 lp_remove_service(have_home);
761 commit_parameters(GLOBAL_SECTION_SNUM);
766 /* Now determine smb.conf WINS settings */
767 if (lp_wins_support())
769 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
772 /* Do we have a homes share? */
773 have_home = lp_servicenumber(HOMES_NAME);
775 if ((winstype == 2) && lp_wins_support())
778 role = lp_server_role();
781 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
782 printf("<form method=post action=wizard>\n");
784 if (have_write_access) {
785 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
786 printf("%s", _("The same will happen if you press the commit button."));
787 printf("<br><br>\n");
789 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
790 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
791 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
792 printf("</center>\n");
796 printf("<center><table border=0>");
797 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
798 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
799 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
800 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
802 if (role == ROLE_DOMAIN_BDC) {
803 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
805 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
806 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
807 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
808 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
810 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
812 /* Print out the list of wins servers */
813 if(lp_wins_server_list()) {
815 const char **wins_servers = lp_wins_server_list();
816 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
819 printf("\"></td></tr>\n");
821 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"));
822 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
824 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
825 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
826 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
827 printf("<td></td></tr>\n");
829 /* Enable this when we are ready ....
830 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
831 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
832 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
833 * printf("<td></td></tr>\n");
836 printf("</table></center>");
839 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
844 /****************************************************************************
845 display a globals editing page
846 ****************************************************************************/
847 static void globals_page(void)
849 unsigned int parm_filter = FLAG_BASIC;
852 printf("<H2>%s</H2>\n", _("Global Parameters"));
854 if (cgi_variable("Commit")) {
855 commit_parameters(GLOBAL_SECTION_SNUM);
859 if ( cgi_variable("ViewMode") )
860 mode = atoi(cgi_variable_nonull("ViewMode"));
861 if ( cgi_variable("BasicMode"))
863 if ( cgi_variable("AdvMode"))
866 printf("<form name=\"swatform\" method=post action=globals>\n");
868 ViewModeBoxes( mode );
871 parm_filter = FLAG_BASIC;
874 parm_filter = FLAG_ADVANCED;
878 if (have_write_access) {
879 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
880 _("Commit Changes"));
883 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
888 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
889 printf("</table>\n");
893 /****************************************************************************
894 display a shares editing page. share is in unix codepage,
895 ****************************************************************************/
896 static void shares_page(void)
898 const char *share = cgi_variable("share");
904 unsigned int parm_filter = FLAG_BASIC;
905 size_t converted_size;
908 snum = lp_servicenumber(share);
910 printf("<H2>%s</H2>\n", _("Share Parameters"));
912 if (cgi_variable("Commit") && snum >= 0) {
913 commit_parameters(snum);
915 snum = lp_servicenumber(share);
918 if (cgi_variable("Delete") && snum >= 0) {
919 lp_remove_service(snum);
925 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
926 snum = lp_servicenumber(share);
929 lp_copy_service(GLOBAL_SECTION_SNUM, share);
930 snum = lp_servicenumber(share);
932 snum = lp_servicenumber(share);
936 printf("<FORM name=\"swatform\" method=post>\n");
940 if ( cgi_variable("ViewMode") )
941 mode = atoi(cgi_variable_nonull("ViewMode"));
942 if ( cgi_variable("BasicMode"))
944 if ( cgi_variable("AdvMode"))
947 ViewModeBoxes( mode );
950 parm_filter = FLAG_BASIC;
953 parm_filter = FLAG_ADVANCED;
956 printf("<br><tr>\n");
957 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
958 printf("<td><select name=share>\n");
960 printf("<option value=\" \"> \n");
961 for (i=0;i<lp_numservices();i++) {
962 s = lp_servicename(i);
963 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
964 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
965 printf("<option %s value=\"%s\">%s\n",
966 (share && strcmp(share,s)==0)?"SELECTED":"",
971 printf("</select></td>\n");
972 if (have_write_access) {
973 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
978 if (have_write_access) {
980 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
981 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
987 if (have_write_access) {
988 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
991 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
997 show_parameters(snum, 1, parm_filter, 0);
998 printf("</table>\n");
1001 printf("</FORM>\n");
1004 /*************************************************************
1005 change a password either locally or remotely
1006 *************************************************************/
1007 static bool change_password(const char *remote_machine, const char *user_name,
1008 const char *old_passwd, const char *new_passwd,
1012 char *err_str = NULL;
1013 char *msg_str = NULL;
1016 printf("%s\n<p>", _("password change in demo mode rejected"));
1020 if (remote_machine != NULL) {
1021 ret = remote_password_change(remote_machine, user_name,
1022 old_passwd, new_passwd, &err_str);
1023 if (err_str != NULL)
1024 printf("%s\n<p>", err_str);
1026 return NT_STATUS_IS_OK(ret);
1029 if(!initialize_password_db(True, NULL)) {
1030 printf("%s\n<p>", _("Can't setup password database vectors."));
1034 ret = local_password_change(user_name, local_flags, new_passwd,
1035 &err_str, &msg_str);
1038 printf("%s\n<p>", msg_str);
1040 printf("%s\n<p>", err_str);
1044 return NT_STATUS_IS_OK(ret);
1047 /****************************************************************************
1048 do the stuff required to add or change a password
1049 ****************************************************************************/
1050 static void chg_passwd(void)
1054 int local_flags = 0;
1056 /* Make sure users name has been specified */
1057 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1058 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1063 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1064 * so if that's what we're doing, skip the rest of the checks
1066 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1069 * If current user is not root, make sure old password has been specified
1070 * If REMOTE change, even root must provide old password
1072 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1073 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1074 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1078 /* If changing a users password on a remote hosts we have to know what host */
1079 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1080 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1084 /* Make sure new passwords have been specified */
1085 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1086 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1087 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1091 /* Make sure new passwords was typed correctly twice */
1092 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1093 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1098 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1099 host = cgi_variable(RHOST);
1100 } else if (am_root()) {
1107 * Set up the local flags.
1110 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1111 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1112 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1113 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1114 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1115 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1117 rslt = change_password(host,
1118 cgi_variable_nonull(SWAT_USER),
1119 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1122 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1125 printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1128 printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1136 /****************************************************************************
1137 display a password editing page
1138 ****************************************************************************/
1139 static void passwd_page(void)
1141 const char *new_name = cgi_user_name();
1144 * After the first time through here be nice. If the user
1145 * changed the User box text to another users name, remember it.
1147 if (cgi_variable(SWAT_USER)) {
1148 new_name = cgi_variable_nonull(SWAT_USER);
1151 if (!new_name) new_name = "";
1153 printf("<H2>%s</H2>\n", _("Server Password Management"));
1155 printf("<FORM name=\"swatform\" method=post>\n");
1157 printf("<table>\n");
1160 * Create all the dialog boxes for data collection
1162 printf("<tr><td> %s : </td>\n", _("User Name"));
1163 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1165 printf("<tr><td> %s : </td>\n", _("Old Password"));
1166 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1168 printf("<tr><td> %s : </td>\n", _("New Password"));
1169 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1170 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1171 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1172 printf("</table>\n");
1175 * Create all the control buttons for requesting action
1177 printf("<input type=submit name=%s value=\"%s\">\n",
1178 CHG_S_PASSWD_FLAG, _("Change Password"));
1179 if (demo_mode || am_root()) {
1180 printf("<input type=submit name=%s value=\"%s\">\n",
1181 ADD_USER_FLAG, _("Add New User"));
1182 printf("<input type=submit name=%s value=\"%s\">\n",
1183 DELETE_USER_FLAG, _("Delete User"));
1184 printf("<input type=submit name=%s value=\"%s\">\n",
1185 DISABLE_USER_FLAG, _("Disable User"));
1186 printf("<input type=submit name=%s value=\"%s\">\n",
1187 ENABLE_USER_FLAG, _("Enable User"));
1189 printf("<p></FORM>\n");
1192 * Do some work if change, add, disable or enable was
1193 * requested. It could be this is the first time through this
1194 * code, so there isn't anything to do. */
1195 if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1196 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1200 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1202 printf("<FORM name=\"swatform\" method=post>\n");
1204 printf("<table>\n");
1207 * Create all the dialog boxes for data collection
1209 printf("<tr><td> %s : </td>\n", _("User Name"));
1210 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1211 printf("<tr><td> %s : </td>\n", _("Old Password"));
1212 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1213 printf("<tr><td> %s : </td>\n", _("New Password"));
1214 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1215 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1216 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1217 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1218 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1223 * Create all the control buttons for requesting action
1225 printf("<input type=submit name=%s value=\"%s\">",
1226 CHG_R_PASSWD_FLAG, _("Change Password"));
1228 printf("<p></FORM>\n");
1231 * Do some work if a request has been made to change the
1232 * password somewhere other than the server. It could be this
1233 * is the first time through this code, so there isn't
1234 * anything to do. */
1235 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1241 /****************************************************************************
1242 display a printers editing page
1243 ****************************************************************************/
1244 static void printers_page(void)
1246 const char *share = cgi_variable("share");
1251 unsigned int parm_filter = FLAG_BASIC;
1254 snum = lp_servicenumber(share);
1256 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1258 printf("<H3>%s</H3>\n", _("Important Note:"));
1259 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1260 printf("%s",_("are autoloaded printers from "));
1261 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1262 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1264 if (cgi_variable("Commit") && snum >= 0) {
1265 commit_parameters(snum);
1266 if (snum >= iNumNonAutoPrintServices)
1270 snum = lp_servicenumber(share);
1273 if (cgi_variable("Delete") && snum >= 0) {
1274 lp_remove_service(snum);
1280 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1281 snum = lp_servicenumber(share);
1282 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1284 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1285 snum = lp_servicenumber(share);
1286 lp_do_parameter(snum, "print ok", "Yes");
1288 snum = lp_servicenumber(share);
1292 printf("<FORM name=\"swatform\" method=post>\n");
1294 if ( cgi_variable("ViewMode") )
1295 mode = atoi(cgi_variable_nonull("ViewMode"));
1296 if ( cgi_variable("BasicMode"))
1298 if ( cgi_variable("AdvMode"))
1301 ViewModeBoxes( mode );
1304 parm_filter = FLAG_BASIC;
1307 parm_filter = FLAG_ADVANCED;
1310 printf("<table>\n");
1311 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1312 printf("<td><select name=\"share\">\n");
1313 if (snum < 0 || !lp_print_ok(snum))
1314 printf("<option value=\" \"> \n");
1315 for (i=0;i<lp_numservices();i++) {
1316 s = lp_servicename(i);
1317 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1318 if (i >= iNumNonAutoPrintServices)
1319 printf("<option %s value=\"%s\">[*]%s\n",
1320 (share && strcmp(share,s)==0)?"SELECTED":"",
1323 printf("<option %s value=\"%s\">%s\n",
1324 (share && strcmp(share,s)==0)?"SELECTED":"",
1328 printf("</select></td>");
1329 if (have_write_access) {
1330 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1333 printf("</table>\n");
1335 if (have_write_access) {
1336 printf("<table>\n");
1337 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1338 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1344 if (have_write_access) {
1345 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1347 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1352 printf("<table>\n");
1353 show_parameters(snum, 1, parm_filter, 1);
1354 printf("</table>\n");
1356 printf("</FORM>\n");
1360 when the _() translation macro is used there is no obvious place to free
1361 the resulting string and there is no easy way to give a static pointer.
1362 All we can do is rotate between some static buffers and hope a single d_printf()
1363 doesn't have more calls to _() than the number of buffers
1366 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1371 msgstr = lang_msg(msgid);
1376 ret = talloc_strdup(ctx, msgstr);
1378 lang_msg_free(msgstr);
1387 * main function for SWAT.
1389 int main(int argc, char *argv[])
1393 struct poptOption long_options[] = {
1395 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1396 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1400 TALLOC_CTX *frame = talloc_stackframe();
1403 umask(S_IWGRP | S_IWOTH);
1405 #if defined(HAVE_SET_AUTH_PARAMETERS)
1406 set_auth_parameters(argc, argv);
1407 #endif /* HAVE_SET_AUTH_PARAMETERS */
1409 /* just in case it goes wild ... */
1414 /* we don't want any SIGPIPE messages */
1415 BlockSignals(True,SIGPIPE);
1417 debug_set_logfile("/dev/null");
1419 /* we don't want stderr screwing us up */
1421 open("/dev/null", O_WRONLY);
1422 setup_logging("swat", DEBUG_FILE);
1426 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1428 /* Parse command line options */
1430 while(poptGetNextOpt(pc) != -1) { }
1432 poptFreeContext(pc);
1434 /* This should set a more apporiate log file */
1438 iNumNonAutoPrintServices = lp_numservices();
1439 pcap_cache_reload(server_event_context(), server_messaging_context(),
1442 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1446 cgi_load_variables();
1448 if (!file_exist(get_dyn_CONFIGFILE())) {
1449 have_read_access = True;
1450 have_write_access = True;
1452 /* check if the authenticated user has write access - if not then
1453 don't show write options */
1454 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1456 /* if the user doesn't have read access to smb.conf then
1457 don't let them view it */
1458 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1461 show_main_buttons();
1463 page = cgi_pathinfo();
1465 /* Root gets full functionality */
1466 if (have_read_access && strcmp(page, "globals")==0) {
1468 } else if (have_read_access && strcmp(page,"shares")==0) {
1470 } else if (have_read_access && strcmp(page,"printers")==0) {
1472 } else if (have_read_access && strcmp(page,"status")==0) {
1474 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1476 } else if (strcmp(page,"passwd")==0) {
1478 } else if (have_read_access && strcmp(page,"wizard")==0) {
1480 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1481 wizard_params_page();
1482 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {